diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index c2478cee8309..8500b6be8318 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,14 @@ # xargs -n1 | sort | uniq -d; # done +# 20110502: new clang import which bumps version from 2.9 to 3.0 +OLD_FILES+=usr/include/clang/2.9/emmintrin.h +OLD_FILES+=usr/include/clang/2.9/mm_malloc.h +OLD_FILES+=usr/include/clang/2.9/mmintrin.h +OLD_FILES+=usr/include/clang/2.9/pmmintrin.h +OLD_FILES+=usr/include/clang/2.9/tmmintrin.h +OLD_FILES+=usr/include/clang/2.9/xmmintrin.h +OLD_DIRS+=usr/include/clang/2.9 # 20110417: removal of Objective-C support OLD_FILES+=usr/include/objc/encoding.h OLD_FILES+=usr/include/objc/hash.h diff --git a/contrib/llvm/include/llvm-c/Disassembler.h b/contrib/llvm/include/llvm-c/Disassembler.h new file mode 100644 index 000000000000..9f10973404b7 --- /dev/null +++ b/contrib/llvm/include/llvm-c/Disassembler.h @@ -0,0 +1,149 @@ +/*===-- llvm-c/Disassembler.h - Disassembler Public 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 provides public interface to a disassembler library. *| +|* LLVM provides an implementation of this interface. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_DISASSEMBLER_H +#define LLVM_C_DISASSEMBLER_H 1 + +#include +#include "llvm/Support/DataTypes.h" + +/** + * An opaque reference to a disassembler context. + */ +typedef void *LLVMDisasmContextRef; + +/** + * The type for the operand information call back function. This is called to + * get the symbolic information for an operand of an instruction. Typically + * this is from the relocation information, symbol table, etc. That block of + * information is saved when the disassembler context is created and passed to + * the call back in the DisInfo parameter. The instruction containing operand + * is at the PC parameter. For some instruction sets, there can be more than + * one operand with symbolic information. To determine the symbolic operand + * information for each operand, the bytes for the specific operand in the + * instruction are specified by the Offset parameter and its byte widith is the + * size parameter. For instructions sets with fixed widths and one symbolic + * operand per instruction, the Offset parameter will be zero and Size parameter + * will be the instruction width. The information is returned in TagBuf and is + * Triple specific with its specific information defined by the value of + * TagType for that Triple. If symbolic information is returned the function + * returns 1 else it returns 0. + */ +typedef int (*LLVMOpInfoCallback)(void *DisInfo, + uint64_t PC, + uint64_t Offset, + uint64_t Size, + int TagType, + void *TagBuf); + +/** + * The initial support in LLVM MC for the most general form of a relocatable + * expression is "AddSymbol - SubtractSymbol + Offset". For some Darwin targets + * this full form is encoded in the relocation information so that AddSymbol and + * SubtractSymbol can be link edited independent of each other. Many other + * platforms only allow a relocatable expression of the form AddSymbol + Offset + * to be encoded. + * + * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct + * LLVMOpInfo1. The value of the relocatable expression for the operand, + * including any PC adjustment, is passed in to the call back in the Value + * field. The symbolic information about the operand is returned using all + * the fields of the structure with the Offset of the relocatable expression + * returned in the Value field. It is possible that some symbols in the + * relocatable expression were assembly temporary symbols, for example + * "Ldata - LpicBase + constant", and only the Values of the symbols without + * symbol names are present in the relocation information. The VariantKind + * type is one of the Target specific #defines below and is used to print + * operands like "_foo@GOT", ":lower16:_foo", etc. + */ +struct LLVMOpInfoSymbol1 { + uint64_t Present; /* 1 if this symbol is present */ + char *Name; /* symbol name if not NULL */ + uint64_t Value; /* symbol value if name is NULL */ +}; +struct LLVMOpInfo1 { + struct LLVMOpInfoSymbol1 AddSymbol; + struct LLVMOpInfoSymbol1 SubtractSymbol; + uint64_t Value; + uint64_t VariantKind; +}; + +/** + * The operand VariantKinds for symbolic disassembly. + */ +#define LLVMDisassembler_VariantKind_None 0 /* all targets */ + +/** + * The ARM target VariantKinds. + */ +#define LLVMDisassembler_VariantKind_ARM_HI16 1 /* :upper16: */ +#define LLVMDisassembler_VariantKind_ARM_LO16 2 /* :lower16: */ + +/** + * The type for the symbol lookup function. This may be called by the + * disassembler for such things like adding a comment for a PC plus a constant + * offset load instruction to use a symbol name instead of a load address value. + * It is passed the block information is saved when the disassembler context is + * created and a value of a symbol to look up. If no symbol is found NULL is + * to be returned. + */ +typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, + uint64_t SymbolValue); + +#ifdef __cplusplus +extern "C" { +#endif /* !defined(__cplusplus) */ + +/** + * Create a disassembler for the TripleName. Symbolic disassembly is supported + * by passing a block of information in the DisInfo parameter and specifing the + * TagType and call back functions as described above. These can all be passed + * as NULL. If successful this returns a disassembler context if not it + * returns NULL. + */ +extern LLVMDisasmContextRef +LLVMCreateDisasm(const char *TripleName, + void *DisInfo, + int TagType, + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp); + +/** + * Dispose of a disassembler context. + */ +extern void +LLVMDisasmDispose(LLVMDisasmContextRef DC); + +/** + * Disassmble a single instruction using the disassembler context specified in + * the parameter DC. The bytes of the instruction are specified in the parameter + * Bytes, and contains at least BytesSize number of bytes. The instruction is + * at the address specified by the PC parameter. If a valid instruction can be + * disassembled its string is returned indirectly in OutString which whos size + * is specified in the parameter OutStringSize. This function returns the + * number of bytes in the instruction or zero if there was no valid instruction. + */ +extern size_t +LLVMDisasmInstruction(LLVMDisasmContextRef DC, + uint8_t *Bytes, + uint64_t BytesSize, + uint64_t PC, + char *OutString, + size_t OutStringSize); + +#ifdef __cplusplus +} +#endif /* !defined(__cplusplus) */ + +#endif /* !defined(LLVM_C_DISASSEMBLER_H) */ diff --git a/contrib/llvm/include/llvm-c/EnhancedDisassembly.h b/contrib/llvm/include/llvm-c/EnhancedDisassembly.h index 28ac0ed2ab35..0c173c2b1999 100644 --- a/contrib/llvm/include/llvm-c/EnhancedDisassembly.h +++ b/contrib/llvm/include/llvm-c/EnhancedDisassembly.h @@ -44,7 +44,7 @@ typedef int (*EDByteReaderCallback)(uint8_t *byte, uint64_t address, void *arg); @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, +typedef int (*EDRegisterReaderCallback)(uint64_t *value, unsigned regID, void* arg); /*! @@ -83,7 +83,7 @@ typedef void *EDTokenRef; Encapsulates an operand of an instruction. */ typedef void *EDOperandRef; - + /*! @functiongroup Getting a disassembler */ @@ -91,7 +91,7 @@ typedef void *EDOperandRef; /*! @function EDGetDisassembler Gets the disassembler for a given target. - @param disassembler A pointer whose target will be filled in with the + @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. @@ -104,12 +104,12 @@ int EDGetDisassembler(EDDisassemblerRef *disassembler, /*! @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 + 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. @@ -117,7 +117,7 @@ int EDGetDisassembler(EDDisassemblerRef *disassembler, int EDGetRegisterName(const char** regName, EDDisassemblerRef disassembler, unsigned regID); - + /*! @function EDRegisterIsStackPointer Determines if a register is one of the platform's stack-pointer registers. @@ -137,16 +137,16 @@ int EDRegisterIsStackPointer(EDDisassemblerRef disassembler, */ 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 + 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. @@ -197,7 +197,7 @@ int EDGetInstString(const char **buf, @result 0 on success; -1 otherwise. */ int EDInstID(unsigned *instID, EDInstRef inst); - + /*! @function EDInstIsBranch @param inst The instruction to be queried. @@ -217,7 +217,7 @@ 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 + @result The ID of the branch target operand, suitable for use with EDCopyOperand. -1 if no such operand exists. */ int EDBranchTargetID(EDInstRef inst); @@ -225,7 +225,7 @@ 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 + @result The ID of the move source operand, suitable for use with EDCopyOperand. -1 if no such operand exists. */ int EDMoveSourceID(EDInstRef inst); @@ -233,7 +233,7 @@ 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 + @result The ID of the move source operand, suitable for use with EDCopyOperand. -1 if no such operand exists. */ int EDMoveTargetID(EDInstRef inst); @@ -241,7 +241,7 @@ int EDMoveTargetID(EDInstRef inst); /*! @functiongroup Creating and querying tokens */ - + /*! @function EDNumTokens @param inst The instruction to be queried. @@ -261,7 +261,7 @@ int EDNumTokens(EDInstRef inst); int EDGetToken(EDTokenRef *token, EDInstRef inst, int index); - + /*! @function EDGetTokenString Gets the disassembled text for a token. @@ -287,7 +287,7 @@ int EDOperandIndexForToken(EDTokenRef token); @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. @@ -335,18 +335,18 @@ int EDLiteralTokenAbsoluteValue(uint64_t *value, /*! @function EDRegisterTokenValue - @param registerID A pointer whose target will be filled in with the LLVM + @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. @@ -366,7 +366,7 @@ int EDNumOperands(EDInstRef inst); int EDGetOperand(EDOperandRef *operand, EDInstRef inst, int index); - + /*! @function EDOperandIsRegister @param operand The operand to be queried. @@ -391,13 +391,13 @@ 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. + 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 @@ -427,7 +427,7 @@ int EDEvaluateOperand(uint64_t *result, EDOperandRef operand, EDRegisterReaderCallback regReader, void *arg); - + #ifdef __BLOCKS__ /*! @@ -458,13 +458,13 @@ typedef int (^EDRegisterBlock_t)(uint64_t *value, unsigned regID); 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 + 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. @@ -505,7 +505,7 @@ int EDBlockVisitTokens(EDInstRef inst, EDTokenVisitor_t visitor); #endif - + #ifdef __cplusplus } #endif diff --git a/contrib/llvm/include/llvm-c/Object.h b/contrib/llvm/include/llvm-c/Object.h new file mode 100644 index 000000000000..6e72b5946644 --- /dev/null +++ b/contrib/llvm/include/llvm-c/Object.h @@ -0,0 +1,77 @@ +/*===-- llvm-c/Object.h - Object Lib C Iface --------------------*- 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 libLLVMObject.a, which */ +/* implements object file reading and writing. */ +/* */ +/* Many exotic languages can interoperate with C code but have a harder time */ +/* with C++ due to name mangling. So in addition to C, this interface enables */ +/* tools written in such languages. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_OBJECT_H +#define LLVM_C_OBJECT_H + +#include "llvm-c/Core.h" +#include "llvm/Config/llvm-config.h" + +#ifdef __cplusplus +#include "llvm/Object/ObjectFile.h" + +extern "C" { +#endif + + +typedef struct LLVMOpaqueObjectFile *LLVMObjectFileRef; + +typedef struct LLVMOpaqueSectionIterator *LLVMSectionIteratorRef; + +LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf); +void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile); + +LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile); +void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI); +LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile, + LLVMSectionIteratorRef SI); +void LLVMMoveToNextSection(LLVMSectionIteratorRef SI); +const char *LLVMGetSectionName(LLVMSectionIteratorRef SI); +uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI); +const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI); + + +#ifdef __cplusplus +} + +namespace llvm { + namespace object { + inline ObjectFile *unwrap(LLVMObjectFileRef OF) { + return reinterpret_cast(OF); + } + + inline LLVMObjectFileRef wrap(const ObjectFile *OF) { + return reinterpret_cast(const_cast(OF)); + } + + inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) { + return reinterpret_cast(SI); + } + + inline LLVMSectionIteratorRef + wrap(const ObjectFile::section_iterator *SI) { + return reinterpret_cast + (const_cast(SI)); + } + } +} + +#endif /* defined(__cplusplus) */ + +#endif + diff --git a/contrib/llvm/include/llvm-c/Transforms/Scalar.h b/contrib/llvm/include/llvm-c/Transforms/Scalar.h index 2ddfb38171c2..cf8d71f5d007 100644 --- a/contrib/llvm/include/llvm-c/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm-c/Transforms/Scalar.h @@ -52,6 +52,9 @@ void LLVMAddLICMPass(LLVMPassManagerRef PM); /** See llvm::createLoopDeletionPass function. */ void LLVMAddLoopDeletionPass(LLVMPassManagerRef PM); +/** See llvm::createLoopIdiomPass function */ +void LLVMAddLoopIdiomPass(LLVMPassManagerRef PM); + /** See llvm::createLoopRotatePass function. */ void LLVMAddLoopRotatePass(LLVMPassManagerRef PM); @@ -76,6 +79,9 @@ void LLVMAddSCCPPass(LLVMPassManagerRef PM); /** See llvm::createScalarReplAggregatesPass function. */ void LLVMAddScalarReplAggregatesPass(LLVMPassManagerRef PM); +/** See llvm::createScalarReplAggregatesPass function. */ +void LLVMAddScalarReplAggregatesPassSSA(LLVMPassManagerRef PM); + /** See llvm::createScalarReplAggregatesPass function. */ void LLVMAddScalarReplAggregatesPassWithThreshold(LLVMPassManagerRef PM, int Threshold); @@ -95,6 +101,19 @@ void LLVMAddDemoteMemoryToRegisterPass(LLVMPassManagerRef PM); /** See llvm::createVerifierPass function. */ void LLVMAddVerifierPass(LLVMPassManagerRef PM); +/** See llvm::createCorrelatedValuePropagationPass function */ +void LLVMAddCorrelatedValuePropagationPass(LLVMPassManagerRef PM); + +/** See llvm::createEarlyCSEPass function */ +void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM); + +/** See llvm::createTypeBasedAliasAnalysisPass function */ +void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); + +/** See llvm::createBasicAliasAnalysisPass function */ +void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); + + #ifdef __cplusplus } #endif /* defined(__cplusplus) */ diff --git a/contrib/llvm/include/llvm-c/lto.h b/contrib/llvm/include/llvm-c/lto.h index 1c42ce0cec77..7ea7ad01a211 100644 --- a/contrib/llvm/include/llvm-c/lto.h +++ b/contrib/llvm/include/llvm-c/lto.h @@ -72,7 +72,7 @@ lto_get_version(void); /** - * Returns the last error string or NULL if last operation was sucessful. + * Returns the last error string or NULL if last operation was successful. */ extern const char* lto_get_error_message(void); @@ -127,7 +127,15 @@ lto_module_create_from_memory(const void* mem, size_t length); * Returns NULL on error (check lto_get_error_message() for details). */ extern lto_module_t -lto_module_create_from_fd(int fd, const char *path, off_t size); +lto_module_create_from_fd(int fd, const char *path, size_t file_size); + +/** + * Loads an object file from disk. The seek point of fd is not preserved. + * Returns NULL on error (check lto_get_error_message() for details). + */ +extern lto_module_t +lto_module_create_from_fd_at_offset(int fd, const char *path, size_t file_size, + size_t map_size, off_t offset); /** @@ -255,7 +263,7 @@ lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); /** * Generates code for all added modules into one native object file. - * On sucess returns a pointer to a generated mach-o/ELF buffer and + * On success returns a pointer to a generated mach-o/ELF buffer and * length set to the buffer size. The buffer is owned by the * lto_code_gen_t and will be freed when lto_codegen_dispose() * is called, or lto_codegen_compile() is called again. @@ -264,6 +272,13 @@ lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); extern const void* lto_codegen_compile(lto_code_gen_t cg, size_t* length); +/** + * Generates code for all added modules into one native object file. + * The name of the file is written to name. Returns true on error. + */ +extern bool +lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); + /** * Sets options to help debug codegen bugs. diff --git a/contrib/llvm/include/llvm/ADT/APFloat.h b/contrib/llvm/include/llvm/ADT/APFloat.h index ca4138b825a6..21b8c86d1d5b 100644 --- a/contrib/llvm/include/llvm/ADT/APFloat.h +++ b/contrib/llvm/include/llvm/ADT/APFloat.h @@ -353,6 +353,10 @@ namespace llvm { unsigned FormatPrecision = 0, unsigned FormatMaxPadding = 3) const; + /// getExactInverse - If this value has an exact multiplicative inverse, + /// store it in inv and return true. + bool getExactInverse(APFloat *inv) const; + private: /* Trivial queries. */ diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h index d1fd3e5034bf..2feef076fa7b 100644 --- a/contrib/llvm/include/llvm/ADT/APInt.h +++ b/contrib/llvm/include/llvm/ADT/APInt.h @@ -818,6 +818,7 @@ class APInt { APInt usub_ov(const APInt &RHS, bool &Overflow) const; APInt sdiv_ov(const APInt &RHS, bool &Overflow) const; APInt smul_ov(const APInt &RHS, bool &Overflow) const; + APInt umul_ov(const APInt &RHS, bool &Overflow) const; APInt sshl_ov(unsigned Amt, bool &Overflow) const; /// @returns the bit value at bitPosition @@ -1372,7 +1373,7 @@ class APInt { /// Calculate the magic number for unsigned division by a constant. struct mu; - mu magicu() const; + mu magicu(unsigned LeadingZeros = 0) const; /// @} /// @name Building-block Operations for APInt and APFloat diff --git a/contrib/llvm/include/llvm/ADT/ArrayRef.h b/contrib/llvm/include/llvm/ADT/ArrayRef.h index d3ea9c0f03b7..97e42cb26602 100644 --- a/contrib/llvm/include/llvm/ADT/ArrayRef.h +++ b/contrib/llvm/include/llvm/ADT/ArrayRef.h @@ -22,8 +22,8 @@ namespace llvm { /// /// This class does not own the underlying data, it is expected to be used in /// situations where the data resides in some other buffer, whose lifetime - /// extends past that of the StringRef. For this reason, it is not in general - /// safe to store a ArrayRef. + /// extends past that of the ArrayRef. For this reason, it is not in general + /// safe to store an ArrayRef. /// /// This is intended to be trivially copyable, so it should be passed by /// value. @@ -79,6 +79,8 @@ namespace llvm { /// empty - Check if the array is empty. bool empty() const { return Length == 0; } + const T *data() const { return Data; } + /// size - Get the array size. size_t size() const { return Length; } @@ -94,10 +96,22 @@ namespace llvm { return Data[Length-1]; } + /// slice(n) - Chop off the first N elements of the array. + ArrayRef slice(unsigned N) { + assert(N <= size() && "Invalid specifier"); + return ArrayRef(data()+N, size()-N); + } + + /// slice(n, m) - Chop off the first N elements of the array, and keep M + /// elements in the array. + ArrayRef slice(unsigned N, unsigned M) { + assert(N+M <= size() && "Invalid specifier"); + return ArrayRef(data()+N, M); + } + /// @} /// @name Operator Overloads /// @{ - const T &operator[](size_t Index) const { assert(Index < Length && "Invalid index!"); return Data[Index]; @@ -106,7 +120,6 @@ namespace llvm { /// @} /// @name Expensive Operations /// @{ - std::vector vec() const { return std::vector(Data, Data+Length); } diff --git a/contrib/llvm/include/llvm/ADT/DenseMap.h b/contrib/llvm/include/llvm/ADT/DenseMap.h index 61d6ae70e1d9..0f1cfebc3672 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMap.h +++ b/contrib/llvm/include/llvm/ADT/DenseMap.h @@ -53,13 +53,13 @@ class DenseMap { CopyFrom(other); } - explicit DenseMap(unsigned NumInitBuckets = 64) { + explicit DenseMap(unsigned NumInitBuckets = 0) { init(NumInitBuckets); } template DenseMap(const InputIt &I, const InputIt &E) { - init(64); + init(NextPowerOf2(std::distance(I, E))); insert(I, E); } @@ -72,7 +72,8 @@ class DenseMap { P->first.~KeyT(); } #ifndef NDEBUG - memset(Buckets, 0x5a, sizeof(BucketT)*NumBuckets); + if (NumBuckets) + memset((void*)Buckets, 0x5a, sizeof(BucketT)*NumBuckets); #endif operator delete(Buckets); } @@ -98,7 +99,10 @@ class DenseMap { unsigned size() const { return NumEntries; } /// Grow the densemap so that it has at least Size buckets. Does not shrink - void resize(size_t Size) { grow(Size); } + void resize(size_t Size) { + if (Size > NumBuckets) + grow(Size); + } void clear() { if (NumEntries == 0 && NumTombstones == 0) return; @@ -248,23 +252,29 @@ class DenseMap { if (NumBuckets) { #ifndef NDEBUG - memset(Buckets, 0x5a, sizeof(BucketT)*NumBuckets); + memset((void*)Buckets, 0x5a, sizeof(BucketT)*NumBuckets); #endif operator delete(Buckets); } - Buckets = static_cast(operator new(sizeof(BucketT) * - other.NumBuckets)); + + NumBuckets = other.NumBuckets; + + if (NumBuckets == 0) { + Buckets = 0; + return; + } + + Buckets = static_cast(operator new(sizeof(BucketT) * NumBuckets)); if (isPodLike::value && isPodLike::value) - memcpy(Buckets, other.Buckets, other.NumBuckets * sizeof(BucketT)); + memcpy(Buckets, other.Buckets, NumBuckets * sizeof(BucketT)); else - for (size_t i = 0; i < other.NumBuckets; ++i) { + for (size_t i = 0; i < NumBuckets; ++i) { new (&Buckets[i].first) KeyT(other.Buckets[i].first); if (!KeyInfoT::isEqual(Buckets[i].first, getEmptyKey()) && !KeyInfoT::isEqual(Buckets[i].first, getTombstoneKey())) new (&Buckets[i].second) ValueT(other.Buckets[i].second); } - NumBuckets = other.NumBuckets; } BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, @@ -279,11 +289,14 @@ class DenseMap { // table completely filled with tombstones, no lookup would ever succeed, // causing infinite loops in lookup. ++NumEntries; - if (NumEntries*4 >= NumBuckets*3 || - NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) { + if (NumEntries*4 >= NumBuckets*3) { this->grow(NumBuckets * 2); LookupBucketFor(Key, TheBucket); } + if (NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) { + this->grow(NumBuckets); + LookupBucketFor(Key, TheBucket); + } // If we are writing over a tombstone, remember this. if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey())) @@ -313,6 +326,11 @@ class DenseMap { unsigned ProbeAmt = 1; BucketT *BucketsPtr = Buckets; + if (NumBuckets == 0) { + FoundBucket = 0; + return false; + } + // FoundTombstone - Keep track of whether we find a tombstone while probing. BucketT *FoundTombstone = 0; const KeyT EmptyKey = getEmptyKey(); @@ -354,6 +372,12 @@ class DenseMap { NumEntries = 0; NumTombstones = 0; NumBuckets = InitBuckets; + + if (InitBuckets == 0) { + Buckets = 0; + return; + } + assert(InitBuckets && (InitBuckets & (InitBuckets-1)) == 0 && "# initial buckets must be a power of two!"); Buckets = static_cast(operator new(sizeof(BucketT)*InitBuckets)); @@ -367,6 +391,9 @@ class DenseMap { unsigned OldNumBuckets = NumBuckets; BucketT *OldBuckets = Buckets; + if (NumBuckets < 64) + NumBuckets = 64; + // Double the number of buckets. while (NumBuckets < AtLeast) NumBuckets <<= 1; @@ -398,7 +425,8 @@ class DenseMap { } #ifndef NDEBUG - memset(OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); + if (OldNumBuckets) + memset((void*)OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); #endif // Free the old table. operator delete(OldBuckets); @@ -431,13 +459,22 @@ class DenseMap { } #ifndef NDEBUG - memset(OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); + memset((void*)OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); #endif // Free the old table. operator delete(OldBuckets); NumEntries = 0; } + +public: + /// Return the approximate size (in bytes) of the actual map. + /// This is just the raw memory used by DenseMap. + /// If entries are pointers to objects, the size of the referenced objects + /// are not included. + size_t getMemorySize() const { + return NumBuckets * sizeof(BucketT); + } }; template > { key ^= (key >> 31); return (unsigned)key; } - static bool isEqual(const Pair& LHS, const Pair& RHS) { return LHS == RHS; } + static bool isEqual(const Pair &LHS, const Pair &RHS) { + return FirstInfo::isEqual(LHS.first, RHS.first) && + SecondInfo::isEqual(LHS.second, RHS.second); + } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h b/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h index b9e5cbdf8c6b..dd13a2c02053 100644 --- a/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h +++ b/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h @@ -143,8 +143,7 @@ class df_iterator : public std::iterator struct FoldingSetTrait; /// for FoldingSetTrait implementations. /// template struct DefaultFoldingSetTrait { - static void Profile(const T& X, FoldingSetNodeID& ID) { + static void Profile(const T &X, FoldingSetNodeID &ID) { X.Profile(ID); } - static void Profile(T& X, FoldingSetNodeID& ID) { + static void Profile(T &X, FoldingSetNodeID &ID) { X.Profile(ID); } @@ -267,7 +267,7 @@ template struct ContextualFoldingSetTrait /// is often much larger than necessary, and the possibility of heap /// allocation means it requires a non-trivial destructor call. class FoldingSetNodeIDRef { - const unsigned* Data; + const unsigned *Data; size_t Size; public: FoldingSetNodeIDRef() : Data(0), Size(0) {} @@ -310,9 +310,10 @@ class FoldingSetNodeID { void AddInteger(unsigned long long I); void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); } void AddString(StringRef String); + void AddNodeID(const FoldingSetNodeID &ID); template - inline void Add(const T& x) { FoldingSetTrait::Profile(x, *this); } + inline void Add(const T &x) { FoldingSetTrait::Profile(x, *this); } /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID /// object to be used to compute a new profile. @@ -548,7 +549,7 @@ class FoldingSetIterator : public FoldingSetIteratorImpl { return static_cast(NodePtr); } - inline FoldingSetIterator& operator++() { // Preincrement + inline FoldingSetIterator &operator++() { // Preincrement advance(); return *this; } @@ -596,10 +597,10 @@ class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl { FoldingSetBucketIterator(void **Bucket, bool) : FoldingSetBucketIteratorImpl(Bucket, true) {} - T& operator*() const { return *static_cast(Ptr); } - T* operator->() const { return static_cast(Ptr); } + T &operator*() const { return *static_cast(Ptr); } + T *operator->() const { return static_cast(Ptr); } - inline FoldingSetBucketIterator& operator++() { // Preincrement + inline FoldingSetBucketIterator &operator++() { // Preincrement advance(); return *this; } @@ -615,36 +616,36 @@ template class FoldingSetNodeWrapper : public FoldingSetNode { T data; public: - explicit FoldingSetNodeWrapper(const T& x) : data(x) {} + explicit FoldingSetNodeWrapper(const T &x) : data(x) {} virtual ~FoldingSetNodeWrapper() {} template - explicit FoldingSetNodeWrapper(const A1& a1) + explicit FoldingSetNodeWrapper(const A1 &a1) : data(a1) {} template - explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2) + explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2) : data(a1,a2) {} template - explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3) + explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3) : data(a1,a2,a3) {} template - explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, - const A4& a4) + explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3, + const A4 &a4) : data(a1,a2,a3,a4) {} template - explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, - const A4& a4, const A5& a5) + explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3, + const A4 &a4, const A5 &a5) : data(a1,a2,a3,a4,a5) {} - void Profile(FoldingSetNodeID& ID) { FoldingSetTrait::Profile(data, ID); } + void Profile(FoldingSetNodeID &ID) { FoldingSetTrait::Profile(data, ID); } - T& getValue() { return data; } - const T& getValue() const { return data; } + T &getValue() { return data; } + const T &getValue() const { return data; } operator T&() { return data; } operator const T&() const { return data; } @@ -661,20 +662,22 @@ class FastFoldingSetNode : public FoldingSetNode { protected: explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {} public: - void Profile(FoldingSetNodeID& ID) const { ID = FastID; } + void Profile(FoldingSetNodeID &ID) const { + ID.AddNodeID(FastID); + } }; //===----------------------------------------------------------------------===// // Partial specializations of FoldingSetTrait. template struct FoldingSetTrait { - static inline void Profile(const T* X, FoldingSetNodeID& ID) { + static inline void Profile(const T *X, FoldingSetNodeID &ID) { ID.AddPointer(X); } }; template struct FoldingSetTrait { - static inline void Profile(const T* X, FoldingSetNodeID& ID) { + static inline void Profile(const T *X, FoldingSetNodeID &ID) { ID.AddPointer(X); } }; diff --git a/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h b/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h index 0d8fcf343385..fa7ccb975e52 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h @@ -10,6 +10,10 @@ // This file defines the ImmutableIntervalMap class. // //===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMMUTABLE_INTERVAL_MAP_H +#define LLVM_ADT_IMMUTABLE_INTERVAL_MAP_H + #include "llvm/ADT/ImmutableMap.h" namespace llvm { @@ -240,3 +244,5 @@ class ImmutableIntervalMap }; } // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/ADT/IntervalMap.h b/contrib/llvm/include/llvm/ADT/IntervalMap.h index 79f24d31c068..f28ebf3b9a5f 100644 --- a/contrib/llvm/include/llvm/ADT/IntervalMap.h +++ b/contrib/llvm/include/llvm/ADT/IntervalMap.h @@ -1328,6 +1328,10 @@ class IntervalMap::const_iterator : /// const_iterator - Create an iterator that isn't pointing anywhere. const_iterator() : map(0) {} + /// setMap - Change the map iterated over. This call must be followed by a + /// call to goToBegin(), goToEnd(), or find() + void setMap(const IntervalMap &m) { map = const_cast(&m); } + /// valid - Return true if the current position is valid, false for end(). bool valid() const { return path.valid(); } diff --git a/contrib/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h b/contrib/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h index 37d4ac9d29df..2f6fd2bd5590 100644 --- a/contrib/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/contrib/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -42,18 +42,16 @@ namespace llvm { //===----------------------------------------------------------------------===// template class RefCountedBase { - unsigned ref_cnt; + mutable unsigned ref_cnt; - protected: + public: RefCountedBase() : ref_cnt(0) {} - void Retain() { ++ref_cnt; } - void Release() { + void Retain() const { ++ref_cnt; } + void Release() const { assert (ref_cnt > 0 && "Reference count is already zero."); - if (--ref_cnt == 0) delete static_cast(this); + if (--ref_cnt == 0) delete static_cast(this); } - - friend class IntrusiveRefCntPtr; }; //===----------------------------------------------------------------------===// @@ -64,21 +62,21 @@ namespace llvm { /// inherit from RefCountedBaseVPTR can't be allocated on stack - /// attempting to do this will produce a compile error. //===----------------------------------------------------------------------===// - template class RefCountedBaseVPTR { - unsigned ref_cnt; + mutable unsigned ref_cnt; protected: RefCountedBaseVPTR() : ref_cnt(0) {} virtual ~RefCountedBaseVPTR() {} - void Retain() { ++ref_cnt; } - void Release() { + void Retain() const { ++ref_cnt; } + void Release() const { assert (ref_cnt > 0 && "Reference count is already zero."); if (--ref_cnt == 0) delete this; } - friend class IntrusiveRefCntPtr; + template + friend class IntrusiveRefCntPtr; }; //===----------------------------------------------------------------------===// @@ -155,6 +153,10 @@ namespace llvm { other.Obj = Obj; Obj = tmp; } + + void resetWithoutRelease() { + Obj = 0; + } private: void retain() { if (Obj) Obj->Retain(); } diff --git a/contrib/llvm/include/llvm/ADT/PointerUnion.h b/contrib/llvm/include/llvm/ADT/PointerUnion.h index 61de042b0ff2..13b98cef07ab 100644 --- a/contrib/llvm/include/llvm/ADT/PointerUnion.h +++ b/contrib/llvm/include/llvm/ADT/PointerUnion.h @@ -19,16 +19,33 @@ namespace llvm { - /// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return - /// false or true respectively. - template - static inline int getPointerUnionTypeNum(PT1 *P) { return 0; } - template - static inline int getPointerUnionTypeNum(PT2 *P) { return 1; } - template - static inline int getPointerUnionTypeNum(...) { return -1; } - - + template + struct PointerUnionTypeSelectorReturn { + typedef T Return; + }; + + /// \brief Get a type based on whether two types are the same or not. For: + /// @code + /// typedef typename PointerUnionTypeSelector::Return Ret; + /// @endcode + /// Ret will be EQ type if T1 is same as T2 or NE type otherwise. + template + struct PointerUnionTypeSelector { + typedef typename PointerUnionTypeSelectorReturn::Return Return; + }; + + template + struct PointerUnionTypeSelector { + typedef typename PointerUnionTypeSelectorReturn::Return Return; + }; + + template + struct PointerUnionTypeSelectorReturn< + PointerUnionTypeSelector > { + typedef typename PointerUnionTypeSelector::Return + Return; + }; + /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion /// for the two template arguments. template @@ -65,6 +82,16 @@ namespace llvm { PointerUnionUIntTraits > ValTy; private: ValTy Val; + + struct IsPT1 { + static const int Num = 0; + }; + struct IsPT2 { + static const int Num = 1; + }; + template + struct UNION_DOESNT_CONTAIN_TYPE { }; + public: PointerUnion() {} @@ -87,8 +114,11 @@ namespace llvm { /// is() return true if the Union currently holds the type matching T. template int is() const { - int TyNo = ::llvm::getPointerUnionTypeNum((T*)0); - assert(TyNo != -1 && "Type query could never succeed on PointerUnion!"); + typedef typename + ::llvm::PointerUnionTypeSelector > >::Return Ty; + int TyNo = Ty::Num; return static_cast(Val.getInt()) == TyNo; } @@ -175,6 +205,34 @@ namespace llvm { typedef PointerUnion ValTy; private: ValTy Val; + + struct IsInnerUnion { + ValTy Val; + IsInnerUnion(ValTy val) : Val(val) { } + template + int is() const { + return Val.template is() && + Val.template get().template is(); + } + template + T get() const { + return Val.template get().template get(); + } + }; + + struct IsPT3 { + ValTy Val; + IsPT3(ValTy val) : Val(val) { } + template + int is() const { + return Val.template is(); + } + template + T get() const { + return Val.template get(); + } + }; + public: PointerUnion3() {} @@ -196,11 +254,12 @@ namespace llvm { /// is() return true if the Union currently holds the type matching T. template int is() const { - // Is it PT1/PT2? - if (::llvm::getPointerUnionTypeNum((T*)0) != -1) - return Val.template is() && - Val.template get().template is(); - return Val.template is(); + // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Ty(Val).is(); } /// get() - Return the value of the specified pointer type. If the @@ -208,11 +267,12 @@ namespace llvm { template T get() const { assert(is() && "Invalid accessor called"); - // Is it PT1/PT2? - if (::llvm::getPointerUnionTypeNum((T*)0) != -1) - return Val.template get().template get(); - - return Val.template get(); + // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Ty(Val).get(); } /// dyn_cast() - If the current value is of the specified pointer type, @@ -302,12 +362,13 @@ namespace llvm { /// is() return true if the Union currently holds the type matching T. template int is() const { - // Is it PT1/PT2? - if (::llvm::getPointerUnionTypeNum((T*)0) != -1) - return Val.template is() && - Val.template get().template is(); - return Val.template is() && - Val.template get().template is(); + // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Val.template is() && + Val.template get().template is(); } /// get() - Return the value of the specified pointer type. If the @@ -315,11 +376,12 @@ namespace llvm { template T get() const { assert(is() && "Invalid accessor called"); - // Is it PT1/PT2? - if (::llvm::getPointerUnionTypeNum((T*)0) != -1) - return Val.template get().template get(); - - return Val.template get().template get(); + // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Val.template get().template get(); } /// dyn_cast() - If the current value is of the specified pointer type, diff --git a/contrib/llvm/include/llvm/ADT/ScopedHashTable.h b/contrib/llvm/include/llvm/ADT/ScopedHashTable.h index af3c482043b1..a6803ee0eddf 100644 --- a/contrib/llvm/include/llvm/ADT/ScopedHashTable.h +++ b/contrib/llvm/include/llvm/ADT/ScopedHashTable.h @@ -96,6 +96,9 @@ class ScopedHashTableScope { ScopedHashTableScope(ScopedHashTable &HT); ~ScopedHashTableScope(); + ScopedHashTableScope *getParentScope() { return PrevScope; } + const ScopedHashTableScope *getParentScope() const { return PrevScope; } + private: friend class ScopedHashTable; ScopedHashTableVal *getLastValInScope() { @@ -141,9 +144,14 @@ class ScopedHashTableIterator { template class ScopedHashTable { +public: + /// ScopeTy - This is a helpful typedef that allows clients to get easy access + /// to the name of the scope for this hash table. + typedef ScopedHashTableScope ScopeTy; +private: typedef ScopedHashTableVal ValTy; DenseMap TopLevelMap; - ScopedHashTableScope *CurScope; + ScopeTy *CurScope; AllocatorTy Allocator; @@ -157,9 +165,6 @@ class ScopedHashTable { assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!"); } - /// ScopeTy - This is a helpful typedef that allows clients to get easy access - /// to the name of the scope for this hash table. - typedef ScopedHashTableScope ScopeTy; /// Access to the allocator. typedef typename ReferenceAdder::result AllocatorRefTy; @@ -180,13 +185,7 @@ class ScopedHashTable { } void insert(const K &Key, const V &Val) { - assert(CurScope && "No scope active!"); - - ScopedHashTableVal *&KeyEntry = TopLevelMap[Key]; - - KeyEntry = ValTy::Create(CurScope->getLastValInScope(), KeyEntry, Key, Val, - Allocator); - CurScope->setLastValInScope(KeyEntry); + insertIntoScope(CurScope, Key, Val); } typedef ScopedHashTableIterator iterator; @@ -199,6 +198,21 @@ class ScopedHashTable { if (I == TopLevelMap.end()) return end(); return iterator(I->second); } + + ScopeTy *getCurScope() { return CurScope; } + const ScopeTy *getCurScope() const { return CurScope; } + + /// insertIntoScope - This inserts the specified key/value at the specified + /// (possibly not the current) scope. While it is ok to insert into a scope + /// that isn't the current one, it isn't ok to insert *underneath* an existing + /// value of the specified key. + void insertIntoScope(ScopeTy *S, const K &Key, const V &Val) { + assert(S && "No scope active!"); + ScopedHashTableVal *&KeyEntry = TopLevelMap[Key]; + KeyEntry = ValTy::Create(S->getLastValInScope(), KeyEntry, Key, Val, + Allocator); + S->setLastValInScope(KeyEntry); + } }; /// ScopedHashTableScope ctor - Install this as the current scope for the hash diff --git a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h index ff32ba87a264..9992858d67b0 100644 --- a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h +++ b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h @@ -133,7 +133,7 @@ class SmallPtrSetImpl { void shrink_and_clear(); /// Grow - Allocate a larger backing store for the buckets and move it over. - void Grow(); + void Grow(unsigned NewSize); void operator=(const SmallPtrSetImpl &RHS); // DO NOT IMPLEMENT. protected: diff --git a/contrib/llvm/include/llvm/ADT/Statistic.h b/contrib/llvm/include/llvm/ADT/Statistic.h index f137ea21d058..fda99c6edbc3 100644 --- a/contrib/llvm/include/llvm/ADT/Statistic.h +++ b/contrib/llvm/include/llvm/ADT/Statistic.h @@ -121,6 +121,9 @@ class Statistic { /// \brief Enable the collection and printing of statistics. void EnableStatistics(); +/// \brief Check if statistics are enabled. +bool AreStatisticsEnabled(); + /// \brief Print statistics to the file returned by CreateInfoOutputFile(). void PrintStatistics(); diff --git a/contrib/llvm/include/llvm/ADT/StringExtras.h b/contrib/llvm/include/llvm/ADT/StringExtras.h index acbed66ef401..5f5c04187ada 100644 --- a/contrib/llvm/include/llvm/ADT/StringExtras.h +++ b/contrib/llvm/include/llvm/ADT/StringExtras.h @@ -20,7 +20,6 @@ #include #include #include -#include namespace llvm { template class SmallVectorImpl; @@ -153,7 +152,7 @@ void SplitString(StringRef Source, SmallVectorImpl &OutFragments, StringRef Delimiters = " \t\n\v\f\r"); -/// HashString - Hash funtion for strings. +/// HashString - Hash function for strings. /// /// This is the Bernstein hash function. // diff --git a/contrib/llvm/include/llvm/ADT/StringMap.h b/contrib/llvm/include/llvm/ADT/StringMap.h index bad0e6f5136a..934cacc78a8c 100644 --- a/contrib/llvm/include/llvm/ADT/StringMap.h +++ b/contrib/llvm/include/llvm/ADT/StringMap.h @@ -17,7 +17,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include -#include namespace llvm { template @@ -81,16 +80,6 @@ class StringMapImpl { StringMapImpl(unsigned InitSize, unsigned ItemSize); void RehashTable(); - /// ShouldRehash - Return true if the table should be rehashed after a new - /// element was recently inserted. - bool ShouldRehash() const { - // If the hash table is now more than 3/4 full, or if fewer than 1/8 of - // the buckets are empty (meaning that many are filled with tombstones), - // grow the table. - return NumItems*4 > NumBuckets*3 || - NumBuckets-(NumItems+NumTombstones) < NumBuckets/8; - } - /// LookupBucketFor - Look up the bucket that the specified string should end /// up in. If it already exists as a key in the map, the Item pointer for the /// specified bucket will be non-null. Otherwise, it will be null. In either @@ -339,9 +328,9 @@ class StringMap : public StringMapImpl { --NumTombstones; Bucket.Item = KeyValue; ++NumItems; + assert(NumItems + NumTombstones <= NumBuckets); - if (ShouldRehash()) - RehashTable(); + RehashTable(); return true; } @@ -359,6 +348,7 @@ class StringMap : public StringMapImpl { } NumItems = 0; + NumTombstones = 0; } /// GetOrCreateValue - Look up the specified key in the table. If a value @@ -378,13 +368,13 @@ class StringMap : public StringMapImpl { if (Bucket.Item == getTombstoneVal()) --NumTombstones; ++NumItems; + assert(NumItems + NumTombstones <= NumBuckets); // Fill in the bucket for the hash table. The FullHashValue was already // filled in by LookupBucketFor. Bucket.Item = NewItem; - if (ShouldRehash()) - RehashTable(); + RehashTable(); return *NewItem; } diff --git a/contrib/llvm/include/llvm/ADT/Triple.h b/contrib/llvm/include/llvm/ADT/Triple.h index e6dcc23258f2..2659bce61750 100644 --- a/contrib/llvm/include/llvm/ADT/Triple.h +++ b/contrib/llvm/include/llvm/ADT/Triple.h @@ -64,7 +64,8 @@ class Triple { x86_64, // X86-64: amd64, x86_64 xcore, // XCore: xcore mblaze, // MBlaze: mblaze - ptx, // PTX: ptx + ptx32, // PTX: ptx (32-bit) + ptx64, // PTX: ptx (64-bit) InvalidArch }; @@ -72,7 +73,8 @@ class Triple { UnknownVendor, Apple, - PC + PC, + SCEI }; enum OSType { UnknownOS, @@ -82,8 +84,10 @@ class Triple { Darwin, DragonFly, FreeBSD, + IOS, Linux, Lv2, // PS3 + MacOSX, MinGW32, // i*86-pc-mingw32, *-w64-mingw32 NetBSD, OpenBSD, @@ -221,21 +225,81 @@ class Triple { /// if the environment component is present). StringRef getOSAndEnvironmentName() const; + /// getOSNumber - Parse the version number from the OS name component of the + /// triple, if present. + /// + /// For example, "fooos1.2.3" would return (1, 2, 3). + /// + /// If an entry is not defined, it will be returned as 0. + void getOSVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const; - /// getDarwinNumber - Parse the 'darwin number' out of the specific target - /// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is - /// not defined, return 0's. This requires that the triple have an OSType of - /// darwin before it is called. - void getDarwinNumber(unsigned &Maj, unsigned &Min, unsigned &Revision) const; - - /// getDarwinMajorNumber - Return just the major version number, this is + /// getOSMajorVersion - Return just the major version number, this is /// specialized because it is a common query. - unsigned getDarwinMajorNumber() const { - unsigned Maj, Min, Rev; - getDarwinNumber(Maj, Min, Rev); + unsigned getOSMajorVersion() const { + unsigned Maj, Min, Micro; + getDarwinNumber(Maj, Min, Micro); return Maj; } + void getDarwinNumber(unsigned &Major, unsigned &Minor, + unsigned &Micro) const { + return getOSVersion(Major, Minor, Micro); + } + + unsigned getDarwinMajorNumber() const { + return getOSMajorVersion(); + } + + /// isOSVersionLT - Helper function for doing comparisons against version + /// numbers included in the target triple. + bool isOSVersionLT(unsigned Major, unsigned Minor = 0, + unsigned Micro = 0) const { + unsigned LHS[3]; + getOSVersion(LHS[0], LHS[1], LHS[2]); + + if (LHS[0] != Major) + return LHS[0] < Major; + if (LHS[1] != Minor) + return LHS[1] < Minor; + if (LHS[2] != Micro) + return LHS[1] < Micro; + + return false; + } + + /// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both + /// "darwin" and "osx" as OS X triples. + bool isMacOSX() const { + return getOS() == Triple::Darwin || getOS() == Triple::MacOSX; + } + + /// isOSDarwin - Is this a "Darwin" OS (OS X or iOS). + bool isOSDarwin() const { + return isMacOSX() ||getOS() == Triple::IOS; + } + + /// isOSWindows - Is this a "Windows" OS. + bool isOSWindows() const { + return getOS() == Triple::Win32 || getOS() == Triple::Cygwin || + getOS() == Triple::MinGW32; + } + + /// isMacOSXVersionLT - Comparison function for checking OS X version + /// compatibility, which handles supporting skewed version numbering schemes + /// used by the "darwin" triples. + unsigned isMacOSXVersionLT(unsigned Major, unsigned Minor = 0, + unsigned Micro = 0) const { + assert(isMacOSX() && "Not an OS X triple!"); + + // If this is OS X, expect a sane version number. + if (getOS() == Triple::MacOSX) + return isOSVersionLT(Major, Minor, Micro); + + // Otherwise, compare to the "Darwin" number. + assert(Major == 10 && "Unexpected major version"); + return isOSVersionLT(Minor + 4, Micro, 0); + } + /// @} /// @name Mutators /// @{ diff --git a/contrib/llvm/include/llvm/ADT/ilist.h b/contrib/llvm/include/llvm/ADT/ilist.h index 865fcb3d8aad..bcacfd9df426 100644 --- a/contrib/llvm/include/llvm/ADT/ilist.h +++ b/contrib/llvm/include/llvm/ADT/ilist.h @@ -289,7 +289,7 @@ template struct simplify_type > { //===----------------------------------------------------------------------===// // /// iplist - The subset of list functionality that can safely be used on nodes -/// of polymorphic types, i.e. a heterogenous list with a common base class that +/// of polymorphic types, i.e. a heterogeneous list with a common base class that /// holds the next/prev pointers. The only state of the list itself is a single /// pointer to the head of the list. /// diff --git a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h index 71a5982c7d39..8f9708b3d889 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -38,7 +38,6 @@ #define LLVM_ANALYSIS_ALIAS_ANALYSIS_H #include "llvm/Support/CallSite.h" -#include namespace llvm { diff --git a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h index e844d10dda03..03149c662e83 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h +++ b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h @@ -259,6 +259,7 @@ class AliasSet : public ilist_node { if (CallSites[i] == CS.getInstruction()) { CallSites[i] = CallSites.back(); CallSites.pop_back(); + --i; --e; // Revisit the moved entry. } } void setVolatile() { Volatile = true; } @@ -283,6 +284,7 @@ class AliasSetTracker { class ASTCallbackVH : public CallbackVH { AliasSetTracker *AST; virtual void deleted(); + virtual void allUsesReplacedWith(Value *); public: ASTCallbackVH(Value *V, AliasSetTracker *AST = 0); ASTCallbackVH &operator=(Value *V); diff --git a/contrib/llvm/include/llvm/Analysis/CFGPrinter.h b/contrib/llvm/include/llvm/Analysis/CFGPrinter.h index ac8f59602dab..61614e34dacc 100644 --- a/contrib/llvm/include/llvm/Analysis/CFGPrinter.h +++ b/contrib/llvm/include/llvm/Analysis/CFGPrinter.h @@ -15,6 +15,7 @@ #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" diff --git a/contrib/llvm/include/llvm/Analysis/DIBuilder.h b/contrib/llvm/include/llvm/Analysis/DIBuilder.h index 417dbc4e802c..5846dbff041a 100644 --- a/contrib/llvm/include/llvm/Analysis/DIBuilder.h +++ b/contrib/llvm/include/llvm/Analysis/DIBuilder.h @@ -16,6 +16,7 @@ #define LLVM_ANALYSIS_DIBUILDER_H #include "llvm/Support/DataTypes.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" namespace llvm { @@ -146,6 +147,30 @@ namespace llvm { uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty); + /// createObjCIVar - Create debugging information entry for Objective-C + /// instance variable. + /// @param Name Member name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param OffsetInBits Member offset. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Ty Parent type. + /// @param PropertyName Name of the Objective C property assoicated with + /// this ivar. + /// @param GetterName Name of the Objective C property getter selector. + /// @param SetterName Name of the Objective C property setter selector. + /// @param PropertyAttributes Objective C property attributes. + DIType createObjCIVar(StringRef Name, DIFile File, + unsigned LineNo, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType Ty, + StringRef PropertyName = StringRef(), + StringRef PropertyGetterName = StringRef(), + StringRef PropertySetterName = StringRef(), + unsigned PropertyAttributes = 0); + /// createClassType - Create debugging information entry for a class. /// @param Scope Scope in which this class is defined. /// @param Name class name. @@ -278,7 +303,7 @@ namespace llvm { DIDescriptor createUnspecifiedParameter(); /// getOrCreateArray - Get a DIArray, create one if required. - DIArray getOrCreateArray(Value *const *Elements, unsigned NumElements); + DIArray getOrCreateArray(ArrayRef Elements); /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. @@ -326,11 +351,14 @@ namespace llvm { /// @param AlwaysPreserve Boolean. Set to true if debug info for this /// variable should be preserved in optimized build. /// @param Flags Flags, e.g. artificial variable. + /// @param ArgNo If this variable is an arugment then this argument's + /// number. 1 indicates 1st argument. DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, DIType Ty, bool AlwaysPreserve = false, - unsigned Flags = 0); + unsigned Flags = 0, + unsigned ArgNo = 0); /// createComplexVariable - Create a new descriptor for the specified @@ -342,12 +370,13 @@ namespace llvm { /// @param File File where this variable is defined. /// @param LineNo Line number. /// @param Ty Variable Type - /// @param Addr A pointer to a vector of complex address operations. - /// @param NumAddr Num of address operations in the vector. + /// @param Addr An array of complex address operations. + /// @param ArgNo If this variable is an arugment then this argument's + /// number. 1 indicates 1st argument. DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile F, unsigned LineNo, - DIType Ty, Value *const *Addr, - unsigned NumAddr); + DIType Ty, ArrayRef Addr, + unsigned ArgNo = 0); /// createFunction - Create a new descriptor for the specified subprogram. /// See comments in DISubprogram for descriptions of these fields. @@ -363,6 +392,7 @@ namespace llvm { /// This flags are used to emit dwarf attributes. /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. + /// @param TParam Function template parameters. DISubprogram createFunction(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, @@ -370,7 +400,9 @@ namespace llvm { bool isDefinition, unsigned Flags = 0, bool isOptimized = false, - Function *Fn = 0); + Function *Fn = 0, + MDNode *TParam = 0, + MDNode *Decl = 0); /// createMethod - Create a new descriptor for the specified C++ method. /// See comments in DISubprogram for descriptions of these fields. @@ -382,7 +414,7 @@ namespace llvm { /// @param Ty Function type. /// @param isLocalToUnit True if this function is not externally visible.. /// @param isDefinition True if this is a function definition. - /// @param Virtuality Attributes describing virutallness. e.g. pure + /// @param Virtuality Attributes describing virtualness. e.g. pure /// virtual function. /// @param VTableIndex Index no of this method in virtual table. /// @param VTableHolder Type that holds vtable. @@ -390,6 +422,7 @@ namespace llvm { /// This flags are used to emit dwarf attributes. /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. + /// @param TParam Function template parameters. DISubprogram createMethod(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, @@ -399,7 +432,8 @@ namespace llvm { MDNode *VTableHolder = 0, unsigned Flags = 0, bool isOptimized = false, - Function *Fn = 0); + Function *Fn = 0, + MDNode *TParam = 0); /// createNameSpace - This creates new descriptor for a namespace /// with the specified parent scope. diff --git a/contrib/llvm/include/llvm/Analysis/DebugInfo.h b/contrib/llvm/include/llvm/Analysis/DebugInfo.h index aa69088b425b..c6cc8f7665ed 100644 --- a/contrib/llvm/include/llvm/Analysis/DebugInfo.h +++ b/contrib/llvm/include/llvm/Analysis/DebugInfo.h @@ -332,6 +332,32 @@ namespace llvm { /// return base type size. uint64_t getOriginalTypeSize() const; + StringRef getObjCPropertyName() const { return getStringField(10); } + StringRef getObjCPropertyGetterName() const { + return getStringField(11); + } + StringRef getObjCPropertySetterName() const { + return getStringField(12); + } + bool isReadOnlyObjCProperty() { + return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; + } + bool isReadWriteObjCProperty() { + return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; + } + bool isAssignObjCProperty() { + return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_assign) != 0; + } + bool isRetainObjCProperty() { + return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_retain) != 0; + } + bool isCopyObjCProperty() { + return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_copy) != 0; + } + bool isNonAtomicObjCProperty() { + return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; + } + /// Verify - Verify that a derived type descriptor is well formed. bool Verify() const; @@ -511,6 +537,10 @@ namespace llvm { bool describes(const Function *F); Function *getFunction() const { return getFunctionField(16); } + DIArray getTemplateParams() const { return getFieldAs(17); } + DISubprogram getFunctionDeclaration() const { + return getFieldAs(18); + } }; /// DIGlobalVariable - This is a wrapper for a global variable. @@ -564,7 +594,13 @@ namespace llvm { DIFile F = getFieldAs(3); return F.getCompileUnit(); } - unsigned getLineNumber() const { return getUnsignedField(4); } + unsigned getLineNumber() const { + return (getUnsignedField(4) << 8) >> 8; + } + unsigned getArgNumber() const { + unsigned L = getUnsignedField(4); + return L >> 24; + } DIType getType() const { return getFieldAs(5); } /// isArtificial - Return true if this variable is marked as "artificial". @@ -586,7 +622,9 @@ namespace llvm { unsigned getNumAddrElements() const; uint64_t getAddrElement(unsigned Idx) const { - return getUInt64Field(Idx+6); + if (getVersion() <= llvm::LLVMDebugVersion8) + return getUInt64Field(Idx+6); + return getUInt64Field(Idx+7); } /// isBlockByrefVariable - Return true if the variable was declared as @@ -660,214 +698,6 @@ namespace llvm { bool Verify() const; }; - /// DIFactory - This object assists with the construction of the various - /// descriptors. - class DIFactory { - Module &M; - LLVMContext& VMContext; - - Function *DeclareFn; // llvm.dbg.declare - Function *ValueFn; // llvm.dbg.value - - DIFactory(const DIFactory &); // DO NOT IMPLEMENT - void operator=(const DIFactory&); // DO NOT IMPLEMENT - public: - enum ComplexAddrKind { OpPlus=1, OpDeref }; - - explicit DIFactory(Module &m); - - /// GetOrCreateArray - Create an descriptor for an array of descriptors. - /// This implicitly uniques the arrays created. - DIArray GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys); - - /// GetOrCreateSubrange - Create a descriptor for a value range. This - /// implicitly uniques the values returned. - DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi); - - /// CreateUnspecifiedParameter - Create unspeicified type descriptor - /// for a subroutine type. - DIDescriptor CreateUnspecifiedParameter(); - - /// CreateCompileUnit - Create a new descriptor for the specified compile - /// unit. - DICompileUnit CreateCompileUnit(unsigned LangID, - StringRef Filename, - StringRef Directory, - StringRef Producer, - bool isMain = false, - bool isOptimized = false, - StringRef Flags = "", - unsigned RunTimeVer = 0); - - /// CreateFile - Create a new descriptor for the specified file. - DIFile CreateFile(StringRef Filename, StringRef Directory, - DICompileUnit CU); - - /// CreateEnumerator - Create a single enumerator value. - DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val); - - /// CreateBasicType - Create a basic type like int, float, etc. - DIBasicType CreateBasicType(DIDescriptor Context, StringRef Name, - DIFile F, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - unsigned Encoding); - - /// CreateBasicType - Create a basic type like int, float, etc. - DIBasicType CreateBasicTypeEx(DIDescriptor Context, StringRef Name, - DIFile F, unsigned LineNumber, - Constant *SizeInBits, Constant *AlignInBits, - Constant *OffsetInBits, unsigned Flags, - unsigned Encoding); - - /// CreateDerivedType - Create a derived type like const qualified type, - /// pointer, typedef, etc. - DIDerivedType CreateDerivedType(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType DerivedFrom); - - /// CreateDerivedType - Create a derived type like const qualified type, - /// pointer, typedef, etc. - DIDerivedType CreateDerivedTypeEx(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, unsigned Flags, - DIType DerivedFrom); - - /// CreateCompositeType - Create a composite type like array, struct, etc. - DICompositeType CreateCompositeType(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RunTimeLang = 0, - MDNode *ContainingType = 0); - - /// CreateTemporaryType - Create a temporary forward-declared type. - DIType CreateTemporaryType(); - DIType CreateTemporaryType(DIFile F); - - /// CreateArtificialType - Create a new DIType with "artificial" flag set. - DIType CreateArtificialType(DIType Ty); - - /// CreateCompositeType - Create a composite type like array, struct, etc. - DICompositeType CreateCompositeTypeEx(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, - unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RunTimeLang = 0, - MDNode *ContainingType = 0); - - /// CreateSubprogram - Create a new descriptor for the specified subprogram. - /// See comments in DISubprogram for descriptions of these fields. - DISubprogram CreateSubprogram(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, unsigned LineNo, - DIType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned VK = 0, - unsigned VIndex = 0, - DIType ContainingType = DIType(), - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = 0); - - /// CreateSubprogramDefinition - Create new subprogram descriptor for the - /// given declaration. - DISubprogram CreateSubprogramDefinition(DISubprogram &SPDeclaration); - - /// CreateGlobalVariable - Create a new descriptor for the specified global. - DIGlobalVariable - CreateGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty, bool isLocalToUnit, - bool isDefinition, llvm::GlobalVariable *GV); - - /// CreateGlobalVariable - Create a new descriptor for the specified constant. - DIGlobalVariable - CreateGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty, bool isLocalToUnit, - bool isDefinition, llvm::Constant *C); - - /// CreateVariable - Create a new descriptor for the specified variable. - DIVariable CreateVariable(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, unsigned LineNo, - DIType Ty, bool AlwaysPreserve = false, - unsigned Flags = 0); - - /// CreateComplexVariable - Create a new descriptor for the specified - /// variable which has a complex address expression for its address. - DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Context, - StringRef Name, DIFile F, unsigned LineNo, - DIType Ty, Value *const *Addr, - unsigned NumAddr); - - /// CreateLexicalBlock - This creates a descriptor for a lexical block - /// with the specified parent context. - DILexicalBlock CreateLexicalBlock(DIDescriptor Context, DIFile F, - unsigned Line = 0, unsigned Col = 0); - - /// CreateNameSpace - This creates new descriptor for a namespace - /// with the specified parent context. - DINameSpace CreateNameSpace(DIDescriptor Context, StringRef Name, - DIFile F, unsigned LineNo); - - /// CreateLocation - Creates a debug info location. - DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, - DIScope S, DILocation OrigLoc); - - /// CreateLocation - Creates a debug info location. - DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, - DIScope S, MDNode *OrigLoc = 0); - - /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. - Instruction *InsertDeclare(llvm::Value *Storage, DIVariable D, - BasicBlock *InsertAtEnd); - - /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. - Instruction *InsertDeclare(llvm::Value *Storage, DIVariable D, - Instruction *InsertBefore); - - /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. - Instruction *InsertDbgValueIntrinsic(llvm::Value *V, uint64_t Offset, - DIVariable D, BasicBlock *InsertAtEnd); - - /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. - Instruction *InsertDbgValueIntrinsic(llvm::Value *V, uint64_t Offset, - DIVariable D, Instruction *InsertBefore); - - // RecordType - Record DIType in a module such that it is not lost even if - // it is not referenced through debug info anchors. - void RecordType(DIType T); - - private: - Constant *GetTagConstant(unsigned TAG); - }; - /// getDISubprogram - Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); diff --git a/contrib/llvm/include/llvm/Analysis/IVUsers.h b/contrib/llvm/include/llvm/Analysis/IVUsers.h index 578e6aba8338..e56d24d583df 100644 --- a/contrib/llvm/include/llvm/Analysis/IVUsers.h +++ b/contrib/llvm/include/llvm/Analysis/IVUsers.h @@ -28,6 +28,7 @@ class IVUsers; class ScalarEvolution; class SCEV; class IVUsers; +class TargetData; /// IVStrideUse - Keep track of one use of a strided induction variable. /// The Expr member keeps track of the expression, User is the actual user @@ -122,6 +123,7 @@ class IVUsers : public LoopPass { LoopInfo *LI; DominatorTree *DT; ScalarEvolution *SE; + TargetData *TD; SmallPtrSet Processed; /// IVUses - A list of all tracked IV uses of induction variable expressions diff --git a/contrib/llvm/include/llvm/Analysis/InlineCost.h b/contrib/llvm/include/llvm/Analysis/InlineCost.h index b08bf57ace96..a0cce515e9e2 100644 --- a/contrib/llvm/include/llvm/Analysis/InlineCost.h +++ b/contrib/llvm/include/llvm/Analysis/InlineCost.h @@ -43,7 +43,7 @@ namespace llvm { /// InlineCost - Represent the cost of inlining a function. This /// supports special values for functions which should "always" or /// "never" be inlined. Otherwise, the cost represents a unitless - /// amount; smaller values increase the likelyhood of the function + /// amount; smaller values increase the likelihood of the function /// being inlined. class InlineCost { enum Kind { diff --git a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h index dff1ba2f7beb..bc6e55f5490a 100644 --- a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -55,6 +55,21 @@ namespace llvm { Value *SimplifyFDivInst(Value *LHS, Value *RHS, const TargetData *TD = 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, + 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, + 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, + 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, diff --git a/contrib/llvm/include/llvm/Analysis/Lint.h b/contrib/llvm/include/llvm/Analysis/Lint.h index eb65d2236441..7c88b137ec3b 100644 --- a/contrib/llvm/include/llvm/Analysis/Lint.h +++ b/contrib/llvm/include/llvm/Analysis/Lint.h @@ -20,8 +20,6 @@ #ifndef LLVM_ANALYSIS_LINT_H #define LLVM_ANALYSIS_LINT_H -#include - namespace llvm { class FunctionPass; diff --git a/contrib/llvm/include/llvm/Analysis/LiveValues.h b/contrib/llvm/include/llvm/Analysis/LiveValues.h deleted file mode 100644 index b92cb7833a7e..000000000000 --- a/contrib/llvm/include/llvm/Analysis/LiveValues.h +++ /dev/null @@ -1,99 +0,0 @@ -//===- LiveValues.h - Liveness information for LLVM IR Values. ------------===// -// -// 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 interface for the LLVM IR Value liveness -// analysis pass. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_LIVEVALUES_H -#define LLVM_ANALYSIS_LIVEVALUES_H - -#include "llvm/Pass.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" - -namespace llvm { - -class DominatorTree; -class LoopInfo; -class Value; - -/// LiveValues - Analysis that provides liveness information for -/// LLVM IR Values. -/// -class LiveValues : public FunctionPass { - DominatorTree *DT; - LoopInfo *LI; - - /// Memo - A bunch of state to be associated with a value. - /// - struct Memo { - /// Used - The set of blocks which contain a use of the value. - /// - SmallPtrSet Used; - - /// LiveThrough - A conservative approximation of the set of blocks in - /// which the value is live-through, meaning blocks properly dominated - /// by the definition, and from which blocks containing uses of the - /// value are reachable. - /// - SmallPtrSet LiveThrough; - - /// Killed - A conservative approximation of the set of blocks in which - /// the value is used and not live-out. - /// - SmallPtrSet Killed; - }; - - /// Memos - Remembers the Memo for each Value. This is populated on - /// demand. - /// - DenseMap Memos; - - /// getMemo - Retrieve an existing Memo for the given value if one - /// is available, otherwise compute a new one. - /// - Memo &getMemo(const Value *V); - - /// compute - Compute a new Memo for the given value. - /// - Memo &compute(const Value *V); - -public: - static char ID; - LiveValues(); - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual bool runOnFunction(Function &F); - virtual void releaseMemory(); - - /// isUsedInBlock - Test if the given value is used in the given block. - /// - bool isUsedInBlock(const Value *V, const BasicBlock *BB); - - /// isLiveThroughBlock - Test if the given value is known to be - /// live-through the given block, meaning that the block is properly - /// dominated by the value's definition, and there exists a block - /// reachable from it that contains a use. This uses a conservative - /// approximation that errs on the side of returning false. - /// - bool isLiveThroughBlock(const Value *V, const BasicBlock *BB); - - /// isKilledInBlock - Test if the given value is known to be killed in - /// the given block, meaning that the block contains a use of the value, - /// and no blocks reachable from the block contain a use. This uses a - /// conservative approximation that errs on the side of returning false. - /// - bool isKilledInBlock(const Value *V, const BasicBlock *BB); -}; - -} // end namespace llvm - -#endif diff --git a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h index 4d5dd1987f28..b56fe08e23d8 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -48,6 +48,11 @@ namespace llvm { /// this occurs when we see a may-aliased store to the memory location we /// care about. /// + /// There are several cases that may be interesting here: + /// 1. Loads are clobbered by may-alias stores. + /// 2. Loads are considered clobbered by partially-aliased loads. The + /// client may choose to analyze deeper into these cases. + /// /// A dependence query on the first instruction of the entry block will /// return a clobber(self) result. Clobber, @@ -350,6 +355,20 @@ namespace llvm { BasicBlock::iterator ScanIt, BasicBlock *BB); + + /// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that + /// looks at a memory location for a load (specified by MemLocBase, Offs, + /// and Size) and compares it against a load. If the specified load could + /// be safely widened to a larger integer load that is 1) still efficient, + /// 2) safe for the target, and 3) would provide the specified memory + /// location value, then this function returns the size in bytes of the + /// load width to use. If not, this returns zero. + static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase, + int64_t MemLocOffs, + unsigned MemLocSize, + const LoadInst *LI, + const TargetData &TD); + private: MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, BasicBlock::iterator ScanIt, diff --git a/contrib/llvm/include/llvm/Analysis/Passes.h b/contrib/llvm/include/llvm/Analysis/Passes.h index 5b0c5b1e6bec..0eff75fe2f8c 100644 --- a/contrib/llvm/include/llvm/Analysis/Passes.h +++ b/contrib/llvm/include/llvm/Analysis/Passes.h @@ -157,12 +157,6 @@ namespace llvm { // ModulePass *createSteensgaardPass(); - //===--------------------------------------------------------------------===// - // - // createLiveValuesPass - This creates an instance of the LiveValues pass. - // - FunctionPass *createLiveValuesPass(); - //===--------------------------------------------------------------------===// // /// createLazyValueInfoPass - This creates an instance of the LazyValueInfo diff --git a/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h b/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h index 263763f7a8db..cef6d2d2a6c8 100644 --- a/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h +++ b/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h @@ -16,7 +16,6 @@ #include "llvm/BasicBlock.h" #include "llvm/Analysis/PathNumbering.h" -#include namespace llvm { diff --git a/contrib/llvm/include/llvm/Analysis/PostDominators.h b/contrib/llvm/include/llvm/Analysis/PostDominators.h index 2cd6ae346eeb..0eddb9105e60 100644 --- a/contrib/llvm/include/llvm/Analysis/PostDominators.h +++ b/contrib/llvm/include/llvm/Analysis/PostDominators.h @@ -14,7 +14,7 @@ #ifndef LLVM_ANALYSIS_POST_DOMINATORS_H #define LLVM_ANALYSIS_POST_DOMINATORS_H -#include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/Analysis/Dominators.h" namespace llvm { @@ -101,37 +101,6 @@ template <> struct GraphTraits } }; -/// PostDominanceFrontier Class - Concrete subclass of DominanceFrontier that is -/// used to compute the a post-dominance frontier. -/// -struct PostDominanceFrontier : public DominanceFrontierBase { - static char ID; - PostDominanceFrontier() - : DominanceFrontierBase(ID, true) { - initializePostDominanceFrontierPass(*PassRegistry::getPassRegistry()); - } - - virtual bool runOnFunction(Function &) { - Frontiers.clear(); - PostDominatorTree &DT = getAnalysis(); - Roots = DT.getRoots(); - if (const DomTreeNode *Root = DT.getRootNode()) - calculate(DT, Root); - return false; - } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired(); - } - -private: - const DomSetType &calculate(const PostDominatorTree &DT, - const DomTreeNode *Node); -}; - -FunctionPass* createPostDomFrontier(); - } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Analysis/RegionInfo.h b/contrib/llvm/include/llvm/Analysis/RegionInfo.h index a36ca110d8c0..9d8954595d61 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionInfo.h +++ b/contrib/llvm/include/llvm/Analysis/RegionInfo.h @@ -28,9 +28,10 @@ #define LLVM_ANALYSIS_REGION_INFO_H #include "llvm/ADT/PointerIntPair.h" -#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Support/Allocator.h" +#include namespace llvm { @@ -145,7 +146,7 @@ inline Region* RegionNode::getNodeAs() const { /// two connections to the remaining graph. It can be used to analyze or /// optimize parts of the control flow graph. /// -/// A simple Region is connected to the remaing graph by just two +/// A simple Region is connected to the remaining graph by just two /// edges. One edge entering the Region and another one leaving the Region. /// /// An extended Region (or just Region) is a subgraph that can be @@ -335,12 +336,16 @@ class Region : public RegionNode { return RI; } + /// PrintStyle - Print region in difference ways. + enum PrintStyle { PrintNone, PrintBB, PrintRN }; + /// @brief Print the region. /// /// @param OS The output stream the Region is printed to. /// @param printTree Print also the tree of subregions. /// @param level The indentation level used for printing. - void print(raw_ostream& OS, bool printTree = true, unsigned level = 0) const; + void print(raw_ostream& OS, bool printTree = true, unsigned level = 0, + enum PrintStyle Style = PrintNone) const; /// @brief Print the region to stderr. void dump() const; @@ -438,7 +443,7 @@ class Region : public RegionNode { /// @brief Move all direct child nodes of this Region to another Region. /// - /// @param To The Region the child nodes will be transfered to. + /// @param To The Region the child nodes will be transferred to. void transferChildrenTo(Region *To); /// @brief Verify if the region is a correct region. diff --git a/contrib/llvm/include/llvm/Analysis/RegionIterator.h b/contrib/llvm/include/llvm/Analysis/RegionIterator.h index ced5b528cbb1..7adc71ca82ac 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionIterator.h +++ b/contrib/llvm/include/llvm/Analysis/RegionIterator.h @@ -20,7 +20,7 @@ namespace llvm { //===----------------------------------------------------------------------===// -/// @brief Hierachical RegionNode successor iterator. +/// @brief Hierarchical RegionNode successor iterator. /// /// This iterator iterates over all successors of a RegionNode. /// diff --git a/contrib/llvm/include/llvm/Analysis/RegionPass.h b/contrib/llvm/include/llvm/Analysis/RegionPass.h index aedc06aa6cf3..5403e09c480c 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionPass.h +++ b/contrib/llvm/include/llvm/Analysis/RegionPass.h @@ -54,7 +54,7 @@ class RegionPass : public Pass { /// @brief Get a pass to print the LLVM IR in the region. /// /// @param O The ouput stream to print the Region. - /// @param Banner The banner to seperate different printed passes. + /// @param Banner The banner to separate different printed passes. /// /// @return The pass to print the LLVM IR in the region. Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h index d1938061bef6..a62f6a80d1a7 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -24,6 +24,7 @@ #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" @@ -72,6 +73,29 @@ namespace llvm { void operator=(const SCEV &); // DO NOT IMPLEMENT public: + /// NoWrapFlags are bitfield indices into SubclassData. + /// + /// Add and Mul expressions may have no-unsigned-wrap or + /// no-signed-wrap properties, which are derived from the IR + /// operator. NSW is a misnomer that we use to mean no signed overflow or + /// underflow. + /// + /// AddRec expression may have a no-self-wraparound property if the + /// result can never reach the start value. This property is independent of + /// the actual start value and step direction. Self-wraparound is defined + /// purely in terms of the recurrence's loop, step size, and + /// bitwidth. Formally, a recurrence with no self-wraparound satisfies: + /// abs(step) * max-iteration(loop) <= unsigned-max(bitwidth). + /// + /// Note that NUW and NSW are also valid properties of a recurrence, and + /// either implies NW. For convenience, NW will be set for a recurrence + /// whenever either NUW or NSW are set. + enum NoWrapFlags { FlagAnyWrap = 0, // No guarantee. + FlagNW = (1 << 0), // No self-wrap. + FlagNUW = (1 << 1), // No unsigned wrap. + FlagNSW = (1 << 2), // No signed wrap. + NoWrapMask = (1 << 3) -1 }; + explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) : FastID(ID), SCEVType(SCEVTy), SubclassData(0) {} @@ -159,6 +183,20 @@ namespace llvm { ProperlyDominatesBlock ///< The SCEV properly dominates the block. }; + /// Convenient NoWrapFlags manipulation that hides enum casts and is + /// visible in the ScalarEvolution name space. + static SCEV::NoWrapFlags maskFlags(SCEV::NoWrapFlags Flags, int Mask) { + return (SCEV::NoWrapFlags)(Flags & Mask); + } + static SCEV::NoWrapFlags setFlags(SCEV::NoWrapFlags Flags, + SCEV::NoWrapFlags OnFlags) { + return (SCEV::NoWrapFlags)(Flags | OnFlags); + } + static SCEV::NoWrapFlags clearFlags(SCEV::NoWrapFlags Flags, + SCEV::NoWrapFlags OffFlags) { + return (SCEV::NoWrapFlags)(Flags & ~OffFlags); + } + private: /// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be /// notified whenever a Value is deleted. @@ -465,44 +503,41 @@ namespace llvm { const SCEV *getSignExtendExpr(const SCEV *Op, const Type *Ty); const SCEV *getAnyExtendExpr(const SCEV *Op, const Type *Ty); const SCEV *getAddExpr(SmallVectorImpl &Ops, - bool HasNUW = false, bool HasNSW = false); + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap); const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS, - bool HasNUW = false, bool HasNSW = false) { + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) { SmallVector Ops; Ops.push_back(LHS); Ops.push_back(RHS); - return getAddExpr(Ops, HasNUW, HasNSW); + return getAddExpr(Ops, Flags); } - const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, - const SCEV *Op2, - bool HasNUW = false, bool HasNSW = false) { + const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) { SmallVector Ops; Ops.push_back(Op0); Ops.push_back(Op1); Ops.push_back(Op2); - return getAddExpr(Ops, HasNUW, HasNSW); + return getAddExpr(Ops, Flags); } const SCEV *getMulExpr(SmallVectorImpl &Ops, - bool HasNUW = false, bool HasNSW = false); + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap); const SCEV *getMulExpr(const SCEV *LHS, const SCEV *RHS, - bool HasNUW = false, bool HasNSW = false) { + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) + { SmallVector Ops; Ops.push_back(LHS); Ops.push_back(RHS); - return getMulExpr(Ops, HasNUW, HasNSW); + return getMulExpr(Ops, Flags); } const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step, - const Loop *L, - bool HasNUW = false, bool HasNSW = false); + const Loop *L, SCEV::NoWrapFlags Flags); const SCEV *getAddRecExpr(SmallVectorImpl &Operands, - const Loop *L, - bool HasNUW = false, bool HasNSW = false); + const Loop *L, SCEV::NoWrapFlags Flags); const SCEV *getAddRecExpr(const SmallVectorImpl &Operands, - const Loop *L, - bool HasNUW = false, bool HasNSW = false) { + const Loop *L, SCEV::NoWrapFlags Flags) { SmallVector NewOp(Operands.begin(), Operands.end()); - return getAddRecExpr(NewOp, L, HasNUW, HasNSW); + return getAddRecExpr(NewOp, L, Flags); } const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getSMaxExpr(SmallVectorImpl &Operands); @@ -537,11 +572,9 @@ namespace llvm { /// const SCEV *getNotSCEV(const SCEV *V); - /// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1, - /// and thus the HasNUW and HasNSW bits apply to the resultant add, not - /// whether the sub would have overflowed. + /// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1. const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS, - bool HasNUW = false, bool HasNSW = false); + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap); /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion /// of the input value to the specified type. If the type must be @@ -586,6 +619,12 @@ namespace llvm { const SCEV *getUMinFromMismatchedTypes(const SCEV *LHS, const SCEV *RHS); + /// getPointerBase - Transitively follow the chain of pointer-type operands + /// until reaching a SCEV that does not have a single pointer operand. This + /// returns a SCEVUnknown pointer for well-formed pointer-type expressions, + /// but corner cases do exist. + const SCEV *getPointerBase(const SCEV *V); + /// getSCEVAtScope - Return a SCEV expression for the specified value /// at the specified scope in the program. The L value specifies a loop /// nest to evaluate the expression at, where null is the top-level or a diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h index db432c8173dd..856d92c97c08 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -160,13 +160,8 @@ namespace llvm { const Type *getType() const { return getOperand(0)->getType(); } - bool hasNoUnsignedWrap() const { return SubclassData & (1 << 0); } - void setHasNoUnsignedWrap(bool B) { - SubclassData = (SubclassData & ~(1 << 0)) | (B << 0); - } - bool hasNoSignedWrap() const { return SubclassData & (1 << 1); } - void setHasNoSignedWrap(bool B) { - SubclassData = (SubclassData & ~(1 << 1)) | (B << 1); + NoWrapFlags getNoWrapFlags(NoWrapFlags Mask = NoWrapMask) const { + return (NoWrapFlags)(SubclassData & Mask); } /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -199,6 +194,11 @@ namespace llvm { S->getSCEVType() == scSMaxExpr || S->getSCEVType() == scUMaxExpr; } + + /// Set flags for a non-recurrence without clearing previously set flags. + void setNoWrapFlags(NoWrapFlags Flags) { + SubclassData |= Flags; + } }; @@ -305,11 +305,12 @@ namespace llvm { /// getStepRecurrence - This method constructs and returns the recurrence /// indicating how much this expression steps by. If this is a polynomial /// of degree N, it returns a chrec of degree N-1. + /// We cannot determine whether the step recurrence has self-wraparound. const SCEV *getStepRecurrence(ScalarEvolution &SE) const { if (isAffine()) return getOperand(1); return SE.getAddRecExpr(SmallVector(op_begin()+1, op_end()), - getLoop()); + getLoop(), FlagAnyWrap); } /// isAffine - Return true if this is an affine AddRec (i.e., it represents @@ -327,6 +328,15 @@ namespace llvm { return getNumOperands() == 3; } + /// Set flags for a recurrence without clearing any previously set flags. + /// For AddRec, either NUW or NSW implies NW. Keep track of this fact here + /// to make it easier to propagate flags. + void setNoWrapFlags(NoWrapFlags Flags) { + if (Flags & (FlagNUW | FlagNSW)) + Flags = ScalarEvolution::setFlags(Flags, FlagNW); + SubclassData |= Flags; + } + /// evaluateAtIteration - Return the value of this chain of recurrences at /// the specified iteration number. const SCEV *evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const; @@ -364,8 +374,7 @@ namespace llvm { const SCEV *const *O, size_t N) : SCEVCommutativeExpr(ID, scSMaxExpr, O, N) { // Max never overflows. - setHasNoUnsignedWrap(true); - setHasNoSignedWrap(true); + setNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW)); } public: @@ -387,8 +396,7 @@ namespace llvm { const SCEV *const *O, size_t N) : SCEVCommutativeExpr(ID, scUMaxExpr, O, N) { // Max never overflows. - setHasNoUnsignedWrap(true); - setHasNoSignedWrap(true); + setNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW)); } public: diff --git a/contrib/llvm/include/llvm/Bitcode/Archive.h b/contrib/llvm/include/llvm/Bitcode/Archive.h index c3c07d8588a3..f89a86cb0f77 100644 --- a/contrib/llvm/include/llvm/Bitcode/Archive.h +++ b/contrib/llvm/include/llvm/Bitcode/Archive.h @@ -25,7 +25,6 @@ namespace llvm { class MemoryBuffer; - class raw_ostream; // Forward declare classes class Module; // From VMCore @@ -436,7 +435,7 @@ class Archive { /// to determine just enough information to create an ArchiveMember object /// which is then inserted into the Archive object's ilist at the location /// given by \p where. - /// @returns true if an error occured, false otherwise + /// @returns true if an error occurred, false otherwise /// @brief Add a file to the archive. bool addFileBefore( const sys::Path& filename, ///< The file to be added @@ -483,7 +482,7 @@ class Archive { bool loadSymbolTable(std::string* ErrMessage); /// @brief Write the symbol table to an ofstream. - void writeSymbolTable(raw_ostream& ARFile); + void writeSymbolTable(std::ofstream& ARFile); /// Writes one ArchiveMember to an ofstream. If an error occurs, returns /// false, otherwise true. If an error occurs and error is non-null then @@ -492,7 +491,7 @@ class Archive { /// @returns true Writing member failed, \p error set to error message bool writeMember( const ArchiveMember& member, ///< The member to be written - raw_ostream& ARFile, ///< The file to write member onto + std::ofstream& ARFile, ///< The file to write member onto bool CreateSymbolTable, ///< Should symbol table be created? bool TruncateNames, ///< Should names be truncated to 11 chars? bool ShouldCompress, ///< Should the member be compressed? diff --git a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h index a071febb102f..58395ba9b4db 100644 --- a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -183,6 +183,10 @@ namespace llvm { /// function. void EmitFunctionBody(); + void emitPrologLabel(const MachineInstr &MI); + + bool needsCFIMoves(); + /// EmitConstantPool - Print to the current output stream assembly /// representations of the constants in the constant pool MCP. This is /// used to print out constants which have been "spilled to memory" by @@ -377,10 +381,17 @@ namespace llvm { /// operands. virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const; + /// getDwarfRegOpSize - get size required to emit given machine location + /// using dwarf encoding. + virtual unsigned getDwarfRegOpSize(const MachineLocation &MLoc) const; + /// getISAEncoding - Get the value for DW_AT_APPLE_isa. Zero if no isa /// encoding specified. virtual unsigned getISAEncoding() { return 0; } + /// EmitDwarfRegOp - Emit dwarf register operation. + virtual void EmitDwarfRegOp(const MachineLocation &MLoc) const; + //===------------------------------------------------------------------===// // Dwarf Lowering Routines //===------------------------------------------------------------------===// @@ -389,6 +400,7 @@ namespace llvm { /// frame. void EmitFrameMoves(const std::vector &Moves, MCSymbol *BaseLabel, bool isEH) const; + void EmitCFIFrameMove(const MachineMove &Move) const; void EmitCFIFrameMoves(const std::vector &Moves) const; //===------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h index 853ebf99a87b..60edcc584559 100644 --- a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h +++ b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h @@ -11,7 +11,7 @@ #ifndef LLVM_CODEGEN_CALCSPILLWEIGHTS_H #define LLVM_CODEGEN_CALCSPILLWEIGHTS_H -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/SlotIndexes.h" #include "llvm/ADT/DenseMap.h" namespace llvm { @@ -29,28 +29,25 @@ namespace llvm { /// @param Size Size of live interval as returnexd by getSize() /// static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size) { - // The magic constant 200 corresponds to approx. 25 instructions since - // SlotIndexes allocate 8 slots per instruction. - // - // The constant is added to avoid depending too much on accidental SlotIndex - // gaps for small intervals. The effect is that small intervals have a spill - // weight that is mostly proportional to the number of uses, while large - // intervals get a spill weight that is closer to a use density. - // - return UseDefFreq / (Size + 200); + // The constant 25 instructions is added to avoid depending too much on + // accidental SlotIndex gaps for small intervals. The effect is that small + // intervals have a spill weight that is mostly proportional to the number + // of uses, while large intervals get a spill weight that is closer to a use + // density. + return UseDefFreq / (Size + 25*SlotIndex::InstrDist); } /// VirtRegAuxInfo - Calculate auxiliary information for a virtual /// register such as its spill weight and allocation hint. class VirtRegAuxInfo { - MachineFunction &mf_; - LiveIntervals &lis_; - const MachineLoopInfo &loops_; - DenseMap hint_; + MachineFunction &MF; + LiveIntervals &LIS; + const MachineLoopInfo &Loops; + DenseMap Hint; public: VirtRegAuxInfo(MachineFunction &mf, LiveIntervals &lis, const MachineLoopInfo &loops) : - mf_(mf), lis_(lis), loops_(loops) {} + MF(mf), LIS(lis), Loops(loops) {} /// CalculateRegClass - recompute the register class for reg from its uses. /// Since the register class can affect the allocation hint, this function diff --git a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h index 2a9bbdfb7ceb..9018ea36e7b5 100644 --- a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h +++ b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h @@ -141,6 +141,8 @@ typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, ISD::ArgFlagsTy &ArgFlags, CCState &State); +typedef enum { Invalid, Prologue, Call } ParmContext; + /// CCState - This class holds information needed while lowering arguments and /// return values. It captures which registers are already assigned and which /// stack slots are used. It provides accessors to allocate these values. @@ -154,6 +156,9 @@ class CCState { unsigned StackOffset; SmallVector UsedRegs; + unsigned FirstByValReg; + bool FirstByValRegValid; + ParmContext CallOrPrologue; public: CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &TM, SmallVector &locs, LLVMContext &C); @@ -288,6 +293,16 @@ class CCState { MVT LocVT, CCValAssign::LocInfo LocInfo, int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags); + // First GPR that carries part of a byval aggregate that's split + // between registers and memory. + unsigned getFirstByValReg() { return FirstByValRegValid ? FirstByValReg : 0; } + void setFirstByValReg(unsigned r) { FirstByValReg = r; FirstByValRegValid = true; } + void clearFirstByValReg() { FirstByValReg = 0; FirstByValRegValid = false; } + bool isFirstByValRegValid() { return FirstByValRegValid; } + + ParmContext getCallOrPrologue() { return CallOrPrologue; } + void setCallOrPrologue(ParmContext pc) { CallOrPrologue = pc; } + private: /// MarkAllocated - Mark a register and all of its aliases as allocated. void MarkAllocated(unsigned Reg); diff --git a/contrib/llvm/include/llvm/CodeGen/EdgeBundles.h b/contrib/llvm/include/llvm/CodeGen/EdgeBundles.h index 2c5215a7927a..8aab3c64f170 100644 --- a/contrib/llvm/include/llvm/CodeGen/EdgeBundles.h +++ b/contrib/llvm/include/llvm/CodeGen/EdgeBundles.h @@ -16,6 +16,7 @@ #ifndef LLVM_CODEGEN_EDGEBUNDLES_H #define LLVM_CODEGEN_EDGEBUNDLES_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntEqClasses.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -29,6 +30,9 @@ class EdgeBundles : public MachineFunctionPass { /// 2*BB->getNumber()+1 -> Outgoing bundle. IntEqClasses EC; + /// Blocks - Map each bundle to a list of basic block numbers. + SmallVector, 4> Blocks; + public: static char ID; EdgeBundles() : MachineFunctionPass(ID) {} @@ -40,6 +44,9 @@ class EdgeBundles : public MachineFunctionPass { /// getNumBundles - Return the total number of bundles in the CFG. unsigned getNumBundles() const { return EC.getNumClasses(); } + /// getBlocks - Return an array of blocks that are connected to Bundle. + ArrayRef getBlocks(unsigned Bundle) { return Blocks[Bundle]; } + /// getMachineFunction - Return the last machine function computed. const MachineFunction *getMachineFunction() const { return MF; } diff --git a/contrib/llvm/include/llvm/CodeGen/FastISel.h b/contrib/llvm/include/llvm/CodeGen/FastISel.h index fbb12005444f..10c4c33dde51 100644 --- a/contrib/llvm/include/llvm/CodeGen/FastISel.h +++ b/contrib/llvm/include/llvm/CodeGen/FastISel.h @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// // // This file defines the FastISel class. -// +// //===----------------------------------------------------------------------===// - + #ifndef LLVM_CODEGEN_FASTISEL_H #define LLVM_CODEGEN_FASTISEL_H @@ -108,7 +108,7 @@ class FastISel { const LoadInst * /*LI*/) { return false; } - + /// recomputeInsertPt - Reset InsertPt to prepare for inserting instructions /// into the current block. void recomputeInsertPt(); @@ -203,16 +203,7 @@ class FastISel { unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm, MVT ImmType); - - /// FastEmit_rf_ - This method is a wrapper of FastEmit_rf. It first tries - /// to emit an instruction with an immediate operand using FastEmit_rf. - /// If that fails, it materializes the immediate into a register and try - /// FastEmit_rr instead. - unsigned FastEmit_rf_(MVT VT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, - const ConstantFP *FPImm, MVT ImmType); - + /// FastEmit_i - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and /// immediate operand be emitted. @@ -250,14 +241,22 @@ class FastISel { unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill); - /// FastEmitInst_ri - Emit a MachineInstr with two register operands - /// and a result register in the given register class. + /// FastEmitInst_ri - Emit a MachineInstr with a register operand, + /// an immediate, and a result register in the given register class. /// unsigned FastEmitInst_ri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, uint64_t Imm); + /// FastEmitInst_rii - Emit a MachineInstr with one register operand + /// and two immediate operands. + /// + unsigned FastEmitInst_rii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + uint64_t Imm1, uint64_t Imm2); + /// FastEmitInst_rf - Emit a MachineInstr with two register operands /// and a result register in the given register class. /// @@ -274,13 +273,18 @@ class FastISel { unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm); - + /// FastEmitInst_i - Emit a MachineInstr with a single immediate /// operand, and a result register in the given register class. unsigned FastEmitInst_i(unsigned MachineInstrOpcode, const TargetRegisterClass *RC, uint64_t Imm); + /// FastEmitInst_ii - Emit a MachineInstr with a two immediate operands. + unsigned FastEmitInst_ii(unsigned MachineInstrOpcode, + const TargetRegisterClass *RC, + uint64_t Imm1, uint64_t Imm2); + /// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg /// from a specified index of a superregister to a specified type. unsigned FastEmitInst_extractsubreg(MVT RetVT, @@ -300,8 +304,8 @@ class FastISel { unsigned UpdateValueMap(const Value* I, unsigned Reg); unsigned createResultReg(const TargetRegisterClass *RC); - - /// TargetMaterializeConstant - Emit a constant in a register using + + /// TargetMaterializeConstant - Emit a constant in a register using /// target-specific logic, such as constant pool loads. virtual unsigned TargetMaterializeConstant(const Constant* C) { return 0; @@ -313,6 +317,10 @@ class FastISel { return 0; } + virtual unsigned TargetMaterializeFloatZero(const ConstantFP* CF) { + return 0; + } + private: bool SelectBinaryOp(const User *I, unsigned ISDOpcode); @@ -323,7 +331,7 @@ class FastISel { bool SelectCall(const User *I); bool SelectBitCast(const User *I); - + bool SelectCast(const User *I, unsigned Opcode); /// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks. diff --git a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index b41f30d8251d..4421cc02d1cd 100644 --- a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -187,7 +187,12 @@ class FunctionLoweringInfo { /// InvalidatePHILiveOutRegInfo - Invalidates a PHI's LiveOutInfo, to be /// called when a block is visited before all of its predecessors. void InvalidatePHILiveOutRegInfo(const PHINode *PN) { - unsigned Reg = ValueMap[PN]; + // PHIs with no uses have no ValueMap entry. + DenseMap::const_iterator It = ValueMap.find(PN); + if (It == ValueMap.end()) + return; + + unsigned Reg = It->second; LiveOutRegInfo.grow(Reg); LiveOutRegInfo[Reg].IsValid = false; } @@ -209,8 +214,9 @@ class FunctionLoweringInfo { void AddCatchInfo(const CallInst &I, MachineModuleInfo *MMI, MachineBasicBlock *MBB); -/// CopyCatchInfo - Copy catch information from DestBB to SrcBB. -void CopyCatchInfo(const BasicBlock *SrcBB, const BasicBlock *DestBB, +/// CopyCatchInfo - Copy catch information from SuccBB (or one of its +/// successors) to LPad. +void CopyCatchInfo(const BasicBlock *SuccBB, const BasicBlock *LPad, MachineModuleInfo *MMI, FunctionLoweringInfo &FLI); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h index 3da11c4a0e0f..f0de9361daeb 100644 --- a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -219,7 +219,7 @@ namespace ISD { // RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition. // These nodes take two operands: the normal LHS and RHS to the add. They // produce two results: the normal result of the add, and a boolean that - // indicates if an overflow occured (*not* a flag, because it may be stored + // indicates if an overflow occurred (*not* a flag, because it may be stored // to memory, etc.). If the type of the boolean is not i1 then the high // bits conform to getBooleanContents. // These nodes are generated from the llvm.[su]add.with.overflow intrinsics. diff --git a/contrib/llvm/include/llvm/CodeGen/JITCodeEmitter.h b/contrib/llvm/include/llvm/CodeGen/JITCodeEmitter.h index fea852305158..88e22d6a24ce 100644 --- a/contrib/llvm/include/llvm/CodeGen/JITCodeEmitter.h +++ b/contrib/llvm/include/llvm/CodeGen/JITCodeEmitter.h @@ -23,8 +23,6 @@ #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/ADT/DenseMap.h" -using namespace std; - namespace llvm { class MachineBasicBlock; @@ -38,7 +36,7 @@ class GlobalValue; class Function; /// JITCodeEmitter - This class defines two sorts of methods: those for -/// emitting the actual bytes of machine code, and those for emitting auxillary +/// emitting the actual bytes of machine code, and those for emitting auxiliary /// structures, such as jump tables, relocations, etc. /// /// Emission of machine code is complicated by the fact that we don't (in diff --git a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h index 88131fbc40ff..c5285cec1e2d 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h @@ -286,6 +286,11 @@ namespace llvm { return valnos[ValNo]; } + /// containsValue - Returns true if VNI belongs to this interval. + bool containsValue(const VNInfo *VNI) const { + return VNI && VNI->id < getNumValNums() && VNI == getValNumInfo(VNI->id); + } + /// getNextValue - Create a new value number and return it. MIIdx specifies /// the instruction that defines the value number. VNInfo *getNextValue(SlotIndex def, MachineInstr *CopyMI, @@ -447,6 +452,11 @@ namespace llvm { addRangeFrom(LR, ranges.begin()); } + /// extendInBlock - If this interval is live before UseIdx in the basic + /// block that starts at StartIdx, extend it to be live at UseIdx and return + /// the value. If there is no live range before UseIdx, return NULL. + VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex UseIdx); + /// join - Join two live intervals (this, and other) together. This applies /// mappings to the value numbers in the LHS/RHS intervals as specified. If /// the intervals are not joinable, this aborts. @@ -543,8 +553,8 @@ namespace llvm { /// } class ConnectedVNInfoEqClasses { - LiveIntervals &lis_; - IntEqClasses eqClass_; + LiveIntervals &LIS; + IntEqClasses EqClass; // Note that values a and b are connected. void Connect(unsigned a, unsigned b); @@ -552,7 +562,7 @@ namespace llvm { unsigned Renumber(); public: - explicit ConnectedVNInfoEqClasses(LiveIntervals &lis) : lis_(lis) {} + explicit ConnectedVNInfoEqClasses(LiveIntervals &lis) : LIS(lis) {} /// Classify - Classify the values in LI into connected components. /// Return the number of connected components. @@ -560,12 +570,13 @@ namespace llvm { /// getEqClass - Classify creates equivalence classes numbered 0..N. Return /// the equivalence class assigned the VNI. - unsigned getEqClass(const VNInfo *VNI) const { return eqClass_[VNI->id]; } + unsigned getEqClass(const VNInfo *VNI) const { return EqClass[VNI->id]; } /// Distribute - Distribute values in LIV[0] into a separate LiveInterval /// for each connected component. LIV must have a LiveInterval for each /// connected component. The LiveIntervals in Liv[1..] must be empty. - void Distribute(LiveInterval *LIV[]); + /// Instructions using LIV[0] are rewritten. + void Distribute(LiveInterval *LIV[], MachineRegisterInfo &MRI); }; diff --git a/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h b/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h index b09f8d111066..8ca58b82c8bb 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -159,7 +159,11 @@ namespace llvm { /// range to just the remaining uses. This method does not compute reaching /// defs for new uses, and it doesn't remove dead defs. /// Dead PHIDef values are marked as unused. - void shrinkToUses(LiveInterval *li); + /// New dead machine instructions are added to the dead vector. + /// Return true if the interval may have been separated into multiple + /// connected components. + bool shrinkToUses(LiveInterval *li, + SmallVectorImpl *dead = 0); // Interval removal @@ -272,7 +276,7 @@ namespace llvm { /// (if any is created) by reference. This is temporary. std::vector addIntervalsForSpills(const LiveInterval& i, - const SmallVectorImpl &SpillIs, + const SmallVectorImpl *SpillIs, const MachineLoopInfo *loopInfo, VirtRegMap& vrm); /// spillPhysRegAroundRegDefsUses - Spill the specified physical register @@ -285,7 +289,7 @@ namespace llvm { /// val# of the specified interval is re-materializable. Also returns true /// by reference if all of the defs are load instructions. bool isReMaterializable(const LiveInterval &li, - const SmallVectorImpl &SpillIs, + const SmallVectorImpl *SpillIs, bool &isLoad); /// isReMaterializable - Returns true if the definition MI of the specified @@ -372,7 +376,7 @@ namespace llvm { /// by reference if the def is a load. bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, MachineInstr *MI, - const SmallVectorImpl &SpillIs, + const SmallVectorImpl *SpillIs, bool &isLoad); /// tryFoldMemoryOperand - Attempts to fold either a spill / restore from diff --git a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h index 1785451c7ec5..ad121572fca0 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -16,6 +16,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/ADT/GraphTraits.h" +#include namespace llvm { @@ -304,10 +305,18 @@ class MachineBasicBlock : public ilist_node { /// it returns end() iterator getFirstTerminator(); + const_iterator getFirstTerminator() const { + return const_cast(this)->getFirstTerminator(); + } + /// getLastNonDebugInstr - returns an iterator to the last non-debug /// instruction in the basic block, or end() iterator getLastNonDebugInstr(); + const_iterator getLastNonDebugInstr() const { + return const_cast(this)->getLastNonDebugInstr(); + } + /// SplitCriticalEdge - Split the critical edge from this block to the /// given successor block, and return the newly created block, or null /// if splitting is not possible. @@ -411,6 +420,14 @@ raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB); void WriteAsOperand(raw_ostream &, const MachineBasicBlock*, bool t); +// This is useful when building IndexedMaps keyed on basic block pointers. +struct MBB2NumberFunctor : + public std::unary_function { + unsigned operator()(const MachineBasicBlock *MBB) const { + return MBB->getNumber(); + } +}; + //===--------------------------------------------------------------------===// // GraphTraits specializations for machine basic block graphs (machine-CFGs) //===--------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/CodeGen/MachineCodeEmitter.h b/contrib/llvm/include/llvm/CodeGen/MachineCodeEmitter.h index 8fc80adf7fb8..428aada7ba13 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineCodeEmitter.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineCodeEmitter.h @@ -34,7 +34,7 @@ class Function; class MCSymbol; /// MachineCodeEmitter - This class defines two sorts of methods: those for -/// emitting the actual bytes of machine code, and those for emitting auxillary +/// emitting the actual bytes of machine code, and those for emitting auxiliary /// structures, such as jump tables, relocations, etc. /// /// Emission of machine code is complicated by the fact that we don't (in @@ -54,7 +54,7 @@ class MachineCodeEmitter { /// allocated for this code buffer. uint8_t *BufferBegin, *BufferEnd; /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting - /// code. This is guranteed to be in the range [BufferBegin,BufferEnd]. If + /// code. This is guaranteed to be in the range [BufferBegin,BufferEnd]. If /// this pointer is at BufferEnd, it will never move due to code emission, and /// all code emission requests will be ignored (this is the buffer overflow /// condition). diff --git a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h index 5727321a0da4..beb16a2824d7 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h @@ -80,7 +80,7 @@ class MachineConstantPoolEntry { } Val; /// The required alignment for this entry. The top bit is set when Val is - /// a MachineConstantPoolValue. + /// a target specific MachineConstantPoolValue. unsigned Alignment; MachineConstantPoolEntry(const Constant *V, unsigned A) @@ -93,6 +93,9 @@ class MachineConstantPoolEntry { Alignment |= 1U << (sizeof(unsigned)*CHAR_BIT-1); } + /// isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry + /// is indeed a target specific constantpool entry, not a wrapper over a + /// Constant. bool isMachineConstantPoolEntry() const { return (int)Alignment < 0; } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 22a82a9d6e75..4ea6aa3396a9 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -15,7 +15,6 @@ #define LLVM_CODEGEN_MACHINEFRAMEINFO_H #include "llvm/ADT/SmallVector.h" -//#include "llvm/ADT/IndexedMap.h" #include "llvm/Support/DataTypes.h" #include #include diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h index 82c5332ccd9f..2724689786e5 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h @@ -50,13 +50,22 @@ class MachineInstr : public ilist_node { enum CommentFlag { ReloadReuse = 0x1 }; - + + enum MIFlag { + NoFlags = 0, + FrameSetup = 1 << 0 // Instruction is used as a part of + // function frame setup code. + }; private: const TargetInstrDesc *TID; // Instruction descriptor. - unsigned short NumImplicitOps; // Number of implicit operands (which + uint16_t NumImplicitOps; // Number of implicit operands (which // are determined at construction time). - unsigned short AsmPrinterFlags; // Various bits of information used by + uint8_t Flags; // Various bits of additional + // information about machine + // instruction. + + uint8_t AsmPrinterFlags; // Various bits of information used by // the AsmPrinter to emit helpful // comments. This is *not* semantic // information. Do not use this for @@ -105,13 +114,13 @@ class MachineInstr : public ilist_node { /// MachineInstr ctor - This constructor create a MachineInstr and add the /// implicit operands. It reserves space for number of operands specified by /// TargetInstrDesc. An explicit DebugLoc is supplied. - explicit MachineInstr(const TargetInstrDesc &TID, const DebugLoc dl, + explicit MachineInstr(const TargetInstrDesc &TID, 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, + MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, const TargetInstrDesc &TID); ~MachineInstr(); @@ -125,12 +134,12 @@ class MachineInstr : public ilist_node { /// getAsmPrinterFlags - Return the asm printer flags bitvector. /// - unsigned short getAsmPrinterFlags() const { return AsmPrinterFlags; } + uint8_t getAsmPrinterFlags() const { return AsmPrinterFlags; } /// clearAsmPrinterFlags - clear the AsmPrinter bitvector /// void clearAsmPrinterFlags() { AsmPrinterFlags = 0; } - + /// getAsmPrinterFlag - Return whether an AsmPrinter flag is set. /// bool getAsmPrinterFlag(CommentFlag Flag) const { @@ -140,9 +149,28 @@ class MachineInstr : public ilist_node { /// setAsmPrinterFlag - Set a flag for the AsmPrinter. /// void setAsmPrinterFlag(CommentFlag Flag) { - AsmPrinterFlags |= (unsigned short)Flag; + AsmPrinterFlags |= (uint8_t)Flag; } - + + /// getFlags - Return the MI flags bitvector. + uint8_t getFlags() const { + return Flags; + } + + /// getFlag - Return whether an MI flag is set. + bool getFlag(MIFlag Flag) const { + return Flags & Flag; + } + + /// setFlag - Set a MI flag. + void setFlag(MIFlag Flag) { + Flags |= (uint8_t)Flag; + } + + void setFlags(unsigned flags) { + Flags = flags; + } + /// clearAsmPrinterFlag - clear specific AsmPrinter flags /// void clearAsmPrinterFlag(CommentFlag Flag) { @@ -152,7 +180,7 @@ class MachineInstr : public ilist_node { /// getDebugLoc - Returns the debug location id of this MachineInstr. /// DebugLoc getDebugLoc() const { return debugLoc; } - + /// getDesc - Returns the target instruction descriptor of this /// MachineInstr. const TargetInstrDesc &getDesc() const { return *TID; } @@ -213,7 +241,7 @@ class MachineInstr : public ilist_node { /// removeFromParent - This method unlinks 'this' from the containing basic /// block, and returns it, but does not delete it. MachineInstr *removeFromParent(); - + /// eraseFromParent - This method unlinks 'this' from the containing basic /// block and deletes it. void eraseFromParent(); @@ -225,14 +253,14 @@ class MachineInstr : public ilist_node { getOpcode() == TargetOpcode::EH_LABEL || getOpcode() == TargetOpcode::GC_LABEL; } - + bool isPrologLabel() const { return getOpcode() == TargetOpcode::PROLOG_LABEL; } bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; } - + bool isPHI() const { return getOpcode() == TargetOpcode::PHI; } bool isKill() const { return getOpcode() == TargetOpcode::KILL; } bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } @@ -329,7 +357,7 @@ class MachineInstr : public ilist_node { int Idx = findRegisterUseOperandIdx(Reg, isKill, TRI); return (Idx == -1) ? NULL : &getOperand(Idx); } - + /// findRegisterDefOperandIdx() - Returns the operand index that is a def of /// the specified register or -1 if it is not found. If isDead is true, defs /// that are not dead are skipped. If Overlap is true, then it also looks for @@ -351,7 +379,7 @@ class MachineInstr : public ilist_node { /// operand list that is used to represent the predicate. It returns -1 if /// none is found. int findFirstPredOperandIdx() const; - + /// isRegTiedToUseOperand - Given the index of a register def operand, /// check if the register def is tied to a source operand, due to either /// two-address elimination or inline assembly constraints. Returns the @@ -399,8 +427,8 @@ class MachineInstr : public ilist_node { void addRegisterDefined(unsigned IncomingReg, const TargetRegisterInfo *RegInfo = 0); - /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as dead - /// except those in the UsedRegs list. + /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as + /// dead except those in the UsedRegs list. void setPhysRegsDeadExcept(const SmallVectorImpl &UsedRegs, const TargetRegisterInfo &TRI); @@ -462,9 +490,9 @@ class MachineInstr : public ilist_node { /// 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 - /// (before the first implicit operand). + /// (before the first implicit operand). void addOperand(const MachineOperand &Op); - + /// setDesc - Replace the instruction descriptor (thus opcode) of /// the current instruction with a new one. /// @@ -501,12 +529,12 @@ class MachineInstr : public ilist_node { /// addImplicitDefUseOperands - Add all implicit def and use operands to /// this instruction. void addImplicitDefUseOperands(); - + /// RemoveRegOperandsFromUseLists - Unlink all of the register operands in /// this instruction from their respective use lists. This requires that the /// operands already be on their use lists. void RemoveRegOperandsFromUseLists(); - + /// AddRegOperandsToUseLists - Add all of the register operands in /// this instruction from their respective use lists. This requires that the /// operands not be on their use lists yet. diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h index 1eb97353088f..967e0197bb7d 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -48,6 +48,7 @@ class MachineInstrBuilder { /// Allow automatic conversion to the machine instruction we are working on. /// operator MachineInstr*() const { return MI; } + MachineInstr *operator->() const { return MI; } operator MachineBasicBlock::iterator() const { return MI; } /// addReg - Add a new virtual register operand... @@ -145,6 +146,16 @@ class MachineInstrBuilder { return *this; } + const MachineInstrBuilder &setMIFlags(unsigned Flags) const { + MI->setFlags(Flags); + return *this; + } + + const MachineInstrBuilder &setMIFlag(MachineInstr::MIFlag Flag) const { + MI->setFlag(Flag); + return *this; + } + // Add a displacement from an existing MachineOperand with an added offset. const MachineInstrBuilder &addDisp(const MachineOperand &Disp, int64_t off) const { diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h index b2224cb051dc..5240729f52d0 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h @@ -18,7 +18,6 @@ #include "Math.h" #include -#include #include namespace PBQP { diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h index 47a287ccf2f6..e96c4cb1e0c1 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h @@ -21,7 +21,6 @@ #include "../HeuristicSolver.h" #include "../HeuristicBase.h" -#include #include namespace PBQP { diff --git a/contrib/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h b/contrib/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h index e2ab899f183f..6ab57f03aee7 100644 --- a/contrib/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h +++ b/contrib/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h @@ -18,14 +18,20 @@ namespace llvm { class MachineInstr; class TargetInstrInfo; + class TargetRegisterInfo; + class MachineRegisterInfo; + class LiveVariables; /// Process IMPLICIT_DEF instructions and make sure there is one implicit_def /// for each use. Add isUndef marker to implicit_def defs and their uses. class ProcessImplicitDefs : public MachineFunctionPass { - private: + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineRegisterInfo *MRI; + LiveVariables *LV; bool CanTurnIntoImplicitDef(MachineInstr *MI, unsigned Reg, - unsigned OpIdx, const TargetInstrInfo *tii_, + unsigned OpIdx, SmallSet &ImpDefRegs); public: diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h index 246831c034d4..26b6773c0530 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h @@ -100,7 +100,7 @@ class RegScavenger { /// getRegsAvailable - Return all available registers in the register class /// in Mask. - void getRegsAvailable(const TargetRegisterClass *RC, BitVector &Mask); + BitVector getRegsAvailable(const TargetRegisterClass *RC); /// FindUnusedReg - Find a unused register of the specified register class. /// Return 0 if none is found. diff --git a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h b/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h index a51e82a6404a..576be821774d 100644 --- a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h @@ -66,6 +66,16 @@ namespace RTLIB { UREM_I32, UREM_I64, UREM_I128, + SDIVREM_I8, + SDIVREM_I16, + SDIVREM_I32, + SDIVREM_I64, + SDIVREM_I128, + UDIVREM_I8, + UDIVREM_I16, + UDIVREM_I32, + UDIVREM_I64, + UDIVREM_I128, NEG_I32, NEG_I64, diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h index 3864ffd50a19..2eb3db319ddf 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h @@ -250,7 +250,9 @@ namespace llvm { unsigned NumSuccsLeft; // # of 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. bool isCall : 1; // Is a function call. + bool isCallOp : 1; // Is a function call operand. bool isTwoAddress : 1; // Is a two-address instruction. bool isCommutable : 1; // Is a commutable instruction. bool hasPhysRegDefs : 1; // Has physreg defs that are being used. @@ -259,6 +261,7 @@ namespace llvm { bool isAvailable : 1; // True once available. bool isScheduled : 1; // True once scheduled. bool isScheduleHigh : 1; // True if preferable to schedule high. + bool isScheduleLow : 1; // True if preferable to schedule low. bool isCloned : 1; // True if this node has been cloned. Sched::Preference SchedulingPref; // Scheduling preference. @@ -278,10 +281,10 @@ namespace llvm { : Node(node), Instr(0), OrigNode(0), NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), - isCall(false), isTwoAddress(false), isCommutable(false), - hasPhysRegDefs(false), hasPhysRegClobbers(false), + isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), + isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isCloned(false), + isScheduleHigh(false), isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -292,10 +295,10 @@ namespace llvm { : Node(0), Instr(instr), OrigNode(0), NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), - isCall(false), isTwoAddress(false), isCommutable(false), - hasPhysRegDefs(false), hasPhysRegClobbers(false), + isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), + isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isCloned(false), + isScheduleHigh(false), isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -305,10 +308,10 @@ namespace llvm { : Node(0), Instr(0), OrigNode(0), NodeNum(~0u), NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), - isCall(false), isTwoAddress(false), isCommutable(false), - hasPhysRegDefs(false), hasPhysRegClobbers(false), + isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), + isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isCloned(false), + isScheduleHigh(false), isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -356,7 +359,7 @@ namespace llvm { void removePred(const SDep &D); /// getDepth - Return the depth of this node, which is the length of the - /// maximum path up to any node with has no predecessors. + /// maximum path up to any node which has no predecessors. unsigned getDepth() const { if (!isDepthCurrent) const_cast(this)->ComputeDepth(); @@ -364,7 +367,7 @@ namespace llvm { } /// getHeight - Return the height of this node, which is the length of the - /// maximum path down to any node with has no successors. + /// maximum path down to any node which has no successors. unsigned getHeight() const { if (!isHeightCurrent) const_cast(this)->ComputeHeight(); @@ -690,11 +693,11 @@ namespace llvm { /// will create a cycle. bool WillCreateCycle(SUnit *SU, SUnit *TargetSU); - /// AddPred - Updates the topological ordering to accomodate an edge + /// AddPred - Updates the topological ordering to accommodate an edge /// to be added from SUnit X to SUnit Y. void AddPred(SUnit *Y, SUnit *X); - /// RemovePred - Updates the topological ordering to accomodate an + /// RemovePred - Updates the topological ordering to accommodate an /// an edge to be removed from the specified node N from the predecessors /// of the current node M. void RemovePred(SUnit *M, SUnit *N); diff --git a/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h index 8850006df84c..118df28abbb4 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ b/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -21,7 +21,6 @@ #include #include -#include namespace llvm { diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h index c9de95bebd54..92fd0c9e1cc1 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -438,12 +438,12 @@ class SelectionDAG { SDValue getConvertRndSat(EVT VT, DebugLoc dl, SDValue Val, SDValue DTy, SDValue STy, SDValue Rnd, SDValue Sat, ISD::CvtCode Code); - + /// getVectorShuffle - Return an ISD::VECTOR_SHUFFLE node. The number of /// elements in VT, which must be a vector type, must match the number of /// mask elements NumElts. A integer mask element equal to -1 is treated as /// undefined. - SDValue getVectorShuffle(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, + SDValue getVectorShuffle(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, const int *MaskElts); /// getSExtOrTrunc - Convert Op, which must be of integer type, to the @@ -671,10 +671,10 @@ class SelectionDAG { /// getMDNode - Return an MDNodeSDNode which holds an MDNode. SDValue getMDNode(const MDNode *MD); - + /// getShiftAmountOperand - Return the specified value casted to /// the target's desired shift amount type. - SDValue getShiftAmountOperand(SDValue Op); + SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op); /// UpdateNodeOperands - *Mutate* the specified node in-place to have the /// specified operands. If the resultant node already exists in the DAG, @@ -829,7 +829,7 @@ class SelectionDAG { /// These functions only replace all existing uses. It's possible that as /// these replacements are being performed, CSE may cause the From node /// to be given new uses. These new uses of From are left in place, and - /// not automatically transfered to To. + /// not automatically transferred to To. /// void ReplaceAllUsesWith(SDValue From, SDValue Op, DAGUpdateListener *UpdateListener = 0); @@ -901,7 +901,7 @@ class SelectionDAG { SmallVector &GetDbgValues(const SDNode* SD) { return DbgInfo->getSDDbgValues(SD); } - + /// TransferDbgValues - Transfer SDDbgValues. void TransferDbgValues(SDValue From, SDValue To); @@ -911,11 +911,11 @@ class SelectionDAG { SDDbgInfo::DbgIterator DbgBegin() { return DbgInfo->DbgBegin(); } SDDbgInfo::DbgIterator DbgEnd() { return DbgInfo->DbgEnd(); } - SDDbgInfo::DbgIterator ByvalParmDbgBegin() { - return DbgInfo->ByvalParmDbgBegin(); + SDDbgInfo::DbgIterator ByvalParmDbgBegin() { + return DbgInfo->ByvalParmDbgBegin(); } - SDDbgInfo::DbgIterator ByvalParmDbgEnd() { - return DbgInfo->ByvalParmDbgEnd(); + SDDbgInfo::DbgIterator ByvalParmDbgEnd() { + return DbgInfo->ByvalParmDbgEnd(); } void dump() const; @@ -972,7 +972,7 @@ class SelectionDAG { /// semantics as an ADD. This handles the equivalence: /// X|Cst == X+Cst iff X&Cst = 0. bool isBaseWithConstantOffset(SDValue Op) const; - + /// isKnownNeverNan - Test whether the given SDValue is known to never be NaN. bool isKnownNeverNaN(SDValue Op) const; @@ -997,8 +997,8 @@ class SelectionDAG { /// vector op and fill the end of the resulting vector with UNDEFS. SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0); - /// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a - /// location that is 'Dist' units away from the location that the 'Base' load + /// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a + /// location that is 'Dist' units away from the location that the 'Base' load /// is loading from. bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, int Dist) const; @@ -1032,7 +1032,7 @@ class SelectionDAG { std::vector ValueTypeNodes; std::map ExtendedValueTypeNodes; StringMap ExternalSymbols; - + std::map,SDNode*> TargetExternalSymbols; }; diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h index 62358e7639ee..ecf394701053 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -127,6 +127,7 @@ class SelectionDAGISel : public MachineFunctionPass { OPC_EmitInteger, OPC_EmitRegister, + OPC_EmitRegister2, OPC_EmitConvertToTarget, OPC_EmitMergeInputChains, OPC_EmitMergeInputChains1_0, @@ -257,7 +258,7 @@ class SelectionDAGISel : public MachineFunctionPass { } virtual SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) { - assert(0 && "Tblgen shoudl generate this!"); + assert(0 && "Tblgen should generate this!"); return SDValue(); } @@ -279,7 +280,8 @@ class SelectionDAGISel : public MachineFunctionPass { void PrepareEHLandingPad(); void SelectAllBasicBlocks(const Function &Fn); - bool TryToFoldFastISelLoad(const LoadInst *LI, FastISel *FastIS); + bool TryToFoldFastISelLoad(const LoadInst *LI, const Instruction *FoldInst, + FastISel *FastIS); void FinishBasicBlock(); void SelectBasicBlock(BasicBlock::const_iterator Begin, diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 64546394ce91..9d265f14516d 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -838,7 +838,7 @@ class TernarySDNode : public SDNode { /// HandleSDNode - This class is used to form a handle around another node that -/// is persistant and is updated across invocations of replaceAllUsesWith on its +/// is persistent and is updated across invocations of replaceAllUsesWith on its /// operand. This node should be directly created by end-users and not added to /// the AllNodes list. class HandleSDNode : public SDNode { diff --git a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h index 1da1e91be14a..33ce675e5cc4 100644 --- a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h +++ b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h @@ -34,77 +34,35 @@ namespace llvm { /// SlotIndex & SlotIndexes classes for the public interface to this /// information. class IndexListEntry { - static const unsigned EMPTY_KEY_INDEX = ~0U & ~3U, - TOMBSTONE_KEY_INDEX = ~0U & ~7U; - IndexListEntry *next, *prev; MachineInstr *mi; unsigned index; - protected: - - typedef enum { EMPTY_KEY, TOMBSTONE_KEY } ReservedEntryType; - - // This constructor is only to be used by getEmptyKeyEntry - // & getTombstoneKeyEntry. It sets index to the given - // value and mi to zero. - IndexListEntry(ReservedEntryType r) : mi(0) { - switch(r) { - case EMPTY_KEY: index = EMPTY_KEY_INDEX; break; - case TOMBSTONE_KEY: index = TOMBSTONE_KEY_INDEX; break; - default: assert(false && "Invalid value for constructor."); - } - next = this; - prev = this; - } - public: - IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) { - assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX && - "Attempt to create invalid index. " - "Available indexes may have been exhausted?."); - } - - bool isValid() const { - return (index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX); - } + IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) {} MachineInstr* getInstr() const { return mi; } void setInstr(MachineInstr *mi) { - assert(isValid() && "Attempt to modify reserved index."); this->mi = mi; } unsigned getIndex() const { return index; } void setIndex(unsigned index) { - assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX && - "Attempt to set index to invalid value."); - assert(isValid() && "Attempt to reset reserved index value."); this->index = index; } IndexListEntry* getNext() { return next; } const IndexListEntry* getNext() const { return next; } void setNext(IndexListEntry *next) { - assert(isValid() && "Attempt to modify reserved index."); this->next = next; } IndexListEntry* getPrev() { return prev; } const IndexListEntry* getPrev() const { return prev; } void setPrev(IndexListEntry *prev) { - assert(isValid() && "Attempt to modify reserved index."); this->prev = prev; } - - // This function returns the index list entry that is to be used for empty - // SlotIndex keys. - static IndexListEntry* getEmptyKeyEntry(); - - // This function returns the index list entry that is to be used for - // tombstone SlotIndex keys. - static IndexListEntry* getTombstoneKeyEntry(); }; // Specialize PointerLikeTypeTraits for IndexListEntry. @@ -130,11 +88,10 @@ namespace llvm { PointerIntPair lie; SlotIndex(IndexListEntry *entry, unsigned slot) - : lie(entry, slot) { - assert(entry != 0 && "Attempt to construct index with 0 pointer."); - } + : lie(entry, slot) {} IndexListEntry& entry() const { + assert(isValid() && "Attempt to compare reserved index."); return *lie.getPointer(); } @@ -148,22 +105,27 @@ namespace llvm { } static inline unsigned getHashValue(const SlotIndex &v) { - IndexListEntry *ptrVal = &v.entry(); - return (unsigned((intptr_t)ptrVal) >> 4) ^ - (unsigned((intptr_t)ptrVal) >> 9); + void *ptrVal = v.lie.getOpaqueValue(); + return (unsigned((intptr_t)ptrVal)) ^ (unsigned((intptr_t)ptrVal) >> 9); } public: + enum { + /// The default distance between instructions as returned by distance(). + /// This may vary as instructions are inserted and removed. + InstrDist = 4*NUM + }; + static inline SlotIndex getEmptyKey() { - return SlotIndex(IndexListEntry::getEmptyKeyEntry(), 0); + return SlotIndex(0, 1); } static inline SlotIndex getTombstoneKey() { - return SlotIndex(IndexListEntry::getTombstoneKeyEntry(), 0); + return SlotIndex(0, 2); } /// Construct an invalid index. - SlotIndex() : lie(IndexListEntry::getEmptyKeyEntry(), 0) {} + SlotIndex() : lie(0, 0) {} // Construct a new slot index from the given one, and set the slot. SlotIndex(const SlotIndex &li, Slot s) @@ -175,8 +137,7 @@ namespace llvm { /// Returns true if this is a valid index. Invalid indicies do /// not point into an index table, and cannot be compared. bool isValid() const { - IndexListEntry *entry = lie.getPointer(); - return ((entry!= 0) && (entry->isValid())); + return lie.getPointer(); } /// Print this index to the given raw_ostream. @@ -187,11 +148,11 @@ namespace llvm { /// Compare two SlotIndex objects for equality. bool operator==(SlotIndex other) const { - return getIndex() == other.getIndex(); + return lie == other.lie; } /// Compare two SlotIndex objects for inequality. bool operator!=(SlotIndex other) const { - return getIndex() != other.getIndex(); + return lie != other.lie; } /// Compare two SlotIndex objects. Return true if the first index @@ -217,6 +178,11 @@ namespace llvm { return getIndex() >= other.getIndex(); } + /// isSameInstr - Return true if A and B refer to the same instruction. + static bool isSameInstr(SlotIndex A, SlotIndex B) { + return A.lie.getPointer() == B.lie.getPointer(); + } + /// Return the distance from this index to the given one. int distance(SlotIndex other) const { return other.getIndex() - getIndex(); @@ -376,15 +342,12 @@ namespace llvm { typedef DenseMap Mi2IndexMap; Mi2IndexMap mi2iMap; - /// MBB2IdxMap - The indexes of the first and last instructions in the - /// specified basic block. - typedef DenseMap > MBB2IdxMap; - MBB2IdxMap mbb2IdxMap; + /// MBBRanges - Map MBB number to (start, stop) indexes. + SmallVector, 8> MBBRanges; /// Idx2MBBMap - Sorted list of pairs of index of first instruction /// and MBB id. - std::vector idx2MBBMap; + SmallVector idx2MBBMap; // IndexListEntry allocator. BumpPtrAllocator ileAllocator; @@ -466,6 +429,9 @@ namespace llvm { insert(getTail(), val); } + /// Renumber locally after inserting newEntry. + void renumberIndexes(IndexListEntry *newEntry); + public: static char ID; @@ -530,7 +496,7 @@ namespace llvm { /// Returns the instruction for the given index, or null if the given /// index has no instruction associated with it. MachineInstr* getInstructionFromIndex(SlotIndex index) const { - return index.entry().getInstr(); + return index.isValid() ? index.entry().getInstr() : 0; } /// Returns the next non-null index. @@ -545,12 +511,55 @@ namespace llvm { return nextNonNull; } + /// getIndexBefore - Returns the index of the last indexed instruction + /// before MI, or the the start index of its basic block. + /// MI is not required to have an index. + SlotIndex getIndexBefore(const MachineInstr *MI) const { + const MachineBasicBlock *MBB = MI->getParent(); + assert(MBB && "MI must be inserted inna basic block"); + MachineBasicBlock::const_iterator I = MI, B = MBB->begin(); + for (;;) { + if (I == B) + return getMBBStartIdx(MBB); + --I; + Mi2IndexMap::const_iterator MapItr = mi2iMap.find(I); + if (MapItr != mi2iMap.end()) + return MapItr->second; + } + } + + /// getIndexAfter - Returns the index of the first indexed instruction + /// after MI, or the end index of its basic block. + /// MI is not required to have an index. + SlotIndex getIndexAfter(const MachineInstr *MI) const { + const MachineBasicBlock *MBB = MI->getParent(); + assert(MBB && "MI must be inserted inna basic block"); + MachineBasicBlock::const_iterator I = MI, E = MBB->end(); + for (;;) { + ++I; + if (I == E) + return getMBBEndIdx(MBB); + Mi2IndexMap::const_iterator MapItr = mi2iMap.find(I); + if (MapItr != mi2iMap.end()) + return MapItr->second; + } + } + + /// Return the (start,end) range of the given basic block number. + const std::pair & + getMBBRange(unsigned Num) const { + return MBBRanges[Num]; + } + /// Return the (start,end) range of the given basic block. const std::pair & - getMBBRange(const MachineBasicBlock *mbb) const { - MBB2IdxMap::const_iterator itr = mbb2IdxMap.find(mbb); - assert(itr != mbb2IdxMap.end() && "MBB not found in maps."); - return itr->second; + getMBBRange(const MachineBasicBlock *MBB) const { + return getMBBRange(MBB->getNumber()); + } + + /// Returns the first index in the given basic block number. + SlotIndex getMBBStartIdx(unsigned Num) const { + return getMBBRange(Num).first; } /// Returns the first index in the given basic block. @@ -558,6 +567,11 @@ namespace llvm { return getMBBRange(mbb).first; } + /// Returns the last index in the given basic block number. + SlotIndex getMBBEndIdx(unsigned Num) const { + return getMBBRange(Num).second; + } + /// Returns the last index in the given basic block. SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { return getMBBRange(mbb).second; @@ -565,10 +579,12 @@ namespace llvm { /// Returns the basic block which the given index falls in. MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { - std::vector::const_iterator I = + if (MachineInstr *MI = getInstructionFromIndex(index)) + return MI->getParent(); + SmallVectorImpl::const_iterator I = std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), index); // Take the pair containing the index - std::vector::const_iterator J = + SmallVectorImpl::const_iterator J = ((I != idx2MBBMap.end() && I->first > index) || (I == idx2MBBMap.end() && idx2MBBMap.size()>0)) ? (I-1): I; @@ -580,7 +596,7 @@ namespace llvm { bool findLiveInMBBs(SlotIndex start, SlotIndex end, SmallVectorImpl &mbbs) const { - std::vector::const_iterator itr = + SmallVectorImpl::const_iterator itr = std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); bool resVal = false; @@ -600,7 +616,7 @@ namespace llvm { assert(start < end && "Backwards ranges not allowed."); - std::vector::const_iterator itr = + SmallVectorImpl::const_iterator itr = std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); if (itr == idx2MBBMap.end()) { @@ -622,95 +638,47 @@ namespace llvm { /// Insert the given machine instruction into the mapping. Returns the /// assigned index. - SlotIndex insertMachineInstrInMaps(MachineInstr *mi, - bool *deferredRenumber = 0) { + /// If Late is set and there are null indexes between mi's neighboring + /// instructions, create the new index after the null indexes instead of + /// before them. + SlotIndex insertMachineInstrInMaps(MachineInstr *mi, bool Late = false) { assert(mi2iMap.find(mi) == mi2iMap.end() && "Instr already indexed."); // Numbering DBG_VALUE instructions could cause code generation to be // affected by debug information. assert(!mi->isDebugValue() && "Cannot number DBG_VALUE instructions."); - MachineBasicBlock *mbb = mi->getParent(); + assert(mi->getParent() != 0 && "Instr must be added to function."); - assert(mbb != 0 && "Instr must be added to function."); - - MBB2IdxMap::iterator mbbRangeItr = mbb2IdxMap.find(mbb); - - assert(mbbRangeItr != mbb2IdxMap.end() && - "Instruction's parent MBB has not been added to SlotIndexes."); - - MachineBasicBlock::iterator miItr(mi); - bool needRenumber = false; - IndexListEntry *newEntry; - // Get previous index, considering that not all instructions are indexed. - IndexListEntry *prevEntry; - for (;;) { - // If mi is at the mbb beginning, get the prev index from the mbb. - if (miItr == mbb->begin()) { - prevEntry = &mbbRangeItr->second.first.entry(); - break; - } - // Otherwise rewind until we find a mapped instruction. - Mi2IndexMap::const_iterator itr = mi2iMap.find(--miItr); - if (itr != mi2iMap.end()) { - prevEntry = &itr->second.entry(); - break; - } + // Get the entries where mi should be inserted. + IndexListEntry *prevEntry, *nextEntry; + if (Late) { + // Insert mi's index immediately before the following instruction. + nextEntry = &getIndexAfter(mi).entry(); + prevEntry = nextEntry->getPrev(); + } else { + // Insert mi's index immediately after the preceeding instruction. + prevEntry = &getIndexBefore(mi).entry(); + nextEntry = prevEntry->getNext(); } - // Get next entry from previous entry. - IndexListEntry *nextEntry = prevEntry->getNext(); - // Get a number for the new instr, or 0 if there's no room currently. // In the latter case we'll force a renumber later. - unsigned dist = nextEntry->getIndex() - prevEntry->getIndex(); - unsigned newNumber = dist > SlotIndex::NUM ? - prevEntry->getIndex() + ((dist >> 1) & ~3U) : 0; - - if (newNumber == 0) { - needRenumber = true; - } + unsigned dist = ((nextEntry->getIndex() - prevEntry->getIndex())/2) & ~3u; + unsigned newNumber = prevEntry->getIndex() + dist; // Insert a new list entry for mi. - newEntry = createEntry(mi, newNumber); + IndexListEntry *newEntry = createEntry(mi, newNumber); insert(nextEntry, newEntry); - + + // Renumber locally if we need to. + if (dist == 0) + renumberIndexes(newEntry); + SlotIndex newIndex(newEntry, SlotIndex::LOAD); mi2iMap.insert(std::make_pair(mi, newIndex)); - - if (miItr == mbb->end()) { - // If this is the last instr in the MBB then we need to fix up the bb - // range: - mbbRangeItr->second.second = SlotIndex(newEntry, SlotIndex::STORE); - } - - // Renumber if we need to. - if (needRenumber) { - if (deferredRenumber == 0) - renumberIndexes(); - else - *deferredRenumber = true; - } - return newIndex; } - /// Add all instructions in the vector to the index list. This method will - /// defer renumbering until all instrs have been added, and should be - /// preferred when adding multiple instrs. - void insertMachineInstrsInMaps(SmallVectorImpl &mis) { - bool renumber = false; - - for (SmallVectorImpl::iterator - miItr = mis.begin(), miEnd = mis.end(); - miItr != miEnd; ++miItr) { - insertMachineInstrInMaps(*miItr, &renumber); - } - - if (renumber) - renumberIndexes(); - } - - /// Remove the given machine instruction from the mapping. void removeMachineInstrFromMaps(MachineInstr *mi) { // remove index -> MachineInstr and @@ -760,21 +728,14 @@ namespace llvm { SlotIndex startIdx(startEntry, SlotIndex::LOAD); SlotIndex endIdx(nextEntry, SlotIndex::LOAD); - mbb2IdxMap.insert( - std::make_pair(mbb, std::make_pair(startIdx, endIdx))); + assert(unsigned(mbb->getNumber()) == MBBRanges.size() && + "Blocks must be added in order"); + MBBRanges.push_back(std::make_pair(startIdx, endIdx)); idx2MBBMap.push_back(IdxMBBPair(startIdx, mbb)); - if (MachineFunction::iterator(mbb) != mbb->getParent()->begin()) { - // Have to update the end index of the previous block. - MachineBasicBlock *priorMBB = - llvm::prior(MachineFunction::iterator(mbb)); - mbb2IdxMap[priorMBB].second = startIdx; - } - renumberIndexes(); std::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare()); - } }; diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index fba3e48c475e..829f580df33d 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -59,6 +59,10 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { virtual const MCSection *getEHFrameSection() const; + virtual void emitPersonalityValue(MCStreamer &Streamer, + const TargetMachine &TM, + const MCSymbol *Sym) const; + const MCSection *getDataRelSection() const { return DataRelSection; } /// getSectionForConstant - Given a constant with the SectionKind, return a @@ -81,6 +85,11 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, MachineModuleInfo *MMI, unsigned Encoding, MCStreamer &Streamer) const; + + // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. + virtual MCSymbol * + getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI) const; }; @@ -94,7 +103,7 @@ class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { /// const MCSection *TLSBSSSection; // Defaults to ".tbss". - /// TLSTLVSection - Section for thread local structure infomation. + /// TLSTLVSection - Section for thread local structure information. /// Contains the source code name of the variable, visibility and a pointer /// to the initial value (.tdata or .tbss). const MCSection *TLSTLVSection; // Defaults to ".tlv". @@ -172,9 +181,14 @@ class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { MachineModuleInfo *MMI, unsigned Encoding, MCStreamer &Streamer) const; + // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. + virtual MCSymbol * + getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI) const; + virtual unsigned getPersonalityEncoding() const; virtual unsigned getLSDAEncoding() const; - virtual unsigned getFDEEncoding() const; + virtual unsigned getFDEEncoding(bool CFI) const; virtual unsigned getTTypeEncoding() const; }; diff --git a/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h b/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h index e1eea325e348..951aff6f938d 100644 --- a/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h +++ b/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h @@ -40,7 +40,7 @@ namespace llvmc { }; /// Edge - Represents an edge of the compilation graph. - class Edge : public llvm::RefCountedBaseVPTR { + class Edge : public llvm::RefCountedBaseVPTR { public: Edge(const std::string& T) : ToolName_(T) {} virtual ~Edge() {} diff --git a/contrib/llvm/include/llvm/CompilerDriver/Tool.h b/contrib/llvm/include/llvm/CompilerDriver/Tool.h index d0926ba98312..18a2b767923e 100644 --- a/contrib/llvm/include/llvm/CompilerDriver/Tool.h +++ b/contrib/llvm/include/llvm/CompilerDriver/Tool.h @@ -33,7 +33,7 @@ namespace llvmc { typedef llvm::StringSet<> InputLanguagesSet; /// Tool - Represents a single tool. - class Tool : public llvm::RefCountedBaseVPTR { + class Tool : public llvm::RefCountedBaseVPTR { public: virtual ~Tool() {} diff --git a/contrib/llvm/include/llvm/Constant.h b/contrib/llvm/include/llvm/Constant.h index 38045fc0c1d6..5f32ce0ac5e2 100644 --- a/contrib/llvm/include/llvm/Constant.h +++ b/contrib/llvm/include/llvm/Constant.h @@ -47,10 +47,6 @@ class Constant : public User { : User(ty, vty, Ops, NumOps) {} void destroyConstantImpl(); - - void setOperand(unsigned i, Value *V) { - User::setOperand(i, V); - } public: /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. @@ -90,15 +86,6 @@ class Constant : public User { /// FIXME: This really should not be in VMCore. PossibleRelocationsTy getRelocationInfo() const; - // Specialize get/setOperand for Users as their operands are always - // constants or BasicBlocks as well. - User *getOperand(unsigned i) { - return static_cast(User::getOperand(i)); - } - const User *getOperand(unsigned i) const { - return static_cast(User::getOperand(i)); - } - /// getVectorElements - This method, which is only valid on constant of vector /// type, returns the elements of the vector in the specified smallvector. /// This handles breaking down a vector undef into undef elements, etc. For diff --git a/contrib/llvm/include/llvm/Constants.h b/contrib/llvm/include/llvm/Constants.h index c4768f842345..eabc3a50aa0a 100644 --- a/contrib/llvm/include/llvm/Constants.h +++ b/contrib/llvm/include/llvm/Constants.h @@ -57,6 +57,8 @@ class ConstantInt : public Constant { public: static ConstantInt *getTrue(LLVMContext &Context); static ConstantInt *getFalse(LLVMContext &Context); + static Constant *getTrue(const Type *Ty); + static Constant *getFalse(const 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. @@ -425,6 +427,8 @@ class ConstantStruct : public Constant { const std::vector &V, bool Packed); static Constant *get(LLVMContext &Context, Constant *const *Vals, unsigned NumVals, bool Packed); + static Constant *get(LLVMContext &Context, bool Packed, + Constant * Val, ...) END_WITH_NULL; /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -599,6 +603,7 @@ struct OperandTraits : DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(BlockAddress, Value) + //===----------------------------------------------------------------------===// /// ConstantExpr - a constant value that is initialized with an expression using /// other constant values. @@ -836,7 +841,7 @@ class ConstantExpr : public Constant { static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS); static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS); - /// Getelementptr form. std::vector is only accepted for convenience: + /// Getelementptr form. Value* is only accepted for convenience; /// all elements must be Constant's. /// static Constant *getGetElementPtr(Constant *C, @@ -880,7 +885,7 @@ class ConstantExpr : public Constant { /// getIndices - Assert that this is an insertvalue or exactvalue /// expression and return the list of indices. - const SmallVector &getIndices() const; + ArrayRef getIndices() const; /// getOpcodeName - Return a string representation for an opcode. const char *getOpcodeName() const; @@ -892,10 +897,7 @@ class ConstantExpr : public Constant { /// getWithOperands - This returns the current constant expression with the /// operands replaced with the specified values. The specified operands must /// match count and type with the existing ones. - Constant *getWithOperands(const std::vector &Ops) const { - return getWithOperands(&Ops[0], (unsigned)Ops.size()); - } - Constant *getWithOperands(Constant *const *Ops, unsigned NumOps) const; + Constant *getWithOperands(ArrayRef Ops) const; virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); diff --git a/contrib/llvm/include/llvm/DebugInfoProbe.h b/contrib/llvm/include/llvm/DebugInfoProbe.h new file mode 100644 index 000000000000..78d00dfeeddf --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfoProbe.h @@ -0,0 +1,67 @@ +//===-- DebugInfoProbe.h - DebugInfo Probe ----------------------*- 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 probe, DebugInfoProbe, that can be used by pass +// manager to analyze how optimizer is treating debugging information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_DEBUGINFOPROBE_H +#define LLVM_TRANSFORMS_UTILS_DEBUGINFOPROBE_H + +#include "llvm/ADT/StringMap.h" + +namespace llvm { + class Function; + class Pass; + class DebugInfoProbeImpl; + + /// DebugInfoProbe - This class provides a interface to monitor + /// how an optimization pass is preserving debugging information. + class DebugInfoProbe { + public: + DebugInfoProbe(); + ~DebugInfoProbe(); + + /// initialize - Collect information before running an optimization pass. + void initialize(StringRef PName, Function &F); + + /// finalize - Collect information after running an optimization pass. This + /// must be used after initialization. + void finalize(Function &F); + + /// report - Report findings. This should be invoked after finalize. + void report(); + + private: + DebugInfoProbeImpl *pImpl; + }; + + /// DebugInfoProbeInfo - This class provides an interface that a pass manager + /// can use to manage debug info probes. + class DebugInfoProbeInfo { + StringMap Probes; + public: + DebugInfoProbeInfo() {} + + /// ~DebugInfoProbeInfo - Report data collected by all probes before deleting + /// them. + ~DebugInfoProbeInfo(); + + /// initialize - Collect information before running an optimization pass. + void initialize(Pass *P, Function &F); + + /// finalize - Collect information after running an optimization pass. This + /// must be used after initialization. + void finalize(Pass *P, Function &F); + }; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/DerivedTypes.h b/contrib/llvm/include/llvm/DerivedTypes.h index 56d1e3e237d6..f1cb33039f81 100644 --- a/contrib/llvm/include/llvm/DerivedTypes.h +++ b/contrib/llvm/include/llvm/DerivedTypes.h @@ -19,6 +19,7 @@ #define LLVM_DERIVED_TYPES_H #include "llvm/Type.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -147,7 +148,7 @@ class FunctionType : public DerivedType { FunctionType(const FunctionType &); // Do not implement const FunctionType &operator=(const FunctionType &); // Do not implement - FunctionType(const Type *Result, const std::vector &Params, + FunctionType(const Type *Result, ArrayRef Params, bool IsVarArgs); public: @@ -156,7 +157,7 @@ class FunctionType : public DerivedType { /// static FunctionType *get( const Type *Result, ///< The result type - const std::vector &Params, ///< The types of the parameters + ArrayRef Params, ///< The types of the parameters bool isVarArg ///< Whether this is a variable argument length function ); @@ -166,7 +167,7 @@ class FunctionType : public DerivedType { const Type *Result, ///< The result type bool isVarArg ///< Whether this is a variable argument length function ) { - return get(Result, std::vector(), isVarArg); + return get(Result, ArrayRef(), isVarArg); } /// isValidReturnType - Return true if the specified type is valid as a return @@ -237,20 +238,19 @@ class StructType : public CompositeType { friend class TypeMap; StructType(const StructType &); // Do not implement const StructType &operator=(const StructType &); // Do not implement - StructType(LLVMContext &C, - const std::vector &Types, bool isPacked); + StructType(LLVMContext &C, ArrayRef Types, bool isPacked); public: /// StructType::get - This static method is the primary way to create a /// StructType. /// static StructType *get(LLVMContext &Context, - const std::vector &Params, + ArrayRef Params, bool isPacked=false); /// StructType::get - Create an empty structure type. /// static StructType *get(LLVMContext &Context, bool isPacked=false) { - return get(Context, std::vector(), isPacked); + return get(Context, llvm::ArrayRef(), isPacked); } /// StructType::get - This static method is a convenience method for diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h index 71698fa00874..a01ad3ae7755 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -21,6 +21,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/Mutex.h" #include "llvm/Target/TargetMachine.h" @@ -117,11 +118,11 @@ class ExecutionEngine { /// The list of Modules that we are JIT'ing from. We use a SmallVector to /// optimize for the case where there is only one module. SmallVector Modules; - + void setTargetData(const TargetData *td) { TD = td; } - + /// getMemoryforGV - Allocate memory for a global variable. virtual char *getMemoryForGV(const GlobalVariable *GV); @@ -155,13 +156,15 @@ class ExecutionEngine { /// pointer is invoked to create it. If this returns null, the JIT will /// abort. void *(*LazyFunctionCreator)(const std::string &); - + /// ExceptionTableRegister - If Exception Handling is set, the JIT will /// register dwarf tables with this function. typedef void (*EERegisterFn)(void*); EERegisterFn ExceptionTableRegister; EERegisterFn ExceptionTableDeregister; - std::vector AllExceptionTables; + /// This maps functions to their exception tables frames. + DenseMap AllExceptionTables; + public: /// lock - This lock protects the ExecutionEngine, JIT, JITResolver and @@ -182,7 +185,7 @@ class ExecutionEngine { /// \param GVsWithCode - Allocating globals with code breaks /// freeMachineCodeForFunction and is probably unsafe and bad for performance. /// However, we have clients who depend on this behavior, so we must support - /// it. Eventually, when we're willing to break some backwards compatability, + /// it. Eventually, when we're willing to break some backwards compatibility, /// this flag should be flipped to false, so that by default /// freeMachineCodeForFunction works. static ExecutionEngine *create(Module *M, @@ -213,7 +216,7 @@ class ExecutionEngine { virtual void addModule(Module *M) { Modules.push_back(M); } - + //===--------------------------------------------------------------------===// const TargetData *getTargetData() const { return TD; } @@ -226,7 +229,7 @@ class ExecutionEngine { /// defines FnName. This is very slow operation and shouldn't be used for /// general code. Function *FindFunctionNamed(const char *FnName); - + /// runFunction - Execute the specified function with the specified arguments, /// and return the result. virtual GenericValue runFunction(Function *F, @@ -243,8 +246,8 @@ class ExecutionEngine { /// /// \param isDtors - Run the destructors instead of constructors. void runStaticConstructorsDestructors(Module *module, bool isDtors); - - + + /// runFunctionAsMain - This is a helper function which wraps runFunction to /// handle the common task of starting up main with the specified argc, argv, /// and envp parameters. @@ -259,21 +262,21 @@ class ExecutionEngine { /// existing data in memory. Mappings are automatically removed when their /// GlobalValue is destroyed. void addGlobalMapping(const GlobalValue *GV, void *Addr); - + /// clearAllGlobalMappings - Clear all global mappings and start over again, /// for use in dynamic compilation scenarios to move globals. void clearAllGlobalMappings(); - + /// clearGlobalMappingsFromModule - Clear all global mappings that came from a /// particular module, because it has been removed from the JIT. void clearGlobalMappingsFromModule(Module *M); - + /// updateGlobalMapping - Replace an existing mapping for GV with a new /// address. This updates both maps as required. If "Addr" is null, the /// entry for the global is removed from the mappings. This returns the old /// value of the pointer, or null if it was not in the map. void *updateGlobalMapping(const GlobalValue *GV, void *Addr); - + /// getPointerToGlobalIfAvailable - This returns the address of the specified /// global value if it is has already been codegen'd, otherwise it returns /// null. @@ -294,7 +297,7 @@ class ExecutionEngine { /// different ways. Return the representation for a blockaddress of the /// specified block. virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0; - + /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use /// a stub to implement lazy compilation if available. See @@ -398,7 +401,7 @@ class ExecutionEngine { void InstallLazyFunctionCreator(void* (*P)(const std::string &)) { LazyFunctionCreator = P; } - + /// InstallExceptionTableRegister - The JIT will use the given function /// to register the exception tables it generates. void InstallExceptionTableRegister(EERegisterFn F) { @@ -407,13 +410,26 @@ class ExecutionEngine { void InstallExceptionTableDeregister(EERegisterFn F) { ExceptionTableDeregister = F; } - + /// RegisterTable - Registers the given pointer as an exception table. It /// uses the ExceptionTableRegister function. - void RegisterTable(void* res) { + void RegisterTable(const Function *fn, void* res) { if (ExceptionTableRegister) { ExceptionTableRegister(res); - AllExceptionTables.push_back(res); + AllExceptionTables[fn] = res; + } + } + + /// DeregisterTable - Deregisters the exception frame previously registered + /// for the given function. + void DeregisterTable(const Function *Fn) { + if (ExceptionTableDeregister) { + DenseMap::iterator frame = + AllExceptionTables.find(Fn); + if(frame != AllExceptionTables.end()) { + ExceptionTableDeregister(frame->second); + AllExceptionTables.erase(frame); + } } } @@ -429,7 +445,7 @@ class ExecutionEngine { void EmitGlobalVariable(const GlobalVariable *GV); GenericValue getConstantValue(const Constant *C); - void LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, + void LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, const Type *Ty); }; @@ -540,8 +556,9 @@ class EngineBuilder { /// setUseMCJIT - Set whether the MC-JIT implementation should be used /// (experimental). - void setUseMCJIT(bool Value) { + EngineBuilder &setUseMCJIT(bool Value) { UseMCJIT = Value; + return *this; } /// setMAttrs - Set cpu-specific attributes. diff --git a/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h b/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h index 384141801667..a63f0da773a2 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -29,11 +29,11 @@ class JITMemoryManager { public: JITMemoryManager() : HasGOT(false) {} virtual ~JITMemoryManager(); - + /// CreateDefaultMemManager - This is used to create the default /// JIT Memory Manager if the client does not provide one to the JIT. static JITMemoryManager *CreateDefaultMemManager(); - + /// setMemoryWritable - When code generation is in progress, /// the code pages may need permissions changed. virtual void setMemoryWritable() = 0; @@ -55,16 +55,16 @@ class JITMemoryManager { /// method is invoked to allocate it. This method is required to set HasGOT /// to true. virtual void AllocateGOT() = 0; - + /// isManagingGOT - Return true if the AllocateGOT method is called. bool isManagingGOT() const { return HasGOT; } - + /// getGOTBase - If this is managing a Global Offset Table, this method should /// return a pointer to its base. virtual uint8_t *getGOTBase() const = 0; - + //===--------------------------------------------------------------------===// // Main Allocation Functions //===--------------------------------------------------------------------===// @@ -91,11 +91,11 @@ class JITMemoryManager { /// startFunctionBody. virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, unsigned Alignment) = 0; - + /// endFunctionBody - This method is called when the JIT is done codegen'ing /// the specified function. At this point we know the size of the JIT /// compiled function. This passes in FunctionStart (which was returned by - /// the startFunctionBody method) and FunctionEnd which is a pointer to the + /// the startFunctionBody method) and FunctionEnd which is a pointer to the /// actual end of the function. This method should mark the space allocated /// and remember where it is in case the client wants to deallocate it. virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, @@ -113,12 +113,12 @@ class JITMemoryManager { /// been deallocated yet. This is never called when the JIT is currently /// emitting a function. virtual void deallocateFunctionBody(void *Body) = 0; - + /// startExceptionTable - When we finished JITing the function, if exception /// handling is set, we emit the exception table. virtual uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) = 0; - + /// endExceptionTable - This method is called when the JIT is done emitting /// the exception table. virtual void endExceptionTable(const Function *F, uint8_t *TableStart, diff --git a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h new file mode 100644 index 000000000000..3dc65e33d4e8 --- /dev/null +++ b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -0,0 +1,75 @@ +//===-- RuntimeDyld.h - Run-time dynamic linker for MC-JIT ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface for the runtime dynamic linker facilities of the MC-JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_RUNTIME_DYLD_H +#define LLVM_RUNTIME_DYLD_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Memory.h" + +namespace llvm { + +class RuntimeDyldImpl; +class MemoryBuffer; + +// 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. +// 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 +public: + RTDyldMemoryManager() {} + virtual ~RTDyldMemoryManager(); + + // Allocate ActualSize bytes, or more, for the named function. Return + // a pointer to the allocated memory and update Size to reflect how much + // memory was acutally allocated. + virtual uint8_t *startFunctionBody(const char *Name, uintptr_t &Size) = 0; + + // Mark the end of the function, including how much of the allocated + // memory was actually used. + virtual void endFunctionBody(const char *Name, uint8_t *FunctionStart, + uint8_t *FunctionEnd) = 0; +}; + +class RuntimeDyld { + RuntimeDyld(const RuntimeDyld &); // DO NOT IMPLEMENT + void operator=(const RuntimeDyld &); // DO NOT IMPLEMENT + + // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public + // interface. + RuntimeDyldImpl *Dyld; +public: + RuntimeDyld(RTDyldMemoryManager*); + ~RuntimeDyld(); + + bool loadObject(MemoryBuffer *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 + // and resolve relocatons based on where they put it). + void *getSymbolAddress(StringRef Name); + // Resolve the relocations for all symbols we currently know about. + void resolveRelocations(); + // Change the address associated with a symbol when resolving relocations. + // Any relocations already associated with the symbol will be re-resolved. + void reassignSymbolAddress(StringRef Name, uint8_t *Addr); + StringRef getErrorString(); +}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/GlobalVariable.h b/contrib/llvm/include/llvm/GlobalVariable.h index 1769c665d062..442e0c0e1b20 100644 --- a/contrib/llvm/include/llvm/GlobalVariable.h +++ b/contrib/llvm/include/llvm/GlobalVariable.h @@ -12,7 +12,7 @@ // // Global variables are constant pointers that refer to hunks of space that are // allocated by either the VM, or by the linker in a static compiler. A global -// variable may have an intial value, which is copied into the executables .data +// variable may have an initial value, which is copied into the executables .data // area. Global Constants are required to have initializers. // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/InitializePasses.h b/contrib/llvm/include/llvm/InitializePasses.h index 02dbfbd26d58..cca0194a60eb 100644 --- a/contrib/llvm/include/llvm/InitializePasses.h +++ b/contrib/llvm/include/llvm/InitializePasses.h @@ -94,12 +94,12 @@ void initializeDominatorTreePass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); void initializeEdgeProfilerPass(PassRegistry&); void initializePathProfilerPass(PassRegistry&); +void initializeGCOVProfilerPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFindUsedTypesPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); -void initializeGEPSplitterPass(PassRegistry&); void initializeGVNPass(PassRegistry&); void initializeGlobalDCEPass(PassRegistry&); void initializeGlobalOptPass(PassRegistry&); @@ -123,7 +123,6 @@ void initializeLintPass(PassRegistry&); void initializeLiveDebugVariablesPass(PassRegistry&); void initializeLiveIntervalsPass(PassRegistry&); void initializeLiveStacksPass(PassRegistry&); -void initializeLiveValuesPass(PassRegistry&); void initializeLiveVariablesPass(PassRegistry&); void initializeLoaderPassPass(PassRegistry&); void initializePathProfileLoaderPassPass(PassRegistry&); @@ -170,7 +169,6 @@ void initializePostDomOnlyPrinterPass(PassRegistry&); void initializePostDomOnlyViewerPass(PassRegistry&); void initializePostDomPrinterPass(PassRegistry&); void initializePostDomViewerPass(PassRegistry&); -void initializePostDominanceFrontierPass(PassRegistry&); void initializePostDominatorTreePass(PassRegistry&); void initializePreAllocSplittingPass(PassRegistry&); void initializePreVerifierPass(PassRegistry&); @@ -196,14 +194,12 @@ void initializeRegionViewerPass(PassRegistry&); void initializeRegisterCoalescerAnalysisGroup(PassRegistry&); void initializeRenderMachineFunctionPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); -void initializeSRETPromotionPass(PassRegistry&); void initializeSROA_DTPass(PassRegistry&); void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); void initializeSimpleRegisterCoalescingPass(PassRegistry&); -void initializeSimplifyHalfPowrLibCallsPass(PassRegistry&); void initializeSimplifyLibCallsPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); diff --git a/contrib/llvm/include/llvm/InstrTypes.h b/contrib/llvm/include/llvm/InstrTypes.h index a166956e1a64..cc9ec3ac76e1 100644 --- a/contrib/llvm/include/llvm/InstrTypes.h +++ b/contrib/llvm/include/llvm/InstrTypes.h @@ -18,7 +18,6 @@ #include "llvm/Instruction.h" #include "llvm/OperandTraits.h" -#include "llvm/Operator.h" #include "llvm/DerivedTypes.h" #include "llvm/ADT/Twine.h" diff --git a/contrib/llvm/include/llvm/Instructions.h b/contrib/llvm/include/llvm/Instructions.h index 17ff763c52bf..54dfe3957fff 100644 --- a/contrib/llvm/include/llvm/Instructions.h +++ b/contrib/llvm/include/llvm/Instructions.h @@ -584,7 +584,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) /// @brief Represent an integer comparison operator. class ICmpInst: public CmpInst { protected: - /// @brief Clone an indentical ICmpInst + /// @brief Clone an identical ICmpInst virtual ICmpInst *clone_impl() const; public: /// @brief Constructor with insert-before-instruction semantics. @@ -735,7 +735,7 @@ class ICmpInst: public CmpInst { /// @brief Represents a floating point comparison operator. class FCmpInst: public CmpInst { protected: - /// @brief Clone an indentical FCmpInst + /// @brief Clone an identical FCmpInst virtual FCmpInst *clone_impl() const; public: /// @brief Constructor with insert-before-instruction semantics. @@ -1811,39 +1811,37 @@ class PHINode : public Instruction { void *operator new(size_t s) { return User::operator new(s, 0); } - explicit PHINode(const Type *Ty, const Twine &NameStr = "", - Instruction *InsertBefore = 0) + explicit PHINode(const Type *Ty, unsigned NumReservedValues, + const Twine &NameStr = "", Instruction *InsertBefore = 0) : Instruction(Ty, Instruction::PHI, 0, 0, InsertBefore), - ReservedSpace(0) { + ReservedSpace(NumReservedValues * 2) { setName(NameStr); + OperandList = allocHungoffUses(ReservedSpace); } - PHINode(const Type *Ty, const Twine &NameStr, BasicBlock *InsertAtEnd) + PHINode(const Type *Ty, unsigned NumReservedValues, const Twine &NameStr, + BasicBlock *InsertAtEnd) : Instruction(Ty, Instruction::PHI, 0, 0, InsertAtEnd), - ReservedSpace(0) { + ReservedSpace(NumReservedValues * 2) { setName(NameStr); + OperandList = allocHungoffUses(ReservedSpace); } protected: virtual PHINode *clone_impl() const; public: - static PHINode *Create(const Type *Ty, const Twine &NameStr = "", + /// Constructors - NumReservedValues is a hint for the number of incoming + /// edges that this phi node will have (use 0 if you really have no idea). + static PHINode *Create(const Type *Ty, unsigned NumReservedValues, + const Twine &NameStr = "", Instruction *InsertBefore = 0) { - return new PHINode(Ty, NameStr, InsertBefore); + return new PHINode(Ty, NumReservedValues, NameStr, InsertBefore); } - static PHINode *Create(const Type *Ty, const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new PHINode(Ty, NameStr, InsertAtEnd); + static PHINode *Create(const Type *Ty, unsigned NumReservedValues, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd); } ~PHINode(); - /// reserveOperandSpace - This method can be used to avoid repeated - /// reallocation of PHI operand lists by reserving space for the correct - /// number of operands before adding them. Unlike normal vector reserves, - /// this method can also be used to trim the operand space. - void reserveOperandSpace(unsigned NumValues) { - resizeOperands(NumValues*2); - } - /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -1912,7 +1910,7 @@ class PHINode : public Instruction { "All operands to PHI node must be the same type as the PHI node!"); unsigned OpNo = NumOperands; if (OpNo+2 > ReservedSpace) - resizeOperands(0); // Get more space! + growOperands(); // Get more space! // Initialize some new operands. NumOperands = OpNo+2; OperandList[OpNo] = V; @@ -1962,7 +1960,7 @@ class PHINode : public Instruction { return isa(V) && classof(cast(V)); } private: - void resizeOperands(unsigned NumOperands); + void growOperands(); }; template <> @@ -2154,7 +2152,7 @@ class SwitchInst : public TerminatorInst { // Operand[2n+1] = BasicBlock to go to on match SwitchInst(const SwitchInst &SI); void init(Value *Value, BasicBlock *Default, unsigned NumReserved); - void resizeOperands(unsigned No); + void growOperands(); // allocate space for exactly zero operands void *operator new(size_t s) { return User::operator new(s, 0); @@ -2306,7 +2304,7 @@ class IndirectBrInst : public TerminatorInst { // Operand[2n+1] = BasicBlock to go to on match IndirectBrInst(const IndirectBrInst &IBI); void init(Value *Address, unsigned NumDests); - void resizeOperands(unsigned No); + void growOperands(); // allocate space for exactly zero operands void *operator new(size_t s) { return User::operator new(s, 0); diff --git a/contrib/llvm/include/llvm/Intrinsics.td b/contrib/llvm/include/llvm/Intrinsics.td index 0c9be78b0d10..a63cd6ab600e 100644 --- a/contrib/llvm/include/llvm/Intrinsics.td +++ b/contrib/llvm/include/llvm/Intrinsics.td @@ -30,7 +30,7 @@ class IntrinsicProperty; def IntrNoMem : IntrinsicProperty; // IntrReadArgMem - This intrinsic reads only from memory that one of its -// arguments points to, but may read an unspecified amount. +// pointer-typed arguments points to, but may read an unspecified amount. def IntrReadArgMem : IntrinsicProperty; // IntrReadMem - This intrinsic reads from unspecified memory, so it cannot be @@ -307,7 +307,7 @@ let Properties = [IntrNoMem] in { def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>; def int_eh_sjlj_callsite: Intrinsic<[], [llvm_i32_ty]>; } -def int_eh_sjlj_dispatch_setup : Intrinsic<[], [llvm_ptr_ty]>; +def int_eh_sjlj_dispatch_setup : Intrinsic<[], []>; def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty]>; @@ -490,3 +490,4 @@ include "llvm/IntrinsicsARM.td" include "llvm/IntrinsicsCellSPU.td" include "llvm/IntrinsicsAlpha.td" include "llvm/IntrinsicsXCore.td" +include "llvm/IntrinsicsPTX.td" diff --git a/contrib/llvm/include/llvm/IntrinsicsARM.td b/contrib/llvm/include/llvm/IntrinsicsARM.td index 546538a57abd..03e9261e60cb 100644 --- a/contrib/llvm/include/llvm/IntrinsicsARM.td +++ b/contrib/llvm/include/llvm/IntrinsicsARM.td @@ -1,10 +1,10 @@ //===- 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. @@ -129,8 +129,12 @@ let Properties = [IntrNoMem, Commutative] in { 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; diff --git a/contrib/llvm/include/llvm/IntrinsicsPTX.td b/contrib/llvm/include/llvm/IntrinsicsPTX.td new file mode 100644 index 000000000000..28379c918dea --- /dev/null +++ b/contrib/llvm/include/llvm/IntrinsicsPTX.td @@ -0,0 +1,92 @@ +//===- IntrinsicsPTX.td - Defines PTX 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 PTX-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "ptx" in { + multiclass PTXReadSpecialRegisterIntrinsic_v4i32 { +// FIXME: Do we need the 128-bit integer type version? +// def _r64 : Intrinsic<[llvm_i128_ty], [], [IntrNoMem]>; + +// FIXME: Enable this once v4i32 support is enabled in back-end. +// def _v4i16 : Intrinsic<[llvm_v4i32_ty], [], [IntrNoMem]>; + + def _x : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin; + def _y : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin; + def _z : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin; + def _w : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin; + } + + class PTXReadSpecialRegisterIntrinsic_r32 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin; + + class PTXReadSpecialRegisterIntrinsic_r64 + : Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>, + GCCBuiltin; +} + +defm int_ptx_read_tid : PTXReadSpecialRegisterIntrinsic_v4i32 + <"__builtin_ptx_read_tid">; +defm int_ptx_read_ntid : PTXReadSpecialRegisterIntrinsic_v4i32 + <"__builtin_ptx_read_ntid">; + +def int_ptx_read_laneid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_laneid">; +def int_ptx_read_warpid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_warpid">; +def int_ptx_read_nwarpid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_nwarpid">; + +defm int_ptx_read_ctaid : PTXReadSpecialRegisterIntrinsic_v4i32 + <"__builtin_ptx_read_ctaid">; +defm int_ptx_read_nctaid : PTXReadSpecialRegisterIntrinsic_v4i32 + <"__builtin_ptx_read_nctaid">; + +def int_ptx_read_smid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_smid">; +def int_ptx_read_nsmid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_nsmid">; +def int_ptx_read_gridid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_gridid">; + +def int_ptx_read_lanemask_eq : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_eq">; +def int_ptx_read_lanemask_le : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_le">; +def int_ptx_read_lanemask_lt : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_lt">; +def int_ptx_read_lanemask_ge : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_ge">; +def int_ptx_read_lanemask_gt : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_gt">; + +def int_ptx_read_clock : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_clock">; +def int_ptx_read_clock64 : PTXReadSpecialRegisterIntrinsic_r64 + <"__builtin_ptx_read_clock64">; + +def int_ptx_read_pm0 : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_pm0">; +def int_ptx_read_pm1 : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_pm1">; +def int_ptx_read_pm2 : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_pm2">; +def int_ptx_read_pm3 : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_pm3">; + +let TargetPrefix = "ptx" in + def int_ptx_bar_sync : Intrinsic<[], [llvm_i32_ty], []>, + GCCBuiltin<"__builtin_ptx_bar_sync">; diff --git a/contrib/llvm/include/llvm/IntrinsicsX86.td b/contrib/llvm/include/llvm/IntrinsicsX86.td index 49462200f093..b44101a11c07 100644 --- a/contrib/llvm/include/llvm/IntrinsicsX86.td +++ b/contrib/llvm/include/llvm/IntrinsicsX86.td @@ -17,6 +17,83 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_int : Intrinsic<[], [llvm_i8_ty]>; } +//===----------------------------------------------------------------------===// +// 3DNow! + +let TargetPrefix = "x86" in { + def int_x86_3dnow_pavgusb : GCCBuiltin<"__builtin_ia32_pavgusb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pf2id : GCCBuiltin<"__builtin_ia32_pf2id">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pfacc : GCCBuiltin<"__builtin_ia32_pfacc">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfadd : GCCBuiltin<"__builtin_ia32_pfadd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfcmpeq : GCCBuiltin<"__builtin_ia32_pfcmpeq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfcmpge : GCCBuiltin<"__builtin_ia32_pfcmpge">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfcmpgt : GCCBuiltin<"__builtin_ia32_pfcmpgt">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfmax : GCCBuiltin<"__builtin_ia32_pfmax">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfmin : GCCBuiltin<"__builtin_ia32_pfmin">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfmul : GCCBuiltin<"__builtin_ia32_pfmul">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfrcp : GCCBuiltin<"__builtin_ia32_pfrcp">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pfrcpit1 : GCCBuiltin<"__builtin_ia32_pfrcpit1">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfrcpit2 : GCCBuiltin<"__builtin_ia32_pfrcpit2">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfrsqrt : GCCBuiltin<"__builtin_ia32_pfrsqrt">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pfrsqit1 : GCCBuiltin<"__builtin_ia32_pfrsqit1">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfsub : GCCBuiltin<"__builtin_ia32_pfsub">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfsubr : GCCBuiltin<"__builtin_ia32_pfsubr">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pi2fd : GCCBuiltin<"__builtin_ia32_pi2fd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pmulhrw : GCCBuiltin<"__builtin_ia32_pmulhrw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// 3DNow! extensions + +let TargetPrefix = "x86" in { + def int_x86_3dnowa_pf2iw : GCCBuiltin<"__builtin_ia32_pf2iw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnowa_pfnacc : GCCBuiltin<"__builtin_ia32_pfnacc">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnowa_pfpnacc : GCCBuiltin<"__builtin_ia32_pfpnacc">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnowa_pi2fw : GCCBuiltin<"__builtin_ia32_pi2fw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnowa_pswapd : + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; +} + //===----------------------------------------------------------------------===// // SSE1 @@ -138,12 +215,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_x86mmx_ty], [IntrNoMem]>; } -// SIMD load ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_loadu_ps : GCCBuiltin<"__builtin_ia32_loadups">, - Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadMem]>; -} - // SIMD store ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">, @@ -452,14 +523,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v2f64_ty], [llvm_x86mmx_ty], [IntrNoMem]>; } -// SIMD load ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_loadu_pd : GCCBuiltin<"__builtin_ia32_loadupd">, - Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadMem]>; - def int_x86_sse2_loadu_dq : GCCBuiltin<"__builtin_ia32_loaddqu">, - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; -} - // SIMD store ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">, @@ -921,68 +984,68 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // String/text processing ops. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse42_pcmpistrm128 : GCCBuiltin<"__builtin_ia32_pcmpistrm128">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistri128 : GCCBuiltin<"__builtin_ia32_pcmpistri128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistria128 : GCCBuiltin<"__builtin_ia32_pcmpistria128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistric128 : GCCBuiltin<"__builtin_ia32_pcmpistric128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistrio128 : GCCBuiltin<"__builtin_ia32_pcmpistrio128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistris128 : GCCBuiltin<"__builtin_ia32_pcmpistris128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistriz128 : GCCBuiltin<"__builtin_ia32_pcmpistriz128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestrm128 : GCCBuiltin<"__builtin_ia32_pcmpestrm128">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestri128 : GCCBuiltin<"__builtin_ia32_pcmpestri128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestria128 : GCCBuiltin<"__builtin_ia32_pcmpestria128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestric128 : GCCBuiltin<"__builtin_ia32_pcmpestric128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestrio128 : GCCBuiltin<"__builtin_ia32_pcmpestrio128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestris128 : GCCBuiltin<"__builtin_ia32_pcmpestris128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestriz128 : GCCBuiltin<"__builtin_ia32_pcmpestriz128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -1571,14 +1634,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[], [llvm_ptrx86mmx_ty, llvm_x86mmx_ty], []>; def int_x86_mmx_palignr_b : GCCBuiltin<"__builtin_ia32_palignr">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_mmx_pextr_w : GCCBuiltin<"__builtin_ia32_vec_ext_v4hi">, - Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty, llvm_i32_ty], + Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_mmx_pinsr_w : GCCBuiltin<"__builtin_ia32_vec_set_v4hi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; } diff --git a/contrib/llvm/include/llvm/IntrinsicsXCore.td b/contrib/llvm/include/llvm/IntrinsicsXCore.td index 944120fc8c6e..e633af045c33 100644 --- a/contrib/llvm/include/llvm/IntrinsicsXCore.td +++ b/contrib/llvm/include/llvm/IntrinsicsXCore.td @@ -9,8 +9,13 @@ //===----------------------------------------------------------------------===// let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". + // Miscellaneous instructions. def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>; def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>; + def int_xcore_getps : Intrinsic<[llvm_i32_ty],[llvm_i32_ty]>; + def int_xcore_setps : Intrinsic<[],[llvm_i32_ty, llvm_i32_ty]>; + def int_xcore_setsr : Intrinsic<[],[llvm_i32_ty]>; + def int_xcore_clrsr : Intrinsic<[],[llvm_i32_ty]>; // Resource instructions. def int_xcore_getr : Intrinsic<[llvm_anyptr_ty],[llvm_i32_ty]>; @@ -48,8 +53,37 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". def int_xcore_setv : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], [NoCapture<0>]>; def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>; + def int_xcore_setclk : Intrinsic<[],[llvm_anyptr_ty, llvm_anyptr_ty], + [NoCapture<0>, NoCapture<1>]>; + def int_xcore_setrdy : Intrinsic<[],[llvm_anyptr_ty, llvm_anyptr_ty], + [NoCapture<0>, NoCapture<1>]>; + def int_xcore_setpsc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; // Intrinsics for events. def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>; + + // If any of the resources owned by the thread are ready this returns the + // vector of one of the ready resources. If no resources owned by the thread + // are ready then the operand passed to the intrinsic is returned. + def int_xcore_checkevent : Intrinsic<[llvm_ptr_ty],[llvm_ptr_ty]>; + def int_xcore_clre : Intrinsic<[],[],[]>; + + // Intrinsics for threads. + def int_xcore_getst : Intrinsic <[llvm_anyptr_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_msync : Intrinsic <[],[llvm_anyptr_ty], [NoCapture<0>]>; + def int_xcore_ssync : Intrinsic <[],[]>; + def int_xcore_mjoin : Intrinsic <[],[llvm_anyptr_ty], [NoCapture<0>]>; + def int_xcore_initsp : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_initpc : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_initlr : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_initcp : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_initdp : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; } diff --git a/contrib/llvm/include/llvm/LinkAllPasses.h b/contrib/llvm/include/llvm/LinkAllPasses.h index 69e1bd919f74..88ee65ac311a 100644 --- a/contrib/llvm/include/llvm/LinkAllPasses.h +++ b/contrib/llvm/include/llvm/LinkAllPasses.h @@ -49,7 +49,6 @@ namespace { (void) llvm::createAliasAnalysisCounterPass(); (void) llvm::createAliasDebugger(); (void) llvm::createArgumentPromotionPass(); - (void) llvm::createStructRetPromotionPass(); (void) llvm::createBasicAliasAnalysisPass(); (void) llvm::createLibCallAliasAnalysisPass(0); (void) llvm::createScalarEvolutionAliasAnalysisPass(); @@ -71,6 +70,7 @@ namespace { (void) llvm::createEdgeProfilerPass(); (void) llvm::createOptimalEdgeProfilerPass(); (void) llvm::createPathProfilerPass(); + (void) llvm::createGCOVProfilerPass(true, true); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); (void) llvm::createGlobalDCEPass(); @@ -84,7 +84,6 @@ namespace { (void) llvm::createLCSSAPass(); (void) llvm::createLICMPass(); (void) llvm::createLazyValueInfoPass(); - (void) llvm::createLiveValuesPass(); (void) llvm::createLoopDependenceAnalysisPass(); (void) llvm::createLoopExtractorPass(); (void) llvm::createLoopSimplifyPass(); @@ -119,7 +118,6 @@ namespace { (void) llvm::createSCCPPass(); (void) llvm::createScalarReplAggregatesPass(); (void) llvm::createSimplifyLibCallsPass(); - (void) llvm::createSimplifyHalfPowrLibCallsPass(); (void) llvm::createSingleLoopExtractorPass(); (void) llvm::createStripSymbolsPass(); (void) llvm::createStripNonDebugSymbolsPass(); @@ -136,7 +134,6 @@ namespace { (void) llvm::createMemCpyOptPass(); (void) llvm::createLoopDeletionPass(); (void) llvm::createPostDomTree(); - (void) llvm::createPostDomFrontier(); (void) llvm::createInstructionNamerPass(); (void) llvm::createFunctionAttrsPass(); (void) llvm::createMergeFunctionsPass(); @@ -145,7 +142,6 @@ namespace { (void) llvm::createDbgInfoPrinterPass(); (void) llvm::createModuleDebugInfoPrinterPass(); (void) llvm::createPartialInliningPass(); - (void) llvm::createGEPSplitterPass(); (void) llvm::createLintPass(); (void) llvm::createSinkingPass(); (void) llvm::createLowerAtomicPass(); diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfo.h b/contrib/llvm/include/llvm/MC/MCAsmInfo.h index 0bf364a6dfcf..873316139457 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmInfo.h +++ b/contrib/llvm/include/llvm/MC/MCAsmInfo.h @@ -20,13 +20,16 @@ #include namespace llvm { + class MCExpr; class MCSection; + class MCStreamer; + class MCSymbol; class MCContext; /// MCAsmInfo - This class is intended to be used as a base class for asm /// properties and features specific to the target. namespace ExceptionHandling { - enum ExceptionsType { None, DwarfTable, DwarfCFI, SjLj }; + enum ExceptionsType { None, DwarfTable, DwarfCFI, SjLj, ARM }; } class MCAsmInfo { @@ -66,10 +69,9 @@ namespace llvm { /// relative expressions. const char *PCSymbol; // Defaults to "$". - /// SeparatorChar - This character, if specified, is used to separate - /// instructions from each other when on the same line. This is used to - /// measure inline asm instructions. - char SeparatorChar; // Defaults to ';' + /// SeparatorString - This string, if specified, is used to separate + /// instructions from each other when on the same line. + const char *SeparatorString; // Defaults to ';' /// CommentColumn - This indicates the comment num (zero-based) at /// which asm comments should be printed. @@ -322,6 +324,16 @@ namespace llvm { return 0; } + virtual const MCExpr * + getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; + + const MCExpr * + getExprForFDESymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; + bool usesSunStyleELFSectionSwitchSyntax() const { return SunStyleELFSectionSwitchSyntax; } @@ -350,8 +362,8 @@ namespace llvm { const char *getPCSymbol() const { return PCSymbol; } - char getSeparatorChar() const { - return SeparatorChar; + const char *getSeparatorString() const { + return SeparatorString; } unsigned getCommentColumn() const { return CommentColumn; @@ -451,7 +463,8 @@ namespace llvm { bool isExceptionHandlingDwarf() const { return (ExceptionsType == ExceptionHandling::DwarfTable || - ExceptionsType == ExceptionHandling::DwarfCFI); + ExceptionsType == ExceptionHandling::DwarfCFI || + ExceptionsType == ExceptionHandling::ARM); } bool doesDwarfRequireFrameSection() const { diff --git a/contrib/llvm/include/llvm/MC/MCAsmLayout.h b/contrib/llvm/include/llvm/MC/MCAsmLayout.h index 01cb0006b362..a4585d1f1953 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmLayout.h +++ b/contrib/llvm/include/llvm/MC/MCAsmLayout.h @@ -36,8 +36,8 @@ class MCAsmLayout { /// List of sections in layout order. llvm::SmallVector SectionOrder; - /// The last fragment which was layed out, or 0 if nothing has been layed - /// out. Fragments are always layed out in order, so all fragments with a + /// 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 LastValidFragment; @@ -58,7 +58,7 @@ class MCAsmLayout { void Invalidate(MCFragment *F); /// \brief Perform layout for a single fragment, assuming that the previous - /// fragment has already been layed out correctly, and the parent section has + /// fragment has already been laid out correctly, and the parent section has /// been initialized. void LayoutFragment(MCFragment *Fragment); diff --git a/contrib/llvm/include/llvm/MC/MCAssembler.h b/contrib/llvm/include/llvm/MC/MCAssembler.h index 30971c62a97e..fc919669e82d 100644 --- a/contrib/llvm/include/llvm/MC/MCAssembler.h +++ b/contrib/llvm/include/llvm/MC/MCAssembler.h @@ -706,7 +706,7 @@ class MCAssembler { /// \param DF The fragment the fixup is inside. /// \param Target [out] On return, the relocatable expression the fixup /// evaluates to. - /// \param Value [out] On return, the value of the fixup as currently layed + /// \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 @@ -745,7 +745,7 @@ class MCAssembler { MCFragment &F, const MCFixup &Fixup); public: - /// Compute the effective fragment size assuming it is layed out at the given + /// Compute the effective fragment size assuming it is laid out at the given /// \arg SectionAddress and \arg FragmentOffset. uint64_t ComputeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const; diff --git a/contrib/llvm/include/llvm/MC/MCContext.h b/contrib/llvm/include/llvm/MC/MCContext.h index 7b26d5493776..070089e2c938 100644 --- a/contrib/llvm/include/llvm/MC/MCContext.h +++ b/contrib/llvm/include/llvm/MC/MCContext.h @@ -45,12 +45,18 @@ namespace llvm { const TargetAsmInfo *TAI; + /// Allocator - Allocator object used for creating machine code objects. + /// + /// We use a bump pointer allocator to avoid the need to track all allocated + /// objects. + BumpPtrAllocator Allocator; + /// Symbols - Bindings of names to symbols. - StringMap Symbols; + StringMap Symbols; /// UsedNames - Keeps tracks of names that were used both for used declared /// and artificial symbols. - StringMap UsedNames; + StringMap UsedNames; /// NextUniqueID - The next ID to dole out to an unnamed assembler temporary /// symbol. @@ -84,6 +90,11 @@ namespace llvm { MCDwarfLoc CurrentDwarfLoc; bool DwarfLocSeen; + /// Honor temporary labels, this is useful for debugging semantic + /// differences between temporary and non-temporary labels (primarily on + /// Darwin). + bool AllowTemporaryLabels; + /// The dwarf line information from the .loc directives for the sections /// with assembled machine instructions have after seeing .loc directives. DenseMap MCLineSections; @@ -91,12 +102,6 @@ namespace llvm { /// the elements were added. std::vector MCLineSectionOrder; - /// Allocator - Allocator object used for creating machine code objects. - /// - /// We use a bump pointer allocator to avoid the need to track all allocated - /// objects. - BumpPtrAllocator Allocator; - void *MachOUniquingMap, *ELFUniquingMap, *COFFUniquingMap; MCSymbol *CreateSymbol(StringRef Name); @@ -109,6 +114,8 @@ namespace llvm { const TargetAsmInfo &getTargetAsmInfo() const { return *TAI; } + void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } + /// @name Symbol Management /// @{ diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler.h b/contrib/llvm/include/llvm/MC/MCDisassembler.h index c9e42eb6c798..ce8759a882eb 100644 --- a/contrib/llvm/include/llvm/MC/MCDisassembler.h +++ b/contrib/llvm/include/llvm/MC/MCDisassembler.h @@ -10,12 +10,14 @@ #define MCDISASSEMBLER_H #include "llvm/Support/DataTypes.h" +#include "llvm-c/Disassembler.h" namespace llvm { class MCInst; class MemoryObject; class raw_ostream; +class MCContext; struct EDInstInfo; @@ -24,7 +26,7 @@ struct EDInstInfo; class MCDisassembler { public: /// Constructor - Performs initial setup for the disassembler. - MCDisassembler() {} + MCDisassembler() : GetOpInfo(0), DisInfo(0), Ctx(0) {} virtual ~MCDisassembler(); @@ -46,13 +48,37 @@ class MCDisassembler { uint64_t address, raw_ostream &vStream) const = 0; - /// getEDInfo - Returns the enhanced insturction information corresponding to + /// 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 EDInstInfo *getEDInfo() const { return (EDInstInfo*)0; } + +private: + // + // Hooks for symbolic disassembly via the public 'C' interface. + // + // The function to get the symbolic information for operands. + LLVMOpInfoCallback GetOpInfo; + // The pointer to the block of symbolic information for above call back. + void *DisInfo; + // The assembly context for creating symbols and MCExprs in place of + // immediate operands when there is symbolic information. + MCContext *Ctx; + +public: + void setupForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo, + void *disInfo, + MCContext *ctx) { + GetOpInfo = getOpInfo; + DisInfo = disInfo; + Ctx = ctx; + } + LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; } + void *getDisInfoBlock() const { return DisInfo; } + MCContext *getMCContext() const { return Ctx; } }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCDwarf.h b/contrib/llvm/include/llvm/MC/MCDwarf.h index 07a7bad15b1e..3bbcf3eb6ed0 100644 --- a/contrib/llvm/include/llvm/MC/MCDwarf.h +++ b/contrib/llvm/include/llvm/MC/MCDwarf.h @@ -23,6 +23,7 @@ #include namespace llvm { + class TargetAsmInfo; class MachineMove; class MCContext; class MCExpr; @@ -230,7 +231,7 @@ namespace llvm { class MCCFIInstruction { public: - enum OpType { Remember, Restore, Move }; + enum OpType { SameValue, Remember, Restore, Move, RelMove }; private: OpType Operation; MCSymbol *Label; @@ -242,10 +243,19 @@ namespace llvm { : Operation(Op), Label(L) { assert(Op == Remember || Op == Restore); } + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned Register) + : Operation(Op), Label(L), Destination(Register) { + assert(Op == SameValue); + } MCCFIInstruction(MCSymbol *L, const MachineLocation &D, const MachineLocation &S) : Operation(Move), Label(L), Destination(D), Source(S) { } + MCCFIInstruction(OpType Op, MCSymbol *L, const MachineLocation &D, + const MachineLocation &S) + : Operation(Op), Label(L), Destination(D), Source(S) { + assert(Op == RelMove); + } OpType getOperation() const { return Operation; } MCSymbol *getLabel() const { return Label; } const MachineLocation &getDestination() const { return Destination; } @@ -254,12 +264,13 @@ namespace llvm { struct MCDwarfFrameInfo { MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), - Instructions(), PersonalityEncoding(0), + Function(0), Instructions(), PersonalityEncoding(), LsdaEncoding(0) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; const MCSymbol *Lsda; + const MCSymbol *Function; std::vector Instructions; unsigned PersonalityEncoding; unsigned LsdaEncoding; @@ -270,9 +281,11 @@ namespace llvm { // // This emits the frame info section. // - static void Emit(MCStreamer &streamer); + static void Emit(MCStreamer &streamer, bool usingCFI); + static void EmitDarwin(MCStreamer &streamer, bool usingCFI); static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); - static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); + static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS, + const TargetAsmInfo &AsmInfo); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCExpr.h b/contrib/llvm/include/llvm/MC/MCExpr.h index fea5249eaba0..521fde6982b5 100644 --- a/contrib/llvm/include/llvm/MC/MCExpr.h +++ b/contrib/llvm/include/llvm/MC/MCExpr.h @@ -19,6 +19,7 @@ class MCAsmInfo; class MCAsmLayout; class MCAssembler; class MCContext; +class MCSection; class MCSectionData; class MCSymbol; class MCValue; @@ -92,6 +93,12 @@ class MCExpr { /// @result - True on success. bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout &Layout) const; + /// FindAssociatedSection - Find the "associated section" for this expression, + /// which is currently defined as the absolute section for constants, or + /// otherwise the section associated with the first defined symbol in the + /// expression. + const MCSection *FindAssociatedSection() const; + /// @} static bool classof(const MCExpr *) { return true; } @@ -420,6 +427,7 @@ class MCTargetExpr : public MCExpr { virtual bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout) const = 0; virtual void AddValueSymbols(MCAssembler *) const = 0; + virtual const MCSection *FindAssociatedSection() const = 0; static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; diff --git a/contrib/llvm/include/llvm/MC/MCInstPrinter.h b/contrib/llvm/include/llvm/MC/MCInstPrinter.h index 96716c775fdf..066955867c59 100644 --- a/contrib/llvm/include/llvm/MC/MCInstPrinter.h +++ b/contrib/llvm/include/llvm/MC/MCInstPrinter.h @@ -25,9 +25,12 @@ class MCInstPrinter { /// assembly emission is disable. raw_ostream *CommentStream; const MCAsmInfo &MAI; + + /// The current set of available features. + unsigned AvailableFeatures; public: MCInstPrinter(const MCAsmInfo &mai) - : CommentStream(0), MAI(mai) {} + : CommentStream(0), MAI(mai), AvailableFeatures(0) {} virtual ~MCInstPrinter(); @@ -41,6 +44,12 @@ class MCInstPrinter { /// getOpcodeName - Return the name of the specified opcode enum (e.g. /// "MOV32ri") or empty if we can't resolve it. virtual StringRef getOpcodeName(unsigned Opcode) const; + + /// getRegName - Return the assembler register name. + virtual StringRef getRegName(unsigned RegNo) const; + + unsigned getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h index 833341eb97f5..8b0d87adabd4 100644 --- a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h @@ -38,6 +38,9 @@ class MCObjectStreamer : public MCStreamer { protected: MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter); + MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &_OS, MCCodeEmitter *_Emitter, + MCAssembler *_Assembler); ~MCObjectStreamer(); MCSectionData *getCurrentSectionData() const { @@ -60,9 +63,9 @@ class MCObjectStreamer : public MCStreamer { virtual void EmitLabel(MCSymbol *Symbol); virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - bool isPCRel, unsigned AddrSpace); - virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); - virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + unsigned AddrSpace); + virtual void EmitULEB128Value(const MCExpr *Value); + virtual void EmitSLEB128Value(const MCExpr *Value); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); virtual void ChangeSection(const MCSection *Section); virtual void EmitInstruction(const MCInst &Inst); diff --git a/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h b/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h index 252696bec317..ab78799fdcd2 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h +++ b/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h @@ -49,6 +49,7 @@ class AsmLexer : public MCAsmLexer { virtual StringRef LexUntilEndOfStatement(); bool isAtStartOfComment(char Char); + bool isAtStatementSeparator(const char *Ptr); const MCAsmInfo &getMAI() const { return MAI; } diff --git a/contrib/llvm/include/llvm/MC/MCSection.h b/contrib/llvm/include/llvm/MC/MCSection.h index 1c01b2f8f3cc..57008177b6d3 100644 --- a/contrib/llvm/include/llvm/MC/MCSection.h +++ b/contrib/llvm/include/llvm/MC/MCSection.h @@ -14,7 +14,6 @@ #ifndef LLVM_MC_MCSECTION_H #define LLVM_MC_MCSECTION_H -#include #include "llvm/ADT/StringRef.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Casting.h" diff --git a/contrib/llvm/include/llvm/MC/MCSectionMachO.h b/contrib/llvm/include/llvm/MC/MCSectionMachO.h index 7633515f2744..bdb17e9008b2 100644 --- a/contrib/llvm/include/llvm/MC/MCSectionMachO.h +++ b/contrib/llvm/include/llvm/MC/MCSectionMachO.h @@ -66,10 +66,10 @@ class MCSectionMachO : public MCSection { /// S_SYMBOL_STUBS - Section with symbol stubs, byte size of stub in /// the Reserved2 field. S_SYMBOL_STUBS = 0x08U, - /// S_SYMBOL_STUBS - Section with only function pointers for + /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for /// initialization. S_MOD_INIT_FUNC_POINTERS = 0x09U, - /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for + /// S_MOD_TERM_FUNC_POINTERS - Section with only function pointers for /// termination. S_MOD_TERM_FUNC_POINTERS = 0x0AU, /// S_COALESCED - Section contains symbols that are to be coalesced. @@ -157,10 +157,12 @@ class MCSectionMachO : public MCSection { /// flavored .s file. If successful, this fills in the specified Out /// parameters and returns an empty string. When an invalid section /// specifier is present, this returns a string indicating the problem. + /// If no TAA was parsed, TAA is not altered, and TAAWasSet becomes false. static std::string ParseSectionSpecifier(StringRef Spec, // In. StringRef &Segment, // Out. StringRef &Section, // Out. unsigned &TAA, // Out. + bool &TAAParsed, // Out. unsigned &StubSize); // Out. virtual void PrintSwitchToSection(const MCAsmInfo &MAI, diff --git a/contrib/llvm/include/llvm/MC/MCStreamer.h b/contrib/llvm/include/llvm/MC/MCStreamer.h index 4451199b7fb3..b005c8bd886b 100644 --- a/contrib/llvm/include/llvm/MC/MCStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCStreamer.h @@ -50,13 +50,12 @@ namespace llvm { MCStreamer(const MCStreamer&); // DO NOT IMPLEMENT MCStreamer &operator=(const MCStreamer&); // DO NOT IMPLEMENT - void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - bool isPCRel, unsigned AddrSpace); - std::vector FrameInfos; MCDwarfFrameInfo *getCurrentFrameInfo(); void EnsureValidFrame(); + const MCSymbol* LastNonPrivate; + /// SectionStack - This is stack of current and previous section /// values saved by PushSection. SmallVector &RegList, + bool isVector); + /// Finish - Finish emission of machine code. virtual void Finish() = 0; }; @@ -485,6 +501,7 @@ namespace llvm { MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, + bool useCFI, MCInstPrinter *InstPrint = 0, MCCodeEmitter *CE = 0, TargetAsmBackend *TAB = 0, diff --git a/contrib/llvm/include/llvm/MC/MCSymbol.h b/contrib/llvm/include/llvm/MC/MCSymbol.h index 7da4d7c15e3b..0583ce56820b 100644 --- a/contrib/llvm/include/llvm/MC/MCSymbol.h +++ b/contrib/llvm/include/llvm/MC/MCSymbol.h @@ -56,6 +56,7 @@ namespace llvm { mutable unsigned IsUsed : 1; private: // MCContext creates and uniques these. + friend class MCExpr; friend class MCContext; MCSymbol(StringRef name, bool isTemporary) : Name(name), Section(0), Value(0), diff --git a/contrib/llvm/include/llvm/Metadata.h b/contrib/llvm/include/llvm/Metadata.h index a6c3f039a11e..c3230251d482 100644 --- a/contrib/llvm/include/llvm/Metadata.h +++ b/contrib/llvm/include/llvm/Metadata.h @@ -17,6 +17,7 @@ #define LLVM_METADATA_H #include "llvm/Value.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist_node.h" @@ -110,28 +111,25 @@ class MDNode : public Value, public FoldingSetNode { void replaceOperand(MDNodeOperand *Op, Value *NewVal); ~MDNode(); - MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, - bool isFunctionLocal); + MDNode(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal); - static MDNode *getMDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, + static MDNode *getMDNode(LLVMContext &C, ArrayRef Vals, FunctionLocalness FL, bool Insert = true); public: // Constructors and destructors. - static MDNode *get(LLVMContext &Context, Value *const *Vals, - unsigned NumVals); + static MDNode *get(LLVMContext &Context, ArrayRef Vals); // getWhenValsUnresolved - Construct MDNode determining function-localness // from isFunctionLocal argument, not by analyzing Vals. - static MDNode *getWhenValsUnresolved(LLVMContext &Context, Value *const *Vals, - unsigned NumVals, bool isFunctionLocal); + static MDNode *getWhenValsUnresolved(LLVMContext &Context, + ArrayRef Vals, + bool isFunctionLocal); - static MDNode *getIfExists(LLVMContext &Context, Value *const *Vals, - unsigned NumVals); + static MDNode *getIfExists(LLVMContext &Context, ArrayRef Vals); /// getTemporary - Return a temporary MDNode, for use in constructing /// cyclic MDNode structures. A temporary MDNode is not uniqued, /// may be RAUW'd, and must be manually deleted with deleteTemporary. - static MDNode *getTemporary(LLVMContext &Context, Value *const *Vals, - unsigned NumVals); + static MDNode *getTemporary(LLVMContext &Context, ArrayRef Vals); /// deleteTemporary - Deallocate a node created by getTemporary. The /// node must not have any users. diff --git a/contrib/llvm/include/llvm/Module.h b/contrib/llvm/include/llvm/Module.h index f95895e95773..aef8eb890fe0 100644 --- a/contrib/llvm/include/llvm/Module.h +++ b/contrib/llvm/include/llvm/Module.h @@ -211,15 +211,20 @@ class Module { void setTargetTriple(StringRef T) { TargetTriple = T; } /// Set the module-scope inline assembly blocks. - void setModuleInlineAsm(StringRef Asm) { GlobalScopeAsm = Asm; } + void setModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm = Asm; + if (!GlobalScopeAsm.empty() && + GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n') + GlobalScopeAsm += '\n'; + } /// Append to the module-scope inline assembly blocks, automatically inserting /// a separating newline if necessary. void appendModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm += Asm; if (!GlobalScopeAsm.empty() && GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n') GlobalScopeAsm += '\n'; - GlobalScopeAsm += Asm; } /// @} @@ -303,7 +308,7 @@ class Module { /// 1. If it does not exist, add a declaration of the global and return it. /// 2. Else, the global exists but has the wrong type: return the function /// with a constantexpr cast to the right type. - /// 3. Finally, if the existing global is the correct delclaration, return + /// 3. Finally, if the existing global is the correct declaration, return /// the existing global. Constant *getOrInsertGlobal(StringRef Name, const Type *Ty); diff --git a/contrib/llvm/include/llvm/Object/MachOObject.h b/contrib/llvm/include/llvm/Object/MachOObject.h index 03d9c147b413..19a399e62fe3 100644 --- a/contrib/llvm/include/llvm/Object/MachOObject.h +++ b/contrib/llvm/include/llvm/Object/MachOObject.h @@ -19,6 +19,7 @@ namespace llvm { class MemoryBuffer; +class raw_ostream; namespace object { @@ -172,7 +173,26 @@ class MachOObject { InMemoryStruct &Res) const; /// @} + + /// @name Object Dump Facilities + /// @{ + /// dump - Support for debugging, callable in GDB: V->dump() + // + void dump() const; + void dumpHeader() const; + + /// print - Implement operator<< on Value. + /// + void print(raw_ostream &O) const; + void printHeader(raw_ostream &O) const; + + /// @} }; + +inline raw_ostream &operator<<(raw_ostream &OS, const MachOObject &V) { + V.print(OS); + return OS; +} } // end namespace object } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Pass.h b/contrib/llvm/include/llvm/Pass.h index ed0fb39f5d6c..04dd8b60547a 100644 --- a/contrib/llvm/include/llvm/Pass.h +++ b/contrib/llvm/include/llvm/Pass.h @@ -13,7 +13,7 @@ // Passes are designed this way so that it is possible to run passes in a cache // and organizationally optimal order without having to specify it at the front // end. This allows arbitrary passes to be strung together and have them -// executed as effeciently as possible. +// executed as efficiently as possible. // // Passes should extend one of the classes below, depending on the guarantees // that it can make about what will be modified as it is run. For example, most @@ -114,7 +114,7 @@ class Pass { void dump() const; // dump - Print to stderr. /// createPrinterPass - Get a Pass appropriate to print the IR this - /// pass operates one (Module, Function or MachineFunction). + /// pass operates on (Module, Function or MachineFunction). virtual Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const = 0; @@ -320,7 +320,7 @@ class BasicBlockPass : public Pass { public: explicit BasicBlockPass(char &pid) : Pass(PT_BasicBlock, pid) {} - /// createPrinterPass - Get a function printer pass. + /// 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 diff --git a/contrib/llvm/include/llvm/PassAnalysisSupport.h b/contrib/llvm/include/llvm/PassAnalysisSupport.h index a3342d51386b..fede1216c3c4 100644 --- a/contrib/llvm/include/llvm/PassAnalysisSupport.h +++ b/contrib/llvm/include/llvm/PassAnalysisSupport.h @@ -142,6 +142,8 @@ class AnalysisResolver { Pass *findImplPass(Pass *P, AnalysisID PI, Function &F); void addAnalysisImplsPair(AnalysisID PI, Pass *P) { + if (findImplPass(PI) == P) + return; std::pair pir = std::make_pair(PI,P); AnalysisImpls.push_back(pir); } diff --git a/contrib/llvm/include/llvm/Support/Allocator.h b/contrib/llvm/include/llvm/Support/Allocator.h index c6807099f85e..a2ad24ffead9 100644 --- a/contrib/llvm/include/llvm/Support/Allocator.h +++ b/contrib/llvm/include/llvm/Support/Allocator.h @@ -177,6 +177,9 @@ class BumpPtrAllocator { unsigned GetNumSlabs() const; void PrintStats() const; + + /// Compute the total physical memory allocated by this allocator. + size_t getTotalMemory() const; }; /// SpecificBumpPtrAllocator - Same as BumpPtrAllocator but allows only diff --git a/contrib/llvm/include/llvm/Support/CFG.h b/contrib/llvm/include/llvm/Support/CFG.h index 9ba71fcca8a5..d2ea12364e9f 100644 --- a/contrib/llvm/include/llvm/Support/CFG.h +++ b/contrib/llvm/include/llvm/Support/CFG.h @@ -41,6 +41,7 @@ class PredIterator : public std::iteratoruse_begin()) { advancePastNonTerminators(); } @@ -64,6 +65,12 @@ class PredIterator : public std::iterator pred_iterator; diff --git a/contrib/llvm/include/llvm/Support/Casting.h b/contrib/llvm/include/llvm/Support/Casting.h index 6bb98064382e..abb5a9aa11d8 100644 --- a/contrib/llvm/include/llvm/Support/Casting.h +++ b/contrib/llvm/include/llvm/Support/Casting.h @@ -192,8 +192,8 @@ template struct cast_convert_val { // cast - Return the argument parameter cast to the specified type. This // casting operator asserts that the type is correct, so it does not return null -// on failure. But it will correctly return NULL when the input is NULL. -// Used Like this: +// on failure. It does not allow a null argument (use cast_or_null for that). +// It is typically used like this: // // cast(myVal)->getParent() // diff --git a/contrib/llvm/include/llvm/Support/CommandLine.h b/contrib/llvm/include/llvm/Support/CommandLine.h index 9ae3d6af32ee..d6098711a07a 100644 --- a/contrib/llvm/include/llvm/Support/CommandLine.h +++ b/contrib/llvm/include/llvm/Support/CommandLine.h @@ -60,6 +60,12 @@ void ParseEnvironmentOptions(const char *progName, const char *envvar, void SetVersionPrinter(void (*func)()); +// PrintOptionValues - Print option values. +// With -print-options print the difference between option values and defaults. +// With -print-all-options print all option values. +// (Currently not perfect, but best-effort.) +void PrintOptionValues(); + // MarkOptionsChanged - Internal helper function. void MarkOptionsChanged(); @@ -230,6 +236,8 @@ class Option { // virtual void printOptionInfo(size_t GlobalWidth) const = 0; + virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0; + virtual void getExtraOptionNames(SmallVectorImpl &) {} // addOccurrence - Wrapper around handleOccurrence that enforces Flags. @@ -302,6 +310,120 @@ template LocationClass location(Ty &L) { return LocationClass(L); } +//===----------------------------------------------------------------------===// +// OptionValue class + +// Support value comparison outside the template. +struct GenericOptionValue { + virtual ~GenericOptionValue() {} + virtual bool compare(const GenericOptionValue &V) const = 0; +}; + +template struct OptionValue; + +// The default value safely does nothing. Option value printing is only +// best-effort. +template +struct OptionValueBase : public GenericOptionValue { + // Temporary storage for argument passing. + typedef OptionValue WrapperType; + + bool hasValue() const { return false; } + + const DataType &getValue() const { assert(false && "no default value"); } + + // Some options may take their value from a different data type. + template + void setValue(const DT& /*V*/) {} + + bool compare(const DataType &/*V*/) const { return false; } + + virtual bool compare(const GenericOptionValue& /*V*/) const { return false; } +}; + +// Simple copy of the option value. +template +class OptionValueCopy : public GenericOptionValue { + DataType Value; + bool Valid; +public: + OptionValueCopy() : Valid(false) {} + + bool hasValue() const { return Valid; } + + const DataType &getValue() const { + assert(Valid && "invalid option value"); + return Value; + } + + void setValue(const DataType &V) { Valid = true; Value = V; } + + bool compare(const DataType &V) const { + return Valid && (Value != V); + } + + virtual bool compare(const GenericOptionValue &V) const { + const OptionValueCopy &VC = + static_cast< const OptionValueCopy& >(V); + if (!VC.hasValue()) return false; + return compare(VC.getValue()); + } +}; + +// Non-class option values. +template +struct OptionValueBase : OptionValueCopy { + typedef DataType WrapperType; +}; + +// Top-level option class. +template +struct OptionValue : OptionValueBase::value> { + OptionValue() {} + + OptionValue(const DataType& V) { + this->setValue(V); + } + // Some options may take their value from a different data type. + template + OptionValue &operator=(const DT& V) { + this->setValue(V); + return *this; + } +}; + +// Other safe-to-copy-by-value common option types. +enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; +template<> +struct OptionValue : OptionValueCopy { + typedef cl::boolOrDefault WrapperType; + + OptionValue() {} + + OptionValue(const cl::boolOrDefault& V) { + this->setValue(V); + } + OptionValue &operator=(const cl::boolOrDefault& V) { + setValue(V); + return *this; + } +}; + +template<> +struct OptionValue : OptionValueCopy { + typedef StringRef WrapperType; + + OptionValue() {} + + OptionValue(const std::string& V) { + this->setValue(V); + } + OptionValue &operator=(const std::string& V) { + setValue(V); + return *this; + } +}; + //===----------------------------------------------------------------------===// // Enum valued command line option // @@ -355,7 +477,6 @@ ValuesClass END_WITH_NULL values(const char *Arg, DataType Val, return Vals; } - //===----------------------------------------------------------------------===// // parser class - Parameterizable parser for different data types. By default, // known data types (string, int, bool) have specialized parsers, that do what @@ -368,7 +489,16 @@ ValuesClass END_WITH_NULL values(const char *Arg, DataType Val, // not need replicated for every instance of the generic parser. This also // allows us to put stuff into CommandLine.cpp // -struct generic_parser_base { +class generic_parser_base { +protected: + class GenericOptionInfo { + public: + GenericOptionInfo(const char *name, const char *helpStr) : + Name(name), HelpStr(helpStr) {} + const char *Name; + const char *HelpStr; + }; +public: virtual ~generic_parser_base() {} // Base class should have virtual-dtor // getNumOptions - Virtual function implemented by generic subclass to @@ -385,11 +515,28 @@ struct generic_parser_base { // Return the width of the option tag for printing... virtual size_t getOptionWidth(const Option &O) const; + virtual const GenericOptionValue &getOptionValue(unsigned N) const = 0; + // printOptionInfo - Print out information about this option. The // to-be-maintained width is specified. // virtual void printOptionInfo(const Option &O, size_t GlobalWidth) const; + void printGenericOptionDiff(const Option &O, const GenericOptionValue &V, + const GenericOptionValue &Default, + size_t GlobalWidth) const; + + // printOptionDiff - print the value of an option and it's default. + // + // Template definition ensures that the option and default have the same + // DataType (via the same AnyOptionValue). + template + void printOptionDiff(const Option &O, const AnyOptionValue &V, + const AnyOptionValue &Default, + size_t GlobalWidth) const { + printGenericOptionDiff(O, V, Default, GlobalWidth); + } + void initialize(Option &O) { // All of the modifiers for the option have been processed by now, so the // argstr field should be stable, copy it down now. @@ -443,13 +590,11 @@ struct generic_parser_base { template class parser : public generic_parser_base { protected: - class OptionInfo { + class OptionInfo : public GenericOptionInfo { public: OptionInfo(const char *name, DataType v, const char *helpStr) : - Name(name), V(v), HelpStr(helpStr) {} - const char *Name; - DataType V; - const char *HelpStr; + GenericOptionInfo(name, helpStr), V(v) {} + OptionValue V; }; SmallVector Values; public: @@ -462,6 +607,11 @@ class parser : public generic_parser_base { return Values[N].HelpStr; } + // getOptionValue - Return the value of option name N. + virtual const GenericOptionValue &getOptionValue(unsigned N) const { + return Values[N].V; + } + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) { StringRef ArgVal; @@ -473,7 +623,7 @@ class parser : public generic_parser_base { for (unsigned i = 0, e = static_cast(Values.size()); i != e; ++i) if (Values[i].Name == ArgVal) { - V = Values[i].V; + V = Values[i].V.getValue(); return false; } @@ -522,11 +672,19 @@ class basic_parser_impl { // non-template implementation of basic_parser // void printOptionInfo(const Option &O, size_t GlobalWidth) const; + // printOptionNoValue - Print a placeholder for options that don't yet support + // printOptionDiff(). + void printOptionNoValue(const Option &O, size_t GlobalWidth) const; + // getValueName - Overload in subclass to provide a better default value. virtual const char *getValueName() const { return "value"; } // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); + +protected: + // A helper for basic_parser::printOptionDiff. + void printOptionName(const Option &O, size_t GlobalWidth) const; }; // basic_parser - The real basic parser is just a template wrapper that provides @@ -536,6 +694,7 @@ template class basic_parser : public basic_parser_impl { public: typedef DataType parser_data_type; + typedef OptionValue OptVal; }; //-------------------------------------------------- @@ -561,6 +720,9 @@ class parser : public basic_parser { // getValueName - Do not print = at all. virtual const char *getValueName() const { return 0; } + void printOptionDiff(const Option &O, bool V, OptVal Default, + size_t GlobalWidth) const; + // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); }; @@ -569,7 +731,6 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser -enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; template<> class parser : public basic_parser { public: @@ -583,6 +744,9 @@ class parser : public basic_parser { // getValueName - Do not print = at all. virtual const char *getValueName() const { return 0; } + void printOptionDiff(const Option &O, boolOrDefault V, OptVal Default, + size_t GlobalWidth) const; + // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); }; @@ -601,6 +765,9 @@ class parser : public basic_parser { // getValueName - Overload in subclass to provide a better default value. virtual const char *getValueName() const { return "int"; } + void printOptionDiff(const Option &O, int V, OptVal Default, + size_t GlobalWidth) const; + // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); }; @@ -620,6 +787,9 @@ class parser : public basic_parser { // getValueName - Overload in subclass to provide a better default value. virtual const char *getValueName() const { return "uint"; } + void printOptionDiff(const Option &O, unsigned V, OptVal Default, + size_t GlobalWidth) const; + // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); }; @@ -638,6 +808,9 @@ class parser : public basic_parser { // getValueName - Overload in subclass to provide a better default value. virtual const char *getValueName() const { return "number"; } + void printOptionDiff(const Option &O, double V, OptVal Default, + size_t GlobalWidth) const; + // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); }; @@ -656,6 +829,9 @@ class parser : public basic_parser { // getValueName - Overload in subclass to provide a better default value. virtual const char *getValueName() const { return "number"; } + void printOptionDiff(const Option &O, float V, OptVal Default, + size_t GlobalWidth) const; + // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); }; @@ -677,6 +853,9 @@ class parser : public basic_parser { // getValueName - Overload in subclass to provide a better default value. virtual const char *getValueName() const { return "string"; } + void printOptionDiff(const Option &O, StringRef V, OptVal Default, + size_t GlobalWidth) const; + // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); }; @@ -698,12 +877,63 @@ class parser : public basic_parser { // getValueName - Overload in subclass to provide a better default value. virtual const char *getValueName() const { return "char"; } + void printOptionDiff(const Option &O, char V, OptVal Default, + size_t GlobalWidth) const; + // An out-of-line virtual method to provide a 'home' for this class. virtual void anchor(); }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +//-------------------------------------------------- +// PrintOptionDiff +// +// This collection of wrappers is the intermediary between class opt and class +// parser to handle all the template nastiness. + +// This overloaded function is selected by the generic parser. +template +void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, + const OptionValue
&Default, size_t GlobalWidth) { + OptionValue
OV = V; + P.printOptionDiff(O, OV, Default, GlobalWidth); +} + +// This is instantiated for basic parsers when the parsed value has a different +// type than the option value. e.g. HelpPrinter. +template +struct OptionDiffPrinter { + void print(const Option &O, const parser P, const ValDT &/*V*/, + const OptionValue &/*Default*/, size_t GlobalWidth) { + P.printOptionNoValue(O, GlobalWidth); + } +}; + +// This is instantiated for basic parsers when the parsed value has the same +// type as the option value. +template +struct OptionDiffPrinter { + void print(const Option &O, const parser
P, const DT &V, + const OptionValue
&Default, size_t GlobalWidth) { + P.printOptionDiff(O, V, Default, GlobalWidth); + } +}; + +// This overloaded function is selected by the basic parser, which may parse a +// different type than the option type. +template +void printOptionDiff( + const Option &O, + const basic_parser &P, + const ValDT &V, const OptionValue &Default, + size_t GlobalWidth) { + + OptionDiffPrinter printer; + printer.print(O, static_cast(P), V, Default, + GlobalWidth); +} + //===----------------------------------------------------------------------===// // applicator class - This class is used because we must use partial // specialization to handle literal string arguments specially (const char* does @@ -753,7 +983,6 @@ void apply(const Mod &M, Opt *O) { applicator::opt(M, *O); } - //===----------------------------------------------------------------------===// // opt_storage class @@ -764,6 +993,7 @@ void apply(const Mod &M, Opt *O) { template class opt_storage { DataType *Location; // Where to store the object... + OptionValue Default; void check() const { assert(Location != 0 && "cl::location(...) not specified for a command " @@ -777,21 +1007,25 @@ class opt_storage { if (Location) return O.error("cl::location(x) specified more than once!"); Location = &L; + Default = L; return false; } template - void setValue(const T &V) { + void setValue(const T &V, bool initial = false) { check(); *Location = V; + if (initial) + Default = V; } DataType &getValue() { check(); return *Location; } const DataType &getValue() const { check(); return *Location; } operator DataType() const { return this->getValue(); } -}; + const OptionValue &getDefault() const { return Default; } +}; // Define how to hold a class type object, such as a string. Since we can // inherit from a class, we do so. This makes us exactly compatible with the @@ -800,11 +1034,19 @@ class opt_storage { template class opt_storage : public DataType { public: + OptionValue Default; + template - void setValue(const T &V) { DataType::operator=(V); } + void setValue(const T &V, bool initial = false) { + DataType::operator=(V); + if (initial) + Default = V; + } DataType &getValue() { return *this; } const DataType &getValue() const { return *this; } + + const OptionValue &getDefault() const { return Default; } }; // Define a partial specialization to handle things we cannot inherit from. In @@ -815,16 +1057,23 @@ template class opt_storage { public: DataType Value; + OptionValue Default; // Make sure we initialize the value with the default constructor for the // type. opt_storage() : Value(DataType()) {} template - void setValue(const T &V) { Value = V; } + void setValue(const T &V, bool initial = false) { + Value = V; + if (initial) + Default = V; + } DataType &getValue() { return Value; } DataType getValue() const { return Value; } + const OptionValue &getDefault() const { return Default; } + operator DataType() const { return getValue(); } // If the datatype is a pointer, support -> on it. @@ -866,13 +1115,20 @@ class opt : public Option, Parser.printOptionInfo(*this, GlobalWidth); } + virtual void printOptionValue(size_t GlobalWidth, bool Force) const { + if (Force || this->getDefault().compare(this->getValue())) { + cl::printOptionDiff( + *this, Parser, this->getValue(), this->getDefault(), GlobalWidth); + } + } + void done() { addArgument(); Parser.initialize(*this); } public: // setInitialValue - Used by the cl::init modifier... - void setInitialValue(const DataType &V) { this->setValue(V); } + void setInitialValue(const DataType &V) { this->setValue(V, true); } ParserClass &getParser() { return Parser; } @@ -1030,6 +1286,9 @@ class list : public Option, public list_storage { Parser.printOptionInfo(*this, GlobalWidth); } + // Unimplemented: list options don't currently store their default value. + virtual void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const {} + void done() { addArgument(); Parser.initialize(*this); @@ -1229,6 +1488,9 @@ class bits : public Option, public bits_storage { Parser.printOptionInfo(*this, GlobalWidth); } + // Unimplemented: bits options don't currently store their default values. + virtual void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const {} + void done() { addArgument(); Parser.initialize(*this); @@ -1320,6 +1582,9 @@ class alias : public Option { virtual size_t getOptionWidth() const; virtual void printOptionInfo(size_t GlobalWidth) const; + // Aliases do not need to print their values. + virtual void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const {} + void done() { if (!hasArgStr()) error("cl::alias must have argument name specified!"); diff --git a/contrib/llvm/include/llvm/Support/Compiler.h b/contrib/llvm/include/llvm/Support/Compiler.h index 67f0fd7e0dc6..e0921572182b 100644 --- a/contrib/llvm/include/llvm/Support/Compiler.h +++ b/contrib/llvm/include/llvm/Support/Compiler.h @@ -126,4 +126,12 @@ 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. +#if defined(__clang__) || (__GNUC__ > 4) \ + || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() +#endif + #endif diff --git a/contrib/llvm/include/llvm/Support/ConstantFolder.h b/contrib/llvm/include/llvm/Support/ConstantFolder.h index bd3765d592db..d0eaa3e487df 100644 --- a/contrib/llvm/include/llvm/Support/ConstantFolder.h +++ b/contrib/llvm/include/llvm/Support/ConstantFolder.h @@ -22,12 +22,10 @@ namespace llvm { -class LLVMContext; - /// ConstantFolder - Create constants with minimum, target independent, folding. class ConstantFolder { public: - explicit ConstantFolder(LLVMContext &) {} + explicit ConstantFolder() {} //===--------------------------------------------------------------------===// // Binary Operators diff --git a/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h index 2e9b5d4aa541..db835e8c2048 100644 --- a/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h +++ b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h @@ -15,6 +15,8 @@ namespace llvm { class StringRef; +class CrashRecoveryContextCleanup; + /// \brief Crash recovery helper object. /// /// This class implements support for running operations in a safe context so @@ -42,10 +44,14 @@ class StringRef; /// Crash recovery contexts may not be nested. class CrashRecoveryContext { void *Impl; + CrashRecoveryContextCleanup *head; public: - CrashRecoveryContext() : Impl(0) {} + CrashRecoveryContext() : Impl(0), head(0) {} ~CrashRecoveryContext(); + + void registerCleanup(CrashRecoveryContextCleanup *cleanup); + void unregisterCleanup(CrashRecoveryContextCleanup *cleanup); /// \brief Enable crash recovery. static void Enable(); @@ -57,6 +63,10 @@ class CrashRecoveryContext { /// thread which is in a protected context. static CrashRecoveryContext *GetCurrent(); + /// \brief Return true if the current thread is recovering from a + /// crash. + static bool isRecoveringFromCrash(); + /// \brief Execute the provide callback function (with the given arguments) in /// a protected context. /// @@ -87,6 +97,99 @@ class CrashRecoveryContext { const std::string &getBacktrace() const; }; +class CrashRecoveryContextCleanup { +protected: + CrashRecoveryContext *context; + CrashRecoveryContextCleanup(CrashRecoveryContext *context) + : context(context), cleanupFired(false) {} +public: + bool cleanupFired; + + virtual ~CrashRecoveryContextCleanup(); + virtual void recoverResources() = 0; + + CrashRecoveryContext *getContext() const { + return context; + } + +private: + friend class CrashRecoveryContext; + CrashRecoveryContextCleanup *prev, *next; +}; + +template +class CrashRecoveryContextCleanupBase : public CrashRecoveryContextCleanup { +protected: + T *resource; + CrashRecoveryContextCleanupBase(CrashRecoveryContext *context, T* resource) + : CrashRecoveryContextCleanup(context), resource(resource) {} +public: + static DERIVED *create(T *x) { + if (x) { + if (CrashRecoveryContext *context = CrashRecoveryContext::GetCurrent()) + return new DERIVED(context, x); + } + return 0; + } +}; + +template +class CrashRecoveryContextDestructorCleanup : public + CrashRecoveryContextCleanupBase, T> { +public: + CrashRecoveryContextDestructorCleanup(CrashRecoveryContext *context, + T *resource) + : CrashRecoveryContextCleanupBase< + CrashRecoveryContextDestructorCleanup, T>(context, resource) {} + + virtual void recoverResources() { + this->resource->~T(); + } +}; + +template +class CrashRecoveryContextDeleteCleanup : public + CrashRecoveryContextCleanupBase, T> { +public: + CrashRecoveryContextDeleteCleanup(CrashRecoveryContext *context, T *resource) + : CrashRecoveryContextCleanupBase< + CrashRecoveryContextDeleteCleanup, T>(context, resource) {} + + virtual void recoverResources() { + delete this->resource; + } +}; + +template +class CrashRecoveryContextReleaseRefCleanup : public + CrashRecoveryContextCleanupBase, T> +{ +public: + CrashRecoveryContextReleaseRefCleanup(CrashRecoveryContext *context, + T *resource) + : CrashRecoveryContextCleanupBase, + T>(context, resource) {} + + virtual void recoverResources() { + this->resource->Release(); + } +}; + +template > +class CrashRecoveryContextCleanupRegistrar { + CrashRecoveryContextCleanup *cleanup; +public: + CrashRecoveryContextCleanupRegistrar(T *x) + : cleanup(Cleanup::create(x)) { + if (cleanup) + cleanup->getContext()->registerCleanup(cleanup); + } + + ~CrashRecoveryContextCleanupRegistrar() { + if (cleanup && !cleanup->cleanupFired) + cleanup->getContext()->unregisterCleanup(cleanup); + } +}; } #endif diff --git a/contrib/llvm/include/llvm/Support/DOTGraphTraits.h b/contrib/llvm/include/llvm/Support/DOTGraphTraits.h index 796c74a21ca8..3cb8164c3c3d 100644 --- a/contrib/llvm/include/llvm/Support/DOTGraphTraits.h +++ b/contrib/llvm/include/llvm/Support/DOTGraphTraits.h @@ -89,8 +89,9 @@ struct DefaultDOTGraphTraits { /// If you want to override the dot attributes printed for a particular edge, /// override this method. - template - static std::string getEdgeAttributes(const void *Node, EdgeIter EI) { + template + static std::string getEdgeAttributes(const void *Node, EdgeIter EI, + const GraphType& Graph) { return ""; } diff --git a/contrib/llvm/include/llvm/Support/DebugLoc.h b/contrib/llvm/include/llvm/Support/DebugLoc.h index ccc344612913..98a05a45a76d 100644 --- a/contrib/llvm/include/llvm/Support/DebugLoc.h +++ b/contrib/llvm/include/llvm/Support/DebugLoc.h @@ -15,6 +15,8 @@ #ifndef LLVM_SUPPORT_DEBUGLOC_H #define LLVM_SUPPORT_DEBUGLOC_H +#include "llvm/ADT/DenseMapInfo.h" + namespace llvm { class MDNode; class LLVMContext; @@ -23,6 +25,24 @@ namespace llvm { /// and MachineInstr to compactly encode file/line/scope information for an /// operation. class DebugLoc { + friend struct DenseMapInfo; + + /// getEmptyKey() - A private constructor that returns an unknown that is + /// not equal to the tombstone key or DebugLoc(). + static DebugLoc getEmptyKey() { + DebugLoc DL; + DL.LineCol = 1; + return DL; + } + + /// getTombstoneKey() - A private constructor that returns an unknown that + /// is not equal to the empty key or DebugLoc(). + static DebugLoc getTombstoneKey() { + DebugLoc DL; + DL.LineCol = 2; + return DL; + } + /// LineCol - This 32-bit value encodes the line and column number for the /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 /// for either means unknown. @@ -75,6 +95,14 @@ namespace llvm { } bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } }; + + template <> + struct DenseMapInfo { + static DebugLoc getEmptyKey(); + static DebugLoc getTombstoneKey(); + static unsigned getHashValue(const DebugLoc &Key); + static bool isEqual(const DebugLoc &LHS, const DebugLoc &RHS); + }; } // end namespace llvm #endif /* LLVM_DEBUGLOC_H */ diff --git a/contrib/llvm/include/llvm/Support/Dwarf.h b/contrib/llvm/include/llvm/Support/Dwarf.h index 5d0b5a943d56..f6d680b8b9d8 100644 --- a/contrib/llvm/include/llvm/Support/Dwarf.h +++ b/contrib/llvm/include/llvm/Support/Dwarf.h @@ -231,6 +231,10 @@ enum dwarf_constants { DW_AT_APPLE_major_runtime_vers = 0x3fe5, DW_AT_APPLE_runtime_class = 0x3fe6, DW_AT_APPLE_omit_frame_ptr = 0x3fe7, + DW_AT_APPLE_property_name = 0x3fe8, + DW_AT_APPLE_property_getter = 0x3fe9, + DW_AT_APPLE_property_setter = 0x3fea, + DW_AT_APPLE_property_attribute = 0x3feb, // Attribute form encodings DW_FORM_addr = 0x01, @@ -407,6 +411,7 @@ enum dwarf_constants { DW_OP_call_ref = 0x9a, DW_OP_form_tls_address = 0x9b, DW_OP_call_frame_cfa = 0x9c, + DW_OP_bit_piece = 0x9d, DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff, @@ -584,7 +589,15 @@ enum dwarf_constants { DW_EH_PE_datarel = 0x30, DW_EH_PE_funcrel = 0x40, DW_EH_PE_aligned = 0x50, - DW_EH_PE_indirect = 0x80 + DW_EH_PE_indirect = 0x80, + + // Apple Objective-C Property Attributes + DW_APPLE_PROPERTY_readonly = 0x01, + DW_APPLE_PROPERTY_readwrite = 0x02, + DW_APPLE_PROPERTY_assign = 0x04, + DW_APPLE_PROPERTY_retain = 0x08, + DW_APPLE_PROPERTY_copy = 0x10, + DW_APPLE_PROPERTY_nonatomic = 0x20 }; /// TagString - Return the string for the specified tag. diff --git a/contrib/llvm/include/llvm/Support/ErrorHandling.h b/contrib/llvm/include/llvm/Support/ErrorHandling.h index 5eca438d8b4a..95b01095c1b2 100644 --- a/contrib/llvm/include/llvm/Support/ErrorHandling.h +++ b/contrib/llvm/include/llvm/Support/ErrorHandling.h @@ -86,16 +86,19 @@ namespace llvm { unsigned line=0); } -/// Prints the message and location info to stderr in !NDEBUG builds. -/// This is intended to be used for "impossible" situations that imply -/// a bug in the compiler. +/// Marks that the current location is not supposed to be reachable. +/// In !NDEBUG builds, prints the message and location info to stderr. +/// In NDEBUG builds, becomes an optimizer hint that the current location +/// is not supposed to be reachable. On compilers that don't support +/// such hints, prints a reduced message instead. /// -/// In NDEBUG mode it only prints "UNREACHABLE executed". -/// Use this instead of assert(0), so that the compiler knows this path -/// is not reachable even for NDEBUG builds. +/// Use this instead of assert(0). It conveys intent more clearly and +/// allows compilers to omit some unnecessary code. #ifndef NDEBUG #define llvm_unreachable(msg) \ ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__) +#elif defined(LLVM_BUILTIN_UNREACHABLE) +#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE #else #define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal() #endif diff --git a/contrib/llvm/include/llvm/Support/FileSystem.h b/contrib/llvm/include/llvm/Support/FileSystem.h index 4001bf0b84e3..4f013f89e86c 100644 --- a/contrib/llvm/include/llvm/Support/FileSystem.h +++ b/contrib/llvm/include/llvm/Support/FileSystem.h @@ -595,7 +595,7 @@ class directory_entry { void replace_filename(const Twine &filename, file_status st = file_status(), file_status symlink_st = file_status()); - StringRef path() const { return Path; } + const std::string &path() const { return Path; } error_code status(file_status &result) const; error_code symlink_status(file_status &result) const; diff --git a/contrib/llvm/include/llvm/Support/FileUtilities.h b/contrib/llvm/include/llvm/Support/FileUtilities.h index 748ce7cea7bd..5456eb730a17 100644 --- a/contrib/llvm/include/llvm/Support/FileUtilities.h +++ b/contrib/llvm/include/llvm/Support/FileUtilities.h @@ -15,13 +15,14 @@ #ifndef LLVM_SUPPORT_FILEUTILITIES_H #define LLVM_SUPPORT_FILEUTILITIES_H +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" namespace llvm { /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if /// the files match, 1 if they are different, and 2 if there is a file error. - /// This function allows you to specify an absolete and relative FP error that + /// This function allows you to specify an absolute and relative FP error that /// is allowed to exist. If you specify a string to fill in for the error /// option, it will set the string to an error message if an error occurs, or /// if the files are different. @@ -37,29 +38,36 @@ namespace llvm { /// specified (if deleteIt is true). /// class FileRemover { - sys::Path Filename; + SmallString<128> Filename; bool DeleteIt; public: FileRemover() : DeleteIt(false) {} - explicit FileRemover(const sys::Path &filename, bool deleteIt = true) - : Filename(filename), DeleteIt(deleteIt) {} + explicit FileRemover(const Twine& filename, bool deleteIt = true) + : DeleteIt(deleteIt) { + filename.toVector(Filename); + } ~FileRemover() { if (DeleteIt) { // Ignore problems deleting the file. - Filename.eraseFromDisk(); + bool existed; + sys::fs::remove(Filename.str(), existed); } } /// setFile - Give ownership of the file to the FileRemover so it will /// be removed when the object is destroyed. If the FileRemover already /// had ownership of a file, remove it first. - void setFile(const sys::Path &filename, bool deleteIt = true) { - if (DeleteIt) - Filename.eraseFromDisk(); + void setFile(const Twine& filename, bool deleteIt = true) { + if (DeleteIt) { + // Ignore problems deleting the file. + bool existed; + sys::fs::remove(Filename.str(), existed); + } - Filename = filename; + Filename.clear(); + filename.toVector(Filename); DeleteIt = deleteIt; } diff --git a/contrib/llvm/include/llvm/Support/GraphWriter.h b/contrib/llvm/include/llvm/Support/GraphWriter.h index 7573ef0dc9e7..eab0c9d18db1 100644 --- a/contrib/llvm/include/llvm/Support/GraphWriter.h +++ b/contrib/llvm/include/llvm/Support/GraphWriter.h @@ -70,7 +70,7 @@ class GraphWriter { for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { std::string label = DTraits.getEdgeSourceLabel(Node, EI); - if (label == "") + if (label.empty()) continue; hasEdgeSourceLabels = true; @@ -78,7 +78,7 @@ class GraphWriter { if (i) O << "|"; - O << "" << DTraits.getEdgeSourceLabel(Node, EI); + O << "" << DOT::EscapeString(label); } if (EI != EE && hasEdgeSourceLabels) @@ -235,12 +235,12 @@ class GraphWriter { DestPort = static_cast(Offset); } - if (DTraits.getEdgeSourceLabel(Node, EI) == "") + if (DTraits.getEdgeSourceLabel(Node, EI).empty()) edgeidx = -1; emitEdge(static_cast(Node), edgeidx, static_cast(TargetNode), DestPort, - DTraits.getEdgeAttributes(Node, EI)); + DTraits.getEdgeAttributes(Node, EI, G)); } } @@ -272,7 +272,7 @@ class GraphWriter { const void *DestNodeID, int DestNodePort, const std::string &Attrs) { if (SrcNodePort > 64) return; // Eminating from truncated part? - if (DestNodePort > 64) DestNodePort = 64; // Targetting the truncated part? + if (DestNodePort > 64) DestNodePort = 64; // Targeting the truncated part? O << "\tNode" << SrcNodeID; if (SrcNodePort >= 0) diff --git a/contrib/llvm/include/llvm/Support/IRBuilder.h b/contrib/llvm/include/llvm/Support/IRBuilder.h index 2394a59c09cb..3878e793dbe0 100644 --- a/contrib/llvm/include/llvm/Support/IRBuilder.h +++ b/contrib/llvm/include/llvm/Support/IRBuilder.h @@ -17,6 +17,8 @@ #include "llvm/Instructions.h" #include "llvm/BasicBlock.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ConstantFolder.h" @@ -152,9 +154,10 @@ class IRBuilderBase { /// CreateGlobalString - Make a new global variable with an initializer that /// has array of i8 type filled in with the nul terminated string value - /// specified. If Name is specified, it is the name of the global variable - /// created. - Value *CreateGlobalString(const char *Str = "", const Twine &Name = ""); + /// specified. The new global variable will be marked mergable with any + /// others of the same contents. If Name is specified, it is the name of the + /// global variable created. + Value *CreateGlobalString(StringRef Str, const Twine &Name = ""); /// getInt1 - Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { @@ -190,6 +193,10 @@ class IRBuilderBase { ConstantInt *getInt64(uint64_t C) { return ConstantInt::get(getInt64Ty(), C); } + + ConstantInt *getInt(const APInt &AI) { + return ConstantInt::get(Context, AI); + } //===--------------------------------------------------------------------===// // Type creation methods @@ -301,7 +308,7 @@ class IRBuilder : public IRBuilderBase, public Inserter { : IRBuilderBase(C), Inserter(I), Folder(F) { } - explicit IRBuilder(LLVMContext &C) : IRBuilderBase(C), Folder(C) { + explicit IRBuilder(LLVMContext &C) : IRBuilderBase(C), Folder() { } explicit IRBuilder(BasicBlock *TheBB, const T &F) @@ -310,12 +317,12 @@ class IRBuilder : public IRBuilderBase, public Inserter { } explicit IRBuilder(BasicBlock *TheBB) - : IRBuilderBase(TheBB->getContext()), Folder(Context) { + : IRBuilderBase(TheBB->getContext()), Folder() { SetInsertPoint(TheBB); } explicit IRBuilder(Instruction *IP) - : IRBuilderBase(IP->getContext()), Folder(Context) { + : IRBuilderBase(IP->getContext()), Folder() { SetInsertPoint(IP); } @@ -325,7 +332,7 @@ class IRBuilder : public IRBuilderBase, public Inserter { } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP) - : IRBuilderBase(TheBB->getContext()), Folder(Context) { + : IRBuilderBase(TheBB->getContext()), Folder() { SetInsertPoint(TheBB, IP); } @@ -861,7 +868,7 @@ class IRBuilder : public IRBuilderBase, public Inserter { /// CreateGlobalStringPtr - Same as CreateGlobalString, but return a pointer /// with "i8*" type instead of a pointer to array of i8. - Value *CreateGlobalStringPtr(const char *Str = "", const Twine &Name = "") { + Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { Value *gv = CreateGlobalString(Str, Name); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; @@ -1070,8 +1077,9 @@ class IRBuilder : public IRBuilderBase, public Inserter { // Instruction creation methods: Other Instructions //===--------------------------------------------------------------------===// - PHINode *CreatePHI(const Type *Ty, const Twine &Name = "") { - return Insert(PHINode::Create(Ty), Name); + PHINode *CreatePHI(const Type *Ty, unsigned NumReservedValues, + const Twine &Name = "") { + return Insert(PHINode::Create(Ty, NumReservedValues), Name); } CallInst *CreateCall(Value *Callee, const Twine &Name = "") { @@ -1101,6 +1109,11 @@ class IRBuilder : public IRBuilderBase, public Inserter { return Insert(CallInst::Create(Callee, Args, Args+5), Name); } + CallInst *CreateCall(Value *Callee, ArrayRef Arg, + const Twine &Name = "") { + return Insert(CallInst::Create(Callee, Arg.begin(), Arg.end(), Name)); + } + template CallInst *CreateCall(Value *Callee, RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, const Twine &Name = "") { diff --git a/contrib/llvm/include/llvm/Support/Memory.h b/contrib/llvm/include/llvm/Support/Memory.h index 9c3f85b958bc..37890e7e4af1 100644 --- a/contrib/llvm/include/llvm/Support/Memory.h +++ b/contrib/llvm/include/llvm/Support/Memory.h @@ -75,12 +75,12 @@ namespace sys { /// setExecutable - Before the JIT can run a block of code, it has to be /// given read and executable privilege. Return true if it is already r-x /// or the system is able to change its previlege. - static bool setExecutable (MemoryBlock &M, std::string *ErrMsg = 0); + static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = 0); /// setWritable - When adding to a block of code, the JIT may need /// to mark a block of code as RW since the protections are on page /// boundaries, and the JIT internal allocations are not page aligned. - static bool setWritable (MemoryBlock &M, std::string *ErrMsg = 0); + static bool setWritable(MemoryBlock &M, std::string *ErrMsg = 0); /// setRangeExecutable - Mark the page containing a range of addresses /// as executable. diff --git a/contrib/llvm/include/llvm/Support/MemoryBuffer.h b/contrib/llvm/include/llvm/Support/MemoryBuffer.h index b6243b7b10dd..d912e86c8b4e 100644 --- a/contrib/llvm/include/llvm/Support/MemoryBuffer.h +++ b/contrib/llvm/include/llvm/Support/MemoryBuffer.h @@ -40,7 +40,8 @@ class MemoryBuffer { MemoryBuffer &operator=(const MemoryBuffer &); // DO NOT IMPLEMENT protected: MemoryBuffer() {} - void init(const char *BufStart, const char *BufEnd); + void init(const char *BufStart, const char *BufEnd, + bool RequiresNullTerminator); public: virtual ~MemoryBuffer(); @@ -63,21 +64,27 @@ class MemoryBuffer { /// specified, this means that the client knows that the file exists and that /// it has the specified size. static error_code getFile(StringRef Filename, OwningPtr &result, - int64_t FileSize = -1); + int64_t FileSize = -1, + bool RequiresNullTerminator = true); static error_code getFile(const char *Filename, OwningPtr &result, - int64_t FileSize = -1); + int64_t FileSize = -1, + bool RequiresNullTerminator = true); /// getOpenFile - Given an already-open file descriptor, read the file and /// return a MemoryBuffer. static error_code getOpenFile(int FD, const char *Filename, OwningPtr &result, - int64_t FileSize = -1); + size_t FileSize = -1, + size_t MapSize = -1, + off_t Offset = 0, + bool RequiresNullTerminator = true); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that InputData must be null terminated. static MemoryBuffer *getMemBuffer(StringRef InputData, - StringRef BufferName = ""); + StringRef BufferName = "", + bool RequiresNullTerminator = true); /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, /// copying the contents and taking ownership of it. InputData does not @@ -112,6 +119,21 @@ class MemoryBuffer { static error_code getFileOrSTDIN(const char *Filename, OwningPtr &result, int64_t FileSize = -1); + + + //===--------------------------------------------------------------------===// + // Provided for performance analysis. + //===--------------------------------------------------------------------===// + + /// The kind of memory backing used to support the MemoryBuffer. + enum BufferKind { + MemoryBuffer_Malloc, + MemoryBuffer_MMap + }; + + /// Return information on the memory mechanism used to support the + /// MemoryBuffer. + virtual BufferKind getBufferKind() const = 0; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/NoFolder.h b/contrib/llvm/include/llvm/Support/NoFolder.h index 92a9fd695e58..5ead26ec25c1 100644 --- a/contrib/llvm/include/llvm/Support/NoFolder.h +++ b/contrib/llvm/include/llvm/Support/NoFolder.h @@ -27,12 +27,10 @@ namespace llvm { -class LLVMContext; - /// NoFolder - Create "constants" (actually, instructions) with no folding. class NoFolder { public: - explicit NoFolder(LLVMContext &) {} + explicit NoFolder() {} //===--------------------------------------------------------------------===// // Binary Operators diff --git a/contrib/llvm/include/llvm/Support/PathV1.h b/contrib/llvm/include/llvm/Support/PathV1.h index d7753a3e71e7..024bb39cedc2 100644 --- a/contrib/llvm/include/llvm/Support/PathV1.h +++ b/contrib/llvm/include/llvm/Support/PathV1.h @@ -608,14 +608,15 @@ namespace sys { /// /// This API is not intended for general use, clients should use /// MemoryBuffer::getFile instead. - static const char *MapInFilePages(int FD, uint64_t FileSize); + static const char *MapInFilePages(int FD, size_t FileSize, + off_t Offset); /// UnMapFilePages - Free pages mapped into the current process by /// MapInFilePages. /// /// This API is not intended for general use, clients should use /// MemoryBuffer::getFile instead. - static void UnMapFilePages(const char *Base, uint64_t FileSize); + static void UnMapFilePages(const char *Base, size_t FileSize); /// @} /// @name Data diff --git a/contrib/llvm/include/llvm/Support/PatternMatch.h b/contrib/llvm/include/llvm/Support/PatternMatch.h index 948ae5176eeb..172480e7ae62 100644 --- a/contrib/llvm/include/llvm/Support/PatternMatch.h +++ b/contrib/llvm/include/llvm/Support/PatternMatch.h @@ -40,6 +40,23 @@ bool match(Val *V, const Pattern &P) { return const_cast(P).match(V); } + +template +struct OneUse_match { + SubPattern_t SubPattern; + + OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} + + template + bool match(OpTy *V) { + return V->hasOneUse() && SubPattern.match(V); + } +}; + +template +inline OneUse_match m_OneUse(const T &SubPattern) { return SubPattern; } + + template struct class_match { template @@ -227,7 +244,25 @@ struct specificval_ty { /// m_Specific - Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } +struct bind_const_intval_ty { + uint64_t &VR; + bind_const_intval_ty(uint64_t &V) : VR(V) {} + + template + bool match(ITy *V) { + if (ConstantInt *CV = dyn_cast(V)) + if (CV->getBitWidth() <= 64) { + VR = CV->getZExtValue(); + return true; + } + return false; + } +}; +/// 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. // diff --git a/contrib/llvm/include/llvm/Support/PrettyStackTrace.h b/contrib/llvm/include/llvm/Support/PrettyStackTrace.h index 6dbce393b97e..9b3ecda50c1e 100644 --- a/contrib/llvm/include/llvm/Support/PrettyStackTrace.h +++ b/contrib/llvm/include/llvm/Support/PrettyStackTrace.h @@ -20,7 +20,7 @@ namespace llvm { class raw_ostream; /// DisablePrettyStackTrace - Set this to true to disable this module. This - /// might be neccessary if the host application installs its own signal + /// might be necessary if the host application installs its own signal /// handlers which conflict with the ones installed by this module. /// Defaults to false. extern bool DisablePrettyStackTrace; diff --git a/contrib/llvm/include/llvm/Support/Program.h b/contrib/llvm/include/llvm/Support/Program.h index 78a495ef2105..96b35660f96b 100644 --- a/contrib/llvm/include/llvm/Support/Program.h +++ b/contrib/llvm/include/llvm/Support/Program.h @@ -102,7 +102,7 @@ namespace sys { ); /// This function terminates the program. - /// @returns true if an error occured. + /// @returns true if an error occurred. /// @see Execute /// @brief Terminates the program. bool Kill diff --git a/contrib/llvm/include/llvm/Support/Regex.h b/contrib/llvm/include/llvm/Support/Regex.h index b46a66889e96..7648e77bfbb5 100644 --- a/contrib/llvm/include/llvm/Support/Regex.h +++ b/contrib/llvm/include/llvm/Support/Regex.h @@ -53,7 +53,7 @@ namespace llvm { /// matches - Match the regex against a given \arg String. /// - /// \param Matches - If given, on a succesful match this will be filled in + /// \param Matches - If given, on a successful match this will be filled in /// with references to the matched group expressions (inside \arg String), /// the first group is always the entire pattern. /// diff --git a/contrib/llvm/include/llvm/Support/Signals.h b/contrib/llvm/include/llvm/Support/Signals.h index 9a84df68ddba..634f4cf76dc0 100644 --- a/contrib/llvm/include/llvm/Support/Signals.h +++ b/contrib/llvm/include/llvm/Support/Signals.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines some helpful functions for dealing with the possibility of -// unix signals occuring while your program is running. +// unix signals occurring while your program is running. // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/Support/SourceMgr.h b/contrib/llvm/include/llvm/Support/SourceMgr.h index a41a633ba6b6..2a712e44bd17 100644 --- a/contrib/llvm/include/llvm/Support/SourceMgr.h +++ b/contrib/llvm/include/llvm/Support/SourceMgr.h @@ -156,10 +156,9 @@ class SMDiagnostic { // Null diagnostic. SMDiagnostic() : SM(0), LineNo(0), ColumnNo(0), ShowLine(0) {} // Diagnostic with no location (e.g. file not found, command line arg error). - SMDiagnostic(const std::string &filename, const std::string &Msg, - bool showline = true) + SMDiagnostic(const std::string &filename, const std::string &Msg) : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), - Message(Msg), ShowLine(showline) {} + Message(Msg), ShowLine(false) {} // Diagnostic with a location. SMDiagnostic(const SourceMgr &sm, SMLoc L, const std::string &FN, @@ -171,7 +170,7 @@ class SMDiagnostic { const SourceMgr *getSourceMgr() const { return SM; } SMLoc getLoc() const { return Loc; } - const std::string &getFilename() { return Filename; } + const std::string &getFilename() const { return Filename; } int getLineNo() const { return LineNo; } int getColumnNo() const { return ColumnNo; } const std::string &getMessage() const { return Message; } diff --git a/contrib/llvm/include/llvm/Support/StandardPasses.h b/contrib/llvm/include/llvm/Support/StandardPasses.h index d774faf38642..8dfd6f98abfd 100644 --- a/contrib/llvm/include/llvm/Support/StandardPasses.h +++ b/contrib/llvm/include/llvm/Support/StandardPasses.h @@ -72,6 +72,7 @@ namespace llvm { Pass *InliningPass) { createStandardAliasAnalysisPasses(PM); + // If all optimizations are disabled, just run the always-inline pass. if (OptimizationLevel == 0) { if (InliningPass) PM->add(InliningPass); @@ -83,9 +84,10 @@ namespace llvm { PM->add(createIPSCCPPass()); // IP SCCP PM->add(createDeadArgEliminationPass()); // Dead argument elimination + + PM->add(createInstructionCombiningPass());// Clean up after IPCP & DAE + PM->add(createCFGSimplificationPass()); // Clean up after IPCP & DAE } - PM->add(createInstructionCombiningPass()); // Clean up after IPCP & DAE - PM->add(createCFGSimplificationPass()); // Clean up after IPCP & DAE // Start of CallGraph SCC passes. if (UnitAtATime && HaveExceptions) @@ -120,7 +122,6 @@ namespace llvm { PM->add(createLoopDeletionPass()); // Delete dead loops if (UnrollLoops) PM->add(createLoopUnrollPass()); // Unroll small loops - PM->add(createInstructionCombiningPass()); // Clean up after the unroller if (OptimizationLevel > 1) PM->add(createGVNPass()); // Remove redundancies PM->add(createMemCpyOptPass()); // Remove memcpy / form memset @@ -134,6 +135,7 @@ namespace llvm { PM->add(createDeadStoreEliminationPass()); // Delete dead stores PM->add(createAggressiveDCEPass()); // Delete dead instructions PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createInstructionCombiningPass()); // Clean up after everything. if (UnitAtATime) { PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes diff --git a/contrib/llvm/include/llvm/Support/TimeValue.h b/contrib/llvm/include/llvm/Support/TimeValue.h index e1227118c22c..94f132a05ca7 100644 --- a/contrib/llvm/include/llvm/Support/TimeValue.h +++ b/contrib/llvm/include/llvm/Support/TimeValue.h @@ -35,13 +35,13 @@ namespace sys { public: /// A constant TimeValue representing the smallest time - /// value permissable by the class. MinTime is some point + /// value permissible by the class. MinTime is some point /// in the distant past, about 300 billion years BCE. /// @brief The smallest possible time value. static const TimeValue MinTime; /// A constant TimeValue representing the largest time - /// value permissable by the class. MaxTime is some point + /// value permissible by the class. MaxTime is some point /// in the distant future, about 300 billion years AD. /// @brief The largest possible time value. static const TimeValue MaxTime; diff --git a/contrib/llvm/include/llvm/Support/system_error.h b/contrib/llvm/include/llvm/Support/system_error.h index e5306ecfb35c..47759b99ecc5 100644 --- a/contrib/llvm/include/llvm/Support/system_error.h +++ b/contrib/llvm/include/llvm/Support/system_error.h @@ -1,4 +1,4 @@ -//===---------------------------- system_error ----------------------------===// +//===---------------------------- system_error ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/Target/SubtargetFeature.h b/contrib/llvm/include/llvm/Target/SubtargetFeature.h index 6c21ae9583e0..4213d9b12ed0 100644 --- a/contrib/llvm/include/llvm/Target/SubtargetFeature.h +++ b/contrib/llvm/include/llvm/Target/SubtargetFeature.h @@ -35,8 +35,8 @@ namespace llvm { struct SubtargetFeatureKV { const char *Key; // K-V key string const char *Desc; // Help descriptor - uint32_t Value; // K-V integer value - uint32_t Implies; // K-V bit mask + uint64_t Value; // K-V integer value + uint64_t Implies; // K-V bit mask // Compare routine for std binary search bool operator<(const SubtargetFeatureKV &S) const { @@ -94,7 +94,7 @@ class SubtargetFeatures { void AddFeature(const std::string &String, bool IsEnabled = true); /// Get feature bits. - uint32_t getBits(const SubtargetFeatureKV *CPUTable, + uint64_t getBits(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, const SubtargetFeatureKV *FeatureTable, size_t FeatureTableSize); diff --git a/contrib/llvm/include/llvm/Target/Target.td b/contrib/llvm/include/llvm/Target/Target.td index 0f7e6aaaf2fa..68f0515f2d17 100644 --- a/contrib/llvm/include/llvm/Target/Target.td +++ b/contrib/llvm/include/llvm/Target/Target.td @@ -32,17 +32,6 @@ class Register { string Namespace = ""; string AsmName = n; - // SpillSize - If this value is set to a non-zero value, it is the size in - // bits of the spill slot required to hold this register. If this value is - // set to zero, the information is inferred from any register classes the - // register belongs to. - int SpillSize = 0; - - // SpillAlignment - This value is used to specify the alignment required for - // spilling the register. Like SpillSize, this should only be explicitly - // specified if the register is not in a register class. - int SpillAlignment = 0; - // Aliases - A list of registers that this register overlaps with. A read or // modification of this register can potentially read or modify the aliased // registers. @@ -78,6 +67,13 @@ class Register { // -1 indicates that the gcc number is undefined and -2 that register number // is invalid for this mode/flavour. list DwarfNumbers = []; + + // CostPerUse - Additional cost of instructions using this register compared + // to other registers in its class. The register allocator will try to + // minimize the number of instructions using a register with a CostPerUse. + // This is used by the x86-64 and ARM Thumb targets where some registers + // require larger instruction encodings. + int CostPerUse = 0; } // RegisterWithSubRegs - This can be used to define instances of Register which @@ -200,6 +196,7 @@ class Instruction { bit isIndirectBranch = 0; // Is this instruction an indirect branch? bit isCompare = 0; // Is this instruction a comparison instruction? bit isMoveImm = 0; // Is this instruction a move immediate instruction? + bit isBitcast = 0; // Is this instruction a bitcast instruction? bit isBarrier = 0; // Can control flow fall through this instruction? bit isCall = 0; // Is this instruction a call instruction? bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand? @@ -590,9 +587,10 @@ class MnemonicAlias { /// InstAlias - This defines an alternate assembly syntax that is allowed to /// match an instruction that has a different (more canonical) assembly /// representation. -class InstAlias { +class InstAlias { string AsmString = Asm; // The .s format to match the instruction with. dag ResultInst = Result; // The MCInst to generate. + bit EmitAlias = Emit; // Emit the alias instead of what's aliased. // Predicates - Predicates that must be true for this to match. list Predicates = []; diff --git a/contrib/llvm/include/llvm/Target/TargetAsmBackend.h b/contrib/llvm/include/llvm/Target/TargetAsmBackend.h index 7527298efa9e..2111f6b7a950 100644 --- a/contrib/llvm/include/llvm/Target/TargetAsmBackend.h +++ b/contrib/llvm/include/llvm/Target/TargetAsmBackend.h @@ -16,6 +16,7 @@ #include "llvm/Support/DataTypes.h" namespace llvm { +class MCELFObjectTargetWriter; class MCFixup; class MCInst; class MCObjectWriter; @@ -40,6 +41,13 @@ class TargetAsmBackend { /// assembler backend to emit the final object file. virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0; + /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable + /// non-standard ELFObjectWriters. + virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { + assert(0 && "createELFObjectTargetWriter is not supported by asm backend"); + return 0; + } + /// hasReliableSymbolDifference - Check whether this target implements /// accurate relocations for differences between symbols. If not, differences /// between symbols will always be relocatable expressions and any references diff --git a/contrib/llvm/include/llvm/Target/TargetAsmInfo.h b/contrib/llvm/include/llvm/Target/TargetAsmInfo.h index 98aab142b8e4..0271b670464e 100644 --- a/contrib/llvm/include/llvm/Target/TargetAsmInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetAsmInfo.h @@ -58,6 +58,14 @@ class TargetAsmInfo { return TLOF->getEHFrameSection(); } + unsigned getFDEEncoding(bool CFI) const { + return TLOF->getFDEEncoding(CFI); + } + + bool isFunctionEHFrameSymbolPrivate() const { + return TLOF->isFunctionEHFrameSymbolPrivate(); + } + unsigned getDwarfRARegNum(bool isEH) const { return TRI->getDwarfRegNum(TRI->getRARegister(), isEH); } diff --git a/contrib/llvm/include/llvm/Target/TargetData.h b/contrib/llvm/include/llvm/Target/TargetData.h index 25065d30bb6e..32e3e2b0b617 100644 --- a/contrib/llvm/include/llvm/Target/TargetData.h +++ b/contrib/llvm/include/llvm/Target/TargetData.h @@ -160,7 +160,18 @@ class TargetData : public ImmutablePass { bool isIllegalInteger(unsigned Width) const { return !isLegalInteger(Width); } - + + /// fitsInLegalInteger - This function returns true if the specified type fits + /// in a native integer type supported by the CPU. For example, if the CPU + /// only supports i32 as a native integer type, then i27 fits in a legal + // integer type but i45 does not. + bool fitsInLegalInteger(unsigned Width) const { + for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i) + if (Width <= LegalIntWidths[i]) + return true; + return false; + } + /// Target pointer alignment unsigned getPointerABIAlignment() const { return PointerABIAlign; } /// Return target's alignment for stack-based pointers diff --git a/contrib/llvm/include/llvm/Target/TargetInstrDesc.h b/contrib/llvm/include/llvm/Target/TargetInstrDesc.h index 8823d5a4d17e..6e20e8a1ba83 100644 --- a/contrib/llvm/include/llvm/Target/TargetInstrDesc.h +++ b/contrib/llvm/include/llvm/Target/TargetInstrDesc.h @@ -105,6 +105,7 @@ namespace TID { IndirectBranch, Compare, MoveImm, + Bitcast, DelaySlot, FoldableAsLoad, MayLoad, @@ -358,6 +359,12 @@ class TargetInstrDesc { bool isMoveImmediate() const { return Flags & (1 << TID::MoveImm); } + + /// isBitcast - Return true if this instruction is a bitcast instruction. + /// + bool isBitcast() const { + return Flags & (1 << TID::Bitcast); + } /// isNotDuplicable - Return true if this instruction cannot be safely /// duplicated. For example, if the instruction has a unique labels attached diff --git a/contrib/llvm/include/llvm/Target/TargetInstrInfo.h b/contrib/llvm/include/llvm/Target/TargetInstrInfo.h index fc7b51ec6c2c..418f3fe062f2 100644 --- a/contrib/llvm/include/llvm/Target/TargetInstrInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetInstrInfo.h @@ -477,7 +477,7 @@ class TargetInstrInfo { } /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to - /// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should + /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads should /// be scheduled togther. On some targets if two loads are loading from /// addresses in the same cache line, it's better if they are scheduled /// together. This function takes two integers that represent the load offsets @@ -641,6 +641,10 @@ class TargetInstrInfo { virtual int getInstrLatency(const InstrItineraryData *ItinData, SDNode *Node) const; + /// isHighLatencyDef - Return true if this opcode has high latency to its + /// result. + virtual bool isHighLatencyDef(int opc) const { return false; } + /// hasHighOperandLatency - Compute operand latency between a def of 'Reg' /// and an use in the current loop, return true if the target considered /// it 'high'. This is used by optimization passes such as machine LICM to diff --git a/contrib/llvm/include/llvm/Target/TargetInstrItineraries.h b/contrib/llvm/include/llvm/Target/TargetInstrItineraries.h index a95b70f6b997..198d5854462f 100644 --- a/contrib/llvm/include/llvm/Target/TargetInstrItineraries.h +++ b/contrib/llvm/include/llvm/Target/TargetInstrItineraries.h @@ -155,9 +155,13 @@ class InstrItineraryData { /// in the itinerary. /// unsigned getStageLatency(unsigned ItinClassIndx) const { - // If the target doesn't provide itinerary information, use a - // simple non-zero default value for all instructions. - if (isEmpty()) + // If the target doesn't provide itinerary information, use a simple + // non-zero default value for all instructions. Some target's provide a + // dummy (Generic) itinerary which should be handled as if it's itinerary is + // empty. We identify this by looking for a reference to stage zero (invalid + // stage). This is different from beginStage == endState != 0, which could + // be used for zero-latency pseudo ops. + if (isEmpty() || Itineraries[ItinClassIndx].FirstStage == 0) return 1; // Calculate the maximum completion time for any stage. diff --git a/contrib/llvm/include/llvm/Target/TargetLibraryInfo.h b/contrib/llvm/include/llvm/Target/TargetLibraryInfo.h index bdd214b6b743..0914b5daa4b2 100644 --- a/contrib/llvm/include/llvm/Target/TargetLibraryInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetLibraryInfo.h @@ -23,9 +23,21 @@ namespace llvm { // void *memcpy(void *s1, const void *s2, size_t n); memcpy, + // void *memmove(void *s1, const void *s2, size_t n); + memmove, + /// void memset_pattern16(void *b, const void *pattern16, size_t len); memset_pattern16, + /// int iprintf(const char *format, ...); + iprintf, + + /// int siprintf(char *str, const char *format, ...); + siprintf, + + /// int fiprintf(FILE *stream, const char *format, ...); + fiprintf, + NumLibFuncs }; } diff --git a/contrib/llvm/include/llvm/Target/TargetLowering.h b/contrib/llvm/include/llvm/Target/TargetLowering.h index ba7574dfdbd7..17d761ce8fb8 100644 --- a/contrib/llvm/include/llvm/Target/TargetLowering.h +++ b/contrib/llvm/include/llvm/Target/TargetLowering.h @@ -39,6 +39,7 @@ namespace llvm { class AllocaInst; class APFloat; class CallInst; + class CCState; class Function; class FastISel; class FunctionLoweringInfo; @@ -189,14 +190,6 @@ class TargetLowering { return RepRegClassCostForVT[VT.getSimpleVT().SimpleTy]; } - /// getRegPressureLimit - Return the register pressure "high water mark" for - /// the specific register class. The scheduler is in high register pressure - /// mode (for the specific register class) if it goes over the limit. - virtual unsigned getRegPressureLimit(const TargetRegisterClass *RC, - MachineFunction &MF) const { - return 0; - } - /// isTypeLegal - Return true if the target has native support for the /// specified value type. This means that it has a register that directly /// holds it without promotions or expansions. @@ -934,6 +927,7 @@ class TargetLowering { bool isCalledByLegalizer() const { return CalledByLegalizer; } void AddToWorklist(SDNode *N); + void RemoveFromWorklist(SDNode *N); SDValue CombineTo(SDNode *N, const std::vector &To, bool AddTo = true); SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true); @@ -1048,7 +1042,7 @@ class TargetLowering { } /// JumpIsExpensive - Tells the code generator not to expand sequence of - /// operations into a seperate sequences that increases the amount of + /// operations into a separate sequences that increases the amount of /// flow control. void setJumpIsExpensive(bool isExpensive = true) { JumpIsExpensive = isExpensive; @@ -1258,6 +1252,9 @@ class TargetLowering { return SDValue(); // this is here to silence compiler errors } + /// HandleByVal - Target-specific cleanup for formal ByVal parameters. + virtual void HandleByVal(CCState *, unsigned &) const {} + /// CanLowerReturn - This hook should be implemented to check whether the /// return values described by the Outs array can fit into the return /// registers. If false is returned, an sret-demotion is performed. @@ -1291,6 +1288,26 @@ class TargetLowering { return false; } + /// mayBeEmittedAsTailCall - Return true if the target may be able emit the + /// call instruction as a tail call. This is used by optimization passes to + /// determine if it's profitable to duplicate return instructions to enable + /// tailcall optimization. + virtual bool mayBeEmittedAsTailCall(CallInst *CI) const { + return false; + } + + /// getTypeForExtArgOrReturn - Return the type that should be used to zero or + /// sign extend a zeroext/signext integer argument or return value. + /// FIXME: Most C calling convention requires the return type to be promoted, + /// 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, + ISD::NodeType ExtendKind) const { + EVT MinVT = getRegisterType(Context, MVT::i32); + return VT.bitsLT(MinVT) ? MinVT : VT; + } + /// LowerOperationWrapper - This callback is invoked by the type legalizer /// to legalize nodes with an illegal operand type but legal result types. /// It replaces the LowerOperation callback in the type Legalizer. diff --git a/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h index 34bf27132de5..7402ed697232 100644 --- a/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h +++ b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -140,6 +140,9 @@ class TargetLoweringObjectFile { const MCSection *getStaticDtorSection() const { return StaticDtorSection; } const MCSection *getLSDASection() const { return LSDASection; } virtual const MCSection *getEHFrameSection() const = 0; + virtual void emitPersonalityValue(MCStreamer &Streamer, + const TargetMachine &TM, + const MCSymbol *Sym) const; const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } const MCSection *getDwarfLineSection() const { return DwarfLineSection; } @@ -218,15 +221,19 @@ class TargetLoweringObjectFile { MachineModuleInfo *MMI, unsigned Encoding, MCStreamer &Streamer) const; + // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. + virtual MCSymbol * + getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI) const; + /// const MCExpr * - getExprForDwarfReference(const MCSymbol *Sym, Mangler *Mang, - MachineModuleInfo *MMI, unsigned Encoding, + getExprForDwarfReference(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const; virtual unsigned getPersonalityEncoding() const; virtual unsigned getLSDAEncoding() const; - virtual unsigned getFDEEncoding() const; + virtual unsigned getFDEEncoding(bool CFI) const; virtual unsigned getTTypeEncoding() const; protected: diff --git a/contrib/llvm/include/llvm/Target/TargetMachine.h b/contrib/llvm/include/llvm/Target/TargetMachine.h index 030bf5b89f77..78f770cc41c3 100644 --- a/contrib/llvm/include/llvm/Target/TargetMachine.h +++ b/contrib/llvm/include/llvm/Target/TargetMachine.h @@ -38,6 +38,7 @@ class PassManager; class Pass; class TargetELFWriterInfo; class formatted_raw_ostream; +class raw_ostream; // Relocation model types. namespace Reloc { @@ -105,7 +106,9 @@ class TargetMachine { unsigned MCRelaxAll : 1; unsigned MCNoExecStack : 1; + unsigned MCSaveTempLabels : 1; unsigned MCUseLoc : 1; + unsigned MCUseCFI : 1; public: virtual ~TargetMachine(); @@ -171,6 +174,14 @@ class TargetMachine { /// relaxed. void setMCRelaxAll(bool Value) { MCRelaxAll = Value; } + /// hasMCSaveTempLabels - Check whether temporary labels will be preserved + /// (i.e., not treated as temporary). + bool hasMCSaveTempLabels() const { return MCSaveTempLabels; } + + /// setMCSaveTempLabels - Set whether temporary labels will be preserved + /// (i.e., not treated as temporary). + void setMCSaveTempLabels(bool Value) { MCSaveTempLabels = Value; } + /// hasMCNoExecStack - Check whether an executable stack is not needed. bool hasMCNoExecStack() const { return MCNoExecStack; } @@ -183,6 +194,12 @@ class TargetMachine { /// setMCUseLoc - Set whether all we should use dwarf's .loc directive. void setMCUseLoc(bool Value) { MCUseLoc = Value; } + /// hasMCUseCFI - Check whether we should use dwarf's .cfi_* directives. + bool hasMCUseCFI() const { return MCUseCFI; } + + /// setMCUseCFI - Set whether all we should use dwarf's .cfi_* directives. + void setMCUseCFI(bool Value) { MCUseCFI = Value; } + /// getRelocationModel - Returns the code generation relocation model. The /// choices are static, PIC, and dynamic-no-pic, and target default. static Reloc::Model getRelocationModel(); @@ -267,6 +284,7 @@ class TargetMachine { /// virtual bool addPassesToEmitMC(PassManagerBase &, MCContext *&, + raw_ostream &, CodeGenOpt::Level, bool = true) { return true; @@ -324,6 +342,7 @@ class LLVMTargetMachine : public TargetMachine { /// virtual bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, + raw_ostream &OS, CodeGenOpt::Level OptLevel, bool DisableVerify = true); diff --git a/contrib/llvm/include/llvm/Target/TargetOptions.h b/contrib/llvm/include/llvm/Target/TargetOptions.h index 97ceffdaecb8..62190c166e3f 100644 --- a/contrib/llvm/include/llvm/Target/TargetOptions.h +++ b/contrib/llvm/include/llvm/Target/TargetOptions.h @@ -157,6 +157,11 @@ namespace llvm { /// wth earlier copy coalescing. extern bool StrongPHIElim; + /// getTrapFunctionName - If this returns a non-empty string, this means isel + /// should lower Intrinsic::trap to a call to the specified function name + /// instead of an ISD::TRAP node. + extern StringRef getTrapFunctionName(); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h b/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h index 121091c9b49b..205e76f9c6fc 100644 --- a/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h @@ -46,6 +46,7 @@ struct TargetRegisterDesc { const unsigned *Overlaps; // Overlapping registers, described above const unsigned *SubRegs; // Sub-register set, described above const unsigned *SuperRegs; // Super-register set, described above + unsigned CostPerUse; // Extra cost of instructions using register. }; class TargetRegisterClass { @@ -426,6 +427,12 @@ class TargetRegisterInfo { return get(RegNo).Name; } + /// getCostPerUse - Return the additional cost of using this register instead + /// of other registers in its class. + unsigned getCostPerUse(unsigned RegNo) const { + return get(RegNo).CostPerUse; + } + /// getNumRegs - Return the number of registers this target has (useful for /// sizing arrays holding per register information) unsigned getNumRegs() const { @@ -588,11 +595,32 @@ class TargetRegisterInfo { } /// getCrossCopyRegClass - Returns a legal register class to copy a register - /// in the specified class to or from. Returns NULL if it is possible to copy - /// between a two registers of the specified class. + /// in the specified class to or from. If it is possible to copy the register + /// directly without using a cross register class copy, return the specified + /// RC. Returns NULL if it is not possible to copy between a two registers of + /// the specified class. virtual const TargetRegisterClass * getCrossCopyRegClass(const TargetRegisterClass *RC) const { - return NULL; + return RC; + } + + /// getLargestLegalSuperClass - Returns the largest super class of RC that is + /// legal to use in the current sub-target and has the same spill size. + /// The returned register class can be used to create virtual registers which + /// means that all its registers can be copied and spilled. + virtual const TargetRegisterClass* + getLargestLegalSuperClass(const TargetRegisterClass *RC) const { + /// The default implementation is very conservative and doesn't allow the + /// register allocator to inflate register classes. + return RC; + } + + /// getRegPressureLimit - Return the register pressure "high water mark" for + /// the specific register class. The scheduler is in high register pressure + /// mode (for the specific register class) if it goes over the limit. + virtual unsigned getRegPressureLimit(const TargetRegisterClass *RC, + MachineFunction &MF) const { + return 0; } /// getAllocationOrder - Returns the register allocation order for a specified @@ -614,6 +642,14 @@ class TargetRegisterInfo { return 0; } + /// avoidWriteAfterWrite - Return true if the register allocator should avoid + /// writing a register from RC in two consecutive instructions. + /// This can avoid pipeline stalls on certain architectures. + /// It does cause increased register pressure, though. + virtual bool avoidWriteAfterWrite(const TargetRegisterClass *RC) const { + return false; + } + /// UpdateRegAllocHint - A callback to allow target a chance to update /// register allocation hints when a register is "changed" (e.g. coalesced) /// to another register. e.g. On ARM, some virtual registers should target @@ -631,6 +667,13 @@ class TargetRegisterInfo { return false; } + /// useFPForScavengingIndex - returns true if the target wants to use + /// frame pointer based accesses to spill to the scavenger emergency spill + /// slot. + virtual bool useFPForScavengingIndex(const MachineFunction &MF) const { + return true; + } + /// requiresFrameIndexScavenging - returns true if the target requires post /// PEI scavenging of registers for materializing frame index constants. virtual bool requiresFrameIndexScavenging(const MachineFunction &MF) const { diff --git a/contrib/llvm/include/llvm/Target/TargetRegistry.h b/contrib/llvm/include/llvm/Target/TargetRegistry.h index f851ad0a9bfb..a464822893ba 100644 --- a/contrib/llvm/include/llvm/Target/TargetRegistry.h +++ b/contrib/llvm/include/llvm/Target/TargetRegistry.h @@ -43,7 +43,7 @@ namespace llvm { MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, - bool useLoc, + bool useLoc, bool useCFI, MCInstPrinter *InstPrint, MCCodeEmitter *CE, TargetAsmBackend *TAB, @@ -78,6 +78,7 @@ namespace llvm { TargetMachine &TM); typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T); typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, + TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI); typedef MCCodeEmitter *(*CodeEmitterCtorTy)(const Target &T, @@ -95,6 +96,7 @@ namespace llvm { formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, + bool useCFI, MCInstPrinter *InstPrint, MCCodeEmitter *CE, TargetAsmBackend *TAB, @@ -286,11 +288,12 @@ namespace llvm { return MCDisassemblerCtorFn(*this); } - MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, + MCInstPrinter *createMCInstPrinter(TargetMachine &TM, + unsigned SyntaxVariant, const MCAsmInfo &MAI) const { if (!MCInstPrinterCtorFn) return 0; - return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI); + return MCInstPrinterCtorFn(*this, TM, SyntaxVariant, MAI); } @@ -327,12 +330,13 @@ namespace llvm { formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, + bool useCFI, MCInstPrinter *InstPrint, MCCodeEmitter *CE, TargetAsmBackend *TAB, bool ShowInst) const { // AsmStreamerCtorFn is default to llvm::createAsmStreamer - return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, + return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI, InstPrint, CE, TAB, ShowInst); } diff --git a/contrib/llvm/include/llvm/Target/TargetSelect.h b/contrib/llvm/include/llvm/Target/TargetSelect.h index 1891f879741a..c5ab90b0e03d 100644 --- a/contrib/llvm/include/llvm/Target/TargetSelect.h +++ b/contrib/llvm/include/llvm/Target/TargetSelect.h @@ -120,6 +120,19 @@ namespace llvm { return true; #endif } + + /// InitializeNativeTargetAsmParser - The main program should call + /// this function to initialize the native target asm parser. + inline bool InitializeNativeTargetAsmParser() { + // If we have a native target, initialize the corresponding asm parser. +#ifdef LLVM_NATIVE_ASMPARSER + LLVM_NATIVE_ASMPARSER(); + return false; +#else + return true; +#endif + } + } #endif diff --git a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td index c9be40d23f00..ff8d07de036c 100644 --- a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -490,6 +490,18 @@ class SDNodeXForm { def NOOP_SDNodeXForm : SDNodeXForm; +//===----------------------------------------------------------------------===// +// PatPred Subclasses. +// +// These allow specifying different sorts of predicates that control whether a +// node is matched. +// +class PatPred; + +class CodePatPred : PatPred { + code PredicateCode = predicate; +} + //===----------------------------------------------------------------------===// // Selection DAG Pattern Fragments. @@ -507,7 +519,8 @@ class PatFrag : SDPatternOperator { dag Operands = ops; dag Fragment = frag; - code Predicate = pred; + code PredicateCode = pred; + code ImmediateCode = [{}]; SDNodeXForm OperandTransform = xform; } @@ -516,6 +529,27 @@ class PatFrag : PatFrag<(ops), frag, pred, xform>; + +// ImmLeaf is a pattern fragment with a constraint on the immediate. The +// constraint is a function that is run on the immediate (always with the value +// sign extended out to an int64_t) as Imm. For example: +// +// def immSExt8 : ImmLeaf; +// +// this is a more convenient form to match 'imm' nodes in than PatLeaf and also +// is preferred over using PatLeaf because it allows the code generator to +// reason more about the constraint. +// +// If FastIsel should ignore all instructions that have an operand of this type, +// the FastIselShouldIgnore flag can be set. This is an optimization to reduce +// the code size of the generated fast instruction selector. +class ImmLeaf + : PatFrag<(ops), (vt imm), [{}], xform> { + let ImmediateCode = pred; + bit FastIselShouldIgnore = 0; +} + + // Leaf fragments. def vtInt : PatLeaf<(vt), [{ return N->getVT().isInteger(); }]>; diff --git a/contrib/llvm/include/llvm/Transforms/IPO.h b/contrib/llvm/include/llvm/Transforms/IPO.h index 12398813cc76..d12fd1db7ab0 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO.h +++ b/contrib/llvm/include/llvm/Transforms/IPO.h @@ -152,7 +152,6 @@ ModulePass *createDeadArgHackingPass(); /// equal to maxElements (maxElements == 0 means always promote). /// Pass *createArgumentPromotionPass(unsigned maxElements = 3); -Pass *createStructRetPromotionPass(); //===----------------------------------------------------------------------===// /// createIPConstantPropagationPass - This pass propagates constants from call diff --git a/contrib/llvm/include/llvm/Transforms/Instrumentation.h b/contrib/llvm/include/llvm/Transforms/Instrumentation.h index aa9873fb8afa..088775a9dfe7 100644 --- a/contrib/llvm/include/llvm/Transforms/Instrumentation.h +++ b/contrib/llvm/include/llvm/Transforms/Instrumentation.h @@ -17,7 +17,6 @@ namespace llvm { class ModulePass; -class FunctionPass; // Insert edge profiling instrumentation ModulePass *createEdgeProfilerPass(); @@ -28,6 +27,9 @@ ModulePass *createOptimalEdgeProfilerPass(); // Insert path profiling instrumentation ModulePass *createPathProfilerPass(); +// Insert GCOV profiling instrumentation +ModulePass *createGCOVProfilerPass(bool EmitNotes = true, bool EmitData = true); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Transforms/Scalar.h b/contrib/llvm/include/llvm/Transforms/Scalar.h index 6f2a38e5840c..de46a8d98407 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar.h @@ -128,7 +128,7 @@ Pass *createLoopInstSimplifyPass(); // // LoopUnroll - This pass is a simple loop unrolling pass. // -Pass *createLoopUnrollPass(); +Pass *createLoopUnrollPass(int Threshold = -1, int Count = -1, int AllowPartial = -1); //===----------------------------------------------------------------------===// // @@ -299,12 +299,6 @@ Pass *createLoopDeletionPass(); /// specific well-known (library) functions. FunctionPass *createSimplifyLibCallsPass(); -//===----------------------------------------------------------------------===// -// -/// createSimplifyHalfPowrLibCallsPass - This is an experimental pass that -/// optimizes specific half_pow functions. -FunctionPass *createSimplifyHalfPowrLibCallsPass(); - //===----------------------------------------------------------------------===// // // CodeGenPrepare - This pass prepares a function for instruction selection. diff --git a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h index 533586028700..90eabef12fa7 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -19,6 +19,7 @@ #include "llvm/BasicBlock.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/DebugLoc.h" namespace llvm { @@ -181,6 +182,10 @@ BasicBlock *SplitBlockPredecessors(BasicBlock *BB, BasicBlock *const *Preds, ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, BasicBlock *Pred); +/// GetFirstDebugLocInBasicBlock - Return first valid DebugLoc entry in a +/// given basic block. +DebugLoc GetFirstDebugLocInBasicBlock(const BasicBlock *BB); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h index 24ebb109a0ad..853de2dc0312 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h @@ -207,7 +207,7 @@ class InlineFunctionInfo { /// /// Note that this only does one level of inlining. For example, if the /// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now -/// exists in the instruction stream. Similiarly this will inline a recursive +/// exists in the instruction stream. Similarly this will inline a recursive /// function by one level. /// bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI); diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Local.h b/contrib/llvm/include/llvm/Transforms/Utils/Local.h index 2823fbb71997..e61dcb347c85 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/Local.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/Local.h @@ -19,14 +19,19 @@ namespace llvm { class User; class BasicBlock; +class Function; class BranchInst; class Instruction; +class DbgDeclareInst; +class StoreInst; +class LoadInst; class Value; class Pass; class PHINode; class AllocaInst; class ConstantExpr; class TargetData; +class DIBuilder; template class SmallVectorImpl; @@ -69,10 +74,6 @@ bool RecursivelyDeleteDeadPHINode(PHINode *PN); /// /// This returns true if it changed the code, note that it can delete /// instructions in other blocks as well in this block. -/// -/// WARNING: Do not use this function on unreachable blocks, as recursive -/// simplification is not able to handle corner-case scenarios that can -/// arise in them. bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD = 0); //===----------------------------------------------------------------------===// @@ -157,6 +158,24 @@ static inline unsigned getKnownAlignment(Value *V, const TargetData *TD = 0) { return getOrEnforceKnownAlignment(V, 0, TD); } +///===---------------------------------------------------------------------===// +/// Dbg Intrinsic utilities +/// + +/// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value +/// that has an associated llvm.dbg.decl intrinsic. +bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, + StoreInst *SI, DIBuilder &Builder); + +/// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value +/// that has an associated llvm.dbg.decl intrinsic. +bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, + LoadInst *LI, DIBuilder &Builder); + +/// LowerDbgDeclare - Lowers llvm.dbg.declare intrinsics into appropriate set +/// of llvm.dbg.value intrinsics. +bool LowerDbgDeclare(Function &F); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/TypeSymbolTable.h b/contrib/llvm/include/llvm/TypeSymbolTable.h index 9fdcb983232c..89ad534ffb88 100644 --- a/contrib/llvm/include/llvm/TypeSymbolTable.h +++ b/contrib/llvm/include/llvm/TypeSymbolTable.h @@ -133,7 +133,7 @@ class TypeSymbolTable : public AbstractTypeUser { /// is refined. virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); - /// This function markes a type as being concrete (defined). + /// This function marks a type as being concrete (defined). virtual void typeBecameConcrete(const DerivedType *AbsTy); /// @} diff --git a/contrib/llvm/include/llvm/User.h b/contrib/llvm/include/llvm/User.h index 1363495f7c07..3f9c28e7b381 100644 --- a/contrib/llvm/include/llvm/User.h +++ b/contrib/llvm/include/llvm/User.h @@ -95,11 +95,11 @@ class User : public Value { OperandList[i] = Val; } const Use &getOperandUse(unsigned i) const { - assert(i < NumOperands && "getOperand() out of range!"); + assert(i < NumOperands && "getOperandUse() out of range!"); return OperandList[i]; } Use &getOperandUse(unsigned i) { - assert(i < NumOperands && "getOperand() out of range!"); + assert(i < NumOperands && "getOperandUse() out of range!"); return OperandList[i]; } diff --git a/contrib/llvm/include/llvm/Value.h b/contrib/llvm/include/llvm/Value.h index 130e2735f525..3a1c3ca298c9 100644 --- a/contrib/llvm/include/llvm/Value.h +++ b/contrib/llvm/include/llvm/Value.h @@ -51,8 +51,8 @@ class MDNode; /// This is a very important LLVM class. It is the base class of all values /// computed by a program that may be used as operands to other values. Value is /// the super class of other important classes such as Instruction and Function. -/// All Values have a Type. Type is not a subclass of Value. All types can have -/// a name and they should belong to some Module. Setting the name on the Value +/// All Values have a Type. Type is not a subclass of Value. Some values can +/// have a name and they belong to some Module. Setting the name on the Value /// automatically updates the module's symbol table. /// /// Every value has a "use list" that keeps track of which other Values are diff --git a/contrib/llvm/lib/Analysis/AliasAnalysis.cpp b/contrib/llvm/lib/Analysis/AliasAnalysis.cpp index be02ddbaa534..c189a0042928 100644 --- a/contrib/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/AliasAnalysis.cpp @@ -86,14 +86,20 @@ AliasAnalysis::getModRefInfo(ImmutableCallSite CS, if (onlyAccessesArgPointees(MRB)) { bool doesAlias = false; - if (doesAccessArgPointees(MRB)) + if (doesAccessArgPointees(MRB)) { + MDNode *CSTag = CS.getInstruction()->getMetadata(LLVMContext::MD_tbaa); for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); - AI != AE; ++AI) - if (!isNoAlias(Location(*AI), Loc)) { + AI != AE; ++AI) { + const Value *Arg = *AI; + if (!Arg->getType()->isPointerTy()) + continue; + Location CSLoc(Arg, UnknownSize, CSTag); + if (!isNoAlias(CSLoc, Loc)) { doesAlias = true; break; } - + } + } if (!doesAlias) return NoModRef; } @@ -138,13 +144,19 @@ AliasAnalysis::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { // CS2's arguments. if (onlyAccessesArgPointees(CS2B)) { AliasAnalysis::ModRefResult R = NoModRef; - if (doesAccessArgPointees(CS2B)) + if (doesAccessArgPointees(CS2B)) { + MDNode *CS2Tag = CS2.getInstruction()->getMetadata(LLVMContext::MD_tbaa); for (ImmutableCallSite::arg_iterator I = CS2.arg_begin(), E = CS2.arg_end(); I != E; ++I) { - R = ModRefResult((R | getModRefInfo(CS1, *I, UnknownSize)) & Mask); + const Value *Arg = *I; + if (!Arg->getType()->isPointerTy()) + continue; + Location CS2Loc(Arg, UnknownSize, CS2Tag); + R = ModRefResult((R | getModRefInfo(CS1, CS2Loc)) & Mask); if (R == Mask) break; } + } return R; } @@ -152,13 +164,20 @@ AliasAnalysis::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { // any of the memory referenced by CS1's arguments. If not, return NoModRef. if (onlyAccessesArgPointees(CS1B)) { AliasAnalysis::ModRefResult R = NoModRef; - if (doesAccessArgPointees(CS1B)) + if (doesAccessArgPointees(CS1B)) { + MDNode *CS1Tag = CS1.getInstruction()->getMetadata(LLVMContext::MD_tbaa); for (ImmutableCallSite::arg_iterator - I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I) - if (getModRefInfo(CS2, *I, UnknownSize) != NoModRef) { + I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I) { + const Value *Arg = *I; + if (!Arg->getType()->isPointerTy()) + continue; + Location CS1Loc(Arg, UnknownSize, CS1Tag); + if (getModRefInfo(CS2, CS1Loc) != NoModRef) { R = Mask; break; } + } + } if (R == NoModRef) return R; } diff --git a/contrib/llvm/lib/Analysis/AliasSetTracker.cpp b/contrib/llvm/lib/Analysis/AliasSetTracker.cpp index 3a46976d66f7..2ed694941212 100644 --- a/contrib/llvm/lib/Analysis/AliasSetTracker.cpp +++ b/contrib/llvm/lib/Analysis/AliasSetTracker.cpp @@ -602,6 +602,10 @@ void AliasSetTracker::ASTCallbackVH::deleted() { // this now dangles! } +void AliasSetTracker::ASTCallbackVH::allUsesReplacedWith(Value *V) { + AST->copyValue(getValPtr(), V); +} + AliasSetTracker::ASTCallbackVH::ASTCallbackVH(Value *V, AliasSetTracker *ast) : CallbackVH(V), AST(ast) {} diff --git a/contrib/llvm/lib/Analysis/Analysis.cpp b/contrib/llvm/lib/Analysis/Analysis.cpp index 1af1c35f5392..6ebe100b1330 100644 --- a/contrib/llvm/lib/Analysis/Analysis.cpp +++ b/contrib/llvm/lib/Analysis/Analysis.cpp @@ -43,14 +43,12 @@ void llvm::initializeAnalysis(PassRegistry &Registry) { initializeLazyValueInfoPass(Registry); initializeLibCallAliasAnalysisPass(Registry); initializeLintPass(Registry); - initializeLiveValuesPass(Registry); initializeLoopDependenceAnalysisPass(Registry); initializeLoopInfoPass(Registry); initializeMemDepPrinterPass(Registry); initializeMemoryDependenceAnalysisPass(Registry); initializeModuleDebugInfoPrinterPass(Registry); initializePostDominatorTreePass(Registry); - initializePostDominanceFrontierPass(Registry); initializeProfileEstimatorPassPass(Registry); initializeNoProfileInfoPass(Registry); initializeNoPathProfileInfoPass(Registry); diff --git a/contrib/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/contrib/llvm/lib/Analysis/BasicAliasAnalysis.cpp index f7bcd9ec44d8..f1bb8a38f090 100644 --- a/contrib/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -350,7 +350,7 @@ DecomposeGEPExpression(const Value *V, int64_t &BaseOffs, Scale *= IndexScale.getSExtValue(); - // If we already had an occurrance of this index variable, merge this + // If we already had an occurrence of this index variable, merge this // scale into it. For example, we want to handle: // A[x][x] -> x*16 + x*4 -> x*20 // This also ensures that 'x' only appears in the index list once. @@ -779,6 +779,26 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS, return NoModRef; break; } + case Intrinsic::arm_neon_vld1: { + // LLVM's vld1 and vst1 intrinsics currently only support a single + // vector register. + uint64_t Size = + TD ? TD->getTypeStoreSize(II->getType()) : UnknownSize; + if (isNoAlias(Location(II->getArgOperand(0), Size, + II->getMetadata(LLVMContext::MD_tbaa)), + Loc)) + return NoModRef; + break; + } + case Intrinsic::arm_neon_vst1: { + uint64_t Size = + TD ? TD->getTypeStoreSize(II->getArgOperand(1)->getType()) : UnknownSize; + if (isNoAlias(Location(II->getArgOperand(0), Size, + II->getMetadata(LLVMContext::MD_tbaa)), + Loc)) + return NoModRef; + break; + } } // The AliasAnalysis base class has some smarts, lets use them. @@ -883,7 +903,7 @@ BasicAliasAnalysis::aliasGEP(const GEPOperator *GEP1, uint64_t V1Size, if (GEP1BaseOffset == 0 && GEP1VariableIndices.empty()) return MustAlias; - // If there is a difference betwen the pointers, but the difference is + // If there is a difference between the pointers, but the difference is // less than the size of the associated memory object, then we know // that the objects are partially overlapping. if (GEP1BaseOffset != 0 && GEP1VariableIndices.empty()) { diff --git a/contrib/llvm/lib/Analysis/CaptureTracking.cpp b/contrib/llvm/lib/Analysis/CaptureTracking.cpp index 42a54d9d1eb3..b2c27d1dfc4b 100644 --- a/contrib/llvm/lib/Analysis/CaptureTracking.cpp +++ b/contrib/llvm/lib/Analysis/CaptureTracking.cpp @@ -17,6 +17,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/Value.h" #include "llvm/Analysis/AliasAnalysis.h" diff --git a/contrib/llvm/lib/Analysis/ConstantFolding.cpp b/contrib/llvm/lib/Analysis/ConstantFolding.cpp index cd8d52c1c465..5de2b04e80dd 100644 --- a/contrib/llvm/lib/Analysis/ConstantFolding.cpp +++ b/contrib/llvm/lib/Analysis/ConstantFolding.cpp @@ -23,6 +23,7 @@ #include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" +#include "llvm/Operator.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallVector.h" @@ -1048,11 +1049,12 @@ llvm::canConstantFoldCallTo(const Function *F) { case Intrinsic::ctpop: case Intrinsic::ctlz: case Intrinsic::cttz: - case Intrinsic::uadd_with_overflow: - case Intrinsic::usub_with_overflow: case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: case Intrinsic::ssub_with_overflow: + case Intrinsic::usub_with_overflow: case Intrinsic::smul_with_overflow: + case Intrinsic::umul_with_overflow: case Intrinsic::convert_from_fp16: case Intrinsic::convert_to_fp16: case Intrinsic::x86_sse_cvtss2si: @@ -1362,7 +1364,8 @@ llvm::ConstantFoldCall(Function *F, case Intrinsic::uadd_with_overflow: case Intrinsic::ssub_with_overflow: case Intrinsic::usub_with_overflow: - case Intrinsic::smul_with_overflow: { + case Intrinsic::smul_with_overflow: + case Intrinsic::umul_with_overflow: { APInt Res; bool Overflow; switch (F->getIntrinsicID()) { @@ -1382,6 +1385,9 @@ llvm::ConstantFoldCall(Function *F, case Intrinsic::smul_with_overflow: Res = Op1->getValue().smul_ov(Op2->getValue(), Overflow); break; + case Intrinsic::umul_with_overflow: + Res = Op1->getValue().umul_ov(Op2->getValue(), Overflow); + break; } Constant *Ops[] = { ConstantInt::get(F->getContext(), Res), diff --git a/contrib/llvm/lib/Analysis/DIBuilder.cpp b/contrib/llvm/lib/Analysis/DIBuilder.cpp index 590a9c17a8fa..dc98c9e67a80 100644 --- a/contrib/llvm/lib/Analysis/DIBuilder.cpp +++ b/contrib/llvm/lib/Analysis/DIBuilder.cpp @@ -50,7 +50,7 @@ void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, MDString::get(VMContext, Flags), ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer) }; - TheCU = DICompileUnit(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + TheCU = DICompileUnit(MDNode::get(VMContext, Elts)); } /// createFile - Create a file descriptor to hold debugging information @@ -63,7 +63,7 @@ DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { MDString::get(VMContext, Directory), TheCU }; - return DIFile(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIFile(MDNode::get(VMContext, Elts)); } /// createEnumerator - Create a single enumerator value. @@ -73,7 +73,7 @@ DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) { MDString::get(VMContext, Name), ConstantInt::get(Type::getInt64Ty(VMContext), Val) }; - return DIEnumerator(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIEnumerator(MDNode::get(VMContext, Elts)); } /// createBasicType - Create debugging information entry for a basic @@ -95,7 +95,7 @@ DIType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createQaulifiedType - Create debugging information entry for a qualified @@ -114,7 +114,7 @@ DIType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags FromTy }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createPointerType - Create debugging information entry for a pointer. @@ -133,7 +133,7 @@ DIType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags PointeeTy }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createReferenceType - Create debugging information entry for a reference. @@ -151,7 +151,7 @@ DIType DIBuilder::createReferenceType(DIType RTy) { ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags RTy }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createTypedef - Create debugging information entry for a typedef. @@ -171,7 +171,7 @@ DIType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags Ty }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createFriend - Create debugging information entry for a 'friend'. @@ -191,7 +191,7 @@ DIType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags FriendTy }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createInheritance - Create debugging information entry to establish @@ -211,7 +211,7 @@ DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, ConstantInt::get(Type::getInt32Ty(VMContext), Flags), BaseTy }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createMemberType - Create debugging information entry for a member. @@ -233,7 +233,36 @@ DIType DIBuilder::createMemberType(StringRef Name, ConstantInt::get(Type::getInt32Ty(VMContext), Flags), Ty }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createObjCIVar - Create debugging information entry for Objective-C +/// instance variable. +DIType DIBuilder::createObjCIVar(StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType Ty, StringRef PropertyName, + StringRef GetterName, StringRef SetterName, + unsigned PropertyAttributes) { + // TAG_member is encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_member), + File, // Or TheCU ? Ty ? + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + Ty, + MDString::get(VMContext, PropertyName), + MDString::get(VMContext, GetterName), + MDString::get(VMContext, SetterName), + ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes) + }; + return DIType(MDNode::get(VMContext, Elts)); } /// createClassType - Create debugging information entry for a class. @@ -260,7 +289,7 @@ DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, VTableHoder, TemplateParams }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createTemplateTypeParameter - Create debugging information for template @@ -278,8 +307,7 @@ DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) }; - return DITemplateTypeParameter(MDNode::get(VMContext, &Elts[0], - array_lengthof(Elts))); + return DITemplateTypeParameter(MDNode::get(VMContext, Elts)); } /// createTemplateValueParameter - Create debugging information for template @@ -299,8 +327,7 @@ DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) }; - return DITemplateValueParameter(MDNode::get(VMContext, &Elts[0], - array_lengthof(Elts))); + return DITemplateValueParameter(MDNode::get(VMContext, Elts)); } /// createStructType - Create debugging information entry for a struct. @@ -325,7 +352,7 @@ DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createUnionType - Create debugging information entry for an union. @@ -350,7 +377,7 @@ DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createSubroutineType - Create subroutine type. @@ -371,7 +398,7 @@ DIType DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) { ConstantInt::get(Type::getInt32Ty(VMContext), 0), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createEnumerationType - Create debugging information entry for an @@ -396,7 +423,7 @@ DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name, ConstantInt::get(Type::getInt32Ty(VMContext), 0), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + MDNode *Node = MDNode::get(VMContext, Elts); NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.enum"); NMD->addOperand(Node); return DIType(Node); @@ -421,7 +448,7 @@ DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, ConstantInt::get(Type::getInt32Ty(VMContext), 0), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createVectorType - Create debugging information entry for a vector. @@ -443,7 +470,7 @@ DIType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, ConstantInt::get(Type::getInt32Ty(VMContext), 0), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), }; - return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DIType(MDNode::get(VMContext, Elts)); } /// createArtificialType - Create a new DIType with "artificial" flag set. @@ -467,7 +494,7 @@ DIType DIBuilder::createArtificialType(DIType Ty) { // Flags are stored at this slot. Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); - return DIType(MDNode::get(VMContext, Elts.data(), Elts.size())); + return DIType(MDNode::get(VMContext, Elts)); } /// retainType - Retain DIType in a module even if it is not referenced @@ -483,7 +510,7 @@ DIDescriptor DIBuilder::createUnspecifiedParameter() { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters) }; - return DIDescriptor(MDNode::get(VMContext, &Elts[0], 1)); + return DIDescriptor(MDNode::get(VMContext, Elts)); } /// createTemporaryType - Create a temporary forward-declared type. @@ -491,7 +518,7 @@ DIType DIBuilder::createTemporaryType() { // Give the temporary MDNode a tag. It doesn't matter what tag we // use here as long as DIType accepts it. Value *Elts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; - MDNode *Node = MDNode::getTemporary(VMContext, Elts, array_lengthof(Elts)); + MDNode *Node = MDNode::getTemporary(VMContext, Elts); return DIType(Node); } @@ -505,17 +532,17 @@ DIType DIBuilder::createTemporaryType(DIFile F) { NULL, F }; - MDNode *Node = MDNode::getTemporary(VMContext, Elts, array_lengthof(Elts)); + MDNode *Node = MDNode::getTemporary(VMContext, Elts); return DIType(Node); } /// getOrCreateArray - Get a DIArray, create one if required. -DIArray DIBuilder::getOrCreateArray(Value *const *Elements, unsigned NumElements) { - if (NumElements == 0) { +DIArray DIBuilder::getOrCreateArray(ArrayRef Elements) { + if (Elements.empty()) { Value *Null = llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)); - return DIArray(MDNode::get(VMContext, &Null, 1)); + return DIArray(MDNode::get(VMContext, Null)); } - return DIArray(MDNode::get(VMContext, Elements, NumElements)); + return DIArray(MDNode::get(VMContext, Elements)); } /// getOrCreateSubrange - Create a descriptor for a value range. This @@ -527,7 +554,7 @@ DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Hi) { ConstantInt::get(Type::getInt64Ty(VMContext), Hi) }; - return DISubrange(MDNode::get(VMContext, &Elts[0], 3)); + return DISubrange(MDNode::get(VMContext, Elts)); } /// createGlobalVariable - Create a new descriptor for the specified global. @@ -548,7 +575,7 @@ createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ Val }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + MDNode *Node = MDNode::get(VMContext, Elts); // Create a named metadata so that we do not lose this mdnode. NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); NMD->addOperand(Node); @@ -575,7 +602,7 @@ createStaticVariable(DIDescriptor Context, StringRef Name, ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ Val }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + MDNode *Node = MDNode::get(VMContext, Elts); // Create a named metadata so that we do not lose this mdnode. NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); NMD->addOperand(Node); @@ -586,17 +613,18 @@ createStaticVariable(DIDescriptor Context, StringRef Name, DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, DIType Ty, - bool AlwaysPreserve, unsigned Flags) { + bool AlwaysPreserve, unsigned Flags, + unsigned ArgNo) { Value *Elts[] = { GetTagConstant(VMContext, Tag), Scope, MDString::get(VMContext, Name), File, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24))), Ty, ConstantInt::get(Type::getInt32Ty(VMContext), Flags) }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + MDNode *Node = MDNode::get(VMContext, Elts); if (AlwaysPreserve) { // The optimizer may remove local variable. If there is an interest // to preserve variable info in such situation then stash it in a @@ -619,18 +647,19 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile F, unsigned LineNo, - DIType Ty, Value *const *Addr, - unsigned NumAddr) { + DIType Ty, ArrayRef Addr, + unsigned ArgNo) { SmallVector Elts; Elts.push_back(GetTagConstant(VMContext, Tag)); Elts.push_back(Scope); Elts.push_back(MDString::get(VMContext, Name)); Elts.push_back(F); - Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)); + Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24)))); Elts.push_back(Ty); - Elts.append(Addr, Addr+NumAddr); + Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext))); + Elts.append(Addr.begin(), Addr.end()); - return DIVariable(MDNode::get(VMContext, Elts.data(), Elts.size())); + return DIVariable(MDNode::get(VMContext, Elts)); } /// createFunction - Create a new descriptor for the specified function. @@ -641,8 +670,9 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context, DIType Ty, bool isLocalToUnit, bool isDefinition, unsigned Flags, bool isOptimized, - Function *Fn) { - + Function *Fn, + MDNode *TParams, + MDNode *Decl) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), @@ -660,9 +690,11 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context, llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), ConstantInt::get(Type::getInt32Ty(VMContext), Flags), ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - Fn + Fn, + TParams, + Decl }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + MDNode *Node = MDNode::get(VMContext, Elts); // Create a named metadata so that we do not lose this mdnode. NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); @@ -682,7 +714,8 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, MDNode *VTableHolder, unsigned Flags, bool isOptimized, - Function *Fn) { + Function *Fn, + MDNode *TParam) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), @@ -700,9 +733,10 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, VTableHolder, ConstantInt::get(Type::getInt32Ty(VMContext), Flags), ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - Fn + Fn, + TParam, }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + MDNode *Node = MDNode::get(VMContext, Elts); // Create a named metadata so that we do not lose this mdnode. NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); @@ -721,7 +755,7 @@ DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) }; - return DINameSpace(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DINameSpace(MDNode::get(VMContext, Elts)); } DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, @@ -736,7 +770,7 @@ DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, File, ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++) }; - return DILexicalBlock(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); + return DILexicalBlock(MDNode::get(VMContext, Elts)); } /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. @@ -747,7 +781,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), VarInfo }; + Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore); } @@ -759,7 +793,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), VarInfo }; + Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; // If this block already has a terminator then insert this intrinsic // before the terminator. @@ -778,7 +812,7 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - Value *Args[] = { MDNode::get(V->getContext(), &V, 1), + Value *Args[] = { MDNode::get(V->getContext(), V), ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), VarInfo }; return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore); @@ -793,7 +827,7 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - Value *Args[] = { MDNode::get(V->getContext(), &V, 1), + Value *Args[] = { MDNode::get(V->getContext(), V), ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), VarInfo }; return CallInst::Create(ValueFn, Args, Args+3, "", InsertAtEnd); diff --git a/contrib/llvm/lib/Analysis/DebugInfo.cpp b/contrib/llvm/lib/Analysis/DebugInfo.cpp index 9db1456edd05..67f8147f4d61 100644 --- a/contrib/llvm/lib/Analysis/DebugInfo.cpp +++ b/contrib/llvm/lib/Analysis/DebugInfo.cpp @@ -725,484 +725,6 @@ void DIVariable::dump() const { print(dbgs()); dbgs() << '\n'; } -//===----------------------------------------------------------------------===// -// DIFactory: Basic Helpers -//===----------------------------------------------------------------------===// - -DIFactory::DIFactory(Module &m) - : M(m), VMContext(M.getContext()), DeclareFn(0), ValueFn(0) {} - -Constant *DIFactory::GetTagConstant(unsigned TAG) { - assert((TAG & LLVMDebugVersionMask) == 0 && - "Tag too large for debug encoding!"); - return ConstantInt::get(Type::getInt32Ty(VMContext), TAG | LLVMDebugVersion); -} - -//===----------------------------------------------------------------------===// -// DIFactory: Primary Constructors -//===----------------------------------------------------------------------===// - -/// GetOrCreateArray - Create an descriptor for an array of descriptors. -/// This implicitly uniques the arrays created. -DIArray DIFactory::GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys) { - if (NumTys == 0) { - Value *Null = llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)); - return DIArray(MDNode::get(VMContext, &Null, 1)); - } - - SmallVector Elts(Tys, Tys+NumTys); - return DIArray(MDNode::get(VMContext, Elts.data(), Elts.size())); -} - -/// GetOrCreateSubrange - Create a descriptor for a value range. This -/// implicitly uniques the values returned. -DISubrange DIFactory::GetOrCreateSubrange(int64_t Lo, int64_t Hi) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_subrange_type), - ConstantInt::get(Type::getInt64Ty(VMContext), Lo), - ConstantInt::get(Type::getInt64Ty(VMContext), Hi) - }; - - return DISubrange(MDNode::get(VMContext, &Elts[0], 3)); -} - -/// CreateUnspecifiedParameter - Create unspeicified type descriptor -/// for the subroutine type. -DIDescriptor DIFactory::CreateUnspecifiedParameter() { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_unspecified_parameters) - }; - return DIDescriptor(MDNode::get(VMContext, &Elts[0], 1)); -} - -/// CreateCompileUnit - Create a new descriptor for the specified compile -/// unit. Note that this does not unique compile units within the module. -DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID, - StringRef Filename, - StringRef Directory, - StringRef Producer, - bool isMain, - bool isOptimized, - StringRef Flags, - unsigned RunTimeVer) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_compile_unit), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - ConstantInt::get(Type::getInt32Ty(VMContext), LangID), - MDString::get(VMContext, Filename), - MDString::get(VMContext, Directory), - MDString::get(VMContext, Producer), - ConstantInt::get(Type::getInt1Ty(VMContext), isMain), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - MDString::get(VMContext, Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer) - }; - - return DICompileUnit(MDNode::get(VMContext, &Elts[0], 10)); -} - -/// CreateFile - Create a new descriptor for the specified file. -DIFile DIFactory::CreateFile(StringRef Filename, - StringRef Directory, - DICompileUnit CU) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_file_type), - MDString::get(VMContext, Filename), - MDString::get(VMContext, Directory), - CU - }; - - return DIFile(MDNode::get(VMContext, &Elts[0], 4)); -} - -/// CreateEnumerator - Create a single enumerator value. -DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){ - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_enumerator), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt64Ty(VMContext), Val) - }; - return DIEnumerator(MDNode::get(VMContext, &Elts[0], 3)); -} - - -/// CreateBasicType - Create a basic type like int, float, etc. -DIBasicType DIFactory::CreateBasicType(DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - unsigned Encoding) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_base_type), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) - }; - return DIBasicType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateBasicType - Create a basic type like int, float, etc. -DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, unsigned Flags, - unsigned Encoding) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_base_type), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - SizeInBits, - AlignInBits, - OffsetInBits, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) - }; - return DIBasicType(MDNode::get(VMContext, &Elts[0], 10)); -} - -/// CreateArtificialType - Create a new DIType with "artificial" flag set. -DIType DIFactory::CreateArtificialType(DIType Ty) { - if (Ty.isArtificial()) - return Ty; - - SmallVector Elts; - MDNode *N = Ty; - assert (N && "Unexpected input DIType!"); - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { - if (Value *V = N->getOperand(i)) - Elts.push_back(V); - else - Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))); - } - - unsigned CurFlags = Ty.getFlags(); - CurFlags = CurFlags | DIType::FlagArtificial; - - // Flags are stored at this slot. - Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); - - return DIType(MDNode::get(VMContext, Elts.data(), Elts.size())); -} - -/// CreateDerivedType - Create a derived type like const qualified type, -/// pointer, typedef, etc. -DIDerivedType DIFactory::CreateDerivedType(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, - unsigned Flags, - DIType DerivedFrom) { - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom, - }; - return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateDerivedType - Create a derived type like const qualified type, -/// pointer, typedef, etc. -DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, - unsigned Flags, - DIType DerivedFrom) { - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - SizeInBits, - AlignInBits, - OffsetInBits, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom, - }; - return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateCompositeType - Create a composite type like array, struct, etc. -DICompositeType DIFactory::CreateCompositeType(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, - unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RuntimeLang, - MDNode *ContainingType) { - - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom, - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang), - ContainingType - }; - - MDNode *Node = MDNode::get(VMContext, &Elts[0], 13); - // Create a named metadata so that we do not lose this enum info. - if (Tag == dwarf::DW_TAG_enumeration_type) { - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.enum"); - NMD->addOperand(Node); - } - return DICompositeType(Node); -} - -/// CreateTemporaryType - Create a temporary forward-declared type. -DIType DIFactory::CreateTemporaryType() { - // Give the temporary MDNode a tag. It doesn't matter what tag we - // use here as long as DIType accepts it. - Value *Elts[] = { - GetTagConstant(DW_TAG_base_type) - }; - MDNode *Node = MDNode::getTemporary(VMContext, Elts, array_lengthof(Elts)); - return DIType(Node); -} - -/// CreateTemporaryType - Create a temporary forward-declared type. -DIType DIFactory::CreateTemporaryType(DIFile F) { - // Give the temporary MDNode a tag. It doesn't matter what tag we - // use here as long as DIType accepts it. - Value *Elts[] = { - GetTagConstant(DW_TAG_base_type), - F.getCompileUnit(), - NULL, - F - }; - MDNode *Node = MDNode::getTemporary(VMContext, Elts, array_lengthof(Elts)); - return DIType(Node); -} - -/// CreateCompositeType - Create a composite type like array, struct, etc. -DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, - unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RuntimeLang, - MDNode *ContainingType) { - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - SizeInBits, - AlignInBits, - OffsetInBits, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom, - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang), - ContainingType - }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], 13); - // Create a named metadata so that we do not lose this enum info. - if (Tag == dwarf::DW_TAG_enumeration_type) { - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.enum"); - NMD->addOperand(Node); - } - return DICompositeType(Node); -} - - -/// CreateSubprogram - Create a new descriptor for the specified subprogram. -/// See comments in DISubprogram for descriptions of these fields. This -/// method does not unique the generated descriptors. -DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, - StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty, - bool isLocalToUnit, - bool isDefinition, - unsigned VK, unsigned VIndex, - DIType ContainingType, - unsigned Flags, - bool isOptimized, - Function *Fn) { - - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_subprogram), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context, - MDString::get(VMContext, Name), - MDString::get(VMContext, DisplayName), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK), - ConstantInt::get(Type::getInt32Ty(VMContext), VIndex), - ContainingType, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - Fn - }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], 17); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); - NMD->addOperand(Node); - return DISubprogram(Node); -} - -/// CreateSubprogramDefinition - Create new subprogram descriptor for the -/// given declaration. -DISubprogram DIFactory::CreateSubprogramDefinition(DISubprogram &SPDeclaration){ - if (SPDeclaration.isDefinition()) - return DISubprogram(SPDeclaration); - - MDNode *DeclNode = SPDeclaration; - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_subprogram), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - DeclNode->getOperand(2), // Context - DeclNode->getOperand(3), // Name - DeclNode->getOperand(4), // DisplayName - DeclNode->getOperand(5), // LinkageName - DeclNode->getOperand(6), // CompileUnit - DeclNode->getOperand(7), // LineNo - DeclNode->getOperand(8), // Type - DeclNode->getOperand(9), // isLocalToUnit - ConstantInt::get(Type::getInt1Ty(VMContext), true), - DeclNode->getOperand(11), // Virtuality - DeclNode->getOperand(12), // VIndex - DeclNode->getOperand(13), // Containting Type - DeclNode->getOperand(14), // Flags - DeclNode->getOperand(15), // isOptimized - SPDeclaration.getFunction() - }; - MDNode *Node =MDNode::get(VMContext, &Elts[0], 16); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); - NMD->addOperand(Node); - return DISubprogram(Node); -} - -/// CreateGlobalVariable - Create a new descriptor for the specified global. -DIGlobalVariable -DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty,bool isLocalToUnit, - bool isDefinition, llvm::GlobalVariable *Val) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_variable), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context, - MDString::get(VMContext, Name), - MDString::get(VMContext, DisplayName), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - Val - }; - - Value *const *Vs = &Elts[0]; - MDNode *Node = MDNode::get(VMContext,Vs, 12); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); - NMD->addOperand(Node); - - return DIGlobalVariable(Node); -} - -/// CreateGlobalVariable - Create a new descriptor for the specified constant. -DIGlobalVariable -DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty,bool isLocalToUnit, - bool isDefinition, llvm::Constant *Val) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_variable), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context, - MDString::get(VMContext, Name), - MDString::get(VMContext, DisplayName), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - Val - }; - - Value *const *Vs = &Elts[0]; - MDNode *Node = MDNode::get(VMContext,Vs, 12); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); - NMD->addOperand(Node); - - return DIGlobalVariable(Node); -} - /// fixupObjcLikeName - Replace contains special characters used /// in a typical Objective-C names with '.' in a given string. static void fixupObjcLikeName(std::string &Str) { @@ -1214,19 +736,6 @@ static void fixupObjcLikeName(std::string &Str) { } } -/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable -/// to hold function specific information. -NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, StringRef FuncName) { - SmallString<32> Out; - if (FuncName.find('[') == StringRef::npos) - return M.getOrInsertNamedMetadata(Twine("llvm.dbg.lv.", FuncName) - .toStringRef(Out)); - std::string Name = FuncName; - fixupObjcLikeName(Name); - return M.getOrInsertNamedMetadata(Twine("llvm.dbg.lv.", Name) - .toStringRef(Out)); -} - /// getFnSpecificMDNode - Return a NameMDNode, if available, that is /// suitable to hold function specific information. NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, StringRef FuncName) { @@ -1237,178 +746,18 @@ NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, StringRef FuncName) { return M.getNamedMetadata(Twine("llvm.dbg.lv.", Name)); } -/// CreateVariable - Create a new descriptor for the specified variable. -DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNo, - DIType Ty, bool AlwaysPreserve, - unsigned Flags) { - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags) - }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], 7); - if (AlwaysPreserve) { - // The optimizer may remove local variable. If there is an interest - // to preserve variable info in such situation then stash it in a - // named mdnode. - DISubprogram Fn(getDISubprogram(Context)); - StringRef FName = "fn"; - if (Fn.getFunction()) - FName = Fn.getFunction()->getName(); - char One = '\1'; - if (FName.startswith(StringRef(&One, 1))) - FName = FName.substr(1); - - - NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, FName); - FnLocals->addOperand(Node); - } - return DIVariable(Node); -} - - -/// CreateComplexVariable - Create a new descriptor for the specified variable -/// which has a complex address expression for its address. -DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context, - StringRef Name, DIFile F, - unsigned LineNo, - DIType Ty, Value *const *Addr, - unsigned NumAddr) { - SmallVector Elts; - Elts.push_back(GetTagConstant(Tag)); - Elts.push_back(Context); - Elts.push_back(MDString::get(VMContext, Name)); - Elts.push_back(F); - Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)); - Elts.push_back(Ty); - Elts.append(Addr, Addr+NumAddr); - - return DIVariable(MDNode::get(VMContext, Elts.data(), Elts.size())); -} - - -/// CreateBlock - This creates a descriptor for a lexical block with the -/// specified parent VMContext. -DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context, - DIFile F, unsigned LineNo, - unsigned Col) { - // Defeat MDNode uniqing for lexical blocks. - static unsigned int unique_id = 0; - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_lexical_block), - Context, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), Col), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++) - }; - return DILexicalBlock(MDNode::get(VMContext, &Elts[0], 6)); -} - -/// CreateNameSpace - This creates new descriptor for a namespace -/// with the specified parent context. -DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name, - DIFile F, - unsigned LineNo) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_namespace), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) - }; - return DINameSpace(MDNode::get(VMContext, &Elts[0], 5)); -} - -/// CreateLocation - Creates a debug info location. -DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo, - DIScope S, DILocation OrigLoc) { - Value *Elts[] = { - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo), - S, - OrigLoc, - }; - return DILocation(MDNode::get(VMContext, &Elts[0], 4)); -} - -//===----------------------------------------------------------------------===// -// DIFactory: Routines for inserting code into a function -//===----------------------------------------------------------------------===// - -/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. -Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, - Instruction *InsertBefore) { - assert(Storage && "no storage passed to dbg.declare"); - assert(D.Verify() && "empty DIVariable passed to dbg.declare"); - if (!DeclareFn) - DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - - Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), - D }; - return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore); -} - -/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. -Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, - BasicBlock *InsertAtEnd) { - assert(Storage && "no storage passed to dbg.declare"); - assert(D.Verify() && "invalid DIVariable passed to dbg.declare"); - if (!DeclareFn) - DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - - Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), - D }; - - // If this block already has a terminator then insert this intrinsic - // before the terminator. - if (TerminatorInst *T = InsertAtEnd->getTerminator()) - return CallInst::Create(DeclareFn, Args, Args+2, "", T); - else - return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd);} - -/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. -Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, - DIVariable D, - Instruction *InsertBefore) { - assert(V && "no value passed to dbg.value"); - assert(D.Verify() && "invalid DIVariable passed to dbg.value"); - if (!ValueFn) - ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - - Value *Args[] = { MDNode::get(V->getContext(), &V, 1), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - D }; - return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore); -} - -/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. -Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, - DIVariable D, - BasicBlock *InsertAtEnd) { - assert(V && "no value passed to dbg.value"); - assert(D.Verify() && "invalid DIVariable passed to dbg.value"); - if (!ValueFn) - ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - - Value *Args[] = { MDNode::get(V->getContext(), &V, 1), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - D }; - return CallInst::Create(ValueFn, Args, Args+3, "", InsertAtEnd); -} - -// RecordType - Record DIType in a module such that it is not lost even if -// it is not referenced through debug info anchors. -void DIFactory::RecordType(DIType T) { - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.ty"); - NMD->addOperand(T); +/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable +/// to hold function specific information. +NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, StringRef FuncName) { + SmallString<32> Out; + if (FuncName.find('[') == StringRef::npos) + return M.getOrInsertNamedMetadata(Twine("llvm.dbg.lv.", FuncName) + .toStringRef(Out)); + + std::string Name = FuncName; + fixupObjcLikeName(Name); + return M.getOrInsertNamedMetadata(Twine("llvm.dbg.lv.", Name) + .toStringRef(Out)); } diff --git a/contrib/llvm/lib/Analysis/IPA/GlobalsModRef.cpp b/contrib/llvm/lib/Analysis/IPA/GlobalsModRef.cpp index 116aaf418ea0..b226d66cd78a 100644 --- a/contrib/llvm/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/contrib/llvm/lib/Analysis/IPA/GlobalsModRef.cpp @@ -602,7 +602,7 @@ void GlobalsModRef::addEscapingUse(Use &U) { // For the purposes of this analysis, it is conservatively correct to treat // a newly escaping value equivalently to a deleted one. We could perhaps // be more precise by processing the new use and attempting to update our - // saved analysis results to accomodate it. + // saved analysis results to accommodate it. deleteValue(U); AliasAnalysis::addEscapingUse(U); diff --git a/contrib/llvm/lib/Analysis/IVUsers.cpp b/contrib/llvm/lib/Analysis/IVUsers.cpp index c8382186df3a..2cda7913f024 100644 --- a/contrib/llvm/lib/Analysis/IVUsers.cpp +++ b/contrib/llvm/lib/Analysis/IVUsers.cpp @@ -21,6 +21,7 @@ #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Target/TargetData.h" #include "llvm/Assembly/Writer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" @@ -83,7 +84,10 @@ bool IVUsers::AddUsersIfInteresting(Instruction *I) { return false; // Void and FP expressions cannot be reduced. // LSR is not APInt clean, do not touch integers bigger than 64-bits. - if (SE->getTypeSizeInBits(I->getType()) > 64) + // Also avoid creating IVs of non-native types. For example, we don't want a + // 64-bit IV in 32-bit code just because the loop has one 64-bit cast. + uint64_t Width = SE->getTypeSizeInBits(I->getType()); + if (Width > 64 || (TD && !TD->isLegalInteger(Width))) return false; if (!Processed.insert(I)) @@ -167,6 +171,7 @@ bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) { LI = &getAnalysis(); DT = &getAnalysis(); SE = &getAnalysis(); + TD = getAnalysisIfAvailable(); // Find all uses of induction variables in this loop, and categorize // them by stride. Start by finding all of the PHI nodes in the header for diff --git a/contrib/llvm/lib/Analysis/InlineCost.cpp b/contrib/llvm/lib/Analysis/InlineCost.cpp index 47f91cfc3bed..a820ecf0372a 100644 --- a/contrib/llvm/lib/Analysis/InlineCost.cpp +++ b/contrib/llvm/lib/Analysis/InlineCost.cpp @@ -501,7 +501,7 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, return InlineCost::getAlways(); if (CalleeFI->Metrics.usesDynamicAlloca) { - // Get infomation about the caller. + // Get information about the caller. FunctionInfo &CallerFI = CachedFunctionInfo[Caller]; // If we haven't calculated this information yet, do so now. @@ -549,7 +549,7 @@ InlineCost InlineCostAnalyzer::getSpecializationCost(Function *Callee, int Cost = 0; - // Look at the orginal size of the callee. Each instruction counts as 5. + // Look at the original size of the callee. Each instruction counts as 5. Cost += CalleeFI->Metrics.NumInsts * InlineConstants::InstrCost; // Offset that with the amount of code that can be constant-folded diff --git a/contrib/llvm/lib/Analysis/InstructionSimplify.cpp b/contrib/llvm/lib/Analysis/InstructionSimplify.cpp index 982dacb50bfc..9d6d3398feb8 100644 --- a/contrib/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/contrib/llvm/lib/Analysis/InstructionSimplify.cpp @@ -18,11 +18,13 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "instsimplify" +#include "llvm/Operator.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/Support/ConstantRange.h" #include "llvm/Support/PatternMatch.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Target/TargetData.h" @@ -899,6 +901,111 @@ Value *llvm::SimplifyFDivInst(Value *Op0, Value *Op1, const TargetData *TD, return ::SimplifyFDivInst(Op0, Op1, TD, DT, RecursionLimit); } +/// SimplifyRem - Given operands for an SRem or URem, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + if (Constant *C0 = dyn_cast(Op0)) { + if (Constant *C1 = dyn_cast(Op1)) { + Constant *Ops[] = { C0, C1 }; + return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, 2, TD); + } + } + + bool isSigned = Opcode == Instruction::SRem; + + // X % undef -> undef + if (match(Op1, m_Undef())) + return Op1; + + // undef % X -> 0 + if (match(Op0, m_Undef())) + return Constant::getNullValue(Op0->getType()); + + // 0 % X -> 0, we don't need to preserve faults! + if (match(Op0, m_Zero())) + return Op0; + + // X % 0 -> undef, we don't need to preserve faults! + if (match(Op1, m_Zero())) + return UndefValue::get(Op0->getType()); + + // X % 1 -> 0 + if (match(Op1, m_One())) + return Constant::getNullValue(Op0->getType()); + + if (Op0->getType()->isIntegerTy(1)) + // It can't be remainder by zero, hence it must be remainder by one. + return Constant::getNullValue(Op0->getType()); + + // X % X -> 0 + if (Op0 == Op1) + return Constant::getNullValue(Op0->getType()); + + // If the operation is with the result of a select instruction, check whether + // operating on either branch of the select always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverSelect(Opcode, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + // If the operation is with the result of a phi instruction, check whether + // operating on all incoming values of the phi always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + return 0; +} + +/// SimplifySRemInst - Given operands for an SRem, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifySRemInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + if (Value *V = SimplifyRem(Instruction::SRem, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifySRemInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifySRemInst(Op0, Op1, TD, DT, RecursionLimit); +} + +/// SimplifyURemInst - Given operands for a URem, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyURemInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + if (Value *V = SimplifyRem(Instruction::URem, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifyURemInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifyURemInst(Op0, Op1, TD, DT, RecursionLimit); +} + +static Value *SimplifyFRemInst(Value *Op0, Value *Op1, const TargetData *, + const DominatorTree *, unsigned) { + // undef % X -> undef (the undef could be a snan). + if (match(Op0, m_Undef())) + return Op0; + + // X % undef -> undef + if (match(Op1, m_Undef())) + return Op1; + + return 0; +} + +Value *llvm::SimplifyFRemInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifyFRemInst(Op0, Op1, TD, DT, RecursionLimit); +} + /// SimplifyShift - Given operands for an Shl, LShr or AShr, see if we can /// fold the result. If not, this returns null. static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1, @@ -1343,7 +1450,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, // the compare, and if only one of them is then we moved it to RHS already. if (isa(LHS) && (isa(RHS) || isa(RHS) || isa(RHS))) - // We already know that LHS != LHS. + // We already know that LHS != RHS. return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred)); // If we are comparing with zero then try hard since this is a common case. @@ -1399,40 +1506,66 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, // See if we are doing a comparison with a constant integer. if (ConstantInt *CI = dyn_cast(RHS)) { - switch (Pred) { - default: break; - case ICmpInst::ICMP_UGT: - if (CI->isMaxValue(false)) // A >u MAX -> FALSE - return ConstantInt::getFalse(CI->getContext()); - break; - case ICmpInst::ICMP_UGE: - if (CI->isMinValue(false)) // A >=u MIN -> TRUE - return ConstantInt::getTrue(CI->getContext()); - break; - case ICmpInst::ICMP_ULT: - if (CI->isMinValue(false)) // A FALSE - return ConstantInt::getFalse(CI->getContext()); - break; - case ICmpInst::ICMP_ULE: - if (CI->isMaxValue(false)) // A <=u MAX -> TRUE - return ConstantInt::getTrue(CI->getContext()); - break; - case ICmpInst::ICMP_SGT: - if (CI->isMaxValue(true)) // A >s MAX -> FALSE - return ConstantInt::getFalse(CI->getContext()); - break; - case ICmpInst::ICMP_SGE: - if (CI->isMinValue(true)) // A >=s MIN -> TRUE - return ConstantInt::getTrue(CI->getContext()); - break; - case ICmpInst::ICMP_SLT: - if (CI->isMinValue(true)) // A FALSE - return ConstantInt::getFalse(CI->getContext()); - break; - case ICmpInst::ICMP_SLE: - if (CI->isMaxValue(true)) // A <=s MAX -> TRUE - return ConstantInt::getTrue(CI->getContext()); - break; + // Rule out tautological comparisons (eg., ult 0 or uge 0). + ConstantRange RHS_CR = ICmpInst::makeConstantRange(Pred, CI->getValue()); + if (RHS_CR.isEmptySet()) + return ConstantInt::getFalse(CI->getContext()); + if (RHS_CR.isFullSet()) + return ConstantInt::getTrue(CI->getContext()); + + // Many binary operators with constant RHS have easy to compute constant + // range. Use them to check whether the comparison is a tautology. + uint32_t Width = CI->getBitWidth(); + APInt Lower = APInt(Width, 0); + APInt Upper = APInt(Width, 0); + ConstantInt *CI2; + if (match(LHS, m_URem(m_Value(), m_ConstantInt(CI2)))) { + // 'urem x, CI2' produces [0, CI2). + Upper = CI2->getValue(); + } else if (match(LHS, m_SRem(m_Value(), m_ConstantInt(CI2)))) { + // 'srem x, CI2' produces (-|CI2|, |CI2|). + Upper = CI2->getValue().abs(); + Lower = (-Upper) + 1; + } else if (match(LHS, m_UDiv(m_Value(), m_ConstantInt(CI2)))) { + // 'udiv x, CI2' produces [0, UINT_MAX / CI2]. + APInt NegOne = APInt::getAllOnesValue(Width); + if (!CI2->isZero()) + Upper = NegOne.udiv(CI2->getValue()) + 1; + } else if (match(LHS, m_SDiv(m_Value(), m_ConstantInt(CI2)))) { + // 'sdiv x, CI2' produces [INT_MIN / CI2, INT_MAX / CI2]. + APInt IntMin = APInt::getSignedMinValue(Width); + APInt IntMax = APInt::getSignedMaxValue(Width); + APInt Val = CI2->getValue().abs(); + if (!Val.isMinValue()) { + Lower = IntMin.sdiv(Val); + Upper = IntMax.sdiv(Val) + 1; + } + } else if (match(LHS, m_LShr(m_Value(), m_ConstantInt(CI2)))) { + // 'lshr x, CI2' produces [0, UINT_MAX >> CI2]. + APInt NegOne = APInt::getAllOnesValue(Width); + if (CI2->getValue().ult(Width)) + Upper = NegOne.lshr(CI2->getValue()) + 1; + } else if (match(LHS, m_AShr(m_Value(), m_ConstantInt(CI2)))) { + // 'ashr x, CI2' produces [INT_MIN >> CI2, INT_MAX >> CI2]. + APInt IntMin = APInt::getSignedMinValue(Width); + APInt IntMax = APInt::getSignedMaxValue(Width); + if (CI2->getValue().ult(Width)) { + Lower = IntMin.ashr(CI2->getValue()); + Upper = IntMax.ashr(CI2->getValue()) + 1; + } + } else if (match(LHS, m_Or(m_Value(), m_ConstantInt(CI2)))) { + // 'or x, CI2' produces [CI2, UINT_MAX]. + Lower = CI2->getValue(); + } else if (match(LHS, m_And(m_Value(), m_ConstantInt(CI2)))) { + // 'and x, CI2' produces [0, CI2]. + Upper = CI2->getValue() + 1; + } + if (Lower != Upper) { + ConstantRange LHS_CR = ConstantRange(Lower, Upper); + if (RHS_CR.contains(LHS_CR)) + return ConstantInt::getTrue(RHS->getContext()); + if (RHS_CR.inverse().contains(LHS_CR)) + return ConstantInt::getFalse(RHS->getContext()); } } @@ -1644,6 +1777,93 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, } } + if (LBO && match(LBO, m_URem(m_Value(), m_Specific(RHS)))) { + bool KnownNonNegative, KnownNegative; + switch (Pred) { + default: + break; + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + ComputeSignBit(LHS, KnownNonNegative, KnownNegative, TD); + if (!KnownNonNegative) + break; + // fall-through + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: + return ConstantInt::getFalse(RHS->getContext()); + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + ComputeSignBit(LHS, KnownNonNegative, KnownNegative, TD); + if (!KnownNonNegative) + break; + // fall-through + case ICmpInst::ICMP_NE: + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: + return ConstantInt::getTrue(RHS->getContext()); + } + } + if (RBO && match(RBO, m_URem(m_Value(), m_Specific(LHS)))) { + bool KnownNonNegative, KnownNegative; + switch (Pred) { + default: + break; + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + ComputeSignBit(RHS, KnownNonNegative, KnownNegative, TD); + if (!KnownNonNegative) + break; + // fall-through + case ICmpInst::ICMP_NE: + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: + return ConstantInt::getTrue(RHS->getContext()); + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + ComputeSignBit(RHS, KnownNonNegative, KnownNegative, TD); + if (!KnownNonNegative) + break; + // fall-through + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: + return ConstantInt::getFalse(RHS->getContext()); + } + } + + if (MaxRecurse && LBO && RBO && LBO->getOpcode() == RBO->getOpcode() && + LBO->getOperand(1) == RBO->getOperand(1)) { + switch (LBO->getOpcode()) { + default: break; + case Instruction::UDiv: + case Instruction::LShr: + if (ICmpInst::isSigned(Pred)) + break; + // fall-through + case Instruction::SDiv: + case Instruction::AShr: + if (!LBO->isExact() && !RBO->isExact()) + break; + if (Value *V = SimplifyICmpInst(Pred, LBO->getOperand(0), + RBO->getOperand(0), TD, DT, MaxRecurse-1)) + return V; + break; + case Instruction::Shl: { + bool NUW = LBO->hasNoUnsignedWrap() && LBO->hasNoUnsignedWrap(); + bool NSW = LBO->hasNoSignedWrap() && RBO->hasNoSignedWrap(); + if (!NUW && !NSW) + break; + if (!NSW && ICmpInst::isSigned(Pred)) + break; + if (Value *V = SimplifyICmpInst(Pred, LBO->getOperand(0), + RBO->getOperand(0), TD, DT, MaxRecurse-1)) + return V; + break; + } + } + } + // If the comparison is with the result of a select instruction, check whether // comparing with either branch of the select always yields the same value. if (isa(LHS) || isa(RHS)) @@ -1879,6 +2099,9 @@ static Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, case Instruction::SDiv: return SimplifySDivInst(LHS, RHS, TD, DT, MaxRecurse); case Instruction::UDiv: return SimplifyUDivInst(LHS, RHS, TD, DT, MaxRecurse); case Instruction::FDiv: return SimplifyFDivInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::SRem: return SimplifySRemInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::URem: return SimplifyURemInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::FRem: return SimplifyFRemInst(LHS, RHS, TD, DT, MaxRecurse); case Instruction::Shl: return SimplifyShlInst(LHS, RHS, /*isNSW*/false, /*isNUW*/false, TD, DT, MaxRecurse); @@ -1973,6 +2196,15 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD, case Instruction::FDiv: Result = SimplifyFDivInst(I->getOperand(0), I->getOperand(1), TD, DT); break; + case Instruction::SRem: + Result = SimplifySRemInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::URem: + Result = SimplifyURemInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::FRem: + Result = SimplifyFRemInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; case Instruction::Shl: Result = SimplifyShlInst(I->getOperand(0), I->getOperand(1), cast(I)->hasNoSignedWrap(), diff --git a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp b/contrib/llvm/lib/Analysis/LazyValueInfo.cpp index 9e7da6ce2de9..d5f0b5c82154 100644 --- a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/contrib/llvm/lib/Analysis/LazyValueInfo.cpp @@ -29,7 +29,6 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include -#include #include using namespace llvm; @@ -268,6 +267,8 @@ class LVILatticeVal { } // end anonymous namespace. namespace llvm { +raw_ostream &operator<<(raw_ostream &OS, const LVILatticeVal &Val) + LLVM_ATTRIBUTE_USED; raw_ostream &operator<<(raw_ostream &OS, const LVILatticeVal &Val) { if (Val.isUndefined()) return OS << "undefined"; diff --git a/contrib/llvm/lib/Analysis/Lint.cpp b/contrib/llvm/lib/Analysis/Lint.cpp index fc7edc0525f9..f130f30c49da 100644 --- a/contrib/llvm/lib/Analysis/Lint.cpp +++ b/contrib/llvm/lib/Analysis/Lint.cpp @@ -606,7 +606,7 @@ Value *Lint::findValueImpl(Value *V, bool OffsetOk, Type::getInt64Ty(V->getContext()))) return findValueImpl(CE->getOperand(0), OffsetOk, Visited); } else if (CE->getOpcode() == Instruction::ExtractValue) { - const SmallVector &Indices = CE->getIndices(); + ArrayRef Indices = CE->getIndices(); if (Value *W = FindInsertedValue(CE->getOperand(0), Indices.begin(), Indices.end())) diff --git a/contrib/llvm/lib/Analysis/LiveValues.cpp b/contrib/llvm/lib/Analysis/LiveValues.cpp deleted file mode 100644 index a0e603419f57..000000000000 --- a/contrib/llvm/lib/Analysis/LiveValues.cpp +++ /dev/null @@ -1,200 +0,0 @@ -//===- LiveValues.cpp - Liveness information for LLVM IR Values. ----------===// -// -// 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 implementation for the LLVM IR Value liveness -// analysis pass. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Analysis/LiveValues.h" -#include "llvm/Instructions.h" -#include "llvm/Analysis/Dominators.h" -#include "llvm/Analysis/LoopInfo.h" -using namespace llvm; - -namespace llvm { - FunctionPass *createLiveValuesPass() { return new LiveValues(); } -} - -char LiveValues::ID = 0; -INITIALIZE_PASS_BEGIN(LiveValues, "live-values", - "Value Liveness Analysis", false, true) -INITIALIZE_PASS_DEPENDENCY(DominatorTree) -INITIALIZE_PASS_DEPENDENCY(LoopInfo) -INITIALIZE_PASS_END(LiveValues, "live-values", - "Value Liveness Analysis", false, true) - -LiveValues::LiveValues() : FunctionPass(ID) { - initializeLiveValuesPass(*PassRegistry::getPassRegistry()); -} - -void LiveValues::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.addRequired(); - AU.setPreservesAll(); -} - -bool LiveValues::runOnFunction(Function &F) { - DT = &getAnalysis(); - LI = &getAnalysis(); - - // This pass' values are computed lazily, so there's nothing to do here. - - return false; -} - -void LiveValues::releaseMemory() { - Memos.clear(); -} - -/// isUsedInBlock - Test if the given value is used in the given block. -/// -bool LiveValues::isUsedInBlock(const Value *V, const BasicBlock *BB) { - Memo &M = getMemo(V); - return M.Used.count(BB); -} - -/// isLiveThroughBlock - Test if the given value is known to be -/// live-through the given block, meaning that the block is properly -/// dominated by the value's definition, and there exists a block -/// reachable from it that contains a use. This uses a conservative -/// approximation that errs on the side of returning false. -/// -bool LiveValues::isLiveThroughBlock(const Value *V, - const BasicBlock *BB) { - Memo &M = getMemo(V); - return M.LiveThrough.count(BB); -} - -/// isKilledInBlock - Test if the given value is known to be killed in -/// the given block, meaning that the block contains a use of the value, -/// and no blocks reachable from the block contain a use. This uses a -/// conservative approximation that errs on the side of returning false. -/// -bool LiveValues::isKilledInBlock(const Value *V, const BasicBlock *BB) { - Memo &M = getMemo(V); - return M.Killed.count(BB); -} - -/// getMemo - Retrieve an existing Memo for the given value if one -/// is available, otherwise compute a new one. -/// -LiveValues::Memo &LiveValues::getMemo(const Value *V) { - DenseMap::iterator I = Memos.find(V); - if (I != Memos.end()) - return I->second; - return compute(V); -} - -/// getImmediateDominator - A handy utility for the specific DominatorTree -/// query that we need here. -/// -static const BasicBlock *getImmediateDominator(const BasicBlock *BB, - const DominatorTree *DT) { - DomTreeNode *Node = DT->getNode(const_cast(BB))->getIDom(); - return Node ? Node->getBlock() : 0; -} - -/// compute - Compute a new Memo for the given value. -/// -LiveValues::Memo &LiveValues::compute(const Value *V) { - Memo &M = Memos[V]; - - // Determine the block containing the definition. - const BasicBlock *DefBB; - // Instructions define values with meaningful live ranges. - if (const Instruction *I = dyn_cast(V)) - DefBB = I->getParent(); - // Arguments can be analyzed as values defined in the entry block. - else if (const Argument *A = dyn_cast(V)) - DefBB = &A->getParent()->getEntryBlock(); - // Constants and other things aren't meaningful here, so just - // return having computed an empty Memo so that we don't come - // here again. The assumption here is that client code won't - // be asking about such values very often. - else - return M; - - // Determine if the value is defined inside a loop. This is used - // to track whether the value is ever used outside the loop, so - // it'll be set to null if the value is either not defined in a - // loop or used outside the loop in which it is defined. - const Loop *L = LI->getLoopFor(DefBB); - - // Track whether the value is used anywhere outside of the block - // in which it is defined. - bool LiveOutOfDefBB = false; - - // Examine each use of the value. - for (Value::const_use_iterator I = V->use_begin(), E = V->use_end(); - I != E; ++I) { - const User *U = *I; - const BasicBlock *UseBB = cast(U)->getParent(); - - // Note the block in which this use occurs. - M.Used.insert(UseBB); - - // If the use block doesn't have successors, the value can be - // considered killed. - if (succ_begin(UseBB) == succ_end(UseBB)) - M.Killed.insert(UseBB); - - // Observe whether the value is used outside of the loop in which - // it is defined. Switch to an enclosing loop if necessary. - for (; L; L = L->getParentLoop()) - if (L->contains(UseBB)) - break; - - // Search for live-through blocks. - const BasicBlock *BB; - if (const PHINode *PHI = dyn_cast(U)) { - // For PHI nodes, start the search at the incoming block paired with the - // incoming value, which must be dominated by the definition. - unsigned Num = PHI->getIncomingValueNumForOperand(I.getOperandNo()); - BB = PHI->getIncomingBlock(Num); - - // A PHI-node use means the value is live-out of it's defining block - // even if that block also contains the only use. - LiveOutOfDefBB = true; - } else { - // Otherwise just start the search at the use. - BB = UseBB; - - // Note if the use is outside the defining block. - LiveOutOfDefBB |= UseBB != DefBB; - } - - // Climb the immediate dominator tree from the use to the definition - // and mark all intermediate blocks as live-through. - for (; BB != DefBB; BB = getImmediateDominator(BB, DT)) { - if (BB != UseBB && !M.LiveThrough.insert(BB)) - break; - } - } - - // If the value is defined inside a loop and is not live outside - // the loop, then each exit block of the loop in which the value - // is used is a kill block. - if (L) { - SmallVector ExitingBlocks; - L->getExitingBlocks(ExitingBlocks); - for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) { - const BasicBlock *ExitingBlock = ExitingBlocks[i]; - if (M.Used.count(ExitingBlock)) - M.Killed.insert(ExitingBlock); - } - } - - // If the value was never used outside the block in which it was - // defined, it's killed in that block. - if (!LiveOutOfDefBB) - M.Killed.insert(DefBB); - - return M; -} diff --git a/contrib/llvm/lib/Analysis/Loads.cpp b/contrib/llvm/lib/Analysis/Loads.cpp index 2ea27fb62fcb..ab34fd653a70 100644 --- a/contrib/llvm/lib/Analysis/Loads.cpp +++ b/contrib/llvm/lib/Analysis/Loads.cpp @@ -17,6 +17,7 @@ #include "llvm/GlobalAlias.h" #include "llvm/GlobalVariable.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h" using namespace llvm; /// AreEquivalentAddressValues - Test if A and B will obviously have the same diff --git a/contrib/llvm/lib/Analysis/LoopPass.cpp b/contrib/llvm/lib/Analysis/LoopPass.cpp index 8e1a7bfef699..10e3f297f9c5 100644 --- a/contrib/llvm/lib/Analysis/LoopPass.cpp +++ b/contrib/llvm/lib/Analysis/LoopPass.cpp @@ -14,8 +14,10 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/LoopPass.h" +#include "llvm/DebugInfoProbe.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Timer.h" using namespace llvm; @@ -51,6 +53,20 @@ class PrintLoopPass : public LoopPass { char PrintLoopPass::ID = 0; } +//===----------------------------------------------------------------------===// +// DebugInfoProbe + +static DebugInfoProbeInfo *TheDebugProbe; +static void createDebugInfoProbe() { + if (TheDebugProbe) return; + + // Constructed the first time this is called. This guarantees that the + // object will be constructed, if -enable-debug-info-probe is set, + // before static globals, thus it will be destroyed before them. + static ManagedStatic DIP; + TheDebugProbe = &*DIP; +} + //===----------------------------------------------------------------------===// // LPPassManager // @@ -223,6 +239,7 @@ void LPPassManager::getAnalysisUsage(AnalysisUsage &Info) const { bool LPPassManager::runOnFunction(Function &F) { LI = &getAnalysis(); bool Changed = false; + createDebugInfoProbe(); // Collect inherited analysis from Module level pass manager. populateInheritedAnalysis(TPM->activeStack); @@ -254,19 +271,21 @@ bool LPPassManager::runOnFunction(Function &F) { // Run all passes on the current Loop. for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { LoopPass *P = getContainedPass(Index); - dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG, CurrentLoop->getHeader()->getName()); dumpRequiredSet(P); initializeAnalysisImpl(P); - + if (TheDebugProbe) + TheDebugProbe->initialize(P, F); { PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader()); TimeRegion PassTimer(getPassTimer(P)); Changed |= P->runOnLoop(CurrentLoop, *this); } + if (TheDebugProbe) + TheDebugProbe->finalize(P, F); if (Changed) dumpPassInfo(P, MODIFICATION_MSG, ON_LOOP_MSG, diff --git a/contrib/llvm/lib/Analysis/MemoryBuiltins.cpp b/contrib/llvm/lib/Analysis/MemoryBuiltins.cpp index 1ab18ca054a2..769c68ce425e 100644 --- a/contrib/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/contrib/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -35,7 +35,13 @@ static bool isMallocCall(const CallInst *CI) { return false; Function *Callee = CI->getCalledFunction(); - if (Callee == 0 || !Callee->isDeclaration() || Callee->getName() != "malloc") + if (Callee == 0 || !Callee->isDeclaration()) + return false; + if (Callee->getName() != "malloc" && + Callee->getName() != "_Znwj" && // operator new(unsigned int) + Callee->getName() != "_Znwm" && // operator new(unsigned long) + Callee->getName() != "_Znaj" && // operator new[](unsigned int) + Callee->getName() != "_Znam") // operator new[](unsigned long) return false; // Check malloc prototype. @@ -189,7 +195,12 @@ const CallInst *llvm::isFreeCall(const Value *I) { if (!CI) return 0; Function *Callee = CI->getCalledFunction(); - if (Callee == 0 || !Callee->isDeclaration() || Callee->getName() != "free") + if (Callee == 0 || !Callee->isDeclaration()) + return 0; + + if (Callee->getName() != "free" && + Callee->getName() != "_ZdlPv" && // operator delete(void*) + Callee->getName() != "_ZdaPv") // operator delete[](void*) return 0; // Check free prototype. diff --git a/contrib/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/contrib/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp index 35043bddfaf6..ce7fab6459ed 100644 --- a/contrib/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -16,6 +16,7 @@ #define DEBUG_TYPE "memdep" #include "llvm/Analysis/MemoryDependenceAnalysis.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" #include "llvm/Function.h" @@ -221,6 +222,96 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall, return MemDepResult::getClobber(ScanIt); } +/// isLoadLoadClobberIfExtendedToFullWidth - Return true if LI is a load that +/// would fully overlap MemLoc if done as a wider legal integer load. +/// +/// MemLocBase, MemLocOffset are lazily computed here the first time the +/// base/offs of memloc is needed. +static bool +isLoadLoadClobberIfExtendedToFullWidth(const AliasAnalysis::Location &MemLoc, + const Value *&MemLocBase, + int64_t &MemLocOffs, + const LoadInst *LI, + const TargetData *TD) { + // If we have no target data, we can't do this. + if (TD == 0) return false; + + // If we haven't already computed the base/offset of MemLoc, do so now. + if (MemLocBase == 0) + MemLocBase = GetPointerBaseWithConstantOffset(MemLoc.Ptr, MemLocOffs, *TD); + + unsigned Size = MemoryDependenceAnalysis:: + getLoadLoadClobberFullWidthSize(MemLocBase, MemLocOffs, MemLoc.Size, + LI, *TD); + return Size != 0; +} + +/// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that +/// looks at a memory location for a load (specified by MemLocBase, Offs, +/// and Size) and compares it against a load. If the specified load could +/// be safely widened to a larger integer load that is 1) still efficient, +/// 2) safe for the target, and 3) would provide the specified memory +/// location value, then this function returns the size in bytes of the +/// load width to use. If not, this returns zero. +unsigned MemoryDependenceAnalysis:: +getLoadLoadClobberFullWidthSize(const Value *MemLocBase, int64_t MemLocOffs, + unsigned MemLocSize, const LoadInst *LI, + const TargetData &TD) { + // We can only extend non-volatile integer loads. + if (!isa(LI->getType()) || LI->isVolatile()) return 0; + + // Get the base of this load. + int64_t LIOffs = 0; + const Value *LIBase = + GetPointerBaseWithConstantOffset(LI->getPointerOperand(), LIOffs, TD); + + // If the two pointers are not based on the same pointer, we can't tell that + // they are related. + if (LIBase != MemLocBase) return 0; + + // Okay, the two values are based on the same pointer, but returned as + // no-alias. This happens when we have things like two byte loads at "P+1" + // and "P+3". Check to see if increasing the size of the "LI" load up to its + // alignment (or the largest native integer type) will allow us to load all + // the bits required by MemLoc. + + // If MemLoc is before LI, then no widening of LI will help us out. + if (MemLocOffs < LIOffs) return 0; + + // Get the alignment of the load in bytes. We assume that it is safe to load + // any legal integer up to this size without a problem. For example, if we're + // looking at an i8 load on x86-32 that is known 1024 byte aligned, we can + // widen it up to an i32 load. If it is known 2-byte aligned, we can widen it + // to i16. + unsigned LoadAlign = LI->getAlignment(); + + int64_t MemLocEnd = MemLocOffs+MemLocSize; + + // If no amount of rounding up will let MemLoc fit into LI, then bail out. + if (LIOffs+LoadAlign < MemLocEnd) return 0; + + // This is the size of the load to try. Start with the next larger power of + // two. + unsigned NewLoadByteSize = LI->getType()->getPrimitiveSizeInBits()/8U; + NewLoadByteSize = NextPowerOf2(NewLoadByteSize); + + while (1) { + // If this load size is bigger than our known alignment or would not fit + // into a native integer register, then we fail. + if (NewLoadByteSize > LoadAlign || + !TD.fitsInLegalInteger(NewLoadByteSize*8)) + return 0; + + // If a load of this width would include all of MemLoc, then we succeed. + if (LIOffs+NewLoadByteSize >= MemLocEnd) + return NewLoadByteSize; + + NewLoadByteSize <<= 1; + } + + return 0; +} + /// getPointerDependencyFrom - Return the instruction on which a memory /// location depends. If isLoad is true, this routine ignores may-aliases with /// read-only operations. If isLoad is false, this routine ignores may-aliases @@ -229,58 +320,31 @@ MemDepResult MemoryDependenceAnalysis:: getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, BasicBlock::iterator ScanIt, BasicBlock *BB) { - Value *InvariantTag = 0; - + const Value *MemLocBase = 0; + int64_t MemLocOffset = 0; + // Walk backwards through the basic block, looking for dependencies. while (ScanIt != BB->begin()) { Instruction *Inst = --ScanIt; - // If we're in an invariant region, no dependencies can be found before - // we pass an invariant-begin marker. - if (InvariantTag == Inst) { - InvariantTag = 0; - continue; - } - if (IntrinsicInst *II = dyn_cast(Inst)) { // Debug intrinsics don't (and can't) cause dependences. if (isa(II)) continue; - // If we pass an invariant-end marker, then we've just entered an - // invariant region and can start ignoring dependencies. - if (II->getIntrinsicID() == Intrinsic::invariant_end) { - // FIXME: This only considers queries directly on the invariant-tagged - // pointer, not on query pointers that are indexed off of them. It'd - // be nice to handle that at some point. - AliasAnalysis::AliasResult R = - AA->alias(AliasAnalysis::Location(II->getArgOperand(2)), MemLoc); - if (R == AliasAnalysis::MustAlias) - InvariantTag = II->getArgOperand(0); - - continue; - } - // If we reach a lifetime begin or end marker, then the query ends here // because the value is undefined. if (II->getIntrinsicID() == Intrinsic::lifetime_start) { // FIXME: This only considers queries directly on the invariant-tagged // pointer, not on query pointers that are indexed off of them. It'd - // be nice to handle that at some point. - AliasAnalysis::AliasResult R = - AA->alias(AliasAnalysis::Location(II->getArgOperand(1)), MemLoc); - if (R == AliasAnalysis::MustAlias) + // be nice to handle that at some point (the right approach is to use + // GetPointerBaseWithConstantOffset). + if (AA->isMustAlias(AliasAnalysis::Location(II->getArgOperand(1)), + MemLoc)) return MemDepResult::getDef(II); continue; } } - // If we're querying on a load and we're in an invariant region, we're done - // at this point. Nothing a load depends on can live in an invariant region. - // - // FIXME: this will prevent us from returning load/load must-aliases, so GVN - // won't remove redundant loads. - if (isLoad && InvariantTag) continue; - // Values depend on loads if the pointers are must aliased. This means that // a load depends on another must aliased load from the same value. if (LoadInst *LI = dyn_cast(Inst)) { @@ -288,27 +352,51 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, // If we found a pointer, check if it could be the same as our pointer. AliasAnalysis::AliasResult R = AA->alias(LoadLoc, MemLoc); - if (R == AliasAnalysis::NoAlias) - continue; - // May-alias loads don't depend on each other without a dependence. - if (isLoad && R != AliasAnalysis::MustAlias) + if (isLoad) { + if (R == AliasAnalysis::NoAlias) { + // If this is an over-aligned integer load (for example, + // "load i8* %P, align 4") see if it would obviously overlap with the + // queried location if widened to a larger load (e.g. if the queried + // location is 1 byte at P+1). If so, return it as a load/load + // clobber result, allowing the client to decide to widen the load if + // it wants to. + if (const IntegerType *ITy = dyn_cast(LI->getType())) + if (LI->getAlignment()*8 > ITy->getPrimitiveSizeInBits() && + isLoadLoadClobberIfExtendedToFullWidth(MemLoc, MemLocBase, + MemLocOffset, LI, TD)) + return MemDepResult::getClobber(Inst); + + continue; + } + + // Must aliased loads are defs of each other. + if (R == AliasAnalysis::MustAlias) + return MemDepResult::getDef(Inst); + + // If we have a partial alias, then return this as a clobber for the + // client to handle. + if (R == AliasAnalysis::PartialAlias) + return MemDepResult::getClobber(Inst); + + // Random may-alias loads don't depend on each other without a + // dependence. + continue; + } + + // Stores don't depend on other no-aliased accesses. + if (R == AliasAnalysis::NoAlias) continue; // Stores don't alias loads from read-only memory. - if (!isLoad && AA->pointsToConstantMemory(LoadLoc)) + if (AA->pointsToConstantMemory(LoadLoc)) continue; - // Stores depend on may and must aliased loads, loads depend on must-alias - // loads. + // Stores depend on may/must aliased loads. return MemDepResult::getDef(Inst); } if (StoreInst *SI = dyn_cast(Inst)) { - // There can't be stores to the value we care about inside an - // invariant region. - if (InvariantTag) continue; - // If alias analysis can tell that this store is guaranteed to not modify // the query pointer, ignore it. Use getModRefInfo to handle cases where // the query pointer points to constant memory etc. @@ -341,8 +429,7 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, (isa(Inst) && extractMallocCall(Inst))) { const Value *AccessPtr = GetUnderlyingObject(MemLoc.Ptr, TD); - if (AccessPtr == Inst || - AA->alias(Inst, 1, AccessPtr, 1) == AliasAnalysis::MustAlias) + if (AccessPtr == Inst || AA->isMustAlias(Inst, AccessPtr)) return MemDepResult::getDef(Inst); continue; } @@ -353,9 +440,6 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, // If the call has no effect on the queried pointer, just ignore it. continue; case AliasAnalysis::Mod: - // If we're in an invariant region, we can ignore calls that ONLY - // modify the pointer. - if (InvariantTag) continue; return MemDepResult::getClobber(Inst); case AliasAnalysis::Ref: // If the call is known to never store to the pointer, and if this is a diff --git a/contrib/llvm/lib/Analysis/PHITransAddr.cpp b/contrib/llvm/lib/Analysis/PHITransAddr.cpp index 93da5a48518d..70dcd0df242d 100644 --- a/contrib/llvm/lib/Analysis/PHITransAddr.cpp +++ b/contrib/llvm/lib/Analysis/PHITransAddr.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/PHITransAddr.h" +#include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/InstructionSimplify.h" diff --git a/contrib/llvm/lib/Analysis/PathNumbering.cpp b/contrib/llvm/lib/Analysis/PathNumbering.cpp index 5d3f6bbc7b6e..7c584daef734 100644 --- a/contrib/llvm/lib/Analysis/PathNumbering.cpp +++ b/contrib/llvm/lib/Analysis/PathNumbering.cpp @@ -38,13 +38,10 @@ #include "llvm/Support/TypeBuilder.h" #include "llvm/Support/raw_ostream.h" -#include #include -#include #include #include #include -#include #include using namespace llvm; @@ -286,7 +283,7 @@ void BallLarusDag::calculatePathNumbers() { BallLarusEdge* exitEdge = addEdge(node, getExit(), 0); exitEdge->setType(BallLarusEdge::SPLITEDGE_PHONY); - // Counters to handle the possibilty of a multi-graph + // Counters to handle the possibility of a multi-graph BasicBlock* oldTarget = 0; unsigned duplicateNumber = 0; diff --git a/contrib/llvm/lib/Analysis/PathProfileVerifier.cpp b/contrib/llvm/lib/Analysis/PathProfileVerifier.cpp index c54977314207..0ae734e259db 100644 --- a/contrib/llvm/lib/Analysis/PathProfileVerifier.cpp +++ b/contrib/llvm/lib/Analysis/PathProfileVerifier.cpp @@ -124,7 +124,7 @@ bool PathProfileVerifier::runOnModule (Module &M) { ProfilePathEdgeVector* pev = currentPath->getPathEdges(); DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": " << currentPath->getCount() << "\n"); - // setup the entry edge (normally path profiling doens't care about this) + // setup the entry edge (normally path profiling doesn't care about this) if (currentPath->getFirstBlockInPath() == &F->getEntryBlock()) edgeArray[arrayMap[0][currentPath->getFirstBlockInPath()][0]] += currentPath->getCount(); diff --git a/contrib/llvm/lib/Analysis/PostDominators.cpp b/contrib/llvm/lib/Analysis/PostDominators.cpp index 3f0deab9ea87..6ed27297923f 100644 --- a/contrib/llvm/lib/Analysis/PostDominators.cpp +++ b/contrib/llvm/lib/Analysis/PostDominators.cpp @@ -28,7 +28,6 @@ using namespace llvm; //===----------------------------------------------------------------------===// char PostDominatorTree::ID = 0; -char PostDominanceFrontier::ID = 0; INITIALIZE_PASS(PostDominatorTree, "postdomtree", "Post-Dominator Tree Construction", true, true) @@ -50,53 +49,3 @@ FunctionPass* llvm::createPostDomTree() { return new PostDominatorTree(); } -//===----------------------------------------------------------------------===// -// PostDominanceFrontier Implementation -//===----------------------------------------------------------------------===// - -INITIALIZE_PASS_BEGIN(PostDominanceFrontier, "postdomfrontier", - "Post-Dominance Frontier Construction", true, true) -INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) -INITIALIZE_PASS_END(PostDominanceFrontier, "postdomfrontier", - "Post-Dominance Frontier Construction", true, true) - -const DominanceFrontier::DomSetType & -PostDominanceFrontier::calculate(const PostDominatorTree &DT, - const DomTreeNode *Node) { - // Loop over CFG successors to calculate DFlocal[Node] - BasicBlock *BB = Node->getBlock(); - DomSetType &S = Frontiers[BB]; // The new set to fill in... - if (getRoots().empty()) return S; - - if (BB) - for (pred_iterator SI = pred_begin(BB), SE = pred_end(BB); - SI != SE; ++SI) { - BasicBlock *P = *SI; - // Does Node immediately dominate this predecessor? - DomTreeNode *SINode = DT[P]; - if (SINode && SINode->getIDom() != Node) - S.insert(P); - } - - // At this point, S is DFlocal. Now we union in DFup's of our children... - // Loop through and visit the nodes that Node immediately dominates (Node's - // children in the IDomTree) - // - for (DomTreeNode::const_iterator - NI = Node->begin(), NE = Node->end(); NI != NE; ++NI) { - DomTreeNode *IDominee = *NI; - const DomSetType &ChildDF = calculate(DT, IDominee); - - DomSetType::const_iterator CDFI = ChildDF.begin(), CDFE = ChildDF.end(); - for (; CDFI != CDFE; ++CDFI) { - if (!DT.properlyDominates(Node, DT[*CDFI])) - S.insert(*CDFI); - } - } - - return S; -} - -FunctionPass* llvm::createPostDomFrontier() { - return new PostDominanceFrontier(); -} diff --git a/contrib/llvm/lib/Analysis/ProfileEstimatorPass.cpp b/contrib/llvm/lib/Analysis/ProfileEstimatorPass.cpp index 667ee1cc348a..b594e2ba5506 100644 --- a/contrib/llvm/lib/Analysis/ProfileEstimatorPass.cpp +++ b/contrib/llvm/lib/Analysis/ProfileEstimatorPass.cpp @@ -140,7 +140,7 @@ void ProfileEstimatorPass::recurseBasicBlock(BasicBlock *BB) { // loop, thus the edge is a backedge, continue and do not check if the // value is valid. if (BBisHeader && BBLoop->contains(*bbi)) { - printEdgeError(edge, "but is backedge, continueing"); + printEdgeError(edge, "but is backedge, continuing"); continue; } // If the edges value is missing (and this is no loop header, and this is diff --git a/contrib/llvm/lib/Analysis/ProfileInfo.cpp b/contrib/llvm/lib/Analysis/ProfileInfo.cpp index 36f211e858d2..173de2c02791 100644 --- a/contrib/llvm/lib/Analysis/ProfileInfo.cpp +++ b/contrib/llvm/lib/Analysis/ProfileInfo.cpp @@ -309,9 +309,9 @@ void ProfileInfoT:: removeEdge(oldedge); } -/// Replaces all occurences of RmBB in the ProfilingInfo with DestBB. +/// Replaces all occurrences of RmBB in the ProfilingInfo with DestBB. /// This checks all edges of the function the blocks reside in and replaces the -/// occurences of RmBB with DestBB. +/// occurrences of RmBB with DestBB. template<> void ProfileInfoT:: replaceAllUses(const BasicBlock *RmBB, const BasicBlock *DestBB) { @@ -812,7 +812,7 @@ void ProfileInfoT::repair(const Function *F) { } if (iw < 0) continue; - // Check the recieving end of the path if it can handle the flow. + // Check the receiving end of the path if it can handle the flow. double ow = getExecutionCount(Dest); Processed.clear(); for (succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB); diff --git a/contrib/llvm/lib/Analysis/ProfileInfoLoader.cpp b/contrib/llvm/lib/Analysis/ProfileInfoLoader.cpp index 25481b2ee671..eaa38dad16a1 100644 --- a/contrib/llvm/lib/Analysis/ProfileInfoLoader.cpp +++ b/contrib/llvm/lib/Analysis/ProfileInfoLoader.cpp @@ -19,7 +19,6 @@ #include "llvm/Support/raw_ostream.h" #include #include -#include using namespace llvm; // ByteSwap - Byteswap 'Var' if 'Really' is true. diff --git a/contrib/llvm/lib/Analysis/RegionInfo.cpp b/contrib/llvm/lib/Analysis/RegionInfo.cpp index e2f6a8bf5d9a..52753cbe85af 100644 --- a/contrib/llvm/lib/Analysis/RegionInfo.cpp +++ b/contrib/llvm/lib/Analysis/RegionInfo.cpp @@ -41,16 +41,15 @@ VerifyRegionInfoX("verify-region-info", cl::location(VerifyRegionInfo), STATISTIC(numRegions, "The # of regions"); STATISTIC(numSimpleRegions, "The # of simple regions"); -//===----------------------------------------------------------------------===// -/// PrintStyle - Print region in difference ways. -enum PrintStyle { PrintNone, PrintBB, PrintRN }; - -static cl::opt printStyle("print-region-style", cl::Hidden, +static cl::opt printStyle("print-region-style", + cl::Hidden, cl::desc("style of printing regions"), cl::values( - clEnumValN(PrintNone, "none", "print no details"), - clEnumValN(PrintBB, "bb", "print regions in detail with block_iterator"), - clEnumValN(PrintRN, "rn", "print regions in detail with element_iterator"), + clEnumValN(Region::PrintNone, "none", "print no details"), + clEnumValN(Region::PrintBB, "bb", + "print regions in detail with block_iterator"), + clEnumValN(Region::PrintRN, "rn", + "print regions in detail with element_iterator"), clEnumValEnd)); //===----------------------------------------------------------------------===// /// Region Implementation @@ -413,7 +412,8 @@ Region *Region::getExpandedRegion() const { return new Region(getEntry(), R->getExit(), RI, DT); } -void Region::print(raw_ostream &OS, bool print_tree, unsigned level) const { +void Region::print(raw_ostream &OS, bool print_tree, unsigned level, + enum PrintStyle Style) const { if (print_tree) OS.indent(level*2) << "[" << level << "] " << getNameStr(); else @@ -422,14 +422,14 @@ void Region::print(raw_ostream &OS, bool print_tree, unsigned level) const { OS << "\n"; - if (printStyle != PrintNone) { + if (Style != PrintNone) { OS.indent(level*2) << "{\n"; OS.indent(level*2 + 2); - if (printStyle == PrintBB) { + if (Style == PrintBB) { for (const_block_iterator I = block_begin(), E = block_end(); I!=E; ++I) OS << **I << ", "; // TODO: remove the last "," - } else if (printStyle == PrintRN) { + } else if (Style == PrintRN) { for (const_element_iterator I = element_begin(), E = element_end(); I!=E; ++I) OS << **I << ", "; // TODO: remove the last ", } @@ -439,14 +439,14 @@ void Region::print(raw_ostream &OS, bool print_tree, unsigned level) const { if (print_tree) for (const_iterator RI = begin(), RE = end(); RI != RE; ++RI) - (*RI)->print(OS, print_tree, level+1); + (*RI)->print(OS, print_tree, level+1, Style); - if (printStyle != PrintNone) + if (Style != PrintNone) OS.indent(level*2) << "} \n"; } void Region::dump() const { - print(dbgs(), true, getDepth()); + print(dbgs(), true, getDepth(), printStyle.getValue()); } void Region::clearNodeCache() { @@ -714,7 +714,7 @@ void RegionInfo::getAnalysisUsage(AnalysisUsage &AU) const { void RegionInfo::print(raw_ostream &OS, const Module *) const { OS << "Region tree:\n"; - TopLevelRegion->print(OS, true, 0); + TopLevelRegion->print(OS, true, 0, printStyle.getValue()); OS << "End region tree\n"; } diff --git a/contrib/llvm/lib/Analysis/RegionPrinter.cpp b/contrib/llvm/lib/Analysis/RegionPrinter.cpp index 0cf0f9050504..a1730b0a3ca1 100644 --- a/contrib/llvm/lib/Analysis/RegionPrinter.cpp +++ b/contrib/llvm/lib/Analysis/RegionPrinter.cpp @@ -70,6 +70,32 @@ struct DOTGraphTraits : public DOTGraphTraits { G->getTopLevelRegion()); } + std::string getEdgeAttributes(RegionNode *srcNode, + GraphTraits::ChildIteratorType CI, RegionInfo *RI) { + + RegionNode *destNode = *CI; + + if (srcNode->isSubRegion() || destNode->isSubRegion()) + return ""; + + // In case of a backedge, do not use it to define the layout of the nodes. + BasicBlock *srcBB = srcNode->getNodeAs(); + BasicBlock *destBB = destNode->getNodeAs(); + + Region *R = RI->getRegionFor(destBB); + + while (R && R->getParent()) + if (R->getParent()->getEntry() == destBB) + R = R->getParent(); + else + break; + + if (R->getEntry() == destBB && R->contains(srcBB)) + return "constraint=false"; + + return ""; + } + // Print the cluster of the subregions. This groups the single basic blocks // and adds a different background color for each group. static void printRegionCluster(const Region *R, GraphWriter &GW, diff --git a/contrib/llvm/lib/Analysis/ScalarEvolution.cpp b/contrib/llvm/lib/Analysis/ScalarEvolution.cpp index 62244ccb3a03..bab4619894c7 100644 --- a/contrib/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/contrib/llvm/lib/Analysis/ScalarEvolution.cpp @@ -157,10 +157,13 @@ void SCEV::print(raw_ostream &OS) const { for (unsigned i = 1, e = AR->getNumOperands(); i != e; ++i) OS << ",+," << *AR->getOperand(i); OS << "}<"; - if (AR->hasNoUnsignedWrap()) + if (AR->getNoWrapFlags(FlagNUW)) OS << "nuw><"; - if (AR->hasNoSignedWrap()) + if (AR->getNoWrapFlags(FlagNSW)) OS << "nsw><"; + if (AR->getNoWrapFlags(FlagNW) && + !AR->getNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW))) + OS << "nw><"; WriteAsOperand(OS, AR->getLoop()->getHeader(), /*PrintType=*/false); OS << ">"; return; @@ -203,7 +206,7 @@ void SCEV::print(raw_ostream &OS) const { OS << "alignof(" << *AllocTy << ")"; return; } - + const Type *CTy; Constant *FieldNo; if (U->isOffsetOf(CTy, FieldNo)) { @@ -212,7 +215,7 @@ void SCEV::print(raw_ostream &OS) const { OS << ")"; return; } - + // Otherwise just print it normally. WriteAsOperand(OS, U->getValue(), false); return; @@ -830,7 +833,7 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Operands.push_back(S); } if (!hasTrunc) - return getAddExpr(Operands, false, false); + return getAddExpr(Operands); UniqueSCEVs.FindNodeOrInsertPos(ID, IP); // Mutates IP, returns NULL. } @@ -845,7 +848,7 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Operands.push_back(S); } if (!hasTrunc) - return getMulExpr(Operands, false, false); + return getMulExpr(Operands); UniqueSCEVs.FindNodeOrInsertPos(ID, IP); // Mutates IP, returns NULL. } @@ -854,7 +857,7 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, SmallVector Operands; for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) Operands.push_back(getTruncateExpr(AddRec->getOperand(i), Ty)); - return getAddRecExpr(Operands, AddRec->getLoop()); + return getAddRecExpr(Operands, AddRec->getLoop(), SCEV::FlagAnyWrap); } // As a special case, fold trunc(undef) to undef. We don't want to @@ -926,10 +929,10 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, // If we have special knowledge that this addrec won't overflow, // we don't need to do any further analysis. - if (AR->hasNoUnsignedWrap()) + if (AR->getNoWrapFlags(SCEV::FlagNUW)) return getAddRecExpr(getZeroExtendExpr(Start, Ty), getZeroExtendExpr(Step, Ty), - L); + L, AR->getNoWrapFlags()); // Check whether the backedge-taken count is SCEVCouldNotCompute. // Note that this serves two purposes: It filters out loops that are @@ -959,12 +962,14 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, getAddExpr(getZeroExtendExpr(Start, WideTy), getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), getZeroExtendExpr(Step, WideTy))); - if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) + if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) { + // Cache knowledge of AR NUW, which is propagated to this AddRec. + const_cast(AR)->setNoWrapFlags(SCEV::FlagNUW); // Return the expression with the addrec on the outside. return getAddRecExpr(getZeroExtendExpr(Start, Ty), getZeroExtendExpr(Step, Ty), - L); - + L, AR->getNoWrapFlags()); + } // Similar to above, only this time treat the step value as signed. // This covers loops that count down. const SCEV *SMul = getMulExpr(CastedMaxBECount, Step); @@ -973,11 +978,15 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, getAddExpr(getZeroExtendExpr(Start, WideTy), getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), getSignExtendExpr(Step, WideTy))); - if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) + if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) { + // Cache knowledge of AR NW, which is propagated to this AddRec. + // Negative step causes unsigned wrap, but it still can't self-wrap. + const_cast(AR)->setNoWrapFlags(SCEV::FlagNW); // Return the expression with the addrec on the outside. return getAddRecExpr(getZeroExtendExpr(Start, Ty), getSignExtendExpr(Step, Ty), - L); + L, AR->getNoWrapFlags()); + } } // If the backedge is guarded by a comparison with the pre-inc value @@ -990,22 +999,29 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, AR, N) || (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_ULT, Start, N) && isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, - AR->getPostIncExpr(*this), N))) + AR->getPostIncExpr(*this), N))) { + // Cache knowledge of AR NUW, which is propagated to this AddRec. + const_cast(AR)->setNoWrapFlags(SCEV::FlagNUW); // Return the expression with the addrec on the outside. return getAddRecExpr(getZeroExtendExpr(Start, Ty), getZeroExtendExpr(Step, Ty), - L); + L, AR->getNoWrapFlags()); + } } else if (isKnownNegative(Step)) { const SCEV *N = getConstant(APInt::getMaxValue(BitWidth) - getSignedRange(Step).getSignedMin()); if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT, AR, N) || (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_UGT, Start, N) && isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT, - AR->getPostIncExpr(*this), N))) + AR->getPostIncExpr(*this), N))) { + // Cache knowledge of AR NW, which is propagated to this AddRec. + // Negative step causes unsigned wrap, but it still can't self-wrap. + const_cast(AR)->setNoWrapFlags(SCEV::FlagNW); // Return the expression with the addrec on the outside. return getAddRecExpr(getZeroExtendExpr(Start, Ty), getSignExtendExpr(Step, Ty), - L); + L, AR->getNoWrapFlags()); + } } } } @@ -1080,10 +1096,10 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, // If we have special knowledge that this addrec won't overflow, // we don't need to do any further analysis. - if (AR->hasNoSignedWrap()) + if (AR->getNoWrapFlags(SCEV::FlagNSW)) return getAddRecExpr(getSignExtendExpr(Start, Ty), getSignExtendExpr(Step, Ty), - L); + L, SCEV::FlagNSW); // Check whether the backedge-taken count is SCEVCouldNotCompute. // Note that this serves two purposes: It filters out loops that are @@ -1113,12 +1129,14 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, getAddExpr(getSignExtendExpr(Start, WideTy), getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), getSignExtendExpr(Step, WideTy))); - if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) + if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) { + // Cache knowledge of AR NSW, which is propagated to this AddRec. + const_cast(AR)->setNoWrapFlags(SCEV::FlagNSW); // Return the expression with the addrec on the outside. return getAddRecExpr(getSignExtendExpr(Start, Ty), getSignExtendExpr(Step, Ty), - L); - + L, AR->getNoWrapFlags()); + } // Similar to above, only this time treat the step value as unsigned. // This covers loops that count up with an unsigned step. const SCEV *UMul = getMulExpr(CastedMaxBECount, Step); @@ -1127,11 +1145,14 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, getAddExpr(getSignExtendExpr(Start, WideTy), getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), getZeroExtendExpr(Step, WideTy))); - if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) + if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) { + // Cache knowledge of AR NSW, which is propagated to this AddRec. + const_cast(AR)->setNoWrapFlags(SCEV::FlagNSW); // Return the expression with the addrec on the outside. return getAddRecExpr(getSignExtendExpr(Start, Ty), getZeroExtendExpr(Step, Ty), - L); + L, AR->getNoWrapFlags()); + } } // If the backedge is guarded by a comparison with the pre-inc value @@ -1144,22 +1165,28 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SLT, AR, N) || (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SLT, Start, N) && isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SLT, - AR->getPostIncExpr(*this), N))) + AR->getPostIncExpr(*this), N))) { + // Cache knowledge of AR NSW, which is propagated to this AddRec. + const_cast(AR)->setNoWrapFlags(SCEV::FlagNSW); // Return the expression with the addrec on the outside. return getAddRecExpr(getSignExtendExpr(Start, Ty), getSignExtendExpr(Step, Ty), - L); + L, AR->getNoWrapFlags()); + } } else if (isKnownNegative(Step)) { const SCEV *N = getConstant(APInt::getSignedMaxValue(BitWidth) - getSignedRange(Step).getSignedMin()); if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SGT, AR, N) || (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGT, Start, N) && isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SGT, - AR->getPostIncExpr(*this), N))) + AR->getPostIncExpr(*this), N))) { + // Cache knowledge of AR NSW, which is propagated to this AddRec. + const_cast(AR)->setNoWrapFlags(SCEV::FlagNSW); // Return the expression with the addrec on the outside. return getAddRecExpr(getSignExtendExpr(Start, Ty), getSignExtendExpr(Step, Ty), - L); + L, AR->getNoWrapFlags()); + } } } } @@ -1213,7 +1240,7 @@ const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op, for (SCEVAddRecExpr::op_iterator I = AR->op_begin(), E = AR->op_end(); I != E; ++I) Ops.push_back(getAnyExtendExpr(*I, Ty)); - return getAddRecExpr(Ops, AR->getLoop()); + return getAddRecExpr(Ops, AR->getLoop(), SCEV::FlagNW); } // As a special case, fold anyext(undef) to undef. We don't want to @@ -1334,7 +1361,9 @@ namespace { /// getAddExpr - Get a canonical add expression, or something simpler if /// possible. const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, - bool HasNUW, bool HasNSW) { + SCEV::NoWrapFlags Flags) { + assert(!(Flags & ~(SCEV::FlagNUW | SCEV::FlagNSW)) && + "only nuw or nsw allowed"); assert(!Ops.empty() && "Cannot get empty add!"); if (Ops.size() == 1) return Ops[0]; #ifndef NDEBUG @@ -1344,8 +1373,11 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, "SCEVAddExpr operand types don't match!"); #endif - // If HasNSW is true and all the operands are non-negative, infer HasNUW. - if (!HasNUW && HasNSW) { + // If FlagNSW is true and all the operands are non-negative, infer FlagNUW. + // And vice-versa. + int SignOrUnsignMask = SCEV::FlagNUW | SCEV::FlagNSW; + SCEV::NoWrapFlags SignOrUnsignWrap = maskFlags(Flags, SignOrUnsignMask); + if (SignOrUnsignWrap && (SignOrUnsignWrap != SignOrUnsignMask)) { bool All = true; for (SmallVectorImpl::const_iterator I = Ops.begin(), E = Ops.end(); I != E; ++I) @@ -1353,7 +1385,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, All = false; break; } - if (All) HasNUW = true; + if (All) Flags = setFlags(Flags, (SCEV::NoWrapFlags)SignOrUnsignMask); } // Sort by complexity, this groups all similar expression types together. @@ -1404,7 +1436,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, FoundMatch = true; } if (FoundMatch) - return getAddExpr(Ops, HasNUW, HasNSW); + return getAddExpr(Ops, Flags); // Check for truncates. If all the operands are truncated from the same // type, see if factoring out the truncate would permit the result to be @@ -1454,7 +1486,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, } if (Ok) { // Evaluate the expression in the larger type. - const SCEV *Fold = getAddExpr(LargeOps, HasNUW, HasNSW); + const SCEV *Fold = getAddExpr(LargeOps, Flags); // If it folds to something simple, use it. Otherwise, don't. if (isa(Fold) || isa(Fold)) return getTruncateExpr(Fold, DstType); @@ -1625,9 +1657,9 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, // Build the new addrec. Propagate the NUW and NSW flags if both the // outer add and the inner addrec are guaranteed to have no overflow. - const SCEV *NewRec = getAddRecExpr(AddRecOps, AddRecLoop, - HasNUW && AddRec->hasNoUnsignedWrap(), - HasNSW && AddRec->hasNoSignedWrap()); + // Always propagate NW. + Flags = AddRec->getNoWrapFlags(setFlags(Flags, SCEV::FlagNW)); + const SCEV *NewRec = getAddRecExpr(AddRecOps, AddRecLoop, Flags); // If all of the other operands were loop invariant, we are done. if (Ops.size() == 1) return NewRec; @@ -1668,7 +1700,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, } Ops.erase(Ops.begin() + OtherIdx); --OtherIdx; } - Ops[Idx] = getAddRecExpr(AddRecOps, AddRecLoop); + // Step size has changed, so we cannot guarantee no self-wraparound. + Ops[Idx] = getAddRecExpr(AddRecOps, AddRecLoop, SCEV::FlagAnyWrap); return getAddExpr(Ops); } @@ -1692,15 +1725,16 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, O, Ops.size()); UniqueSCEVs.InsertNode(S, IP); } - if (HasNUW) S->setHasNoUnsignedWrap(true); - if (HasNSW) S->setHasNoSignedWrap(true); + S->setNoWrapFlags(Flags); return S; } /// getMulExpr - Get a canonical multiply expression, or something simpler if /// possible. const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, - bool HasNUW, bool HasNSW) { + SCEV::NoWrapFlags Flags) { + assert(Flags == maskFlags(Flags, SCEV::FlagNUW | SCEV::FlagNSW) && + "only nuw or nsw allowed"); assert(!Ops.empty() && "Cannot get empty mul!"); if (Ops.size() == 1) return Ops[0]; #ifndef NDEBUG @@ -1710,8 +1744,11 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, "SCEVMulExpr operand types don't match!"); #endif - // If HasNSW is true and all the operands are non-negative, infer HasNUW. - if (!HasNUW && HasNSW) { + // If FlagNSW is true and all the operands are non-negative, infer FlagNUW. + // And vice-versa. + int SignOrUnsignMask = SCEV::FlagNUW | SCEV::FlagNSW; + SCEV::NoWrapFlags SignOrUnsignWrap = maskFlags(Flags, SignOrUnsignMask); + if (SignOrUnsignWrap && (SignOrUnsignWrap != SignOrUnsignMask)) { bool All = true; for (SmallVectorImpl::const_iterator I = Ops.begin(), E = Ops.end(); I != E; ++I) @@ -1719,7 +1756,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, All = false; break; } - if (All) HasNUW = true; + if (All) Flags = setFlags(Flags, (SCEV::NoWrapFlags)SignOrUnsignMask); } // Sort by complexity, this groups all similar expression types together. @@ -1759,12 +1796,12 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, } else if (Ops[0]->isAllOnesValue()) { // If we have a mul by -1 of an add, try distributing the -1 among the // add operands. - if (Ops.size() == 2) + if (Ops.size() == 2) { if (const SCEVAddExpr *Add = dyn_cast(Ops[1])) { SmallVector NewOps; bool AnyFolded = false; - for (SCEVAddRecExpr::op_iterator I = Add->op_begin(), E = Add->op_end(); - I != E; ++I) { + for (SCEVAddRecExpr::op_iterator I = Add->op_begin(), + E = Add->op_end(); I != E; ++I) { const SCEV *Mul = getMulExpr(Ops[0], *I); if (!isa(Mul)) AnyFolded = true; NewOps.push_back(Mul); @@ -1772,6 +1809,18 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, if (AnyFolded) return getAddExpr(NewOps); } + else if (const SCEVAddRecExpr * + AddRec = dyn_cast(Ops[1])) { + // Negation preserves a recurrence's no self-wrap property. + SmallVector Operands; + for (SCEVAddRecExpr::op_iterator I = AddRec->op_begin(), + E = AddRec->op_end(); I != E; ++I) { + Operands.push_back(getMulExpr(Ops[0], *I)); + } + return getAddRecExpr(Operands, AddRec->getLoop(), + AddRec->getNoWrapFlags(SCEV::FlagNW)); + } + } } if (Ops.size() == 1) @@ -1831,9 +1880,11 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // Build the new addrec. Propagate the NUW and NSW flags if both the // outer mul and the inner addrec are guaranteed to have no overflow. - const SCEV *NewRec = getAddRecExpr(NewOps, AddRecLoop, - HasNUW && AddRec->hasNoUnsignedWrap(), - HasNSW && AddRec->hasNoSignedWrap()); + // + // No self-wrap cannot be guaranteed after changing the step size, but + // will be inferred if either NUW or NSW is true. + Flags = AddRec->getNoWrapFlags(clearFlags(Flags, SCEV::FlagNW)); + const SCEV *NewRec = getAddRecExpr(NewOps, AddRecLoop, Flags); // If all of the other operands were loop invariant, we are done. if (Ops.size() == 1) return NewRec; @@ -1869,7 +1920,8 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, getMulExpr(G, B), getMulExpr(B, D)); const SCEV *NewAddRec = getAddRecExpr(NewStart, NewStep, - F->getLoop()); + F->getLoop(), + SCEV::FlagAnyWrap); if (Ops.size() == 2) return NewAddRec; Ops[Idx] = AddRec = cast(NewAddRec); Ops.erase(Ops.begin() + OtherIdx); --OtherIdx; @@ -1897,8 +1949,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, O, Ops.size()); UniqueSCEVs.InsertNode(S, IP); } - if (HasNUW) S->setHasNoUnsignedWrap(true); - if (HasNSW) S->setHasNoSignedWrap(true); + S->setNoWrapFlags(Flags); return S; } @@ -1938,11 +1989,12 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS, getZeroExtendExpr(AR, ExtTy) == getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy), getZeroExtendExpr(Step, ExtTy), - AR->getLoop())) { + AR->getLoop(), SCEV::FlagAnyWrap)) { SmallVector Operands; for (unsigned i = 0, e = AR->getNumOperands(); i != e; ++i) Operands.push_back(getUDivExpr(AR->getOperand(i), RHS)); - return getAddRecExpr(Operands, AR->getLoop()); + return getAddRecExpr(Operands, AR->getLoop(), + SCEV::FlagNW); } // (A*B)/C --> A*(B/C) if safe and B/C can be folded. if (const SCEVMulExpr *M = dyn_cast(LHS)) { @@ -1963,7 +2015,7 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS, } } // (A+B)/C --> (A/C + B/C) if safe and A/C and B/C can be folded. - if (const SCEVAddRecExpr *A = dyn_cast(LHS)) { + if (const SCEVAddExpr *A = dyn_cast(LHS)) { SmallVector Operands; for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i) Operands.push_back(getZeroExtendExpr(A->getOperand(i), ExtTy)); @@ -2006,27 +2058,26 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS, /// getAddRecExpr - Get an add recurrence expression for the specified loop. /// Simplify the expression as much as possible. -const SCEV *ScalarEvolution::getAddRecExpr(const SCEV *Start, - const SCEV *Step, const Loop *L, - bool HasNUW, bool HasNSW) { +const SCEV *ScalarEvolution::getAddRecExpr(const SCEV *Start, const SCEV *Step, + const Loop *L, + SCEV::NoWrapFlags Flags) { SmallVector Operands; Operands.push_back(Start); if (const SCEVAddRecExpr *StepChrec = dyn_cast(Step)) if (StepChrec->getLoop() == L) { Operands.append(StepChrec->op_begin(), StepChrec->op_end()); - return getAddRecExpr(Operands, L); + return getAddRecExpr(Operands, L, maskFlags(Flags, SCEV::FlagNW)); } Operands.push_back(Step); - return getAddRecExpr(Operands, L, HasNUW, HasNSW); + return getAddRecExpr(Operands, L, Flags); } /// getAddRecExpr - Get an add recurrence expression for the specified loop. /// Simplify the expression as much as possible. const SCEV * ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, - const Loop *L, - bool HasNUW, bool HasNSW) { + const Loop *L, SCEV::NoWrapFlags Flags) { if (Operands.size() == 1) return Operands[0]; #ifndef NDEBUG const Type *ETy = getEffectiveSCEVType(Operands[0]->getType()); @@ -2040,7 +2091,7 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, if (Operands.back()->isZero()) { Operands.pop_back(); - return getAddRecExpr(Operands, L, HasNUW, HasNSW); // {X,+,0} --> X + return getAddRecExpr(Operands, L, SCEV::FlagAnyWrap); // {X,+,0} --> X } // It's tempting to want to call getMaxBackedgeTakenCount count here and @@ -2049,8 +2100,11 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, // meaningful BE count at this point (and if we don't, we'd be stuck // with a SCEVCouldNotCompute as the cached BE count). - // If HasNSW is true and all the operands are non-negative, infer HasNUW. - if (!HasNUW && HasNSW) { + // If FlagNSW is true and all the operands are non-negative, infer FlagNUW. + // And vice-versa. + int SignOrUnsignMask = SCEV::FlagNUW | SCEV::FlagNSW; + SCEV::NoWrapFlags SignOrUnsignWrap = maskFlags(Flags, SignOrUnsignMask); + if (SignOrUnsignWrap && (SignOrUnsignWrap != SignOrUnsignMask)) { bool All = true; for (SmallVectorImpl::const_iterator I = Operands.begin(), E = Operands.end(); I != E; ++I) @@ -2058,7 +2112,7 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, All = false; break; } - if (All) HasNUW = true; + if (All) Flags = setFlags(Flags, (SCEV::NoWrapFlags)SignOrUnsignMask); } // Canonicalize nested AddRecs in by nesting them in order of loop depth. @@ -2081,16 +2135,29 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, break; } if (AllInvariant) { - NestedOperands[0] = getAddRecExpr(Operands, L); + // Create a recurrence for the outer loop with the same step size. + // + // The outer recurrence keeps its NW flag but only keeps NUW/NSW if the + // inner recurrence has the same property. + SCEV::NoWrapFlags OuterFlags = + maskFlags(Flags, SCEV::FlagNW | NestedAR->getNoWrapFlags()); + + NestedOperands[0] = getAddRecExpr(Operands, L, OuterFlags); AllInvariant = true; for (unsigned i = 0, e = NestedOperands.size(); i != e; ++i) if (!isLoopInvariant(NestedOperands[i], NestedLoop)) { AllInvariant = false; break; } - if (AllInvariant) + if (AllInvariant) { // Ok, both add recurrences are valid after the transformation. - return getAddRecExpr(NestedOperands, NestedLoop, HasNUW, HasNSW); + // + // The inner recurrence keeps its NW flag but only keeps NUW/NSW if + // the outer recurrence has the same property. + SCEV::NoWrapFlags InnerFlags = + maskFlags(NestedAR->getNoWrapFlags(), SCEV::FlagNW | Flags); + return getAddRecExpr(NestedOperands, NestedLoop, InnerFlags); + } } // Reset Operands to its original state. Operands[0] = NestedAR; @@ -2114,8 +2181,7 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, O, Operands.size(), L); UniqueSCEVs.InsertNode(S, IP); } - if (HasNUW) S->setHasNoUnsignedWrap(true); - if (HasNSW) S->setHasNoSignedWrap(true); + S->setNoWrapFlags(Flags); return S; } @@ -2510,17 +2576,17 @@ const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) { return getMinusSCEV(AllOnes, V); } -/// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1, -/// and thus the HasNUW and HasNSW bits apply to the resultant add, not -/// whether the sub would have overflowed. +/// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1. const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS, - bool HasNUW, bool HasNSW) { + SCEV::NoWrapFlags Flags) { + assert(!maskFlags(Flags, SCEV::FlagNUW) && "subtraction does not have NUW"); + // Fast path: X - X --> 0. if (LHS == RHS) return getConstant(LHS->getType(), 0); // X - Y --> X + -Y - return getAddExpr(LHS, getNegativeSCEV(RHS), HasNUW, HasNSW); + return getAddExpr(LHS, getNegativeSCEV(RHS), Flags); } /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion of the @@ -2652,6 +2718,36 @@ const SCEV *ScalarEvolution::getUMinFromMismatchedTypes(const SCEV *LHS, return getUMinExpr(PromotedLHS, PromotedRHS); } +/// getPointerBase - Transitively follow the chain of pointer-type operands +/// until reaching a SCEV that does not have a single pointer operand. This +/// returns a SCEVUnknown pointer for well-formed pointer-type expressions, +/// but corner cases do exist. +const SCEV *ScalarEvolution::getPointerBase(const SCEV *V) { + // A pointer operand may evaluate to a nonpointer expression, such as null. + if (!V->getType()->isPointerTy()) + return V; + + if (const SCEVCastExpr *Cast = dyn_cast(V)) { + return getPointerBase(Cast->getOperand()); + } + else if (const SCEVNAryExpr *NAry = dyn_cast(V)) { + const SCEV *PtrOp = 0; + for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end(); + I != E; ++I) { + if ((*I)->getType()->isPointerTy()) { + // Cannot find the base of an expression with multiple pointer operands. + if (PtrOp) + return V; + PtrOp = *I; + } + } + if (!PtrOp) + return V; + return getPointerBase(PtrOp); + } + return V; +} + /// PushDefUseChildren - Push users of the given Instruction /// onto the given Worklist. static void @@ -2773,44 +2869,34 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) { if (isLoopInvariant(Accum, L) || (isa(Accum) && cast(Accum)->getLoop() == L)) { - bool HasNUW = false; - bool HasNSW = false; + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap; // If the increment doesn't overflow, then neither the addrec nor // the post-increment will overflow. if (const AddOperator *OBO = dyn_cast(BEValueV)) { if (OBO->hasNoUnsignedWrap()) - HasNUW = true; + Flags = setFlags(Flags, SCEV::FlagNUW); if (OBO->hasNoSignedWrap()) - HasNSW = true; - } else if (const GEPOperator *GEP = - dyn_cast(BEValueV)) { - // If the increment is a GEP, then we know it won't perform a - // signed overflow, because the address space cannot be - // wrapped around. - // - // NOTE: This isn't strictly true, because you could have an - // object straddling the 2G address boundary in a 32-bit address - // space (for example). We really want to model this as a "has - // no signed/unsigned wrap" where the base pointer is treated as - // unsigned and the increment is known to not have signed - // wrapping. - // - // This is a highly theoretical concern though, and this is good - // enough for all cases we know of at this point. :) - // - HasNSW |= GEP->isInBounds(); + Flags = setFlags(Flags, SCEV::FlagNSW); + } else if (const GEPOperator *GEP = + dyn_cast(BEValueV)) { + // If the increment is an inbounds GEP, then we know the address + // space cannot be wrapped around. We cannot make any guarantee + // about signed or unsigned overflow because pointers are + // unsigned but we may have a negative index from the base + // pointer. + if (GEP->isInBounds()) + Flags = setFlags(Flags, SCEV::FlagNW); } const SCEV *StartVal = getSCEV(StartValueV); - const SCEV *PHISCEV = - getAddRecExpr(StartVal, Accum, L, HasNUW, HasNSW); + const SCEV *PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags); // Since the no-wrap flags are on the increment, they apply to the // post-incremented value as well. if (isLoopInvariant(Accum, L)) (void)getAddRecExpr(getAddExpr(StartVal, Accum), - Accum, L, HasNUW, HasNSW); + Accum, L, Flags); // Okay, for the entire analysis of this edge we assumed the PHI // to be symbolic. We now need to go back and purge all of the @@ -2834,8 +2920,11 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) { // initial step of the addrec evolution. if (StartVal == getMinusSCEV(AddRec->getOperand(0), AddRec->getOperand(1))) { + // FIXME: For constant StartVal, we should be able to infer + // no-wrap flags. const SCEV *PHISCEV = - getAddRecExpr(StartVal, AddRec->getOperand(1), L); + getAddRecExpr(StartVal, AddRec->getOperand(1), L, + SCEV::FlagAnyWrap); // Okay, for the entire analysis of this edge we assumed the PHI // to be symbolic. We now need to go back and purge all of the @@ -2899,8 +2988,9 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) { IndexS = getTruncateOrSignExtend(IndexS, IntPtrTy); // Multiply the index by the element size to compute the element offset. - const SCEV *LocalOffset = getMulExpr(IndexS, ElementSize, /*NUW*/ false, - /*NSW*/ isInBounds); + const SCEV *LocalOffset = getMulExpr(IndexS, ElementSize, + isInBounds ? SCEV::FlagNSW : + SCEV::FlagAnyWrap); // Add the element offset to the running total offset. TotalOffset = getAddExpr(TotalOffset, LocalOffset); @@ -2911,8 +3001,8 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) { const SCEV *BaseS = getSCEV(Base); // Add the total offset from all the GEP indices to the base. - return getAddExpr(BaseS, TotalOffset, /*NUW*/ false, - /*NSW*/ isInBounds); + return getAddExpr(BaseS, TotalOffset, + isInBounds ? SCEV::FlagNSW : SCEV::FlagAnyWrap); } /// GetMinTrailingZeros - Determine the minimum number of zero bits that S is @@ -3074,7 +3164,7 @@ ScalarEvolution::getUnsignedRange(const SCEV *S) { if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) { // If there's no unsigned wrap, the value will never be less than its // initial value. - if (AddRec->hasNoUnsignedWrap()) + if (AddRec->getNoWrapFlags(SCEV::FlagNUW)) if (const SCEVConstant *C = dyn_cast(AddRec->getStart())) if (!C->getValue()->isZero()) ConservativeResult = @@ -3216,7 +3306,7 @@ ScalarEvolution::getSignedRange(const SCEV *S) { if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) { // If there's no signed wrap, and all the operands have the same sign or // zero, the value won't ever change sign. - if (AddRec->hasNoSignedWrap()) { + if (AddRec->getNoWrapFlags(SCEV::FlagNSW)) { bool AllNonNeg = true; bool AllNonPos = true; for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) { @@ -3349,7 +3439,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { SmallVector MulOps; MulOps.push_back(getSCEV(U->getOperand(1))); for (Value *Op = U->getOperand(0); - Op->getValueID() == Instruction::Mul + Value::InstructionVal; + Op->getValueID() == Instruction::Mul + Value::InstructionVal; Op = U->getOperand(0)) { U = cast(Op); MulOps.push_back(getSCEV(U->getOperand(1))); @@ -3411,10 +3501,8 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { // transfer the no-wrap flags, since an or won't introduce a wrap. if (const SCEVAddRecExpr *NewAR = dyn_cast(S)) { const SCEVAddRecExpr *OldAR = cast(LHS); - if (OldAR->hasNoUnsignedWrap()) - const_cast(NewAR)->setHasNoUnsignedWrap(true); - if (OldAR->hasNoSignedWrap()) - const_cast(NewAR)->setHasNoSignedWrap(true); + const_cast(NewAR)->setNoWrapFlags( + OldAR->getNoWrapFlags()); } return S; } @@ -3700,19 +3788,20 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { if (!Pair.second) return Pair.first->second; - BackedgeTakenInfo BECount = ComputeBackedgeTakenCount(L); - if (BECount.Exact != getCouldNotCompute()) { - assert(isLoopInvariant(BECount.Exact, L) && - isLoopInvariant(BECount.Max, L) && + BackedgeTakenInfo Result = getCouldNotCompute(); + BackedgeTakenInfo Computed = ComputeBackedgeTakenCount(L); + if (Computed.Exact != getCouldNotCompute()) { + assert(isLoopInvariant(Computed.Exact, L) && + isLoopInvariant(Computed.Max, L) && "Computed backedge-taken count isn't loop invariant for loop!"); ++NumTripCountsComputed; // Update the value in the map. - Pair.first->second = BECount; + Result = Computed; } else { - if (BECount.Max != getCouldNotCompute()) + if (Computed.Max != getCouldNotCompute()) // Update the value in the map. - Pair.first->second = BECount; + Result = Computed; if (isa(L->getHeader()->begin())) // Only count loops that have phi nodes as not being computable. ++NumTripCountsNotComputed; @@ -3723,7 +3812,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { // conservative estimates made without the benefit of trip count // information. This is similar to the code in forgetLoop, except that // it handles SCEVUnknown PHI nodes specially. - if (BECount.hasAnyInfo()) { + if (Computed.hasAnyInfo()) { SmallVector Worklist; PushLoopPHIs(L, Worklist); @@ -3754,7 +3843,13 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { PushDefUseChildren(I, Worklist); } } - return Pair.first->second; + + // Re-lookup the insert position, since the call to + // ComputeBackedgeTakenCount above could result in a + // recusive call to getBackedgeTakenInfo (on a different + // loop), which would invalidate the iterator computed + // earlier. + return BackedgeTakenCounts.find(L)->second = Result; } /// forgetLoop - This method should be called by the client when it has @@ -4022,105 +4117,6 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L, return ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB)); } -static const SCEVAddRecExpr * -isSimpleUnwrappingAddRec(const SCEV *S, const Loop *L) { - const SCEVAddRecExpr *SA = dyn_cast(S); - - // The SCEV must be an addrec of this loop. - if (!SA || SA->getLoop() != L || !SA->isAffine()) - return 0; - - // The SCEV must be known to not wrap in some way to be interesting. - if (!SA->hasNoUnsignedWrap() && !SA->hasNoSignedWrap()) - return 0; - - // The stride must be a constant so that we know if it is striding up or down. - if (!isa(SA->getOperand(1))) - return 0; - return SA; -} - -/// getMinusSCEVForExitTest - When considering an exit test for a loop with a -/// "x != y" exit test, we turn this into a computation that evaluates x-y != 0, -/// and this function returns the expression to use for x-y. We know and take -/// advantage of the fact that this subtraction is only being used in a -/// comparison by zero context. -/// -static const SCEV *getMinusSCEVForExitTest(const SCEV *LHS, const SCEV *RHS, - const Loop *L, ScalarEvolution &SE) { - // If either LHS or RHS is an AddRec SCEV (of this loop) that is known to not - // wrap (either NSW or NUW), then we know that the value will either become - // the other one (and thus the loop terminates), that the loop will terminate - // through some other exit condition first, or that the loop has undefined - // behavior. This information is useful when the addrec has a stride that is - // != 1 or -1, because it means we can't "miss" the exit value. - // - // In any of these three cases, it is safe to turn the exit condition into a - // "counting down" AddRec (to zero) by subtracting the two inputs as normal, - // but since we know that the "end cannot be missed" we can force the - // resulting AddRec to be a NUW addrec. Since it is counting down, this means - // that the AddRec *cannot* pass zero. - - // See if LHS and RHS are addrec's we can handle. - const SCEVAddRecExpr *LHSA = isSimpleUnwrappingAddRec(LHS, L); - const SCEVAddRecExpr *RHSA = isSimpleUnwrappingAddRec(RHS, L); - - // If neither addrec is interesting, just return a minus. - if (RHSA == 0 && LHSA == 0) - return SE.getMinusSCEV(LHS, RHS); - - // If only one of LHS and RHS are an AddRec of this loop, make sure it is LHS. - if (RHSA && LHSA == 0) { - // Safe because a-b === b-a for comparisons against zero. - std::swap(LHS, RHS); - std::swap(LHSA, RHSA); - } - - // Handle the case when only one is advancing in a non-overflowing way. - if (RHSA == 0) { - // If RHS is loop varying, then we can't predict when LHS will cross it. - if (!SE.isLoopInvariant(RHS, L)) - return SE.getMinusSCEV(LHS, RHS); - - // If LHS has a positive stride, then we compute RHS-LHS, because the loop - // is counting up until it crosses RHS (which must be larger than LHS). If - // it is negative, we compute LHS-RHS because we're counting down to RHS. - const ConstantInt *Stride = - cast(LHSA->getOperand(1))->getValue(); - if (Stride->getValue().isNegative()) - std::swap(LHS, RHS); - - return SE.getMinusSCEV(RHS, LHS, true /*HasNUW*/); - } - - // If both LHS and RHS are interesting, we have something like: - // a+i*4 != b+i*8. - const ConstantInt *LHSStride = - cast(LHSA->getOperand(1))->getValue(); - const ConstantInt *RHSStride = - cast(RHSA->getOperand(1))->getValue(); - - // If the strides are equal, then this is just a (complex) loop invariant - // comparison of a and b. - if (LHSStride == RHSStride) - return SE.getMinusSCEV(LHSA->getStart(), RHSA->getStart()); - - // If the signs of the strides differ, then the negative stride is counting - // down to the positive stride. - if (LHSStride->getValue().isNegative() != RHSStride->getValue().isNegative()){ - if (RHSStride->getValue().isNegative()) - std::swap(LHS, RHS); - } else { - // If LHS's stride is smaller than RHS's stride, then "b" must be less than - // "a" and "b" is RHS is counting up (catching up) to LHS. This is true - // whether the strides are positive or negative. - if (RHSStride->getValue().slt(LHSStride->getValue())) - std::swap(LHS, RHS); - } - - return SE.getMinusSCEV(LHS, RHS, true /*HasNUW*/); -} - /// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of times the /// backedge of the specified loop will execute if its exit condition /// were a conditional branch of the ICmpInst ExitCond, TBB, and FBB. @@ -4180,8 +4176,7 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, switch (Cond) { case ICmpInst::ICMP_NE: { // while (X != Y) // Convert to: while (X-Y != 0) - BackedgeTakenInfo BTI = HowFarToZero(getMinusSCEVForExitTest(LHS, RHS, L, - *this), L); + BackedgeTakenInfo BTI = HowFarToZero(getMinusSCEV(LHS, RHS), L); if (BTI.hasAnyInfo()) return BTI; break; } @@ -4706,7 +4701,15 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) { for (++i; i != e; ++i) NewOps.push_back(getSCEVAtScope(AddRec->getOperand(i), L)); - AddRec = cast(getAddRecExpr(NewOps, AddRec->getLoop())); + const SCEV *FoldedRec = + getAddRecExpr(NewOps, AddRec->getLoop(), + AddRec->getNoWrapFlags(SCEV::FlagNW)); + AddRec = dyn_cast(FoldedRec); + // The addrec may be folded to a nonrecurrence, for example, if the + // induction variable is multiplied by zero after constant folding. Go + // ahead and return the folded value. + if (!AddRec) + return FoldedRec; break; } @@ -4871,6 +4874,11 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) { /// HowFarToZero - Return the number of times a backedge comparing the specified /// value to zero will execute. If not computable, return CouldNotCompute. +/// +/// This is only used for loops with a "x != y" exit test. The exit condition is +/// now expressed as a single expression, V = x-y. So the exit test is +/// effectively V != 0. We know and take advantage of the fact that this +/// expression only being used in a comparison by zero context. ScalarEvolution::BackedgeTakenInfo ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { // If the value is a constant @@ -4903,7 +4911,7 @@ ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { R2->getValue()))) { if (CB->getZExtValue() == false) std::swap(R1, R2); // R1 is the minimum root now. - + // We can only use this value if the chrec ends up with an exact zero // value at this index. When solving for "X*X != 5", for example, we // should not accept a root of 2. @@ -4934,26 +4942,43 @@ ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { const SCEV *Start = getSCEVAtScope(AddRec->getStart(), L->getParentLoop()); const SCEV *Step = getSCEVAtScope(AddRec->getOperand(1), L->getParentLoop()); - // If the AddRec is NUW, then (in an unsigned sense) it cannot be counting up - // to wrap to 0, it must be counting down to equal 0. Also, while counting - // down, it cannot "miss" 0 (which would cause it to wrap), regardless of what - // the stride is. As such, NUW addrec's will always become zero in - // "start / -stride" steps, and we know that the division is exact. - if (AddRec->hasNoUnsignedWrap()) - // FIXME: We really want an "isexact" bit for udiv. - return getUDivExpr(Start, getNegativeSCEV(Step)); - // For now we handle only constant steps. + // + // TODO: Handle a nonconstant Step given AddRec. If the + // AddRec is NUW, then (in an unsigned sense) it cannot be counting up to wrap + // to 0, it must be counting down to equal 0. Consequently, N = Start / -Step. + // We have not yet seen any such cases. const SCEVConstant *StepC = dyn_cast(Step); if (StepC == 0) return getCouldNotCompute(); - // First, handle unitary steps. - if (StepC->getValue()->equalsInt(1)) // 1*N = -Start (mod 2^BW), so: - return getNegativeSCEV(Start); // N = -Start (as unsigned) - - if (StepC->getValue()->isAllOnesValue()) // -1*N = -Start (mod 2^BW), so: - return Start; // N = Start (as unsigned) + // For positive steps (counting up until unsigned overflow): + // N = -Start/Step (as unsigned) + // For negative steps (counting down to zero): + // N = Start/-Step + // First compute the unsigned distance from zero in the direction of Step. + bool CountDown = StepC->getValue()->getValue().isNegative(); + const SCEV *Distance = CountDown ? Start : getNegativeSCEV(Start); + + // Handle unitary steps, which cannot wraparound. + // 1*N = -Start; -1*N = Start (mod 2^BW), so: + // N = Distance (as unsigned) + if (StepC->getValue()->equalsInt(1) || StepC->getValue()->isAllOnesValue()) + return Distance; + + // If the recurrence is known not to wraparound, unsigned divide computes the + // back edge count. We know that the value will either become zero (and thus + // the loop terminates), that the loop will terminate through some other exit + // condition first, or that the loop has undefined behavior. This means + // we can't "miss" the exit value, even with nonunit stride. + // + // FIXME: Prove that loops always exhibits *acceptable* undefined + // behavior. Loops must exhibit defined behavior until a wrapped value is + // actually used. So the trip count computed by udiv could be smaller than the + // number of well-defined iterations. + if (AddRec->getNoWrapFlags(SCEV::FlagNW)) + // FIXME: We really want an "isexact" bit for udiv. + return getUDivExpr(Distance, CountDown ? getNegativeSCEV(Step) : Step); // Then, try to solve the above equation provided that Start is constant. if (const SCEVConstant *StartC = dyn_cast(Start)) @@ -5220,12 +5245,12 @@ bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred, case ICmpInst::ICMP_SLE: if (!getSignedRange(RHS).getSignedMax().isMaxSignedValue()) { RHS = getAddExpr(getConstant(RHS->getType(), 1, true), RHS, - /*HasNUW=*/false, /*HasNSW=*/true); + SCEV::FlagNSW); Pred = ICmpInst::ICMP_SLT; Changed = true; } else if (!getSignedRange(LHS).getSignedMin().isMinSignedValue()) { LHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), LHS, - /*HasNUW=*/false, /*HasNSW=*/true); + SCEV::FlagNSW); Pred = ICmpInst::ICMP_SLT; Changed = true; } @@ -5233,12 +5258,12 @@ bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred, case ICmpInst::ICMP_SGE: if (!getSignedRange(RHS).getSignedMin().isMinSignedValue()) { RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS, - /*HasNUW=*/false, /*HasNSW=*/true); + SCEV::FlagNSW); Pred = ICmpInst::ICMP_SGT; Changed = true; } else if (!getSignedRange(LHS).getSignedMax().isMaxSignedValue()) { LHS = getAddExpr(getConstant(RHS->getType(), 1, true), LHS, - /*HasNUW=*/false, /*HasNSW=*/true); + SCEV::FlagNSW); Pred = ICmpInst::ICMP_SGT; Changed = true; } @@ -5246,12 +5271,12 @@ bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred, case ICmpInst::ICMP_ULE: if (!getUnsignedRange(RHS).getUnsignedMax().isMaxValue()) { RHS = getAddExpr(getConstant(RHS->getType(), 1, true), RHS, - /*HasNUW=*/true, /*HasNSW=*/false); + SCEV::FlagNUW); Pred = ICmpInst::ICMP_ULT; Changed = true; } else if (!getUnsignedRange(LHS).getUnsignedMin().isMinValue()) { LHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), LHS, - /*HasNUW=*/true, /*HasNSW=*/false); + SCEV::FlagNUW); Pred = ICmpInst::ICMP_ULT; Changed = true; } @@ -5259,12 +5284,12 @@ bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred, case ICmpInst::ICMP_UGE: if (!getUnsignedRange(RHS).getUnsignedMin().isMinValue()) { RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS, - /*HasNUW=*/true, /*HasNSW=*/false); + SCEV::FlagNUW); Pred = ICmpInst::ICMP_UGT; Changed = true; } else if (!getUnsignedRange(LHS).getUnsignedMax().isMaxValue()) { LHS = getAddExpr(getConstant(RHS->getType(), 1, true), LHS, - /*HasNUW=*/true, /*HasNSW=*/false); + SCEV::FlagNUW); Pred = ICmpInst::ICMP_UGT; Changed = true; } @@ -5646,6 +5671,13 @@ const SCEV *ScalarEvolution::getBECount(const SCEV *Start, "This code doesn't handle negative strides yet!"); const Type *Ty = Start->getType(); + + // When Start == End, we have an exact BECount == 0. Short-circuit this case + // here because SCEV may not be able to determine that the unsigned division + // after rounding is zero. + if (Start == End) + return getConstant(Ty, 0); + const SCEV *NegOne = getConstant(Ty, (uint64_t)-1); const SCEV *Diff = getMinusSCEV(End, Start); const SCEV *RoundUp = getAddExpr(Step, NegOne); @@ -5683,8 +5715,8 @@ ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS, return getCouldNotCompute(); // Check to see if we have a flag which makes analysis easy. - bool NoWrap = isSigned ? AddRec->hasNoSignedWrap() : - AddRec->hasNoUnsignedWrap(); + bool NoWrap = isSigned ? AddRec->getNoWrapFlags(SCEV::FlagNSW) : + AddRec->getNoWrapFlags(SCEV::FlagNUW); if (AddRec->isAffine()) { unsigned BitWidth = getTypeSizeInBits(AddRec->getType()); @@ -5768,7 +5800,16 @@ ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS, // The maximum backedge count is similar, except using the minimum start // value and the maximum end value. - const SCEV *MaxBECount = getBECount(MinStart, MaxEnd, Step, NoWrap); + // If we already have an exact constant BECount, use it instead. + const SCEV *MaxBECount = isa(BECount) ? BECount + : getBECount(MinStart, MaxEnd, Step, NoWrap); + + // If the stride is nonconstant, and NoWrap == true, then + // getBECount(MinStart, MaxEnd) may not compute. This would result in an + // exact BECount and invalid MaxBECount, which should be avoided to catch + // more optimization opportunities. + if (isa(MaxBECount)) + MaxBECount = BECount; return BackedgeTakenInfo(BECount, MaxBECount); } @@ -5791,7 +5832,8 @@ const SCEV *SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range, if (!SC->getValue()->isZero()) { SmallVector Operands(op_begin(), op_end()); Operands[0] = SE.getConstant(SC->getType(), 0); - const SCEV *Shifted = SE.getAddRecExpr(Operands, getLoop()); + const SCEV *Shifted = SE.getAddRecExpr(Operands, getLoop(), + getNoWrapFlags(FlagNW)); if (const SCEVAddRecExpr *ShiftedAddRec = dyn_cast(Shifted)) return ShiftedAddRec->getNumIterationsInRange( @@ -5852,7 +5894,9 @@ const SCEV *SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range, // Range.getUpper() is crossed. SmallVector NewOps(op_begin(), op_end()); NewOps[0] = SE.getNegativeSCEV(SE.getConstant(Range.getUpper())); - const SCEV *NewAddRec = SE.getAddRecExpr(NewOps, getLoop()); + const SCEV *NewAddRec = SE.getAddRecExpr(NewOps, getLoop(), + // getNoWrapFlags(FlagNW) + FlagAnyWrap); // Next, solve the constructed addrec std::pair Roots = diff --git a/contrib/llvm/lib/Analysis/ScalarEvolutionExpander.cpp b/contrib/llvm/lib/Analysis/ScalarEvolutionExpander.cpp index b7c110f28cf9..8e5a40008d88 100644 --- a/contrib/llvm/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/contrib/llvm/lib/Analysis/ScalarEvolutionExpander.cpp @@ -262,7 +262,8 @@ static bool FactorOutConstant(const SCEV *&S, const SCEV *Start = A->getStart(); if (!FactorOutConstant(Start, Remainder, Factor, SE, TD)) return false; - S = SE.getAddRecExpr(Start, Step, A->getLoop()); + // FIXME: can use A->getNoWrapFlags(FlagNW) + S = SE.getAddRecExpr(Start, Step, A->getLoop(), SCEV::FlagAnyWrap); return true; } @@ -314,7 +315,9 @@ static void SplitAddRecs(SmallVectorImpl &Ops, const SCEV *Zero = SE.getConstant(Ty, 0); AddRecs.push_back(SE.getAddRecExpr(Zero, A->getStepRecurrence(SE), - A->getLoop())); + A->getLoop(), + // FIXME: A->getNoWrapFlags(FlagNW) + SCEV::FlagAnyWrap)); if (const SCEVAddExpr *Add = dyn_cast(Start)) { Ops[i] = Zero; Ops.append(Add->op_begin(), Add->op_end()); @@ -823,7 +826,9 @@ static void ExposePointerBase(const SCEV *&Base, const SCEV *&Rest, Rest = SE.getAddExpr(Rest, SE.getAddRecExpr(SE.getConstant(A->getType(), 0), A->getStepRecurrence(SE), - A->getLoop())); + A->getLoop(), + // FIXME: A->getNoWrapFlags(FlagNW) + SCEV::FlagAnyWrap)); } if (const SCEVAddExpr *A = dyn_cast(Base)) { Base = A->getOperand(A->getNumOperands()-1); @@ -858,7 +863,8 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, // loop already visited by LSR for example, but it wouldn't have // to be. do { - if (IncV->getNumOperands() == 0 || isa(IncV)) { + if (IncV->getNumOperands() == 0 || isa(IncV) || + (isa(IncV) && !isa(IncV))) { IncV = 0; break; } @@ -926,14 +932,14 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, Value *StepV = expandCodeFor(Step, IntTy, L->getHeader()->begin()); // Create the PHI. - Builder.SetInsertPoint(L->getHeader(), L->getHeader()->begin()); - PHINode *PN = Builder.CreatePHI(ExpandTy, "lsr.iv"); + BasicBlock *Header = L->getHeader(); + Builder.SetInsertPoint(Header, Header->begin()); + pred_iterator HPB = pred_begin(Header), HPE = pred_end(Header); + PHINode *PN = Builder.CreatePHI(ExpandTy, std::distance(HPB, HPE), "lsr.iv"); rememberInstruction(PN); // Create the step instructions and populate the PHI. - BasicBlock *Header = L->getHeader(); - for (pred_iterator HPI = pred_begin(Header), HPE = pred_end(Header); - HPI != HPE; ++HPI) { + for (pred_iterator HPI = HPB; HPI != HPE; ++HPI) { BasicBlock *Pred = *HPI; // Add a start value. @@ -1004,10 +1010,11 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { if (!SE.properlyDominates(Start, L->getHeader())) { PostLoopOffset = Start; Start = SE.getConstant(Normalized->getType(), 0); - Normalized = - cast(SE.getAddRecExpr(Start, - Normalized->getStepRecurrence(SE), - Normalized->getLoop())); + Normalized = cast( + SE.getAddRecExpr(Start, Normalized->getStepRecurrence(SE), + Normalized->getLoop(), + // FIXME: Normalized->getNoWrapFlags(FlagNW) + SCEV::FlagAnyWrap)); } // Strip off any non-loop-dominating component from the addrec step. @@ -1018,7 +1025,10 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { Step = SE.getConstant(Normalized->getType(), 1); Normalized = cast(SE.getAddRecExpr(Start, Step, - Normalized->getLoop())); + Normalized->getLoop(), + // FIXME: Normalized + // ->getNoWrapFlags(FlagNW) + SCEV::FlagAnyWrap)); } // Expand the core addrec. If we need post-loop scaling, force it to @@ -1081,7 +1091,9 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { SmallVector NewOps(S->getNumOperands()); for (unsigned i = 0, e = S->getNumOperands(); i != e; ++i) NewOps[i] = SE.getAnyExtendExpr(S->op_begin()[i], CanonicalIV->getType()); - Value *V = expand(SE.getAddRecExpr(NewOps, S->getLoop())); + Value *V = expand(SE.getAddRecExpr(NewOps, S->getLoop(), + // FIXME: S->getNoWrapFlags(FlagNW) + SCEV::FlagAnyWrap)); BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); BasicBlock::iterator NewInsertPt = @@ -1098,7 +1110,8 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { if (!S->getStart()->isZero()) { SmallVector NewOps(S->op_begin(), S->op_end()); NewOps[0] = SE.getConstant(Ty, 0); - const SCEV *Rest = SE.getAddRecExpr(NewOps, L); + // FIXME: can use S->getNoWrapFlags() + const SCEV *Rest = SE.getAddRecExpr(NewOps, L, SCEV::FlagAnyWrap); // Turn things like ptrtoint+arithmetic+inttoptr into GEP. See the // comments on expandAddToGEP for details. @@ -1128,12 +1141,13 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { // Create and insert the PHI node for the induction variable in the // specified loop. BasicBlock *Header = L->getHeader(); - CanonicalIV = PHINode::Create(Ty, "indvar", Header->begin()); + pred_iterator HPB = pred_begin(Header), HPE = pred_end(Header); + CanonicalIV = PHINode::Create(Ty, std::distance(HPB, HPE), "indvar", + Header->begin()); rememberInstruction(CanonicalIV); Constant *One = ConstantInt::get(Ty, 1); - for (pred_iterator HPI = pred_begin(Header), HPE = pred_end(Header); - HPI != HPE; ++HPI) { + for (pred_iterator HPI = HPB; HPI != HPE; ++HPI) { BasicBlock *HP = *HPI; if (L->contains(HP)) { // Insert a unit add instruction right before the terminator @@ -1333,7 +1347,7 @@ void SCEVExpander::rememberInstruction(Value *I) { InsertedValues.insert(I); // If we just claimed an existing instruction and that instruction had - // been the insert point, adjust the insert point forward so that + // been the insert point, adjust the insert point forward so that // subsequently inserted code will be dominated. if (Builder.GetInsertPoint() == I) { BasicBlock::iterator It = cast(I); @@ -1361,8 +1375,9 @@ SCEVExpander::getOrInsertCanonicalInductionVariable(const Loop *L, assert(Ty->isIntegerTy() && "Can only insert integer induction variables!"); // Build a SCEV for {0,+,1}. + // Conservatively use FlagAnyWrap for now. const SCEV *H = SE.getAddRecExpr(SE.getConstant(Ty, 0), - SE.getConstant(Ty, 1), L); + SE.getConstant(Ty, 1), L, SCEV::FlagAnyWrap); // Emit code for it. BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); diff --git a/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp b/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp index ac36cef89ebb..60e630aaab88 100644 --- a/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp +++ b/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp @@ -97,7 +97,8 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, const SCEV *N = TransformForPostIncUse(Kind, O, LUser, 0, Loops, SE, DT); Operands.push_back(N); } - const SCEV *Result = SE.getAddRecExpr(Operands, L); + // Conservatively use AnyWrap until/unless we need FlagNW. + const SCEV *Result = SE.getAddRecExpr(Operands, L, SCEV::FlagAnyWrap); switch (Kind) { default: llvm_unreachable("Unexpected transform name!"); case NormalizeAutodetect: diff --git a/contrib/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp b/contrib/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp index 40e18ab2fbfa..0faf1398ec76 100644 --- a/contrib/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -31,7 +31,7 @@ // // The second field identifies the type's parent node in the tree, or // is null or omitted for a root node. A type is considered to alias -// all of its decendents and all of its ancestors in the tree. Also, +// all of its descendants and all of its ancestors in the tree. Also, // a type is considered to alias all types in other trees, so that // bitcode produced from multiple front-ends is handled conservatively. // @@ -59,6 +59,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/Passes.h" +#include "llvm/Constants.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Metadata.h" diff --git a/contrib/llvm/lib/Analysis/ValueTracking.cpp b/contrib/llvm/lib/Analysis/ValueTracking.cpp index 1060bc5349e4..8f18dd278aa0 100644 --- a/contrib/llvm/lib/Analysis/ValueTracking.cpp +++ b/contrib/llvm/lib/Analysis/ValueTracking.cpp @@ -429,6 +429,29 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, KnownZero |= LHSKnownZero & Mask; KnownOne |= LHSKnownOne & Mask; } + + // Are we still trying to solve for the sign bit? + if (Mask.isNegative() && !KnownZero.isNegative() && !KnownOne.isNegative()){ + OverflowingBinaryOperator *OBO = cast(I); + if (OBO->hasNoSignedWrap()) { + if (I->getOpcode() == Instruction::Add) { + // Adding two positive numbers can't wrap into negative + if (LHSKnownZero.isNegative() && KnownZero2.isNegative()) + KnownZero |= APInt::getSignBit(BitWidth); + // and adding two negative numbers can't wrap into positive. + else if (LHSKnownOne.isNegative() && KnownOne2.isNegative()) + KnownOne |= APInt::getSignBit(BitWidth); + } else { + // Subtracting a negative number from a positive one can't wrap + if (LHSKnownZero.isNegative() && KnownOne2.isNegative()) + KnownZero |= APInt::getSignBit(BitWidth); + // neither can subtracting a positive number from a negative one. + else if (LHSKnownOne.isNegative() && KnownZero2.isNegative()) + KnownOne |= APInt::getSignBit(BitWidth); + } + } + } + return; } case Instruction::SRem: @@ -460,6 +483,19 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); } } + + // The sign bit is the LHS's sign bit, except when the result of the + // remainder is zero. + if (Mask.isNegative() && KnownZero.isNonNegative()) { + APInt Mask2 = APInt::getSignBit(BitWidth); + APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0); + ComputeMaskedBits(I->getOperand(0), Mask2, LHSKnownZero, LHSKnownOne, TD, + Depth+1); + // If it's known zero, our sign bit is also zero. + if (LHSKnownZero.isNegative()) + KnownZero |= LHSKnownZero; + } + break; case Instruction::URem: { if (ConstantInt *Rem = dyn_cast(I->getOperand(1))) { @@ -597,6 +633,10 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, // Otherwise take the unions of the known bit sets of the operands, // taking conservative care to avoid excessive recursion. if (Depth < MaxDepth - 1 && !KnownZero && !KnownOne) { + // Skip if every incoming value references to ourself. + if (P->hasConstantValue() == P) + break; + KnownZero = APInt::getAllOnesValue(BitWidth); KnownOne = APInt::getAllOnesValue(BitWidth); for (unsigned i = 0, e = P->getNumIncomingValues(); i != e; ++i) { @@ -684,6 +724,16 @@ bool llvm::isPowerOfTwo(Value *V, const TargetData *TD, unsigned Depth) { return isPowerOfTwo(SI->getTrueValue(), TD, Depth) && isPowerOfTwo(SI->getFalseValue(), TD, Depth); + // An exact divide or right shift can only shift off zero bits, so the result + // is a power of two only if the first operand is a power of two and not + // copying a sign bit (sdiv int_min, 2). + if (match(V, m_LShr(m_Value(), m_Value())) || + match(V, m_UDiv(m_Value(), m_Value()))) { + PossiblyExactOperator *PEO = cast(V); + if (PEO->isExact()) + return isPowerOfTwo(PEO->getOperand(0), TD, Depth); + } + return false; } @@ -720,6 +770,11 @@ bool llvm::isKnownNonZero(Value *V, const TargetData *TD, unsigned Depth) { // shl X, Y != 0 if X is odd. Note that the value of the shift is undefined // if the lowest bit is shifted off the end. if (BitWidth && match(V, m_Shl(m_Value(X), m_Value(Y)))) { + // shl nuw can't remove any non-zero bits. + BinaryOperator *BO = cast(V); + if (BO->hasNoUnsignedWrap()) + return isKnownNonZero(X, TD, Depth); + APInt KnownZero(BitWidth, 0); APInt KnownOne(BitWidth, 0); ComputeMaskedBits(X, APInt(BitWidth, 1), KnownZero, KnownOne, TD, Depth); @@ -729,11 +784,22 @@ bool llvm::isKnownNonZero(Value *V, const TargetData *TD, unsigned Depth) { // shr X, Y != 0 if X is negative. Note that the value of the shift is not // defined if the sign bit is shifted off the end. else if (match(V, m_Shr(m_Value(X), m_Value(Y)))) { + // shr exact can only shift out zero bits. + BinaryOperator *BO = cast(V); + if (BO->isExact()) + return isKnownNonZero(X, TD, Depth); + bool XKnownNonNegative, XKnownNegative; ComputeSignBit(X, XKnownNonNegative, XKnownNegative, TD, Depth); if (XKnownNegative) return true; } + // div exact can only produce a zero if the dividend is zero. + else if (match(V, m_IDiv(m_Value(X), m_Value()))) { + BinaryOperator *BO = cast(V); + if (BO->isExact()) + return isKnownNonZero(X, TD, Depth); + } // X + Y. else if (match(V, m_Add(m_Value(X), m_Value(Y)))) { bool XKnownNonNegative, XKnownNegative; @@ -1262,7 +1328,7 @@ static Value *BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, break; } } - // If we succesfully found a value for each of our subaggregates + // If we successfully found a value for each of our subaggregates if (To) return To; } @@ -1691,7 +1757,7 @@ llvm::GetUnderlyingObject(Value *V, const TargetData *TD, unsigned MaxLookup) { } else { // See if InstructionSimplify knows any relevant tricks. if (Instruction *I = dyn_cast(V)) - // TODO: Aquire a DominatorTree and use it. + // TODO: Acquire a DominatorTree and use it. if (Value *Simplified = SimplifyInstruction(I, TD, 0)) { V = Simplified; continue; diff --git a/contrib/llvm/lib/Archive/ArchiveWriter.cpp b/contrib/llvm/lib/Archive/ArchiveWriter.cpp index c5ad5fc41cd1..8fcc7aa29cc8 100644 --- a/contrib/llvm/lib/Archive/ArchiveWriter.cpp +++ b/contrib/llvm/lib/Archive/ArchiveWriter.cpp @@ -18,7 +18,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Process.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" #include "llvm/Support/system_error.h" #include @@ -28,7 +27,7 @@ using namespace llvm; // Write an integer using variable bit rate encoding. This saves a few bytes // per entry in the symbol table. -static inline void writeInteger(unsigned num, raw_ostream& ARFile) { +static inline void writeInteger(unsigned num, std::ofstream& ARFile) { while (1) { if (num < 0x80) { // done? ARFile << (unsigned char)num; @@ -202,14 +201,14 @@ Archive::addFileBefore(const sys::Path& filePath, iterator where, bool Archive::writeMember( const ArchiveMember& member, - raw_ostream& ARFile, + std::ofstream& ARFile, bool CreateSymbolTable, bool TruncateNames, bool ShouldCompress, std::string* ErrMsg ) { - unsigned filepos = ARFile.tell(); + unsigned filepos = ARFile.tellp(); filepos -= 8; // Get the data and its size either from the @@ -282,7 +281,7 @@ Archive::writeMember( ARFile.write(data,fSize); // Make sure the member is an even length - if ((ARFile.tell() & 1) == 1) + if ((ARFile.tellp() & 1) == 1) ARFile << ARFILE_PAD; // Close the mapped file if it was opened @@ -292,7 +291,7 @@ Archive::writeMember( // Write out the LLVM symbol table as an archive member to the file. void -Archive::writeSymbolTable(raw_ostream& ARFile) { +Archive::writeSymbolTable(std::ofstream& ARFile) { // Construct the symbol table's header ArchiveMemberHeader Hdr; @@ -316,7 +315,7 @@ Archive::writeSymbolTable(raw_ostream& ARFile) { #ifndef NDEBUG // Save the starting position of the symbol tables data content. - unsigned startpos = ARFile.tell(); + unsigned startpos = ARFile.tellp(); #endif // Write out the symbols sequentially @@ -333,7 +332,7 @@ Archive::writeSymbolTable(raw_ostream& ARFile) { #ifndef NDEBUG // Now that we're done with the symbol table, get the ending file position - unsigned endpos = ARFile.tell(); + unsigned endpos = ARFile.tellp(); #endif // Make sure that the amount we wrote is what we pre-computed. This is @@ -362,20 +361,25 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, } // Create a temporary file to store the archive in - SmallString<128> TempArchivePath; - int ArchFD; - if (error_code ec = - sys::fs::unique_file("%%-%%-%%-%%-" + sys::path::filename(archPath.str()), - ArchFD, TempArchivePath)) { - if (ErrMsg) *ErrMsg = ec.message(); + sys::Path TmpArchive = archPath; + if (TmpArchive.createTemporaryFileOnDisk(ErrMsg)) return true; - } // Make sure the temporary gets removed if we crash - sys::RemoveFileOnSignal(sys::Path(TempArchivePath.str())); + sys::RemoveFileOnSignal(TmpArchive); // Create archive file for output. - raw_fd_ostream ArchiveFile(ArchFD, true); + std::ios::openmode io_mode = std::ios::out | std::ios::trunc | + std::ios::binary; + std::ofstream ArchiveFile(TmpArchive.c_str(), io_mode); + + // Check for errors opening or creating archive file. + if (!ArchiveFile.is_open() || ArchiveFile.bad()) { + TmpArchive.eraseFromDisk(); + if (ErrMsg) + *ErrMsg = "Error opening archive file: " + archPath.str(); + return true; + } // If we're creating a symbol table, reset it now if (CreateSymbolTable) { @@ -391,9 +395,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, for (MembersList::iterator I = begin(), E = end(); I != E; ++I) { if (writeMember(*I, ArchiveFile, CreateSymbolTable, TruncateNames, Compress, ErrMsg)) { + TmpArchive.eraseFromDisk(); ArchiveFile.close(); - bool existed; - sys::fs::remove(TempArchivePath.str(), existed); return true; } } @@ -408,12 +411,12 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, // ensure compatibility with other archivers we need to put the symbol // table first in the file. Unfortunately, this means mapping the file // we just wrote back in and copying it to the destination file. - SmallString<128> TempArchiveWithSymbolTablePath; + sys::Path FinalFilePath = archPath; // Map in the archive we just wrote. { OwningPtr arch; - if (error_code ec = MemoryBuffer::getFile(TempArchivePath.c_str(), arch)) { + if (error_code ec = MemoryBuffer::getFile(TmpArchive.c_str(), arch)) { if (ErrMsg) *ErrMsg = ec.message(); return true; @@ -422,15 +425,17 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, // Open another temporary file in order to avoid invalidating the // mmapped data - if (error_code ec = - sys::fs::unique_file("%%-%%-%%-%%-" + sys::path::filename(archPath.str()), - ArchFD, TempArchiveWithSymbolTablePath)) { - if (ErrMsg) *ErrMsg = ec.message(); + if (FinalFilePath.createTemporaryFileOnDisk(ErrMsg)) + return true; + sys::RemoveFileOnSignal(FinalFilePath); + + std::ofstream FinalFile(FinalFilePath.c_str(), io_mode); + if (!FinalFile.is_open() || FinalFile.bad()) { + TmpArchive.eraseFromDisk(); + if (ErrMsg) + *ErrMsg = "Error opening archive file: " + FinalFilePath.str(); return true; } - sys::RemoveFileOnSignal(sys::Path(TempArchiveWithSymbolTablePath.str())); - - raw_fd_ostream FinalFile(ArchFD, true); // Write the file magic number FinalFile << ARFILE_MAGIC; @@ -443,8 +448,7 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, if (foreignST) { if (writeMember(*foreignST, FinalFile, false, false, false, ErrMsg)) { FinalFile.close(); - bool existed; - sys::fs::remove(TempArchiveWithSymbolTablePath.str(), existed); + TmpArchive.eraseFromDisk(); return true; } } @@ -462,11 +466,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, } // free arch. // Move the final file over top of TmpArchive - if (error_code ec = sys::fs::rename(TempArchiveWithSymbolTablePath.str(), - TempArchivePath.str())) { - if (ErrMsg) *ErrMsg = ec.message(); + if (FinalFilePath.renamePathOnDisk(TmpArchive, ErrMsg)) return true; - } } // Before we replace the actual archive, we need to forget all the @@ -474,11 +475,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, // this because we cannot replace an open file on Windows. cleanUpMemory(); - if (error_code ec = sys::fs::rename(TempArchivePath.str(), - archPath.str())) { - if (ErrMsg) *ErrMsg = ec.message(); + if (TmpArchive.renamePathOnDisk(archPath, ErrMsg)) return true; - } // Set correct read and write permissions after temporary file is moved // to final destination path. diff --git a/contrib/llvm/lib/AsmParser/LLParser.cpp b/contrib/llvm/lib/AsmParser/LLParser.cpp index cdfacbebbfc3..a2c53bef364f 100644 --- a/contrib/llvm/lib/AsmParser/LLParser.cpp +++ b/contrib/llvm/lib/AsmParser/LLParser.cpp @@ -249,11 +249,7 @@ bool LLParser::ParseModuleAsm() { if (ParseToken(lltok::kw_asm, "expected 'module asm'") || ParseStringConstant(AsmStr)) return true; - const std::string &AsmSoFar = M->getModuleInlineAsm(); - if (AsmSoFar.empty()) - M->setModuleInlineAsm(AsmStr); - else - M->setModuleInlineAsm(AsmSoFar+"\n"+AsmStr); + M->appendModuleInlineAsm(AsmStr); return false; } @@ -518,7 +514,7 @@ bool LLParser::ParseMDNodeID(MDNode *&Result) { if (Result) return false; // Otherwise, create MDNode forward reference. - MDNode *FwdNode = MDNode::getTemporary(Context, 0, 0); + MDNode *FwdNode = MDNode::getTemporary(Context, ArrayRef()); ForwardRefMDNodes[MID] = std::make_pair(FwdNode, Lex.getLoc()); if (NumberedMetadata.size() <= MID) @@ -576,7 +572,7 @@ bool LLParser::ParseStandaloneMetadata() { ParseToken(lltok::rbrace, "expected end of metadata node")) return true; - MDNode *Init = MDNode::get(Context, Elts.data(), Elts.size()); + MDNode *Init = MDNode::get(Context, Elts); // See if this was forward referenced, if so, handle it. std::map, LocTy> >::iterator @@ -2502,7 +2498,7 @@ bool LLParser::ParseMetadataListValue(ValID &ID, PerFunctionState *PFS) { ParseToken(lltok::rbrace, "expected end of metadata node")) return true; - ID.MDNodeVal = MDNode::get(Context, Elts.data(), Elts.size()); + ID.MDNodeVal = MDNode::get(Context, Elts); ID.Kind = ValID::t_MDNode; return false; } @@ -3638,8 +3634,7 @@ int LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) { if (!Ty->isFirstClassType()) return Error(TypeLoc, "phi node must have first class type"); - PHINode *PN = PHINode::Create(Ty); - PN->reserveOperandSpace(PHIVals.size()); + PHINode *PN = PHINode::Create(Ty, PHIVals.size()); for (unsigned i = 0, e = PHIVals.size(); i != e; ++i) PN->addIncoming(PHIVals[i].first, PHIVals[i].second); Inst = PN; diff --git a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index dbf8da027996..19f57cf6907b 100644 --- a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -301,8 +301,7 @@ void BitcodeReaderValueList::ResolveConstantForwardRefs() { NewC = ConstantVector::get(NewOps); } else { assert(isa(UserC) && "Must be a ConstantExpr."); - NewC = cast(UserC)->getWithOperands(&NewOps[0], - NewOps.size()); + NewC = cast(UserC)->getWithOperands(NewOps); } UserC->replaceAllUsesWith(NewC); @@ -350,7 +349,7 @@ Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) { } // Create and return a placeholder, which will later be RAUW'd. - Value *V = MDNode::getTemporary(Context, 0, 0); + Value *V = MDNode::getTemporary(Context, ArrayRef()); MDValuePtrs[Idx] = V; return V; } @@ -844,9 +843,7 @@ bool BitcodeReader::ParseMetadata() { else Elts.push_back(NULL); } - Value *V = MDNode::getWhenValsUnresolved(Context, - Elts.data(), Elts.size(), - IsFunctionLocal); + Value *V = MDNode::getWhenValsUnresolved(Context, Elts, IsFunctionLocal); IsFunctionLocal = false; MDValueList.AssignValue(V, NextMDValueNo++); break; @@ -2288,9 +2285,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { const Type *Ty = getTypeByID(Record[0]); if (!Ty) return Error("Invalid PHI record"); - PHINode *PN = PHINode::Create(Ty); + PHINode *PN = PHINode::Create(Ty, (Record.size()-1)/2); InstructionList.push_back(PN); - PN->reserveOperandSpace((Record.size()-1)/2); for (unsigned i = 0, e = Record.size()-1; i != e; i += 2) { Value *V = getFnValueByID(Record[1+i], Ty); diff --git a/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index f8ef8c668c47..e34137f6155a 100644 --- a/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -197,7 +197,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { // Loop over all of the types, emitting each in turn. for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { - const Type *T = TypeList[i].first; + const Type *T = TypeList[i]; int AbbrevToUse = 0; unsigned Code = 0; diff --git a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp index 2f02262c36af..21f004a7dc53 100644 --- a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "ValueEnumerator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" @@ -21,22 +23,10 @@ #include using namespace llvm; -static bool isSingleValueType(const std::pair &P) { - return P.first->isSingleValueType(); -} - static bool isIntegerValue(const std::pair &V) { return V.first->getType()->isIntegerTy(); } -static bool CompareByFrequency(const std::pair &P1, - const std::pair &P2) { - return P1.second > P2.second; -} - /// ValueEnumerator - Enumerate module-level information. ValueEnumerator::ValueEnumerator(const Module *M) { // Enumerate the global variables. @@ -120,18 +110,72 @@ ValueEnumerator::ValueEnumerator(const Module *M) { // Optimize constant ordering. OptimizeConstants(FirstConstant, Values.size()); - // Sort the type table by frequency so that most commonly used types are early - // in the table (have low bit-width). - std::stable_sort(Types.begin(), Types.end(), CompareByFrequency); - - // Partition the Type ID's so that the single-value types occur before the - // aggregate types. This allows the aggregate types to be dropped from the - // type table after parsing the global variable initializers. - std::partition(Types.begin(), Types.end(), isSingleValueType); + OptimizeTypes(); // Now that we rearranged the type table, rebuild TypeMap. for (unsigned i = 0, e = Types.size(); i != e; ++i) - TypeMap[Types[i].first] = i+1; + TypeMap[Types[i]] = i+1; +} + +struct TypeAndDeps { + const Type *Ty; + unsigned NumDeps; +}; + +static int CompareByDeps(const void *a, const void *b) { + const TypeAndDeps &ta = *(const TypeAndDeps*) a; + const TypeAndDeps &tb = *(const TypeAndDeps*) b; + return ta.NumDeps - tb.NumDeps; +} + +static void VisitType(const Type *Ty, SmallPtrSet &Visited, + std::vector &Out) { + if (Visited.count(Ty)) + return; + + Visited.insert(Ty); + + for (Type::subtype_iterator I2 = Ty->subtype_begin(), + E2 = Ty->subtype_end(); I2 != E2; ++I2) { + const Type *InnerType = I2->get(); + VisitType(InnerType, Visited, Out); + } + + Out.push_back(Ty); +} + +void ValueEnumerator::OptimizeTypes(void) { + // If the types form a DAG, this will compute a topological sort and + // no forward references will be needed when reading them in. + // If there are cycles, this is a simple but reasonable heuristic for + // the minimum feedback arc set problem. + const unsigned NumTypes = Types.size(); + std::vector TypeDeps; + TypeDeps.resize(NumTypes); + + for (unsigned I = 0; I < NumTypes; ++I) { + const Type *Ty = Types[I]; + TypeDeps[I].Ty = Ty; + TypeDeps[I].NumDeps = 0; + } + + for (unsigned I = 0; I < NumTypes; ++I) { + const Type *Ty = TypeDeps[I].Ty; + for (Type::subtype_iterator I2 = Ty->subtype_begin(), + E2 = Ty->subtype_end(); I2 != E2; ++I2) { + const Type *InnerType = I2->get(); + unsigned InnerIndex = TypeMap.lookup(InnerType) - 1; + TypeDeps[InnerIndex].NumDeps++; + } + } + array_pod_sort(TypeDeps.begin(), TypeDeps.end(), CompareByDeps); + + SmallPtrSet Visited; + Types.clear(); + Types.reserve(NumTypes); + for (unsigned I = 0; I < NumTypes; ++I) { + VisitType(TypeDeps[I].Ty, Visited, Types); + } } unsigned ValueEnumerator::getInstructionID(const Instruction *Inst) const { @@ -319,7 +363,7 @@ void ValueEnumerator::EnumerateValue(const Value *V) { // Initializers for globals are handled explicitly elsewhere. } else if (isa(C) && cast(C)->isString()) { // Do not enumerate the initializers for an array of simple characters. - // The initializers just polute the value table, and we emit the strings + // The initializers just pollute the value table, and we emit the strings // specially. } else if (C->getNumOperands()) { // If a constant has operands, enumerate them. This makes sure that if a @@ -352,14 +396,12 @@ void ValueEnumerator::EnumerateValue(const Value *V) { void ValueEnumerator::EnumerateType(const Type *Ty) { unsigned &TypeID = TypeMap[Ty]; - if (TypeID) { - // If we've already seen this type, just increase its occurrence count. - Types[TypeID-1].second++; + // We've already seen this type. + if (TypeID) return; - } // First time we saw this type, add it. - Types.push_back(std::make_pair(Ty, 1U)); + Types.push_back(Ty); TypeID = Types.size(); // Enumerate subtypes. @@ -381,7 +423,7 @@ void ValueEnumerator::EnumerateOperandType(const Value *V) { // This constant may have operands, make sure to enumerate the types in // them. for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { - const User *Op = C->getOperand(i); + const Value *Op = C->getOperand(i); // Don't enumerate basic blocks here, this happens as operands to // blockaddress. diff --git a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h index cd1d2371b701..1e42a2667669 100644 --- a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h +++ b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h @@ -36,8 +36,7 @@ class MDSymbolTable; class ValueEnumerator { public: - // For each type, we remember its Type* and occurrence frequency. - typedef std::vector > TypeList; + typedef std::vector TypeList; // For each value, we remember its Value* and occurrence frequency. typedef std::vector > ValueList; @@ -136,6 +135,7 @@ class ValueEnumerator { private: void OptimizeConstants(unsigned CstStart, unsigned CstEnd); + void OptimizeTypes(); void EnumerateMDNodeOperands(const MDNode *N); void EnumerateMetadata(const Value *MD); diff --git a/contrib/llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp b/contrib/llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp index b520d8fcedc0..5c809f7fd668 100644 --- a/contrib/llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp +++ b/contrib/llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp @@ -357,7 +357,7 @@ void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, RegRefs = State->GetRegRefs(); // Handle dead defs by simulating a last-use of the register just - // after the def. A dead def can occur because the def is truely + // after the def. A dead def can occur because the def is truly // dead, or because only a subregister is live at the def. If we // don't do this the dead def will be incorrectly merged into the // previous def. diff --git a/contrib/llvm/lib/CodeGen/Analysis.cpp b/contrib/llvm/lib/CodeGen/Analysis.cpp index 36638c36de67..125e64196f15 100644 --- a/contrib/llvm/lib/CodeGen/Analysis.cpp +++ b/contrib/llvm/lib/CodeGen/Analysis.cpp @@ -211,7 +211,6 @@ bool llvm::isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr, const BasicBlock *ExitBB = I->getParent(); const TerminatorInst *Term = ExitBB->getTerminator(); const ReturnInst *Ret = dyn_cast(Term); - const Function *F = ExitBB->getParent(); // The block must end in a return statement or unreachable. // @@ -250,6 +249,7 @@ bool llvm::isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr, // Conservatively require the attributes of the call to match those of // the return. Ignore noalias because it doesn't affect the call sequence. + const Function *F = ExitBB->getParent(); unsigned CallerRetAttr = F->getAttributes().getRetAttributes(); if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias) return false; diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp new file mode 100644 index 000000000000..0db28a636ad8 --- /dev/null +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -0,0 +1,87 @@ +//===-- CodeGen/AsmPrinter/ARMException.cpp - ARM EHABI Exception Impl ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing DWARF exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "DwarfException.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +using namespace llvm; + +ARMException::ARMException(AsmPrinter *A) + : DwarfException(A), + shouldEmitTable(false), shouldEmitMoves(false), shouldEmitTableModule(false) + {} + +ARMException::~ARMException() {} + +void ARMException::EndModule() { +} + +/// BeginFunction - Gather pre-function exception information. Assumes it's +/// being emitted immediately after the function entry point. +void ARMException::BeginFunction(const MachineFunction *MF) { + Asm->OutStreamer.EmitFnStart(); + if (!Asm->MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", + Asm->getFunctionNumber())); +} + +/// EndFunction - Gather and emit post-function exception information. +/// +void ARMException::EndFunction() { + if (Asm->MF->getFunction()->doesNotThrow() && !UnwindTablesMandatory) + Asm->OutStreamer.EmitCantUnwind(); + else { + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", + Asm->getFunctionNumber())); + + // Emit references to personality. + if (const Function * Personality = + MMI->getPersonalities()[MMI->getPersonalityIndex()]) { + MCSymbol *PerSym = Asm->Mang->getSymbol(Personality); + Asm->OutStreamer.EmitSymbolAttribute(PerSym, MCSA_Global); + Asm->OutStreamer.EmitPersonality(PerSym); + } + + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); + + Asm->OutStreamer.EmitHandlerData(); + + // Emit actual exception table + EmitExceptionTable(); + } + + Asm->OutStreamer.EmitFnEnd(); +} diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 9cb882e6a1bb..8116f8d5925f 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -33,10 +33,12 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Assembly/Writer.h" #include "llvm/ADT/SmallString.h" @@ -70,17 +72,17 @@ static unsigned getGVAlignmentLog2(const GlobalValue *GV, const TargetData &TD, unsigned NumBits = 0; if (const GlobalVariable *GVar = dyn_cast(GV)) NumBits = TD.getPreferredAlignmentLog(GVar); - + // If InBits is specified, round it to it. if (InBits > NumBits) NumBits = InBits; - + // If the GV has a specified alignment, take it into account. if (GV->getAlignment() == 0) return NumBits; - + unsigned GVAlign = Log2_32(GV->getAlignment()); - + // If the GVAlign is larger than NumBits, or if we are required to obey // NumBits because the GV has an assigned section, obey it. if (GVAlign > NumBits || GV->hasSection()) @@ -104,16 +106,16 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) AsmPrinter::~AsmPrinter() { assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized"); - + if (GCMetadataPrinters != 0) { gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); - + for (gcp_map_type::iterator I = GCMap.begin(), E = GCMap.end(); I != E; ++I) delete I->second; delete &GCMap; GCMetadataPrinters = 0; } - + delete &OutStreamer; } @@ -156,9 +158,9 @@ bool AsmPrinter::doInitialization(Module &M) { // Initialize TargetLoweringObjectFile. const_cast(getObjFileLowering()) .Initialize(OutContext, TM); - + Mang = new Mangler(OutContext, *TM.getTargetData()); - + // Allow the target to emit any magic that it wants at the start of the file. EmitStartOfAsmFile(M); @@ -196,6 +198,9 @@ bool AsmPrinter::doInitialization(Module &M) { case ExceptionHandling::DwarfCFI: DE = new DwarfCFIException(this); break; + case ExceptionHandling::ARM: + DE = new ARMException(this); + break; } return false; @@ -250,56 +255,52 @@ void AsmPrinter::EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const { /// EmitGlobalVariable - Emit the specified global variable to the .s file. void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { - if (!GV->hasInitializer()) // External globals require no code. - return; - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GV)) - return; + if (GV->hasInitializer()) { + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GV)) + return; - if (isVerbose()) { - WriteAsOperand(OutStreamer.GetCommentOS(), GV, - /*PrintType=*/false, GV->getParent()); - OutStreamer.GetCommentOS() << '\n'; - } - - MCSymbol *GVSym = Mang->getSymbol(GV); - EmitVisibility(GVSym, GV->getVisibility()); - - if (MAI->hasDotTypeDotSizeDirective()) - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); - - SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); - - const TargetData *TD = TM.getTargetData(); - uint64_t Size = TD->getTypeAllocSize(GV->getType()->getElementType()); - - // If the alignment is specified, we *must* obey it. Overaligning a global - // with a specified alignment is a prompt way to break globals emitted to - // sections and expected to be contiguous (e.g. ObjC metadata). - unsigned AlignLog = getGVAlignmentLog2(GV, *TD); - - // Handle common and BSS local symbols (.lcomm). - if (GVKind.isCommon() || GVKind.isBSSLocal()) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - if (isVerbose()) { WriteAsOperand(OutStreamer.GetCommentOS(), GV, /*PrintType=*/false, GV->getParent()); OutStreamer.GetCommentOS() << '\n'; } - + } + + MCSymbol *GVSym = Mang->getSymbol(GV); + EmitVisibility(GVSym, GV->getVisibility()); + + if (!GV->hasInitializer()) // External globals require no extra code. + return; + + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); + + SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); + + const TargetData *TD = TM.getTargetData(); + uint64_t Size = TD->getTypeAllocSize(GV->getType()->getElementType()); + + // If the alignment is specified, we *must* obey it. Overaligning a global + // with a specified alignment is a prompt way to break globals emitted to + // sections and expected to be contiguous (e.g. ObjC metadata). + unsigned AlignLog = getGVAlignmentLog2(GV, *TD); + + // Handle common and BSS local symbols (.lcomm). + if (GVKind.isCommon() || GVKind.isBSSLocal()) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + // Handle common symbols. if (GVKind.isCommon()) { unsigned Align = 1 << AlignLog; if (!getObjFileLowering().getCommDirectiveSupportsAlignment()) Align = 0; - + // .comm _foo, 42, 4 OutStreamer.EmitCommonSymbol(GVSym, Size, Align); return; } - + // Handle local BSS symbols. if (MAI->hasMachoZeroFillDirective()) { const MCSection *TheSection = @@ -308,7 +309,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog); return; } - + if (MAI->hasLCOMMDirective()) { // .lcomm _foo, 42 OutStreamer.EmitLocalCommonSymbol(GVSym, Size); @@ -318,14 +319,14 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { unsigned Align = 1 << AlignLog; if (!getObjFileLowering().getCommDirectiveSupportsAlignment()) Align = 0; - + // .local _foo OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Local); // .comm _foo, 42, 4 OutStreamer.EmitCommonSymbol(GVSym, Size, Align); return; } - + const MCSection *TheSection = getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM); @@ -333,14 +334,14 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // emission. if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective()) { if (Size == 0) Size = 1; // zerofill of 0 bytes is undefined. - + // .globl _foo OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); // .zerofill __DATA, __common, _foo, 400, 5 OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog); return; } - + // Handle thread local data for mach-o which requires us to output an // additional structure of data and mangle the original symbol so that we // can reference it later. @@ -353,31 +354,31 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // specific code. if (GVKind.isThreadLocal() && MAI->hasMachoTBSSDirective()) { // Emit the .tbss symbol - MCSymbol *MangSym = + MCSymbol *MangSym = OutContext.GetOrCreateSymbol(GVSym->getName() + Twine("$tlv$init")); - + if (GVKind.isThreadBSS()) OutStreamer.EmitTBSSSymbol(TheSection, MangSym, Size, 1 << AlignLog); else if (GVKind.isThreadData()) { OutStreamer.SwitchSection(TheSection); - EmitAlignment(AlignLog, GV); + EmitAlignment(AlignLog, GV); OutStreamer.EmitLabel(MangSym); - + EmitGlobalConstant(GV->getInitializer()); } - + OutStreamer.AddBlankLine(); - + // Emit the variable struct for the runtime. - const MCSection *TLVSect + const MCSection *TLVSect = getObjFileLowering().getTLSExtraDataSection(); - + OutStreamer.SwitchSection(TLVSect); // Emit the linkage here. EmitLinkage(GV->getLinkage(), GVSym); OutStreamer.EmitLabel(GVSym); - + // Three pointers in size: // - __tlv_bootstrap - used to make sure support exists // - spare pointer, used when mapped by the runtime @@ -387,7 +388,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { PtrSize, 0); OutStreamer.EmitIntValue(0, PtrSize, 0); OutStreamer.EmitSymbolValue(MangSym, PtrSize, 0); - + OutStreamer.AddBlankLine(); return; } @@ -404,7 +405,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { if (MAI->hasDotTypeDotSizeDirective()) // .size foo, 42 OutStreamer.EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext)); - + OutStreamer.AddBlankLine(); } @@ -413,7 +414,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { void AsmPrinter::EmitFunctionHeader() { // Print out constants referenced by the function EmitConstantPool(); - + // Print the 'header' of function. const Function *F = MF->getFunction(); @@ -435,7 +436,7 @@ void AsmPrinter::EmitFunctionHeader() { // Emit the CurrentFnSym. This is a virtual function to allow targets to // do their wild and crazy things as required. EmitFunctionEntryLabel(); - + // If the function had address-taken blocks that got deleted, then we have // references to the dangling symbols. Emit them at the start of the function // so that we don't get references to undefined symbols. @@ -445,17 +446,17 @@ void AsmPrinter::EmitFunctionHeader() { OutStreamer.AddComment("Address taken block that was later removed"); OutStreamer.EmitLabel(DeadBlockSyms[i]); } - + // Add some workaround for linkonce linkage on Cygwin\MinGW. if (MAI->getLinkOnceDirective() != 0 && (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) { // FIXME: What is this? - MCSymbol *FakeStub = + MCSymbol *FakeStub = OutContext.GetOrCreateSymbol(Twine("Lllvm$workaround$fake$stub$")+ CurrentFnSym->getName()); OutStreamer.EmitLabel(FakeStub); } - + // Emit pre-function debug and/or EH information. if (DE) { NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); @@ -480,44 +481,16 @@ void AsmPrinter::EmitFunctionEntryLabel() { } -static void EmitDebugLoc(DebugLoc DL, const MachineFunction *MF, - raw_ostream &CommentOS) { - const LLVMContext &Ctx = MF->getFunction()->getContext(); - if (!DL.isUnknown()) { // Print source line info. - DIScope Scope(DL.getScope(Ctx)); - // Omit the directory, because it's likely to be long and uninteresting. - if (Scope.Verify()) - CommentOS << Scope.getFilename(); - else - CommentOS << ""; - CommentOS << ':' << DL.getLine(); - if (DL.getCol() != 0) - CommentOS << ':' << DL.getCol(); - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(DL.getInlinedAt(Ctx)); - if (!InlinedAtDL.isUnknown()) { - CommentOS << "[ "; - EmitDebugLoc(InlinedAtDL, MF, CommentOS); - CommentOS << " ]"; - } - } -} - /// EmitComments - Pretty-print comments for instructions. static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) { const MachineFunction *MF = MI.getParent()->getParent(); const TargetMachine &TM = MF->getTarget(); - - DebugLoc DL = MI.getDebugLoc(); - if (!DL.isUnknown()) { // Print source line info. - EmitDebugLoc(DL, MF, CommentOS); - CommentOS << '\n'; - } - + // Check for spills and reloads int FI; - + const MachineFrameInfo *FrameInfo = MF->getFrameInfo(); - + // We assume a single instruction only has a spill or reload, not // both. const MachineMemOperand *MMO; @@ -538,7 +511,7 @@ static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) { if (FrameInfo->isSpillSlotObjectIndex(FI)) CommentOS << MMO->getSize() << "-byte Folded Spill\n"; } - + // Check for spill-induced copies if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse)) CommentOS << " Reload Reuse\n"; @@ -612,21 +585,61 @@ static bool EmitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { } OS << AP.TM.getRegisterInfo()->getName(MI->getOperand(0).getReg()); } - + OS << '+' << MI->getOperand(1).getImm(); // NOTE: Want this comment at start of line, don't emit with AddComment. AP.OutStreamer.EmitRawText(OS.str()); return true; } +bool AsmPrinter::needsCFIMoves() { + if (UnwindTablesMandatory) + return true; + + if (MMI->hasDebugInfo() && !MAI->doesDwarfRequireFrameSection()) + return true; + + if (MF->getFunction()->doesNotThrow()) + return false; + + return true; +} + +void AsmPrinter::emitPrologLabel(const MachineInstr &MI) { + MCSymbol *Label = MI.getOperand(0).getMCSymbol(); + + if (MAI->doesDwarfRequireFrameSection() || + MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI) + OutStreamer.EmitLabel(Label); + + if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI) + return; + + if (!needsCFIMoves()) + return; + + MachineModuleInfo &MMI = MF->getMMI(); + std::vector &Moves = MMI.getFrameMoves(); + bool FoundOne = false; + (void)FoundOne; + for (std::vector::iterator I = Moves.begin(), + E = Moves.end(); I != E; ++I) { + if (I->getLabel() == Label) { + EmitCFIFrameMove(*I); + FoundOne = true; + } + } + assert(FoundOne); +} + /// EmitFunctionBody - This method emits the body and trailer for a /// function. void AsmPrinter::EmitFunctionBody() { // Emit target-specific gunk before the function body. EmitFunctionBodyStart(); - + bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo(); - + // Print out code for the function. bool HasAnyRealCode = false; const MachineInstr *LastMI = 0; @@ -649,12 +662,15 @@ void AsmPrinter::EmitFunctionBody() { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); DD->beginInstruction(II); } - + if (isVerbose()) EmitComments(*II, OutStreamer.GetCommentOS()); switch (II->getOpcode()) { case TargetOpcode::PROLOG_LABEL: + emitPrologLabel(*II); + break; + case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: OutStreamer.EmitLabel(II->getOperand(0).getMCSymbol()); @@ -675,10 +691,13 @@ void AsmPrinter::EmitFunctionBody() { if (isVerbose()) EmitKill(II, *this); break; default: + if (!TM.hasMCUseLoc()) + MCLineEntry::Make(&OutStreamer, getCurrentSection()); + EmitInstruction(II); break; } - + if (ShouldPrintDebugScopes) { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); DD->endInstruction(II); @@ -705,10 +724,10 @@ void AsmPrinter::EmitFunctionBody() { } else // Target not mc-ized yet. OutStreamer.EmitRawText(StringRef("\tnop\n")); } - + // Emit target-specific gunk after the function body. EmitFunctionBodyEnd(); - + // If the target wants a .size directive for the size of the function, emit // it. if (MAI->hasDotTypeDotSizeDirective()) { @@ -716,14 +735,14 @@ void AsmPrinter::EmitFunctionBody() { // difference between the function label and the temp label. MCSymbol *FnEndLabel = OutContext.CreateTempSymbol(); OutStreamer.EmitLabel(FnEndLabel); - + const MCExpr *SizeExp = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(FnEndLabel, OutContext), MCSymbolRefExpr::Create(CurrentFnSym, OutContext), OutContext); OutStreamer.EmitELFSize(CurrentFnSym, SizeExp); } - + // Emit post-function debug information. if (DD) { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); @@ -734,20 +753,71 @@ void AsmPrinter::EmitFunctionBody() { DE->EndFunction(); } MMI->EndFunction(); - + // Print out jump tables referenced by the function. EmitJumpTableInfo(); - + OutStreamer.AddBlankLine(); } /// getDebugValueLocation - Get location information encoded by DBG_VALUE /// operands. -MachineLocation AsmPrinter::getDebugValueLocation(const MachineInstr *MI) const { +MachineLocation AsmPrinter:: +getDebugValueLocation(const MachineInstr *MI) const { // Target specific DBG_VALUE instructions are handled by each target. return MachineLocation(); } +/// getDwarfRegOpSize - get size required to emit given machine location using +/// dwarf encoding. +unsigned AsmPrinter::getDwarfRegOpSize(const MachineLocation &MLoc) const { + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + unsigned DWReg = RI->getDwarfRegNum(MLoc.getReg(), false); + if (int Offset = MLoc.getOffset()) { + // If the value is at a certain offset from frame register then + // use DW_OP_breg. + if (DWReg < 32) + return 1 + MCAsmInfo::getSLEB128Size(Offset); + else + return 1 + MCAsmInfo::getULEB128Size(MLoc.getReg()) + + MCAsmInfo::getSLEB128Size(Offset); + } + if (DWReg < 32) + return 1; + + return 1 + MCAsmInfo::getULEB128Size(DWReg); +} + +/// EmitDwarfRegOp - Emit dwarf register operation. +void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const { + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + unsigned Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); + if (int Offset = MLoc.getOffset()) { + if (Reg < 32) { + OutStreamer.AddComment( + dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg)); + EmitInt8(dwarf::DW_OP_breg0 + Reg); + } else { + OutStreamer.AddComment("DW_OP_bregx"); + EmitInt8(dwarf::DW_OP_bregx); + OutStreamer.AddComment(Twine(Reg)); + EmitULEB128(Reg); + } + EmitSLEB128(Offset); + } else { + if (Reg < 32) { + OutStreamer.AddComment( + dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg)); + EmitInt8(dwarf::DW_OP_reg0 + Reg); + } else { + OutStreamer.AddComment("DW_OP_regx"); + EmitInt8(dwarf::DW_OP_regx); + OutStreamer.AddComment(Twine(Reg)); + EmitULEB128(Reg); + } + } +} + bool AsmPrinter::doFinalization(Module &M) { // Emit global variables. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); @@ -782,7 +852,7 @@ bool AsmPrinter::doFinalization(Module &M) { } delete DD; DD = 0; } - + // If the target wants to know about weak references, print them all. if (MAI->getWeakRefDirective()) { // FIXME: This is not lazy, it would be nice to only print weak references @@ -796,7 +866,7 @@ bool AsmPrinter::doFinalization(Module &M) { if (!I->hasExternalWeakLinkage()) continue; OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference); } - + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { if (!I->hasExternalWeakLinkage()) continue; OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference); @@ -822,7 +892,7 @@ bool AsmPrinter::doFinalization(Module &M) { EmitVisibility(Name, I->getVisibility()); // Emit the directives as assignments aka .set: - OutStreamer.EmitAssignment(Name, + OutStreamer.EmitAssignment(Name, MCSymbolRefExpr::Create(Target, OutContext)); } } @@ -839,14 +909,14 @@ bool AsmPrinter::doFinalization(Module &M) { if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty()) if (const MCSection *S = MAI->getNonexecutableStackSection(OutContext)) OutStreamer.SwitchSection(S); - + // Allow the target to emit any magic that it wants at the end of the file, // after everything else has gone out. EmitEndOfAsmFile(M); - + delete Mang; Mang = 0; MMI = 0; - + OutStreamer.Finish(); return false; } @@ -886,7 +956,7 @@ void AsmPrinter::EmitConstantPool() { for (unsigned i = 0, e = CP.size(); i != e; ++i) { const MachineConstantPoolEntry &CPE = CP[i]; unsigned Align = CPE.getAlignment(); - + SectionKind Kind; switch (CPE.getRelocationInfo()) { default: llvm_unreachable("Unknown section kind"); @@ -904,7 +974,7 @@ void AsmPrinter::EmitConstantPool() { } const MCSection *S = getObjFileLowering().getSectionForConstant(Kind); - + // The number of sections are small, just do a linear search from the // last section to the first. bool Found = false; @@ -953,7 +1023,7 @@ void AsmPrinter::EmitConstantPool() { } /// EmitJumpTableInfo - Print assembly representations of the jump tables used -/// by the current function to the current output stream. +/// by the current function to the current output stream. /// void AsmPrinter::EmitJumpTableInfo() { const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); @@ -962,7 +1032,7 @@ void AsmPrinter::EmitJumpTableInfo() { const std::vector &JT = MJTI->getJumpTables(); if (JT.empty()) return; - // Pick the directive to use to print the jump table entries, and switch to + // Pick the directive to use to print the jump table entries, and switch to // the appropriate section. const Function *F = MF->getFunction(); bool JTInDiffSection = false; @@ -978,18 +1048,18 @@ void AsmPrinter::EmitJumpTableInfo() { OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F,Mang,TM)); } else { // Otherwise, drop it in the readonly section. - const MCSection *ReadOnlySection = + const MCSection *ReadOnlySection = getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly()); OutStreamer.SwitchSection(ReadOnlySection); JTInDiffSection = true; } EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData()))); - + for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { const std::vector &JTBBs = JT[JTI].MBBs; - - // If this jump table was deleted, ignore it. + + // If this jump table was deleted, ignore it. if (JTBBs.empty()) continue; // For the EK_LabelDifference32 entry, if the target supports .set, emit a @@ -1003,15 +1073,15 @@ void AsmPrinter::EmitJumpTableInfo() { for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { const MachineBasicBlock *MBB = JTBBs[ii]; if (!EmittedSets.insert(MBB)) continue; - + // .set LJTSet, LBB32-base const MCExpr *LHS = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); OutStreamer.EmitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()), MCBinaryExpr::CreateSub(LHS, Base, OutContext)); } - } - + } + // On some targets (e.g. Darwin) we want to emit two consecutive labels // before each jump table. The first label is never referenced, but tells // the assembler and linker the extents of the jump table object. The @@ -1064,8 +1134,8 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, // If the .set directive is supported, this is emitted as: // .set L4_5_set_123, LBB123 - LJTI1_2 // .word L4_5_set_123 - - // If we have emitted set directives for the jump table entries, print + + // If we have emitted set directives for the jump table entries, print // them rather than the entries themselves. If we're emitting PIC, then // emit the table entries as differences between two text section labels. if (MAI->hasSetDirective()) { @@ -1081,9 +1151,9 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, break; } } - + assert(Value && "Unknown entry kind!"); - + unsigned EntrySize = MJTI->getEntrySize(*TM.getTargetData()); OutStreamer.EmitValue(Value, EntrySize, /*addrspace*/0); } @@ -1103,18 +1173,18 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { if (GV->getSection() == "llvm.metadata" || GV->hasAvailableExternallyLinkage()) return true; - + if (!GV->hasAppendingLinkage()) return false; assert(GV->hasInitializer() && "Not a special LLVM global!"); - + const TargetData *TD = TM.getTargetData(); unsigned Align = Log2_32(TD->getPointerPrefAlignment()); if (GV->getName() == "llvm.global_ctors") { OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection()); EmitAlignment(Align); EmitXXStructorList(GV->getInitializer()); - + if (TM.getRelocationModel() == Reloc::Static && MAI->hasStaticCtorDtorReferenceInStaticMode()) { StringRef Sym(".constructors_used"); @@ -1122,8 +1192,8 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { MCSA_Reference); } return true; - } - + } + if (GV->getName() == "llvm.global_dtors") { OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection()); EmitAlignment(Align); @@ -1137,7 +1207,7 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { } return true; } - + return false; } @@ -1148,7 +1218,7 @@ void AsmPrinter::EmitLLVMUsedList(Constant *List) { // Should be an array of 'i8*'. ConstantArray *InitList = dyn_cast(List); if (InitList == 0) return; - + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { const GlobalValue *GV = dyn_cast(InitList->getOperand(i)->stripPointerCasts()); @@ -1157,7 +1227,7 @@ void AsmPrinter::EmitLLVMUsedList(Constant *List) { } } -/// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the +/// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the /// function pointers, ignoring the init priority. void AsmPrinter::EmitXXStructorList(Constant *List) { // Should be an array of '{ int, void ()* }' structs. The first value is the @@ -1203,11 +1273,11 @@ void AsmPrinter::EmitInt32(int Value) const { void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const { // Get the Hi-Lo expression. - const MCExpr *Diff = + const MCExpr *Diff = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(Hi, OutContext), MCSymbolRefExpr::Create(Lo, OutContext), OutContext); - + if (!MAI->hasSetDirective()) { OutStreamer.EmitValue(Diff, Size, 0/*AddrSpace*/); return; @@ -1219,27 +1289,27 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/); } -/// EmitLabelOffsetDifference - Emit something like ".long Hi+Offset-Lo" +/// EmitLabelOffsetDifference - Emit something like ".long Hi+Offset-Lo" /// where the size in bytes of the directive is specified by Size and Hi/Lo /// specify the labels. This implicitly uses .set if it is available. void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, - const MCSymbol *Lo, unsigned Size) + const MCSymbol *Lo, unsigned Size) const { - + // Emit Hi+Offset - Lo // Get the Hi+Offset expression. const MCExpr *Plus = - MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Hi, OutContext), + MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Hi, OutContext), MCConstantExpr::Create(Offset, OutContext), OutContext); - + // Get the Hi+Offset-Lo expression. - const MCExpr *Diff = + const MCExpr *Diff = MCBinaryExpr::CreateSub(Plus, MCSymbolRefExpr::Create(Lo, OutContext), OutContext); - - if (!MAI->hasSetDirective()) + + if (!MAI->hasSetDirective()) OutStreamer.EmitValue(Diff, 4, 0/*AddrSpace*/); else { // Otherwise, emit with .set (aka assignment). @@ -1249,22 +1319,22 @@ void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, } } -/// EmitLabelPlusOffset - Emit something like ".long Label+Offset" +/// EmitLabelPlusOffset - Emit something like ".long Label+Offset" /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. This implicitly uses .set if it is available. void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, - unsigned Size) + unsigned Size) const { - + // Emit Label+Offset const MCExpr *Plus = - MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Label, OutContext), + MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Label, OutContext), MCConstantExpr::Create(Offset, OutContext), OutContext); - + OutStreamer.EmitValue(Plus, 4, 0/*AddrSpace*/); } - + //===----------------------------------------------------------------------===// @@ -1276,9 +1346,9 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, // void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const { if (GV) NumBits = getGVAlignmentLog2(GV, *TM.getTargetData(), NumBits); - + if (NumBits == 0) return; // 1-byte aligned: no need to emit alignment. - + if (getCurrentSection()->getKind().isText()) OutStreamer.EmitCodeAlignment(1 << NumBits); else @@ -1293,25 +1363,25 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const { /// static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { MCContext &Ctx = AP.OutContext; - + if (CV->isNullValue() || isa(CV)) return MCConstantExpr::Create(0, Ctx); if (const ConstantInt *CI = dyn_cast(CV)) return MCConstantExpr::Create(CI->getZExtValue(), Ctx); - + if (const GlobalValue *GV = dyn_cast(CV)) return MCSymbolRefExpr::Create(AP.Mang->getSymbol(GV), Ctx); if (const BlockAddress *BA = dyn_cast(CV)) return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx); - + const ConstantExpr *CE = dyn_cast(CV); if (CE == 0) { llvm_unreachable("Unknown constant value to lower!"); return MCConstantExpr::Create(0, Ctx); } - + switch (CE->getOpcode()) { default: // If the code isn't optimized, there may be outstanding folding @@ -1339,21 +1409,21 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { SmallVector IdxVec(CE->op_begin()+1, CE->op_end()); int64_t Offset = TD.getIndexedOffset(PtrVal->getType(), &IdxVec[0], IdxVec.size()); - + const MCExpr *Base = LowerConstant(CE->getOperand(0), AP); if (Offset == 0) return Base; - + // Truncate/sext the offset to the pointer size. if (TD.getPointerSizeInBits() != 64) { int SExtAmount = 64-TD.getPointerSizeInBits(); Offset = (Offset << SExtAmount) >> SExtAmount; } - + return MCBinaryExpr::CreateAdd(Base, MCConstantExpr::Create(Offset, Ctx), Ctx); } - + case Instruction::Trunc: // We emit the value and depend on the assembler to truncate the generated // expression properly. This is important for differences between @@ -1372,7 +1442,7 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { false/*ZExt*/); return LowerConstant(Op, AP); } - + case Instruction::PtrToInt: { const TargetData &TD = *AP.TM.getTargetData(); // Support only foldable casts to/from pointers that can be eliminated by @@ -1394,7 +1464,7 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { const MCExpr *MaskExpr = MCConstantExpr::Create(~0ULL >> (64-InBits), Ctx); return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx); } - + // The MC library also has a right-shift operator, but it isn't consistently // signed or unsigned between different targets. case Instruction::Add: @@ -1435,7 +1505,7 @@ static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace, EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP); return; } - + // Otherwise, it can be emitted as .ascii. SmallVector TmpVec; TmpVec.reserve(CA->getNumOperands()); @@ -1493,7 +1563,7 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace); return; } - + if (CFP->getType()->isFloatTy()) { if (AP.isVerbose()) { float Val = CFP->getValueAPF().convertToFloat(); @@ -1503,7 +1573,7 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, AP.OutStreamer.EmitIntValue(Val, 4, AddrSpace); return; } - + if (CFP->getType()->isX86_FP80Ty()) { // all long double variants are printed as hex // API needed to prevent premature destruction @@ -1518,7 +1588,7 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, AP.OutStreamer.GetCommentOS() << "x86_fp80 ~= " << DoubleVal.convertToDouble() << '\n'; } - + if (AP.TM.getTargetData()->isBigEndian()) { AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace); AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); @@ -1526,14 +1596,14 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace); } - + // Emit the tail padding for the long double. const TargetData &TD = *AP.TM.getTargetData(); AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) - TD.getTypeStoreSize(CFP->getType()), AddrSpace); return; } - + assert(CFP->getType()->isPPC_FP128Ty() && "Floating point constant type not handled"); // All long double variants are printed as hex @@ -1588,10 +1658,10 @@ static void EmitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace, return; } } - + if (const ConstantArray *CVA = dyn_cast(CV)) return EmitGlobalConstantArray(CVA, AddrSpace, AP); - + if (const ConstantStruct *CVS = dyn_cast(CV)) return EmitGlobalConstantStruct(CVS, AddrSpace, AP); @@ -1603,10 +1673,10 @@ static void EmitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace, AP.OutStreamer.EmitIntValue(0, Size, AddrSpace); return; } - + if (const ConstantVector *V = dyn_cast(CV)) return EmitGlobalConstantVector(V, AddrSpace, AP); - + // Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it // thread the streamer with EmitValue. AP.OutStreamer.EmitValue(LowerConstant(CV, AP), @@ -1703,7 +1773,7 @@ MCSymbol *AsmPrinter::GetExternalSymbolSymbol(StringRef Sym) const { SmallString<60> NameStr; Mang->getNameWithPrefix(NameStr, Sym); return OutContext.GetOrCreateSymbol(NameStr.str()); -} +} @@ -1740,10 +1810,10 @@ static void EmitBasicBlockLoopComments(const MachineBasicBlock &MBB, // Add loop depth information const MachineLoop *Loop = LI->getLoopFor(&MBB); if (Loop == 0) return; - + MachineBasicBlock *Header = Loop->getHeader(); assert(Header && "No header for loop"); - + // If this block is not a loop header, just print out what is the loop header // and return. if (Header != &MBB) { @@ -1753,21 +1823,21 @@ static void EmitBasicBlockLoopComments(const MachineBasicBlock &MBB, " Depth="+Twine(Loop->getLoopDepth())); return; } - + // Otherwise, it is a loop header. Print out information about child and // parent loops. raw_ostream &OS = AP.OutStreamer.GetCommentOS(); - - PrintParentLoopComment(OS, Loop->getParentLoop(), AP.getFunctionNumber()); - + + PrintParentLoopComment(OS, Loop->getParentLoop(), AP.getFunctionNumber()); + OS << "=>"; OS.indent(Loop->getLoopDepth()*2-2); - + OS << "This "; if (Loop->empty()) OS << "Inner "; OS << "Loop Header: Depth=" + Twine(Loop->getLoopDepth()) << '\n'; - + PrintChildLoopComment(OS, Loop, AP.getFunctionNumber()); } @@ -1788,7 +1858,7 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { const BasicBlock *BB = MBB->getBasicBlock(); if (isVerbose()) OutStreamer.AddComment("Block address taken"); - + std::vector Syms = MMI->getAddrLabelSymbolToEmit(BB); for (unsigned i = 0, e = Syms.size(); i != e; ++i) @@ -1801,9 +1871,9 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { if (const BasicBlock *BB = MBB->getBasicBlock()) if (BB->hasName()) OutStreamer.AddComment("%" + BB->getName()); - + EmitBasicBlockLoopComments(*MBB, LI, *this); - + // NOTE: Want this comment at start of line, don't emit with AddComment. OutStreamer.EmitRawText(Twine(MAI->getCommentString()) + " BB#" + Twine(MBB->getNumber()) + ":"); @@ -1823,7 +1893,7 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition) const { MCSymbolAttr Attr = MCSA_Invalid; - + switch (Visibility) { default: break; case GlobalValue::HiddenVisibility: @@ -1850,23 +1920,23 @@ isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { // then nothing falls through to it. if (MBB->isLandingPad() || MBB->pred_empty()) return false; - + // If there isn't exactly one predecessor, it can't be a fall through. MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; ++PI2; if (PI2 != MBB->pred_end()) return false; - + // The predecessor has to be immediately before this block. const MachineBasicBlock *Pred = *PI; - + if (!Pred->isLayoutSuccessor(MBB)) return false; - + // If the block is completely empty, then it definitely does fall through. if (Pred->empty()) return true; - + // Otherwise, check the last instruction. const MachineInstr &LastInst = Pred->back(); return !LastInst.getDesc().isBarrier(); @@ -1882,9 +1952,9 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { gcp_map_type::iterator GCPI = GCMap.find(S); if (GCPI != GCMap.end()) return GCPI->second; - + const char *Name = S->getName().c_str(); - + for (GCMetadataPrinterRegistry::iterator I = GCMetadataPrinterRegistry::begin(), E = GCMetadataPrinterRegistry::end(); I != E; ++I) @@ -1894,7 +1964,7 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { GCMap.insert(std::make_pair(S, GMP)); return GMP; } - + report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name)); return 0; } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index 98a1bf2f1ce4..6d1708a2ce80 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -155,7 +155,7 @@ void AsmPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { const TargetLoweringObjectFile &TLOF = getObjFileLowering(); const MCExpr *Exp = - TLOF.getExprForDwarfReference(Sym, Mang, MMI, Encoding, OutStreamer); + TLOF.getExprForDwarfReference(Sym, Encoding, OutStreamer); OutStreamer.EmitAbsValue(Exp, GetSizeOfEncodedValue(Encoding)); } @@ -277,42 +277,42 @@ void AsmPrinter::EmitFrameMoves(const std::vector &Moves, } } +/// EmitFrameMoves - Emit a frame instruction. +void AsmPrinter::EmitCFIFrameMove(const MachineMove &Move) const { + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + assert(!Src.isReg() && "Machine move not supported yet."); + + if (Src.getReg() == MachineLocation::VirtualFP) { + OutStreamer.EmitCFIDefCfaOffset(-Src.getOffset()); + } else { + assert("Machine move not supported yet"); + // Reg + Offset + } + } else if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { + assert(Dst.isReg() && "Machine move not supported yet."); + OutStreamer.EmitCFIDefCfaRegister(RI->getDwarfRegNum(Dst.getReg(), true)); + } else { + assert(!Dst.isReg() && "Machine move not supported yet."); + OutStreamer.EmitCFIOffset(RI->getDwarfRegNum(Src.getReg(), true), + Dst.getOffset()); + } +} + /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. void AsmPrinter::EmitCFIFrameMoves(const std::vector &Moves) const { - const TargetRegisterInfo *RI = TM.getRegisterInfo(); - - int stackGrowth = TM.getTargetData()->getPointerSize(); - if (TM.getFrameLowering()->getStackGrowthDirection() != - TargetFrameLowering::StackGrowsUp) - stackGrowth *= -1; - for (unsigned i = 0, N = Moves.size(); i < N; ++i) { const MachineMove &Move = Moves[i]; MCSymbol *Label = Move.getLabel(); // Throw out move if the label is invalid. if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. - const MachineLocation &Dst = Move.getDestination(); - const MachineLocation &Src = Move.getSource(); - - // If advancing cfa. - if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { - assert(!Src.isReg() && "Machine move not supported yet."); - - if (Src.getReg() == MachineLocation::VirtualFP) { - OutStreamer.EmitCFIDefCfaOffset(-Src.getOffset()); - } else { - assert("Machine move not supported yet"); - // Reg + Offset - } - } else if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { - assert(Dst.isReg() && "Machine move not supported yet."); - OutStreamer.EmitCFIDefCfaRegister(RI->getDwarfRegNum(Dst.getReg(), true)); - } else { - assert(!Dst.isReg() && "Machine move not supported yet."); - OutStreamer.EmitCFIOffset(RI->getDwarfRegNum(Src.getReg(), true), - Dst.getOffset()); - } + EmitCFIFrameMove(Move); } } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.h index d56c0947795e..7d61f1edff4a 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.h @@ -70,7 +70,6 @@ namespace llvm { public: DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {} - virtual ~DIEAbbrev() {} // Accessors. unsigned getTag() const { return Tag; } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index 68be2eed8f0e..dbd52c4981b3 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -32,6 +32,7 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -40,7 +41,7 @@ using namespace llvm; DwarfCFIException::DwarfCFIException(AsmPrinter *A) : DwarfException(A), - shouldEmitTable(false), shouldEmitMoves(false), shouldEmitTableModule(false) + shouldEmitPersonality(false), shouldEmitLSDA(false), shouldEmitMoves(false) {} DwarfCFIException::~DwarfCFIException() {} @@ -51,81 +52,85 @@ void DwarfCFIException::EndModule() { if (!Asm->MAI->isExceptionHandlingDwarf()) return; - if (!shouldEmitTableModule) - return; - const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + unsigned PerEncoding = TLOF.getPersonalityEncoding(); - // Begin eh frame section. - Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); + if ((PerEncoding & 0x70) != dwarf::DW_EH_PE_pcrel) + return; // Emit references to all used personality functions + bool AtLeastOne = false; const std::vector &Personalities = MMI->getPersonalities(); for (size_t i = 0, e = Personalities.size(); i != e; ++i) { - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("personality", i)); - Asm->EmitReference(Personalities[i], PerEncoding); + if (!Personalities[i]) + continue; + MCSymbol *Sym = Asm->Mang->getSymbol(Personalities[i]); + TLOF.emitPersonalityValue(Asm->OutStreamer, Asm->TM, Sym); + AtLeastOne = true; + } + + if (AtLeastOne && !TLOF.isFunctionEHFrameSymbolPrivate()) { + // This is a temporary hack to keep sections in the same order they + // were before. This lets us produce bit identical outputs while + // transitioning to CFI. + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); } } /// BeginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. void DwarfCFIException::BeginFunction(const MachineFunction *MF) { - shouldEmitTable = shouldEmitMoves = false; + shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; // If any landing pads survive, we need an EH table. - shouldEmitTable = !MMI->getLandingPads().empty(); + bool hasLandingPads = !MMI->getLandingPads().empty(); // See if we need frame move info. - shouldEmitMoves = - !Asm->MF->getFunction()->doesNotThrow() || UnwindTablesMandatory; - - if (shouldEmitMoves || shouldEmitTable) - // Assumes in correct section after the entry point. - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", - Asm->getFunctionNumber())); - - shouldEmitTableModule |= shouldEmitTable; - - if (shouldEmitMoves) { - const TargetFrameLowering *TFL = Asm->TM.getFrameLowering(); - Asm->OutStreamer.EmitCFIStartProc(); - - // Indicate locations of general callee saved registers in frame. - std::vector Moves; - TFL->getInitialFrameState(Moves); - Asm->EmitCFIFrameMoves(Moves); - Asm->EmitCFIFrameMoves(MMI->getFrameMoves()); - } - - if (!shouldEmitTable) - return; + shouldEmitMoves = Asm->needsCFIMoves(); const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + unsigned PerEncoding = TLOF.getPersonalityEncoding(); + const Function *Per = MMI->getPersonalities()[MMI->getPersonalityIndex()]; + + shouldEmitPersonality = hasLandingPads && + PerEncoding != dwarf::DW_EH_PE_omit && Per; - // Provide LSDA information. unsigned LSDAEncoding = TLOF.getLSDAEncoding(); - if (LSDAEncoding != dwarf::DW_EH_PE_omit) - Asm->OutStreamer.EmitCFILsda(Asm->GetTempSymbol("exception", - Asm->getFunctionNumber()), - LSDAEncoding); + shouldEmitLSDA = shouldEmitPersonality && + LSDAEncoding != dwarf::DW_EH_PE_omit; + + if (!shouldEmitPersonality && !shouldEmitMoves) + return; + + Asm->OutStreamer.EmitCFIStartProc(); // Indicate personality routine, if any. - unsigned PerEncoding = TLOF.getPersonalityEncoding(); - if (PerEncoding != dwarf::DW_EH_PE_omit && - MMI->getPersonalities()[MMI->getPersonalityIndex()]) - Asm->OutStreamer.EmitCFIPersonality(Asm->GetTempSymbol("personality", - MMI->getPersonalityIndex()), - PerEncoding); + if (!shouldEmitPersonality) + return; + + const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(Per, Asm->Mang, MMI); + Asm->OutStreamer.EmitCFIPersonality(Sym, PerEncoding); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", + Asm->getFunctionNumber())); + + // Provide LSDA information. + if (!shouldEmitLSDA) + return; + + Asm->OutStreamer.EmitCFILsda(Asm->GetTempSymbol("exception", + Asm->getFunctionNumber()), + LSDAEncoding); } /// EndFunction - Gather and emit post-function exception information. /// void DwarfCFIException::EndFunction() { - if (!shouldEmitMoves && !shouldEmitTable) return; + if (!shouldEmitPersonality && !shouldEmitMoves) + return; - if (shouldEmitMoves) - Asm->OutStreamer.EmitCFIEndProc(); + Asm->OutStreamer.EmitCFIEndProc(); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber())); @@ -133,6 +138,6 @@ void DwarfCFIException::EndFunction() { // Map all labels and get rid of any dead landing pads. MMI->TidyLandingPads(); - if (shouldEmitTable) + if (shouldEmitPersonality) EmitExceptionTable(); } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp new file mode 100644 index 000000000000..7ce0cfe8e79e --- /dev/null +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -0,0 +1,983 @@ +//===-- llvm/CodeGen/DwarfCompileUnit.cpp - Dwarf Compile Unit ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf compile unit. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dwarfdebug" + +#include "DwarfCompileUnit.h" +#include "DwarfDebug.h" +#include "llvm/Constants.h" +#include "llvm/Analysis/DIBuilder.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +/// CompileUnit - Compile unit constructor. +CompileUnit::CompileUnit(unsigned I, DIE *D, AsmPrinter *A, DwarfDebug *DW) + : ID(I), CUDie(D), Asm(A), DD(DW), IndexTyDie(0) { + DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); +} + +/// ~CompileUnit - Destructor for compile unit. +CompileUnit::~CompileUnit() { + for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) + DIEBlocks[j]->~DIEBlock(); +} + +/// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug +/// information entry. +DIEEntry *CompileUnit::createDIEEntry(DIE *Entry) { + DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry); + return Value; +} + +/// addUInt - Add an unsigned integer attribute data and value. +/// +void CompileUnit::addUInt(DIE *Die, unsigned Attribute, + unsigned Form, uint64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(false, Integer); + DIEValue *Value = Integer == 1 ? + DIEIntegerOne : new (DIEValueAllocator) DIEInteger(Integer); + Die->addValue(Attribute, Form, Value); +} + +/// addSInt - Add an signed integer attribute data and value. +/// +void CompileUnit::addSInt(DIE *Die, unsigned Attribute, + unsigned Form, int64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(true, Integer); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer); + Die->addValue(Attribute, Form, Value); +} + +/// addString - Add a string attribute data and value. DIEString only +/// keeps string reference. +void CompileUnit::addString(DIE *Die, unsigned Attribute, unsigned Form, + StringRef String) { + DIEValue *Value = new (DIEValueAllocator) DIEString(String); + Die->addValue(Attribute, Form, Value); +} + +/// addLabel - Add a Dwarf label attribute data and value. +/// +void CompileUnit::addLabel(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Label) { + DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); + Die->addValue(Attribute, Form, Value); +} + +/// addDelta - Add a label delta attribute data and value. +/// +void CompileUnit::addDelta(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Hi, const MCSymbol *Lo) { + DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); + Die->addValue(Attribute, Form, Value); +} + +/// addDIEEntry - Add a DIE attribute data and value. +/// +void CompileUnit::addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, + DIE *Entry) { + Die->addValue(Attribute, Form, createDIEEntry(Entry)); +} + + +/// addBlock - Add block data. +/// +void CompileUnit::addBlock(DIE *Die, unsigned Attribute, unsigned Form, + DIEBlock *Block) { + Block->ComputeSize(Asm); + DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on. + Die->addValue(Attribute, Block->BestForm(), Block); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DIVariable V) { + // Verify variable. + if (!V.Verify()) + return; + + unsigned Line = V.getLineNumber(); + if (Line == 0) + return; + unsigned FileID = DD->GetOrCreateSourceID(V.getContext().getFilename(), + V.getContext().getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DIGlobalVariable G) { + // Verify global variable. + if (!G.Verify()) + return; + + unsigned Line = G.getLineNumber(); + if (Line == 0) + return; + unsigned FileID = DD->GetOrCreateSourceID(G.getContext().getFilename(), + G.getContext().getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DISubprogram SP) { + // Verify subprogram. + if (!SP.Verify()) + return; + // If the line number is 0, don't add it. + if (SP.getLineNumber() == 0) + return; + + unsigned Line = SP.getLineNumber(); + if (!SP.getContext().Verify()) + return; + unsigned FileID = DD->GetOrCreateSourceID(SP.getFilename(), SP.getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DIType Ty) { + // Verify type. + if (!Ty.Verify()) + return; + + unsigned Line = Ty.getLineNumber(); + if (Line == 0 || !Ty.getContext().Verify()) + return; + unsigned FileID = DD->GetOrCreateSourceID(Ty.getFilename(), Ty.getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DINameSpace NS) { + // Verify namespace. + if (!NS.Verify()) + return; + + unsigned Line = NS.getLineNumber(); + if (Line == 0) + return; + StringRef FN = NS.getFilename(); + + unsigned FileID = DD->GetOrCreateSourceID(FN, NS.getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addVariableAddress - Add DW_AT_location attribute for a +/// DbgVariable based on provided MachineLocation. +void CompileUnit::addVariableAddress(DbgVariable *&DV, DIE *Die, + MachineLocation Location) { + if (DV->variableHasComplexAddress()) + addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); + else if (DV->isBlockByrefVariable()) + addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); + else + addAddress(Die, dwarf::DW_AT_location, Location); +} + +/// addRegisterOp - Add register operand. +void CompileUnit::addRegisterOp(DIE *TheDie, unsigned Reg) { + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned DWReg = RI->getDwarfRegNum(Reg, false); + if (DWReg < 32) + addUInt(TheDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + DWReg); + else { + addUInt(TheDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + addUInt(TheDie, 0, dwarf::DW_FORM_udata, DWReg); + } +} + +/// addRegisterOffset - Add register offset. +void CompileUnit::addRegisterOffset(DIE *TheDie, unsigned Reg, + int64_t Offset) { + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned DWReg = RI->getDwarfRegNum(Reg, false); + const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); + if (Reg == TRI->getFrameRegister(*Asm->MF)) + // If variable offset is based in frame register then use fbreg. + addUInt(TheDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_fbreg); + else if (DWReg < 32) + addUInt(TheDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + DWReg); + else { + addUInt(TheDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(TheDie, 0, dwarf::DW_FORM_udata, DWReg); + } + addSInt(TheDie, 0, dwarf::DW_FORM_sdata, Offset); +} + +/// addAddress - Add an address attribute to a die based on the location +/// provided. +void CompileUnit::addAddress(DIE *Die, unsigned Attribute, + const MachineLocation &Location) { + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + if (Location.isReg()) + addRegisterOp(Block, Location.getReg()); + else + addRegisterOffset(Block, Location.getReg(), Location.getOffset()); + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, 0, Block); +} + +/// addComplexAddress - Start with the address based on the location provided, +/// and generate the DWARF information necessary to find the actual variable +/// given the extra address information encoded in the DIVariable, starting from +/// the starting location. Add the DWARF information to the die. +/// +void CompileUnit::addComplexAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + unsigned N = DV->getNumAddrElements(); + unsigned i = 0; + if (Location.isReg()) { + if (N >= 2 && DV->getAddrElement(0) == DIBuilder::OpPlus) { + // If first address element is OpPlus then emit + // DW_OP_breg + Offset instead of DW_OP_reg + Offset. + addRegisterOffset(Block, Location.getReg(), DV->getAddrElement(1)); + i = 2; + } else + addRegisterOp(Block, Location.getReg()); + } + else + addRegisterOffset(Block, Location.getReg(), Location.getOffset()); + + for (;i < N; ++i) { + uint64_t Element = DV->getAddrElement(i); + if (Element == DIBuilder::OpPlus) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i)); + } else if (Element == DIBuilder::OpDeref) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + } else llvm_unreachable("unknown DIBuilder Opcode"); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, 0, Block); +} + +/* Byref variables, in Blocks, are declared by the programmer as "SomeType + VarName;", but the compiler creates a __Block_byref_x_VarName struct, and + gives the variable VarName either the struct, or a pointer to the struct, as + its type. This is necessary for various behind-the-scenes things the + compiler needs to do with by-reference variables in Blocks. + + However, as far as the original *programmer* is concerned, the variable + should still have type 'SomeType', as originally declared. + + The function getBlockByrefType dives into the __Block_byref_x_VarName + struct to find the original type of the variable, which is then assigned to + the variable's Debug Information Entry as its real type. So far, so good. + However now the debugger will expect the variable VarName to have the type + SomeType. So we need the location attribute for the variable to be an + expression that explains to the debugger how to navigate through the + pointers and struct to find the actual variable of type SomeType. + + The following function does just that. We start by getting + the "normal" location for the variable. This will be the location + of either the struct __Block_byref_x_VarName or the pointer to the + struct __Block_byref_x_VarName. + + The struct will look something like: + + struct __Block_byref_x_VarName { + ... + struct __Block_byref_x_VarName *forwarding; + ... + SomeType VarName; + ... + }; + + If we are given the struct directly (as our starting point) we + need to tell the debugger to: + + 1). Add the offset of the forwarding field. + + 2). Follow that pointer to get the real __Block_byref_x_VarName + struct to use (the real one may have been copied onto the heap). + + 3). Add the offset for the field VarName, to find the actual variable. + + If we started with a pointer to the struct, then we need to + dereference that pointer first, before the other steps. + Translating this into DWARF ops, we will need to append the following + to the current location description for the variable: + + DW_OP_deref -- optional, if we start with a pointer + DW_OP_plus_uconst + DW_OP_deref + DW_OP_plus_uconst + + That is what this function does. */ + +/// addBlockByrefAddress - Start with the address based on the location +/// provided, and generate the DWARF information necessary to find the +/// actual Block variable (navigating the Block struct) based on the +/// starting location. Add the DWARF information to the die. For +/// more information, read large comment just above here. +/// +void CompileUnit::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + DIType Ty = DV->getType(); + DIType TmpTy = Ty; + unsigned Tag = Ty.getTag(); + bool isPointer = false; + + StringRef varName = DV->getName(); + + if (Tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty); + TmpTy = DTy.getTypeDerivedFrom(); + isPointer = true; + } + + DICompositeType blockStruct = DICompositeType(TmpTy); + + // Find the __forwarding field and the variable field in the __Block_byref + // struct. + DIArray Fields = blockStruct.getTypeArray(); + DIDescriptor varField = DIDescriptor(); + DIDescriptor forwardingField = DIDescriptor(); + + for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { + DIDescriptor Element = Fields.getElement(i); + DIDerivedType DT = DIDerivedType(Element); + StringRef fieldName = DT.getName(); + if (fieldName == "__forwarding") + forwardingField = Element; + else if (fieldName == varName) + varField = Element; + } + + // Get the offsets for the forwarding field and the variable field. + unsigned forwardingFieldOffset = + DIDerivedType(forwardingField).getOffsetInBits() >> 3; + unsigned varFieldOffset = + DIDerivedType(varField).getOffsetInBits() >> 3; + + // Decode the original location, and use that as the start of the byref + // variable's location. + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + // If we started with a pointer to the __Block_byref... struct, then + // the first thing we need to do is dereference the pointer (DW_OP_deref). + if (isPointer) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Next add the offset for the '__forwarding' field: + // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in + // adding the offset if it's 0. + if (forwardingFieldOffset > 0) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, forwardingFieldOffset); + } + + // Now dereference the __forwarding field to get to the real __Block_byref + // struct: DW_OP_deref. + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Now that we've got the real __Block_byref... struct, add the offset + // for the variable's field to get to the location of the actual variable: + // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. + if (varFieldOffset > 0) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, varFieldOffset); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, 0, Block); +} + +/// addConstantValue - Add constant value entry in variable DIE. +bool CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO) { + assert (MO.isImm() && "Invalid machine operand!"); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + unsigned Imm = MO.getImm(); + addUInt(Block, 0, dwarf::DW_FORM_udata, Imm); + addBlock(Die, dwarf::DW_AT_const_value, 0, Block); + return true; +} + +/// addConstantFPValue - Add constant value entry in variable DIE. +bool CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { + assert (MO.isFPImm() && "Invalid machine operand!"); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + APFloat FPImm = MO.getFPImm()->getValueAPF(); + + // Get the raw data form of the floating point. + const APInt FltVal = FPImm.bitcastToAPInt(); + const char *FltPtr = (const char*)FltVal.getRawData(); + + int NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. + bool LittleEndian = Asm->getTargetData().isLittleEndian(); + int Incr = (LittleEndian ? 1 : -1); + int Start = (LittleEndian ? 0 : NumBytes - 1); + int Stop = (LittleEndian ? NumBytes : -1); + + // Output the constant to DWARF one byte at a time. + for (; Start != Stop; Start += Incr) + addUInt(Block, 0, dwarf::DW_FORM_data1, + (unsigned char)0xFF & FltPtr[Start]); + + addBlock(Die, dwarf::DW_AT_const_value, 0, Block); + return true; +} + +/// addConstantValue - Add constant value entry in variable DIE. +bool CompileUnit::addConstantValue(DIE *Die, ConstantInt *CI, + bool Unsigned) { + if (CI->getBitWidth() <= 64) { + if (Unsigned) + addUInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, + CI->getZExtValue()); + else + addSInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, + CI->getSExtValue()); + return true; + } + + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + // Get the raw data form of the large APInt. + const APInt Val = CI->getValue(); + const char *Ptr = (const char*)Val.getRawData(); + + int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte. + bool LittleEndian = Asm->getTargetData().isLittleEndian(); + int Incr = (LittleEndian ? 1 : -1); + int Start = (LittleEndian ? 0 : NumBytes - 1); + int Stop = (LittleEndian ? NumBytes : -1); + + // Output the constant to DWARF one byte at a time. + for (; Start != Stop; Start += Incr) + addUInt(Block, 0, dwarf::DW_FORM_data1, + (unsigned char)0xFF & Ptr[Start]); + + addBlock(Die, dwarf::DW_AT_const_value, 0, Block); + return true; +} + +/// addTemplateParams - Add template parameters in buffer. +void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) { + // Add template parameters. + for (unsigned i = 0, e = TParams.getNumElements(); i != e; ++i) { + DIDescriptor Element = TParams.getElement(i); + if (Element.isTemplateTypeParameter()) + Buffer.addChild(getOrCreateTemplateTypeParameterDIE( + DITemplateTypeParameter(Element))); + else if (Element.isTemplateValueParameter()) + Buffer.addChild(getOrCreateTemplateValueParameterDIE( + DITemplateValueParameter(Element))); + } + +} +/// addToContextOwner - Add Die into the list of its context owner's children. +void CompileUnit::addToContextOwner(DIE *Die, DIDescriptor Context) { + if (Context.isType()) { + DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context)); + ContextDIE->addChild(Die); + } else if (Context.isNameSpace()) { + DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context)); + ContextDIE->addChild(Die); + } else if (Context.isSubprogram()) { + DIE *ContextDIE = DD->createSubprogramDIE(DISubprogram(Context)); + ContextDIE->addChild(Die); + } else if (DIE *ContextDIE = getDIE(Context)) + ContextDIE->addChild(Die); + else + addDie(Die); +} + +/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the +/// given DIType. +DIE *CompileUnit::getOrCreateTypeDIE(DIType Ty) { + DIE *TyDIE = getDIE(Ty); + if (TyDIE) + return TyDIE; + + // Create new type. + TyDIE = new DIE(dwarf::DW_TAG_base_type); + insertDIE(Ty, TyDIE); + if (Ty.isBasicType()) + constructTypeDIE(*TyDIE, DIBasicType(Ty)); + else if (Ty.isCompositeType()) + constructTypeDIE(*TyDIE, DICompositeType(Ty)); + else { + assert(Ty.isDerivedType() && "Unknown kind of DIType"); + constructTypeDIE(*TyDIE, DIDerivedType(Ty)); + } + + addToContextOwner(TyDIE, Ty.getContext()); + return TyDIE; +} + +/// addType - Add a new type attribute to the specified entity. +void CompileUnit::addType(DIE *Entity, DIType Ty) { + if (!Ty.Verify()) + return; + + // Check for pre-existence. + DIEEntry *Entry = getDIEEntry(Ty); + // If it exists then use the existing value. + if (Entry) { + Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); + return; + } + + // Construct type. + DIE *Buffer = getOrCreateTypeDIE(Ty); + + // Set up proxy. + Entry = createDIEEntry(Buffer); + insertDIEEntry(Ty, Entry); + + Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); +} + +/// constructTypeDIE - Construct basic type die from DIBasicType. +void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { + // Get core information. + StringRef Name = BTy.getName(); + Buffer.setTag(dwarf::DW_TAG_base_type); + addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + BTy.getEncoding()); + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + uint64_t Size = BTy.getSizeInBits() >> 3; + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); +} + +/// constructTypeDIE - Construct derived type die from DIDerivedType. +void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { + // Get core information. + StringRef Name = DTy.getName(); + uint64_t Size = DTy.getSizeInBits() >> 3; + unsigned Tag = DTy.getTag(); + + // FIXME - Workaround for templates. + if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type; + + Buffer.setTag(Tag); + + // Map to main type, void will not have a type. + DIType FromTy = DTy.getTypeDerivedFrom(); + addType(&Buffer, FromTy); + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + + // Add source line info if available and TyDesc is not a forward declaration. + if (!DTy.isForwardDecl()) + addSourceLine(&Buffer, DTy); +} + +/// constructTypeDIE - Construct type DIE from DICompositeType. +void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { + // Get core information. + StringRef Name = CTy.getName(); + + uint64_t Size = CTy.getSizeInBits() >> 3; + unsigned Tag = CTy.getTag(); + Buffer.setTag(Tag); + + switch (Tag) { + case dwarf::DW_TAG_vector_type: + case dwarf::DW_TAG_array_type: + constructArrayTypeDIE(Buffer, &CTy); + break; + case dwarf::DW_TAG_enumeration_type: { + DIArray Elements = CTy.getTypeArray(); + + // Add enumerators to enumeration type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIE *ElemDie = NULL; + DIDescriptor Enum(Elements.getElement(i)); + if (Enum.isEnumerator()) { + ElemDie = constructEnumTypeDIE(DIEnumerator(Enum)); + Buffer.addChild(ElemDie); + } + } + } + break; + case dwarf::DW_TAG_subroutine_type: { + // Add return type. + DIArray Elements = CTy.getTypeArray(); + DIDescriptor RTy = Elements.getElement(0); + addType(&Buffer, DIType(RTy)); + + bool isPrototyped = true; + // Add arguments. + for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Ty = Elements.getElement(i); + if (Ty.isUnspecifiedParameter()) { + DIE *Arg = new DIE(dwarf::DW_TAG_unspecified_parameters); + Buffer.addChild(Arg); + isPrototyped = false; + } else { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + addType(Arg, DIType(Ty)); + Buffer.addChild(Arg); + } + } + // Add prototype flag. + if (isPrototyped) + addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + } + break; + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_class_type: { + // Add elements to structure type. + DIArray Elements = CTy.getTypeArray(); + + // A forward struct declared type may not have elements available. + unsigned N = Elements.getNumElements(); + if (N == 0) + break; + + // Add elements to structure type. + for (unsigned i = 0; i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + DIE *ElemDie = NULL; + if (Element.isSubprogram()) { + DISubprogram SP(Element); + ElemDie = DD->createSubprogramDIE(DISubprogram(Element)); + if (SP.isProtected()) + addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_protected); + else if (SP.isPrivate()) + addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_private); + else + addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_public); + if (SP.isExplicit()) + addUInt(ElemDie, dwarf::DW_AT_explicit, dwarf::DW_FORM_flag, 1); + } + else if (Element.isVariable()) { + DIVariable DV(Element); + ElemDie = new DIE(dwarf::DW_TAG_variable); + addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + DV.getName()); + addType(ElemDie, DV.getType()); + addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + addSourceLine(ElemDie, DV); + } else if (Element.isDerivedType()) + ElemDie = createMemberDIE(DIDerivedType(Element)); + else + continue; + Buffer.addChild(ElemDie); + } + + if (CTy.isAppleBlockExtension()) + addUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1); + + unsigned RLang = CTy.getRunTimeLang(); + if (RLang) + addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, + dwarf::DW_FORM_data1, RLang); + + DICompositeType ContainingType = CTy.getContainingType(); + if (DIDescriptor(ContainingType).isCompositeType()) + addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, + getOrCreateTypeDIE(DIType(ContainingType))); + else { + DIDescriptor Context = CTy.getContext(); + addToContextOwner(&Buffer, Context); + } + + if (Tag == dwarf::DW_TAG_class_type) + addTemplateParams(Buffer, CTy.getTemplateParams()); + + break; + } + default: + break; + } + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type + || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) + { + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + else { + // Add zero size if it is not a forward declaration. + if (CTy.isForwardDecl()) + addUInt(&Buffer, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + else + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, 0); + } + + // Add source line info if available. + if (!CTy.isForwardDecl()) + addSourceLine(&Buffer, CTy); + } +} + +/// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE +/// for the given DITemplateTypeParameter. +DIE * +CompileUnit::getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP) { + DIE *ParamDIE = getDIE(TP); + if (ParamDIE) + return ParamDIE; + + ParamDIE = new DIE(dwarf::DW_TAG_template_type_parameter); + addType(ParamDIE, TP.getType()); + addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TP.getName()); + return ParamDIE; +} + +/// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE +/// for the given DITemplateValueParameter. +DIE * +CompileUnit::getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TPV) { + DIE *ParamDIE = getDIE(TPV); + if (ParamDIE) + return ParamDIE; + + ParamDIE = new DIE(dwarf::DW_TAG_template_value_parameter); + addType(ParamDIE, TPV.getType()); + if (!TPV.getName().empty()) + addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TPV.getName()); + addUInt(ParamDIE, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, + TPV.getValue()); + return ParamDIE; +} + +/// constructSubrangeDIE - Construct subrange DIE from DISubrange. +void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){ + DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); + addDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); + int64_t L = SR.getLo(); + int64_t H = SR.getHi(); + + // The L value defines the lower bounds which is typically zero for C/C++. The + // H value is the upper bounds. Values are 64 bit. H - L + 1 is the size + // of the array. If L > H then do not emit DW_AT_lower_bound and + // DW_AT_upper_bound attributes. If L is zero and H is also zero then the + // array has one element and in such case do not emit lower bound. + + if (L > H) { + Buffer.addChild(DW_Subrange); + return; + } + if (L) + addSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); + addSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); + Buffer.addChild(DW_Subrange); +} + +/// constructArrayTypeDIE - Construct array type DIE from DICompositeType. +void CompileUnit::constructArrayTypeDIE(DIE &Buffer, + DICompositeType *CTy) { + Buffer.setTag(dwarf::DW_TAG_array_type); + if (CTy->getTag() == dwarf::DW_TAG_vector_type) + addUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1); + + // Emit derived type. + addType(&Buffer, CTy->getTypeDerivedFrom()); + DIArray Elements = CTy->getTypeArray(); + + // Get an anonymous type for index type. + DIE *IdxTy = getIndexTyDie(); + if (!IdxTy) { + // Construct an anonymous type for index type. + IdxTy = new DIE(dwarf::DW_TAG_base_type); + addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t)); + addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + dwarf::DW_ATE_signed); + addDie(IdxTy); + setIndexTyDie(IdxTy); + } + + // Add subranges to array type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + if (Element.getTag() == dwarf::DW_TAG_subrange_type) + constructSubrangeDIE(Buffer, DISubrange(Element), IdxTy); + } +} + +/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. +DIE *CompileUnit::constructEnumTypeDIE(DIEnumerator ETy) { + DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator); + StringRef Name = ETy.getName(); + addString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + int64_t Value = ETy.getEnumValue(); + addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); + return Enumerator; +} + +/// createMemberDIE - Create new member DIE. +DIE *CompileUnit::createMemberDIE(DIDerivedType DT) { + DIE *MemberDie = new DIE(DT.getTag()); + StringRef Name = DT.getName(); + if (!Name.empty()) + addString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + addType(MemberDie, DT.getTypeDerivedFrom()); + + addSourceLine(MemberDie, DT); + + DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); + addUInt(MemLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + + uint64_t Size = DT.getSizeInBits(); + uint64_t FieldSize = DT.getOriginalTypeSize(); + + if (Size != FieldSize) { + // Handle bitfield. + addUInt(MemberDie, dwarf::DW_AT_byte_size, 0, DT.getOriginalTypeSize()>>3); + addUInt(MemberDie, dwarf::DW_AT_bit_size, 0, DT.getSizeInBits()); + + uint64_t Offset = DT.getOffsetInBits(); + uint64_t AlignMask = ~(DT.getAlignInBits() - 1); + uint64_t HiMark = (Offset + FieldSize) & AlignMask; + uint64_t FieldOffset = (HiMark - FieldSize); + Offset -= FieldOffset; + + // Maybe we need to work from the other end. + if (Asm->getTargetData().isLittleEndian()) + Offset = FieldSize - (Offset + Size); + addUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset); + + // Here WD_AT_data_member_location points to the anonymous + // field that includes this bit field. + addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, FieldOffset >> 3); + + } else + // This is not a bitfield. + addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3); + + if (DT.getTag() == dwarf::DW_TAG_inheritance + && DT.isVirtual()) { + + // For C++, virtual base classes are not at fixed offset. Use following + // expression to extract appropriate offset from vtable. + // BaseAddr = ObAddr + *((*ObAddr) - Offset) + + DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock(); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits()); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, + VBaseLocationDie); + } else + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); + + if (DT.isProtected()) + addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_protected); + else if (DT.isPrivate()) + addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_private); + // Otherwise C++ member and base classes are considered public. + else if (DT.getCompileUnit().getLanguage() == dwarf::DW_LANG_C_plus_plus) + addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_public); + if (DT.isVirtual()) + addUInt(MemberDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, + dwarf::DW_VIRTUALITY_virtual); + + // Objective-C properties. + StringRef PropertyName = DT.getObjCPropertyName(); + if (!PropertyName.empty()) { + addString(MemberDie, dwarf::DW_AT_APPLE_property_name, dwarf::DW_FORM_string, + PropertyName); + StringRef GetterName = DT.getObjCPropertyGetterName(); + if (!GetterName.empty()) + addString(MemberDie, dwarf::DW_AT_APPLE_property_getter, + dwarf::DW_FORM_string, GetterName); + StringRef SetterName = DT.getObjCPropertySetterName(); + if (!SetterName.empty()) + addString(MemberDie, dwarf::DW_AT_APPLE_property_setter, + dwarf::DW_FORM_string, SetterName); + unsigned PropertyAttributes = 0; + if (DT.isReadOnlyObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_readonly; + if (DT.isReadWriteObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_readwrite; + if (DT.isAssignObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_assign; + if (DT.isRetainObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_retain; + if (DT.isCopyObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_copy; + if (DT.isNonAtomicObjCProperty()) + PropertyAttributes |= dwarf::DW_APPLE_PROPERTY_nonatomic; + if (PropertyAttributes) + addUInt(MemberDie, dwarf::DW_AT_APPLE_property_attribute, 0, + PropertyAttributes); + } + return MemberDie; +} diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h new file mode 100644 index 000000000000..f4f6fb8b0df4 --- /dev/null +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -0,0 +1,282 @@ +//===-- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit ---*- 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 support for writing dwarf compile unit. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H +#define CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H + +#include "DIE.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/OwningPtr.h" + +namespace llvm { + +class DwarfDebug; +class MachineLocation; +class MachineOperand; +class ConstantInt; +class DbgVariable; + +//===----------------------------------------------------------------------===// +/// CompileUnit - This dwarf writer support class manages information associate +/// with a source file. +class CompileUnit { + /// ID - File identifier for source. + /// + unsigned ID; + + /// Die - Compile unit debug information entry. + /// + const OwningPtr CUDie; + + /// Asm - Target of Dwarf emission. + AsmPrinter *Asm; + + DwarfDebug *DD; + + /// IndexTyDie - An anonymous type for index type. Owned by CUDie. + DIE *IndexTyDie; + + /// MDNodeToDieMap - Tracks the mapping of unit level debug informaton + /// variables to debug information entries. + DenseMap MDNodeToDieMap; + + /// MDNodeToDIEEntryMap - Tracks the mapping of unit level debug informaton + /// descriptors to debug information entries using a DIEEntry proxy. + DenseMap MDNodeToDIEEntryMap; + + /// Globals - A map of globally visible named entities for this unit. + /// + StringMap Globals; + + /// GlobalTypes - A map of globally visible types for this unit. + /// + StringMap GlobalTypes; + + /// DIEBlocks - A list of all the DIEBlocks in use. + std::vector DIEBlocks; + +public: + CompileUnit(unsigned I, DIE *D, AsmPrinter *A, DwarfDebug *DW); + ~CompileUnit(); + + // Accessors. + unsigned getID() const { return ID; } + DIE* getCUDie() const { return CUDie.get(); } + const StringMap &getGlobals() const { return Globals; } + const StringMap &getGlobalTypes() const { return GlobalTypes; } + + /// hasContent - Return true if this compile unit has something to write out. + /// + bool hasContent() const { return !CUDie->getChildren().empty(); } + + /// addGlobal - Add a new global entity to the compile unit. + /// + void addGlobal(StringRef Name, DIE *Die) { Globals[Name] = Die; } + + /// addGlobalType - Add a new global type to the compile unit. + /// + void addGlobalType(StringRef Name, DIE *Die) { + GlobalTypes[Name] = Die; + } + + /// getDIE - Returns the debug information entry map slot for the + /// specified debug variable. + DIE *getDIE(const MDNode *N) { return MDNodeToDieMap.lookup(N); } + + DIEBlock *getDIEBlock() { + return new (DIEValueAllocator) DIEBlock(); + } + + /// insertDIE - Insert DIE into the map. + void insertDIE(const MDNode *N, DIE *D) { + MDNodeToDieMap.insert(std::make_pair(N, D)); + } + + /// getDIEEntry - Returns the debug information entry for the speciefied + /// debug variable. + DIEEntry *getDIEEntry(const MDNode *N) { + DenseMap::iterator I = + MDNodeToDIEEntryMap.find(N); + if (I == MDNodeToDIEEntryMap.end()) + return NULL; + return I->second; + } + + /// insertDIEEntry - Insert debug information entry into the map. + void insertDIEEntry(const MDNode *N, DIEEntry *E) { + MDNodeToDIEEntryMap.insert(std::make_pair(N, E)); + } + + /// addDie - Adds or interns the DIE to the compile unit. + /// + void addDie(DIE *Buffer) { + this->CUDie->addChild(Buffer); + } + + // getIndexTyDie - Get an anonymous type for index type. + DIE *getIndexTyDie() { + return IndexTyDie; + } + + // setIndexTyDie - Set D as anonymous type for index which can be reused + // later. + void setIndexTyDie(DIE *D) { + IndexTyDie = D; + } +public: + + /// addUInt - Add an unsigned integer attribute data and value. + /// + void addUInt(DIE *Die, unsigned Attribute, unsigned Form, uint64_t Integer); + + /// addSInt - Add an signed integer attribute data and value. + /// + void addSInt(DIE *Die, unsigned Attribute, unsigned Form, int64_t Integer); + + /// addString - Add a string attribute data and value. + /// + void addString(DIE *Die, unsigned Attribute, unsigned Form, + const StringRef Str); + + /// addLabel - Add a Dwarf label attribute data and value. + /// + void addLabel(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Label); + + /// addDelta - Add a label delta attribute data and value. + /// + void addDelta(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Hi, const MCSymbol *Lo); + + /// addDIEEntry - Add a DIE attribute data and value. + /// + void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry); + + /// addBlock - Add block data. + /// + void addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block); + + /// addSourceLine - Add location information to specified debug information + /// entry. + void addSourceLine(DIE *Die, DIVariable V); + void addSourceLine(DIE *Die, DIGlobalVariable G); + void addSourceLine(DIE *Die, DISubprogram SP); + void addSourceLine(DIE *Die, DIType Ty); + void addSourceLine(DIE *Die, DINameSpace NS); + + /// addAddress - Add an address attribute to a die based on the location + /// provided. + void addAddress(DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + /// addConstantValue - Add constant value entry in variable DIE. + bool addConstantValue(DIE *Die, const MachineOperand &MO); + bool addConstantValue(DIE *Die, ConstantInt *CI, bool Unsigned); + + /// addConstantFPValue - Add constant value entry in variable DIE. + bool addConstantFPValue(DIE *Die, const MachineOperand &MO); + + /// addTemplateParams - Add template parameters in buffer. + void addTemplateParams(DIE &Buffer, DIArray TParams); + + /// addRegisterOp - Add register operand. + void addRegisterOp(DIE *TheDie, unsigned Reg); + + /// addRegisterOffset - Add register offset. + void addRegisterOffset(DIE *TheDie, unsigned Reg, int64_t Offset); + + /// addComplexAddress - Start with the address based on the location provided, + /// and generate the DWARF information necessary to find the actual variable + /// (navigating the extra location information encoded in the type) based on + /// the starting location. Add the DWARF information to the die. + /// + void addComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + // FIXME: Should be reformulated in terms of addComplexAddress. + /// addBlockByrefAddress - Start with the address based on the location + /// provided, and generate the DWARF information necessary to find the + /// actual Block variable (navigating the Block struct) based on the + /// starting location. Add the DWARF information to the die. Obsolete, + /// please use addComplexAddress instead. + /// + void addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + /// addVariableAddress - Add DW_AT_location attribute for a + /// DbgVariable based on provided MachineLocation. + void addVariableAddress(DbgVariable *&DV, DIE *Die, MachineLocation Location); + + /// addToContextOwner - Add Die into the list of its context owner's children. + void addToContextOwner(DIE *Die, DIDescriptor Context); + + /// addType - Add a new type attribute to the specified entity. + void addType(DIE *Entity, DIType Ty); + + /// getOrCreateNameSpace - Create a DIE for DINameSpace. + DIE *getOrCreateNameSpace(DINameSpace NS); + + /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the + /// given DIType. + DIE *getOrCreateTypeDIE(DIType Ty); + + /// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE + /// for the given DITemplateTypeParameter. + DIE *getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP); + + /// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE + /// for the given DITemplateValueParameter. + DIE *getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TVP); + + /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug + /// information entry. + DIEEntry *createDIEEntry(DIE *Entry); + + void addPubTypes(DISubprogram SP); + + /// constructTypeDIE - Construct basic type die from DIBasicType. + void constructTypeDIE(DIE &Buffer, + DIBasicType BTy); + + /// constructTypeDIE - Construct derived type die from DIDerivedType. + void constructTypeDIE(DIE &Buffer, + DIDerivedType DTy); + + /// constructTypeDIE - Construct type DIE from DICompositeType. + void constructTypeDIE(DIE &Buffer, + DICompositeType CTy); + + /// constructSubrangeDIE - Construct subrange DIE from DISubrange. + void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy); + + /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. + void constructArrayTypeDIE(DIE &Buffer, + DICompositeType *CTy); + + /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. + DIE *constructEnumTypeDIE(DIEnumerator ETy); + + /// createMemberDIE - Create new member DIE. + DIE *createMemberDIE(DIDerivedType DT); + +private: + + // DIEValueAllocator - All DIEValues are allocated through this allocator. + BumpPtrAllocator DIEValueAllocator; + DIEInteger *DIEIntegerOne; +}; + +} // end llvm namespace +#endif diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 780fa405ef51..26da8006b30e 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -14,6 +14,7 @@ #define DEBUG_TYPE "dwarfdebug" #include "DwarfDebug.h" #include "DIE.h" +#include "DwarfCompileUnit.h" #include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/Instructions.h" @@ -52,7 +53,7 @@ static cl::opt DisableDebugInfoPrinting("disable-debug-info-print", cl::desc("Disable debug info printing")); static cl::opt UnknownLocations("use-unknown-locations", cl::Hidden, - cl::desc("Make an absense of debug location information explicit."), + cl::desc("Make an absence of debug location information explicit."), cl::init(false)); #ifndef NDEBUG @@ -72,189 +73,56 @@ static const unsigned InitAbbreviationsSetSize = 9; // log2(512) namespace llvm { -//===----------------------------------------------------------------------===// -/// CompileUnit - This dwarf writer support class manages information associate -/// with a source file. -class CompileUnit { - /// ID - File identifier for source. - /// - unsigned ID; - - /// Die - Compile unit debug information entry. - /// - const OwningPtr CUDie; - - /// IndexTyDie - An anonymous type for index type. Owned by CUDie. - DIE *IndexTyDie; - - /// MDNodeToDieMap - Tracks the mapping of unit level debug informaton - /// variables to debug information entries. - DenseMap MDNodeToDieMap; - - /// MDNodeToDIEEntryMap - Tracks the mapping of unit level debug informaton - /// descriptors to debug information entries using a DIEEntry proxy. - DenseMap MDNodeToDIEEntryMap; - - /// Globals - A map of globally visible named entities for this unit. - /// - StringMap Globals; - - /// GlobalTypes - A map of globally visible types for this unit. - /// - StringMap GlobalTypes; - -public: - CompileUnit(unsigned I, DIE *D) - : ID(I), CUDie(D), IndexTyDie(0) {} - - // Accessors. - unsigned getID() const { return ID; } - DIE* getCUDie() const { return CUDie.get(); } - const StringMap &getGlobals() const { return Globals; } - const StringMap &getGlobalTypes() const { return GlobalTypes; } - - /// hasContent - Return true if this compile unit has something to write out. - /// - bool hasContent() const { return !CUDie->getChildren().empty(); } - - /// addGlobal - Add a new global entity to the compile unit. - /// - void addGlobal(StringRef Name, DIE *Die) { Globals[Name] = Die; } - - /// addGlobalType - Add a new global type to the compile unit. - /// - void addGlobalType(StringRef Name, DIE *Die) { - GlobalTypes[Name] = Die; - } - - /// getDIE - Returns the debug information entry map slot for the - /// specified debug variable. - DIE *getDIE(const MDNode *N) { return MDNodeToDieMap.lookup(N); } - - /// insertDIE - Insert DIE into the map. - void insertDIE(const MDNode *N, DIE *D) { - MDNodeToDieMap.insert(std::make_pair(N, D)); - } - - /// getDIEEntry - Returns the debug information entry for the speciefied - /// debug variable. - DIEEntry *getDIEEntry(const MDNode *N) { - DenseMap::iterator I = - MDNodeToDIEEntryMap.find(N); - if (I == MDNodeToDIEEntryMap.end()) - return NULL; - return I->second; - } - - /// insertDIEEntry - Insert debug information entry into the map. - void insertDIEEntry(const MDNode *N, DIEEntry *E) { - MDNodeToDIEEntryMap.insert(std::make_pair(N, E)); - } - - /// addDie - Adds or interns the DIE to the compile unit. - /// - void addDie(DIE *Buffer) { - this->CUDie->addChild(Buffer); - } - - // getIndexTyDie - Get an anonymous type for index type. - DIE *getIndexTyDie() { - return IndexTyDie; - } - - // setIndexTyDie - Set D as anonymous type for index which can be reused - // later. - void setIndexTyDie(DIE *D) { - IndexTyDie = D; - } - -}; - -//===----------------------------------------------------------------------===// -/// DbgVariable - This class is used to track local variable information. -/// -class DbgVariable { - DIVariable Var; // Variable Descriptor. - DIE *TheDIE; // Variable DIE. - unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries. -public: - // AbsVar may be NULL. - DbgVariable(DIVariable V) : Var(V), TheDIE(0), DotDebugLocOffset(~0U) {} - - // Accessors. - DIVariable getVariable() const { return Var; } - void setDIE(DIE *D) { TheDIE = D; } - DIE *getDIE() const { return TheDIE; } - void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } - unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; } - StringRef getName() const { return Var.getName(); } - unsigned getTag() const { return Var.getTag(); } - bool variableHasComplexAddress() const { - assert(Var.Verify() && "Invalid complex DbgVariable!"); - return Var.hasComplexAddress(); - } - bool isBlockByrefVariable() const { - assert(Var.Verify() && "Invalid complex DbgVariable!"); - return Var.isBlockByrefVariable(); - } - unsigned getNumAddrElements() const { - assert(Var.Verify() && "Invalid complex DbgVariable!"); - return Var.getNumAddrElements(); - } - uint64_t getAddrElement(unsigned i) const { - return Var.getAddrElement(i); - } - DIType getType() const { - DIType Ty = Var.getType(); - // FIXME: isBlockByrefVariable should be reformulated in terms of complex - // addresses instead. - if (Var.isBlockByrefVariable()) { - /* Byref variables, in Blocks, are declared by the programmer as - "SomeType VarName;", but the compiler creates a - __Block_byref_x_VarName struct, and gives the variable VarName - either the struct, or a pointer to the struct, as its type. This - is necessary for various behind-the-scenes things the compiler - needs to do with by-reference variables in blocks. - - However, as far as the original *programmer* is concerned, the - variable should still have type 'SomeType', as originally declared. - - The following function dives into the __Block_byref_x_VarName - struct to find the original type of the variable. This will be - passed back to the code generating the type for the Debug - Information Entry for the variable 'VarName'. 'VarName' will then - have the original type 'SomeType' in its debug information. - - The original type 'SomeType' will be the type of the field named - 'VarName' inside the __Block_byref_x_VarName struct. - - NOTE: In order for this to not completely fail on the debugger - side, the Debug Information Entry for the variable VarName needs to - have a DW_AT_location that tells the debugger how to unwind through - the pointers and __Block_byref_x_VarName struct to find the actual - value of the variable. The function addBlockByrefType does this. */ - DIType subType = Ty; - unsigned tag = Ty.getTag(); - - if (tag == dwarf::DW_TAG_pointer_type) { - DIDerivedType DTy = DIDerivedType(Ty); - subType = DTy.getTypeDerivedFrom(); - } - - DICompositeType blockStruct = DICompositeType(subType); - DIArray Elements = blockStruct.getTypeArray(); - - for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Element = Elements.getElement(i); - DIDerivedType DT = DIDerivedType(Element); - if (getName() == DT.getName()) - return (DT.getTypeDerivedFrom()); - } - return Ty; +DIType DbgVariable::getType() const { + DIType Ty = Var.getType(); + // FIXME: isBlockByrefVariable should be reformulated in terms of complex + // addresses instead. + if (Var.isBlockByrefVariable()) { + /* Byref variables, in Blocks, are declared by the programmer as + "SomeType VarName;", but the compiler creates a + __Block_byref_x_VarName struct, and gives the variable VarName + either the struct, or a pointer to the struct, as its type. This + is necessary for various behind-the-scenes things the compiler + needs to do with by-reference variables in blocks. + + However, as far as the original *programmer* is concerned, the + variable should still have type 'SomeType', as originally declared. + + The following function dives into the __Block_byref_x_VarName + struct to find the original type of the variable. This will be + passed back to the code generating the type for the Debug + Information Entry for the variable 'VarName'. 'VarName' will then + have the original type 'SomeType' in its debug information. + + The original type 'SomeType' will be the type of the field named + 'VarName' inside the __Block_byref_x_VarName struct. + + NOTE: In order for this to not completely fail on the debugger + side, the Debug Information Entry for the variable VarName needs to + have a DW_AT_location that tells the debugger how to unwind through + the pointers and __Block_byref_x_VarName struct to find the actual + value of the variable. The function addBlockByrefType does this. */ + DIType subType = Ty; + unsigned tag = Ty.getTag(); + + if (tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty); + subType = DTy.getTypeDerivedFrom(); + } + + DICompositeType blockStruct = DICompositeType(subType); + DIArray Elements = blockStruct.getTypeArray(); + + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + DIDerivedType DT = DIDerivedType(Element); + if (getName() == DT.getName()) + return (DT.getTypeDerivedFrom()); } return Ty; } -}; + return Ty; +} //===----------------------------------------------------------------------===// /// DbgRange - This is used to track range of instructions with identical @@ -396,15 +264,12 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) DwarfStrSectionSym = TextSectionSym = 0; DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0; FunctionBeginSym = FunctionEndSym = 0; - DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); beginModule(M); } } DwarfDebug::~DwarfDebug() { - for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) - DIEBlocks[j]->~DIEBlock(); } MCSymbol *DwarfDebug::getStringPoolEntry(StringRef Str) { @@ -439,852 +304,6 @@ void DwarfDebug::assignAbbrevNumber(DIEAbbrev &Abbrev) { } } -/// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug -/// information entry. -DIEEntry *DwarfDebug::createDIEEntry(DIE *Entry) { - DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry); - return Value; -} - -/// addUInt - Add an unsigned integer attribute data and value. -/// -void DwarfDebug::addUInt(DIE *Die, unsigned Attribute, - unsigned Form, uint64_t Integer) { - if (!Form) Form = DIEInteger::BestForm(false, Integer); - DIEValue *Value = Integer == 1 ? - DIEIntegerOne : new (DIEValueAllocator) DIEInteger(Integer); - Die->addValue(Attribute, Form, Value); -} - -/// addSInt - Add an signed integer attribute data and value. -/// -void DwarfDebug::addSInt(DIE *Die, unsigned Attribute, - unsigned Form, int64_t Integer) { - if (!Form) Form = DIEInteger::BestForm(true, Integer); - DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer); - Die->addValue(Attribute, Form, Value); -} - -/// addString - Add a string attribute data and value. DIEString only -/// keeps string reference. -void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form, - StringRef String) { - DIEValue *Value = new (DIEValueAllocator) DIEString(String); - Die->addValue(Attribute, Form, Value); -} - -/// addLabel - Add a Dwarf label attribute data and value. -/// -void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Label) { - DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); - Die->addValue(Attribute, Form, Value); -} - -/// addDelta - Add a label delta attribute data and value. -/// -void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Hi, const MCSymbol *Lo) { - DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); - Die->addValue(Attribute, Form, Value); -} - -/// addDIEEntry - Add a DIE attribute data and value. -/// -void DwarfDebug::addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, - DIE *Entry) { - Die->addValue(Attribute, Form, createDIEEntry(Entry)); -} - - -/// addBlock - Add block data. -/// -void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form, - DIEBlock *Block) { - Block->ComputeSize(Asm); - DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on. - Die->addValue(Attribute, Block->BestForm(), Block); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DIVariable V) { - // Verify variable. - if (!V.Verify()) - return; - - unsigned Line = V.getLineNumber(); - if (Line == 0) - return; - unsigned FileID = GetOrCreateSourceID(V.getContext().getFilename()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DIGlobalVariable G) { - // Verify global variable. - if (!G.Verify()) - return; - - unsigned Line = G.getLineNumber(); - if (Line == 0) - return; - unsigned FileID = GetOrCreateSourceID(G.getContext().getFilename()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DISubprogram SP) { - // Verify subprogram. - if (!SP.Verify()) - return; - // If the line number is 0, don't add it. - if (SP.getLineNumber() == 0) - return; - - unsigned Line = SP.getLineNumber(); - if (!SP.getContext().Verify()) - return; - unsigned FileID = GetOrCreateSourceID(SP.getFilename()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DIType Ty) { - // Verify type. - if (!Ty.Verify()) - return; - - unsigned Line = Ty.getLineNumber(); - if (Line == 0 || !Ty.getContext().Verify()) - return; - unsigned FileID = GetOrCreateSourceID(Ty.getFilename()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DINameSpace NS) { - // Verify namespace. - if (!NS.Verify()) - return; - - unsigned Line = NS.getLineNumber(); - if (Line == 0) - return; - StringRef FN = NS.getFilename(); - - unsigned FileID = GetOrCreateSourceID(FN); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addVariableAddress - Add DW_AT_location attribute for a DbgVariable based -/// on provided frame index. -void DwarfDebug::addVariableAddress(DbgVariable *&DV, DIE *Die, int64_t FI) { - MachineLocation Location; - unsigned FrameReg; - const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); - int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); - Location.set(FrameReg, Offset); - - if (DV->variableHasComplexAddress()) - addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); - else if (DV->isBlockByrefVariable()) - addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); - else - addAddress(Die, dwarf::DW_AT_location, Location); -} - -/// addComplexAddress - Start with the address based on the location provided, -/// and generate the DWARF information necessary to find the actual variable -/// given the extra address information encoded in the DIVariable, starting from -/// the starting location. Add the DWARF information to the die. -/// -void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die, - unsigned Attribute, - const MachineLocation &Location) { - DIType Ty = DV->getType(); - - // Decode the original location, and use that as the start of the byref - // variable's location. - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); - unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - - if (Location.isReg()) { - if (Reg < 32) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); - } else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - } else { - if (Reg < 32) - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); - else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - - addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); - } - - for (unsigned i = 0, N = DV->getNumAddrElements(); i < N; ++i) { - uint64_t Element = DV->getAddrElement(i); - - if (Element == DIBuilder::OpPlus) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i)); - } else if (Element == DIBuilder::OpDeref) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - } else llvm_unreachable("unknown DIBuilder Opcode"); - } - - // Now attach the location information to the DIE. - addBlock(Die, Attribute, 0, Block); -} - -/* Byref variables, in Blocks, are declared by the programmer as "SomeType - VarName;", but the compiler creates a __Block_byref_x_VarName struct, and - gives the variable VarName either the struct, or a pointer to the struct, as - its type. This is necessary for various behind-the-scenes things the - compiler needs to do with by-reference variables in Blocks. - - However, as far as the original *programmer* is concerned, the variable - should still have type 'SomeType', as originally declared. - - The function getBlockByrefType dives into the __Block_byref_x_VarName - struct to find the original type of the variable, which is then assigned to - the variable's Debug Information Entry as its real type. So far, so good. - However now the debugger will expect the variable VarName to have the type - SomeType. So we need the location attribute for the variable to be an - expression that explains to the debugger how to navigate through the - pointers and struct to find the actual variable of type SomeType. - - The following function does just that. We start by getting - the "normal" location for the variable. This will be the location - of either the struct __Block_byref_x_VarName or the pointer to the - struct __Block_byref_x_VarName. - - The struct will look something like: - - struct __Block_byref_x_VarName { - ... - struct __Block_byref_x_VarName *forwarding; - ... - SomeType VarName; - ... - }; - - If we are given the struct directly (as our starting point) we - need to tell the debugger to: - - 1). Add the offset of the forwarding field. - - 2). Follow that pointer to get the real __Block_byref_x_VarName - struct to use (the real one may have been copied onto the heap). - - 3). Add the offset for the field VarName, to find the actual variable. - - If we started with a pointer to the struct, then we need to - dereference that pointer first, before the other steps. - Translating this into DWARF ops, we will need to append the following - to the current location description for the variable: - - DW_OP_deref -- optional, if we start with a pointer - DW_OP_plus_uconst - DW_OP_deref - DW_OP_plus_uconst - - That is what this function does. */ - -/// addBlockByrefAddress - Start with the address based on the location -/// provided, and generate the DWARF information necessary to find the -/// actual Block variable (navigating the Block struct) based on the -/// starting location. Add the DWARF information to the die. For -/// more information, read large comment just above here. -/// -void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, - unsigned Attribute, - const MachineLocation &Location) { - DIType Ty = DV->getType(); - DIType TmpTy = Ty; - unsigned Tag = Ty.getTag(); - bool isPointer = false; - - StringRef varName = DV->getName(); - - if (Tag == dwarf::DW_TAG_pointer_type) { - DIDerivedType DTy = DIDerivedType(Ty); - TmpTy = DTy.getTypeDerivedFrom(); - isPointer = true; - } - - DICompositeType blockStruct = DICompositeType(TmpTy); - - // Find the __forwarding field and the variable field in the __Block_byref - // struct. - DIArray Fields = blockStruct.getTypeArray(); - DIDescriptor varField = DIDescriptor(); - DIDescriptor forwardingField = DIDescriptor(); - - for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { - DIDescriptor Element = Fields.getElement(i); - DIDerivedType DT = DIDerivedType(Element); - StringRef fieldName = DT.getName(); - if (fieldName == "__forwarding") - forwardingField = Element; - else if (fieldName == varName) - varField = Element; - } - - // Get the offsets for the forwarding field and the variable field. - unsigned forwardingFieldOffset = - DIDerivedType(forwardingField).getOffsetInBits() >> 3; - unsigned varFieldOffset = - DIDerivedType(varField).getOffsetInBits() >> 3; - - // Decode the original location, and use that as the start of the byref - // variable's location. - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); - unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - - if (Location.isReg()) { - if (Reg < 32) - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); - else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - } else { - if (Reg < 32) - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); - else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - - addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); - } - - // If we started with a pointer to the __Block_byref... struct, then - // the first thing we need to do is dereference the pointer (DW_OP_deref). - if (isPointer) - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - - // Next add the offset for the '__forwarding' field: - // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in - // adding the offset if it's 0. - if (forwardingFieldOffset > 0) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, 0, dwarf::DW_FORM_udata, forwardingFieldOffset); - } - - // Now dereference the __forwarding field to get to the real __Block_byref - // struct: DW_OP_deref. - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - - // Now that we've got the real __Block_byref... struct, add the offset - // for the variable's field to get to the location of the actual variable: - // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. - if (varFieldOffset > 0) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, 0, dwarf::DW_FORM_udata, varFieldOffset); - } - - // Now attach the location information to the DIE. - addBlock(Die, Attribute, 0, Block); -} - -/// addAddress - Add an address attribute to a die based on the location -/// provided. -void DwarfDebug::addAddress(DIE *Die, unsigned Attribute, - const MachineLocation &Location) { - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); - unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - - if (RI->getFrameRegister(*Asm->MF) == Location.getReg() - && Location.getOffset()) { - // If variable offset is based in frame register then use fbreg. - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_fbreg); - addSInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); - addBlock(Die, Attribute, 0, Block); - return; - } - - if (Location.isReg()) { - if (Reg < 32) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); - } else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - } else { - if (Reg < 32) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); - } else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - - addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); - } - - addBlock(Die, Attribute, 0, Block); -} - -/// addRegisterAddress - Add register location entry in variable DIE. -bool DwarfDebug::addRegisterAddress(DIE *Die, const MachineOperand &MO) { - assert (MO.isReg() && "Invalid machine operand!"); - if (!MO.getReg()) - return false; - MachineLocation Location; - Location.set(MO.getReg()); - addAddress(Die, dwarf::DW_AT_location, Location); - return true; -} - -/// addConstantValue - Add constant value entry in variable DIE. -bool DwarfDebug::addConstantValue(DIE *Die, const MachineOperand &MO) { - assert (MO.isImm() && "Invalid machine operand!"); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - unsigned Imm = MO.getImm(); - addUInt(Block, 0, dwarf::DW_FORM_udata, Imm); - addBlock(Die, dwarf::DW_AT_const_value, 0, Block); - return true; -} - -/// addConstantFPValue - Add constant value entry in variable DIE. -bool DwarfDebug::addConstantFPValue(DIE *Die, const MachineOperand &MO) { - assert (MO.isFPImm() && "Invalid machine operand!"); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - APFloat FPImm = MO.getFPImm()->getValueAPF(); - - // Get the raw data form of the floating point. - const APInt FltVal = FPImm.bitcastToAPInt(); - const char *FltPtr = (const char*)FltVal.getRawData(); - - int NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. - bool LittleEndian = Asm->getTargetData().isLittleEndian(); - int Incr = (LittleEndian ? 1 : -1); - int Start = (LittleEndian ? 0 : NumBytes - 1); - int Stop = (LittleEndian ? NumBytes : -1); - - // Output the constant to DWARF one byte at a time. - for (; Start != Stop; Start += Incr) - addUInt(Block, 0, dwarf::DW_FORM_data1, - (unsigned char)0xFF & FltPtr[Start]); - - addBlock(Die, dwarf::DW_AT_const_value, 0, Block); - return true; -} - -/// addConstantValue - Add constant value entry in variable DIE. -bool DwarfDebug::addConstantValue(DIE *Die, ConstantInt *CI, - bool Unsigned) { - if (CI->getBitWidth() <= 64) { - if (Unsigned) - addUInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, - CI->getZExtValue()); - else - addSInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, - CI->getSExtValue()); - return true; - } - - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - - // Get the raw data form of the large APInt. - const APInt Val = CI->getValue(); - const char *Ptr = (const char*)Val.getRawData(); - - int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte. - bool LittleEndian = Asm->getTargetData().isLittleEndian(); - int Incr = (LittleEndian ? 1 : -1); - int Start = (LittleEndian ? 0 : NumBytes - 1); - int Stop = (LittleEndian ? NumBytes : -1); - - // Output the constant to DWARF one byte at a time. - for (; Start != Stop; Start += Incr) - addUInt(Block, 0, dwarf::DW_FORM_data1, - (unsigned char)0xFF & Ptr[Start]); - - addBlock(Die, dwarf::DW_AT_const_value, 0, Block); - return true; -} - -/// addToContextOwner - Add Die into the list of its context owner's children. -void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) { - if (Context.isType()) { - DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context)); - ContextDIE->addChild(Die); - } else if (Context.isNameSpace()) { - DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context)); - ContextDIE->addChild(Die); - } else if (Context.isSubprogram()) { - DIE *ContextDIE = createSubprogramDIE(DISubprogram(Context)); - ContextDIE->addChild(Die); - } else if (DIE *ContextDIE = getCompileUnit(Context)->getDIE(Context)) - ContextDIE->addChild(Die); - else - getCompileUnit(Context)->addDie(Die); -} - -/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the -/// given DIType. -DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) { - CompileUnit *TypeCU = getCompileUnit(Ty); - DIE *TyDIE = TypeCU->getDIE(Ty); - if (TyDIE) - return TyDIE; - - // Create new type. - TyDIE = new DIE(dwarf::DW_TAG_base_type); - TypeCU->insertDIE(Ty, TyDIE); - if (Ty.isBasicType()) - constructTypeDIE(*TyDIE, DIBasicType(Ty)); - else if (Ty.isCompositeType()) - constructTypeDIE(*TyDIE, DICompositeType(Ty)); - else { - assert(Ty.isDerivedType() && "Unknown kind of DIType"); - constructTypeDIE(*TyDIE, DIDerivedType(Ty)); - } - - addToContextOwner(TyDIE, Ty.getContext()); - return TyDIE; -} - -/// addType - Add a new type attribute to the specified entity. -void DwarfDebug::addType(DIE *Entity, DIType Ty) { - if (!Ty.Verify()) - return; - - // Check for pre-existence. - CompileUnit *TypeCU = getCompileUnit(Ty); - DIEEntry *Entry = TypeCU->getDIEEntry(Ty); - // If it exists then use the existing value. - if (Entry) { - Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); - return; - } - - // Construct type. - DIE *Buffer = getOrCreateTypeDIE(Ty); - - // Set up proxy. - Entry = createDIEEntry(Buffer); - TypeCU->insertDIEEntry(Ty, Entry); - - Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); -} - -/// constructTypeDIE - Construct basic type die from DIBasicType. -void DwarfDebug::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { - // Get core information. - StringRef Name = BTy.getName(); - Buffer.setTag(dwarf::DW_TAG_base_type); - addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, - BTy.getEncoding()); - - // Add name if not anonymous or intermediate type. - if (!Name.empty()) - addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - uint64_t Size = BTy.getSizeInBits() >> 3; - addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); -} - -/// constructTypeDIE - Construct derived type die from DIDerivedType. -void DwarfDebug::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { - // Get core information. - StringRef Name = DTy.getName(); - uint64_t Size = DTy.getSizeInBits() >> 3; - unsigned Tag = DTy.getTag(); - - // FIXME - Workaround for templates. - if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type; - - Buffer.setTag(Tag); - - // Map to main type, void will not have a type. - DIType FromTy = DTy.getTypeDerivedFrom(); - addType(&Buffer, FromTy); - - // Add name if not anonymous or intermediate type. - if (!Name.empty()) - addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - - // Add size if non-zero (derived types might be zero-sized.) - if (Size) - addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); - - // Add source line info if available and TyDesc is not a forward declaration. - if (!DTy.isForwardDecl()) - addSourceLine(&Buffer, DTy); -} - -/// constructTypeDIE - Construct type DIE from DICompositeType. -void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { - // Get core information. - StringRef Name = CTy.getName(); - - uint64_t Size = CTy.getSizeInBits() >> 3; - unsigned Tag = CTy.getTag(); - Buffer.setTag(Tag); - - switch (Tag) { - case dwarf::DW_TAG_vector_type: - case dwarf::DW_TAG_array_type: - constructArrayTypeDIE(Buffer, &CTy); - break; - case dwarf::DW_TAG_enumeration_type: { - DIArray Elements = CTy.getTypeArray(); - - // Add enumerators to enumeration type. - for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { - DIE *ElemDie = NULL; - DIDescriptor Enum(Elements.getElement(i)); - if (Enum.isEnumerator()) { - ElemDie = constructEnumTypeDIE(DIEnumerator(Enum)); - Buffer.addChild(ElemDie); - } - } - } - break; - case dwarf::DW_TAG_subroutine_type: { - // Add return type. - DIArray Elements = CTy.getTypeArray(); - DIDescriptor RTy = Elements.getElement(0); - addType(&Buffer, DIType(RTy)); - - bool isPrototyped = true; - // Add arguments. - for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Ty = Elements.getElement(i); - if (Ty.isUnspecifiedParameter()) { - DIE *Arg = new DIE(dwarf::DW_TAG_unspecified_parameters); - Buffer.addChild(Arg); - isPrototyped = false; - } else { - DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - addType(Arg, DIType(Ty)); - Buffer.addChild(Arg); - } - } - // Add prototype flag. - if (isPrototyped) - addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); - } - break; - case dwarf::DW_TAG_structure_type: - case dwarf::DW_TAG_union_type: - case dwarf::DW_TAG_class_type: { - // Add elements to structure type. - DIArray Elements = CTy.getTypeArray(); - - // A forward struct declared type may not have elements available. - unsigned N = Elements.getNumElements(); - if (N == 0) - break; - - // Add elements to structure type. - for (unsigned i = 0; i < N; ++i) { - DIDescriptor Element = Elements.getElement(i); - DIE *ElemDie = NULL; - if (Element.isSubprogram()) { - DISubprogram SP(Element); - ElemDie = createSubprogramDIE(DISubprogram(Element)); - if (SP.isProtected()) - addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_protected); - else if (SP.isPrivate()) - addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_private); - else - addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_public); - if (SP.isExplicit()) - addUInt(ElemDie, dwarf::DW_AT_explicit, dwarf::DW_FORM_flag, 1); - } - else if (Element.isVariable()) { - DIVariable DV(Element); - ElemDie = new DIE(dwarf::DW_TAG_variable); - addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, - DV.getName()); - addType(ElemDie, DV.getType()); - addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); - addSourceLine(ElemDie, DV); - } else if (Element.isDerivedType()) - ElemDie = createMemberDIE(DIDerivedType(Element)); - else - continue; - Buffer.addChild(ElemDie); - } - - if (CTy.isAppleBlockExtension()) - addUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1); - - unsigned RLang = CTy.getRunTimeLang(); - if (RLang) - addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, - dwarf::DW_FORM_data1, RLang); - - DICompositeType ContainingType = CTy.getContainingType(); - if (DIDescriptor(ContainingType).isCompositeType()) - addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, - getOrCreateTypeDIE(DIType(ContainingType))); - else { - DIDescriptor Context = CTy.getContext(); - addToContextOwner(&Buffer, Context); - } - - if (Tag == dwarf::DW_TAG_class_type) { - DIArray TParams = CTy.getTemplateParams(); - unsigned N = TParams.getNumElements(); - // Add template parameters. - for (unsigned i = 0; i < N; ++i) { - DIDescriptor Element = TParams.getElement(i); - if (Element.isTemplateTypeParameter()) - Buffer.addChild(getOrCreateTemplateTypeParameterDIE( - DITemplateTypeParameter(Element))); - else if (Element.isTemplateValueParameter()) - Buffer.addChild(getOrCreateTemplateValueParameterDIE( - DITemplateValueParameter(Element))); - } - } - break; - } - default: - break; - } - - // Add name if not anonymous or intermediate type. - if (!Name.empty()) - addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - - if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type - || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) - { - // Add size if non-zero (derived types might be zero-sized.) - if (Size) - addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); - else { - // Add zero size if it is not a forward declaration. - if (CTy.isForwardDecl()) - addUInt(&Buffer, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - else - addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, 0); - } - - // Add source line info if available. - if (!CTy.isForwardDecl()) - addSourceLine(&Buffer, CTy); - } -} - -/// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE -/// for the given DITemplateTypeParameter. -DIE * -DwarfDebug::getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP) { - CompileUnit *TypeCU = getCompileUnit(TP); - DIE *ParamDIE = TypeCU->getDIE(TP); - if (ParamDIE) - return ParamDIE; - - ParamDIE = new DIE(dwarf::DW_TAG_template_type_parameter); - addType(ParamDIE, TP.getType()); - addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TP.getName()); - return ParamDIE; -} - -/// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE -/// for the given DITemplateValueParameter. -DIE * -DwarfDebug::getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TPV) { - CompileUnit *TVCU = getCompileUnit(TPV); - DIE *ParamDIE = TVCU->getDIE(TPV); - if (ParamDIE) - return ParamDIE; - - ParamDIE = new DIE(dwarf::DW_TAG_template_value_parameter); - addType(ParamDIE, TPV.getType()); - addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TPV.getName()); - addUInt(ParamDIE, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, - TPV.getValue()); - return ParamDIE; -} - -/// constructSubrangeDIE - Construct subrange DIE from DISubrange. -void DwarfDebug::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){ - int64_t L = SR.getLo(); - int64_t H = SR.getHi(); - DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); - - addDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); - if (L) - addSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); - addSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); - - Buffer.addChild(DW_Subrange); -} - -/// constructArrayTypeDIE - Construct array type DIE from DICompositeType. -void DwarfDebug::constructArrayTypeDIE(DIE &Buffer, - DICompositeType *CTy) { - Buffer.setTag(dwarf::DW_TAG_array_type); - if (CTy->getTag() == dwarf::DW_TAG_vector_type) - addUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1); - - // Emit derived type. - addType(&Buffer, CTy->getTypeDerivedFrom()); - DIArray Elements = CTy->getTypeArray(); - - // Get an anonymous type for index type. - CompileUnit *TheCU = getCompileUnit(*CTy); - DIE *IdxTy = TheCU->getIndexTyDie(); - if (!IdxTy) { - // Construct an anonymous type for index type. - IdxTy = new DIE(dwarf::DW_TAG_base_type); - addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t)); - addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, - dwarf::DW_ATE_signed); - TheCU->addDie(IdxTy); - TheCU->setIndexTyDie(IdxTy); - } - - // Add subranges to array type. - for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Element = Elements.getElement(i); - if (Element.getTag() == dwarf::DW_TAG_subrange_type) - constructSubrangeDIE(Buffer, DISubrange(Element), IdxTy); - } -} - -/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. -DIE *DwarfDebug::constructEnumTypeDIE(DIEnumerator ETy) { - DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator); - StringRef Name = ETy.getName(); - addString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - int64_t Value = ETy.getEnumValue(); - addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); - return Enumerator; -} - /// getRealLinkageName - If special LLVM prefix that is used to inform the asm /// printer to not emit usual symbol prefix before the symbol name is used then /// return linkage name after skipping this special LLVM prefix. @@ -1295,84 +314,6 @@ static StringRef getRealLinkageName(StringRef LinkageName) { return LinkageName; } -/// createMemberDIE - Create new member DIE. -DIE *DwarfDebug::createMemberDIE(DIDerivedType DT) { - DIE *MemberDie = new DIE(DT.getTag()); - StringRef Name = DT.getName(); - if (!Name.empty()) - addString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - - addType(MemberDie, DT.getTypeDerivedFrom()); - - addSourceLine(MemberDie, DT); - - DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); - addUInt(MemLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - - uint64_t Size = DT.getSizeInBits(); - uint64_t FieldSize = DT.getOriginalTypeSize(); - - if (Size != FieldSize) { - // Handle bitfield. - addUInt(MemberDie, dwarf::DW_AT_byte_size, 0, DT.getOriginalTypeSize()>>3); - addUInt(MemberDie, dwarf::DW_AT_bit_size, 0, DT.getSizeInBits()); - - uint64_t Offset = DT.getOffsetInBits(); - uint64_t AlignMask = ~(DT.getAlignInBits() - 1); - uint64_t HiMark = (Offset + FieldSize) & AlignMask; - uint64_t FieldOffset = (HiMark - FieldSize); - Offset -= FieldOffset; - - // Maybe we need to work from the other end. - if (Asm->getTargetData().isLittleEndian()) - Offset = FieldSize - (Offset + Size); - addUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset); - - // Here WD_AT_data_member_location points to the anonymous - // field that includes this bit field. - addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, FieldOffset >> 3); - - } else - // This is not a bitfield. - addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3); - - if (DT.getTag() == dwarf::DW_TAG_inheritance - && DT.isVirtual()) { - - // For C++, virtual base classes are not at fixed offset. Use following - // expression to extract appropriate offset from vtable. - // BaseAddr = ObAddr + *((*ObAddr) - Offset) - - DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock(); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits()); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); - - addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, - VBaseLocationDie); - } else - addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); - - if (DT.isProtected()) - addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_protected); - else if (DT.isPrivate()) - addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_private); - // Otherwise C++ member and base classes are considered public. - else if (DT.getCompileUnit().getLanguage() == dwarf::DW_LANG_C_plus_plus) - addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_public); - if (DT.isVirtual()) - addUInt(MemberDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, - dwarf::DW_VIRTUALITY_virtual); - return MemberDie; -} - /// createSubprogramDIE - Create new DIE using SP. DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) { CompileUnit *SPCU = getCompileUnit(SP); @@ -1381,19 +322,35 @@ DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) { return SPDie; SPDie = new DIE(dwarf::DW_TAG_subprogram); + + // DW_TAG_inlined_subroutine may refer to this DIE. + SPCU->insertDIE(SP, SPDie); + + // Add to context owner. + SPCU->addToContextOwner(SPDie, SP.getContext()); + + // Add function template parameters. + SPCU->addTemplateParams(*SPDie, SP.getTemplateParams()); + + // If this DIE is going to refer declaration info using AT_specification + // then there is no need to add other attributes. + if (SP.getFunctionDeclaration().isSubprogram()) + return SPDie; + // Constructors and operators for anonymous aggregates do not have names. if (!SP.getName().empty()) - addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName()); + SPCU->addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + SP.getName()); StringRef LinkageName = SP.getLinkageName(); if (!LinkageName.empty()) - addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, - getRealLinkageName(LinkageName)); + SPCU->addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, + getRealLinkageName(LinkageName)); - addSourceLine(SPDie, SP); + SPCU->addSourceLine(SPDie, SP); if (SP.isPrototyped()) - addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); // Add Return Type. DICompositeType SPTy = SP.getType(); @@ -1401,24 +358,24 @@ DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) { unsigned SPTag = SPTy.getTag(); if (Args.getNumElements() == 0 || SPTag != dwarf::DW_TAG_subroutine_type) - addType(SPDie, SPTy); + SPCU->addType(SPDie, SPTy); else - addType(SPDie, DIType(Args.getElement(0))); + SPCU->addType(SPDie, DIType(Args.getElement(0))); unsigned VK = SP.getVirtuality(); if (VK) { - addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - addUInt(Block, 0, dwarf::DW_FORM_udata, SP.getVirtualIndex()); - addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block); + SPCU->addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK); + DIEBlock *Block = SPCU->getDIEBlock(); + SPCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + SPCU->addUInt(Block, 0, dwarf::DW_FORM_udata, SP.getVirtualIndex()); + SPCU->addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block); ContainingTypeMap.insert(std::make_pair(SPDie, SP.getContainingType())); } if (!SP.isDefinition()) { - addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - + SPCU->addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + // Add arguments. Do not add arguments for subprogram definition. They will // be handled while processing variables. DICompositeType SPTy = SP.getType(); @@ -1429,32 +386,26 @@ DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) { for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); DIType ATy = DIType(DIType(Args.getElement(i))); - addType(Arg, ATy); + SPCU->addType(Arg, ATy); if (ATy.isArtificial()) - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); SPDie->addChild(Arg); } } if (SP.isArtificial()) - addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); if (!SP.isLocalToUnit()) - addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); if (SP.isOptimized()) - addUInt(SPDie, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(SPDie, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); if (unsigned isa = Asm->getISAEncoding()) { - addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa); + SPCU->addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa); } - // DW_TAG_inlined_subroutine may refer to this DIE. - SPCU->insertDIE(SP, SPDie); - - // Add to context owner. - addToContextOwner(SPDie, SP.getContext()); - return SPDie; } @@ -1509,51 +460,57 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) { assert(SPDie && "Unable to find subprogram DIE!"); DISubprogram SP(SPNode); - // There is not any need to generate specification DIE for a function - // defined at compile unit level. If a function is defined inside another - // function then gdb prefers the definition at top level and but does not - // expect specification DIE in parent function. So avoid creating - // specification DIE for a function defined inside a function. - if (SP.isDefinition() && !SP.getContext().isCompileUnit() && - !SP.getContext().isFile() && - !isSubprogramContext(SP.getContext())) { - addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - - // Add arguments. - DICompositeType SPTy = SP.getType(); - DIArray Args = SPTy.getTypeArray(); - unsigned SPTag = SPTy.getTag(); - if (SPTag == dwarf::DW_TAG_subroutine_type) - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - DIType ATy = DIType(DIType(Args.getElement(i))); - addType(Arg, ATy); - if (ATy.isArtificial()) - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); - SPDie->addChild(Arg); - } - DIE *SPDeclDie = SPDie; - SPDie = new DIE(dwarf::DW_TAG_subprogram); - addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, - SPDeclDie); - SPCU->addDie(SPDie); + DISubprogram SPDecl = SP.getFunctionDeclaration(); + if (SPDecl.isSubprogram()) + // Refer function declaration directly. + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + createSubprogramDIE(SPDecl)); + else { + // There is not any need to generate specification DIE for a function + // defined at compile unit level. If a function is defined inside another + // function then gdb prefers the definition at top level and but does not + // expect specification DIE in parent function. So avoid creating + // specification DIE for a function defined inside a function. + if (SP.isDefinition() && !SP.getContext().isCompileUnit() && + !SP.getContext().isFile() && + !isSubprogramContext(SP.getContext())) { + SPCU-> addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + + // Add arguments. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + if (SPTag == dwarf::DW_TAG_subroutine_type) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + DIType ATy = DIType(DIType(Args.getElement(i))); + SPCU->addType(Arg, ATy); + if (ATy.isArtificial()) + SPCU->addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPDie->addChild(Arg); + } + DIE *SPDeclDie = SPDie; + SPDie = new DIE(dwarf::DW_TAG_subprogram); + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + SPDeclDie); + SPCU->addDie(SPDie); + } } - // Pick up abstract subprogram DIE. if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) { SPDie = new DIE(dwarf::DW_TAG_subprogram); - addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, - dwarf::DW_FORM_ref4, AbsSPDIE); + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, AbsSPDIE); SPCU->addDie(SPDie); } - addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber())); - addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - Asm->GetTempSymbol("func_end", Asm->getFunctionNumber())); + SPCU->addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber())); + SPCU->addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_end", Asm->getFunctionNumber())); const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); - addAddress(SPDie, dwarf::DW_AT_frame_base, Location); + SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location); return SPDie; } @@ -1570,13 +527,14 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { if (Ranges.empty()) return 0; + CompileUnit *TheCU = getCompileUnit(Scope->getScopeNode()); SmallVector::const_iterator RI = Ranges.begin(); if (Ranges.size() > 1) { // .debug_range section has not been laid out yet. Emit offset in // .debug_range as a uint, size 4, for now. emitDIE will handle // DW_AT_ranges appropriately. - addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, - DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize()); + TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, + DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize()); for (SmallVector::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); @@ -1595,8 +553,8 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); assert(End->isDefined() && "Invalid end label for an inlined scope!"); - addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start); - addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End); + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start); + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End); return ScopeDIE; } @@ -1636,11 +594,11 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { CompileUnit *TheCU = getCompileUnit(InlinedSP); DIE *OriginDIE = TheCU->getDIE(InlinedSP); assert(OriginDIE && "Unable to find Origin DIE!"); - addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, - dwarf::DW_FORM_ref4, OriginDIE); + TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, OriginDIE); - addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel); - addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel); + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel); + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel); InlinedSubprogramDIEs.insert(OriginDIE); @@ -1656,8 +614,8 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { I->second.push_back(std::make_pair(StartLabel, ScopeDIE)); DILocation DL(Scope->getInlinedAt()); - addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, TheCU->getID()); - addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber()); + TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, TheCU->getID()); + TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber()); return ScopeDIE; } @@ -1686,7 +644,7 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { // Define variable debug information entry. DIE *VariableDie = new DIE(Tag); - + CompileUnit *VariableCU = getCompileUnit(DV->getVariable()); DIE *AbsDIE = NULL; DenseMap::iterator V2AVI = VarToAbstractVarMap.find(DV); @@ -1694,20 +652,23 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { AbsDIE = V2AVI->second->getDIE(); if (AbsDIE) - addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, - dwarf::DW_FORM_ref4, AbsDIE); + VariableCU->addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, AbsDIE); else { - addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - addSourceLine(VariableDie, DV->getVariable()); + VariableCU->addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + Name); + VariableCU->addSourceLine(VariableDie, DV->getVariable()); // Add variable type. - addType(VariableDie, DV->getType()); + VariableCU->addType(VariableDie, DV->getType()); } if (Tag == dwarf::DW_TAG_formal_parameter && DV->getType().isArtificial()) - addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + VariableCU->addUInt(VariableDie, dwarf::DW_AT_artificial, + dwarf::DW_FORM_flag, 1); else if (DIVariable(DV->getVariable()).isArtificial()) - addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + VariableCU->addUInt(VariableDie, dwarf::DW_AT_artificial, + dwarf::DW_FORM_flag, 1); if (Scope->isAbstractScope()) { DV->setDIE(VariableDie); @@ -1718,7 +679,7 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { unsigned Offset = DV->getDotDebugLocOffset(); if (Offset != ~0U) { - addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4, + VariableCU->addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4, Asm->GetTempSymbol("debug_loc", Offset)); DV->setDIE(VariableDie); UseDotDebugLocEntry.insert(VariableDie); @@ -1738,22 +699,30 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); if (DVInsn->getOperand(1).isImm() && TRI->getFrameRegister(*Asm->MF) == RegOp.getReg()) { - addVariableAddress(DV, VariableDie, DVInsn->getOperand(1).getImm()); - updated = true; - } else - updated = addRegisterAddress(VariableDie, RegOp); - } - else if (DVInsn->getOperand(0).isImm()) - updated = addConstantValue(VariableDie, DVInsn->getOperand(0)); - else if (DVInsn->getOperand(0).isFPImm()) - updated = - addConstantFPValue(VariableDie, DVInsn->getOperand(0)); - } else { - MachineLocation Location = Asm->getDebugValueLocation(DVInsn); - if (Location.getReg()) { - addAddress(VariableDie, dwarf::DW_AT_location, Location); + unsigned FrameReg = 0; + const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); + int Offset = + TFI->getFrameIndexReference(*Asm->MF, + DVInsn->getOperand(1).getImm(), + FrameReg); + MachineLocation Location(FrameReg, Offset); + VariableCU->addVariableAddress(DV, VariableDie, Location); + + } else if (RegOp.getReg()) + VariableCU->addVariableAddress(DV, VariableDie, + MachineLocation(RegOp.getReg())); updated = true; } + else if (DVInsn->getOperand(0).isImm()) + updated = VariableCU->addConstantValue(VariableDie, + DVInsn->getOperand(0)); + else if (DVInsn->getOperand(0).isFPImm()) + updated = + VariableCU->addConstantFPValue(VariableDie, DVInsn->getOperand(0)); + } else { + VariableCU->addVariableAddress(DV, VariableDie, + Asm->getDebugValueLocation(DVInsn)); + updated = true; } if (!updated) { // If variableDie is not updated then DBG_VALUE instruction does not @@ -1767,15 +736,21 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { // .. else use frame index, if available. int FI = 0; - if (findVariableFrameIndex(DV, &FI)) - addVariableAddress(DV, VariableDie, FI); - + if (findVariableFrameIndex(DV, &FI)) { + unsigned FrameReg = 0; + const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); + int Offset = + TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); + MachineLocation Location(FrameReg, Offset); + VariableCU->addVariableAddress(DV, VariableDie, Location); + } + DV->setDIE(VariableDie); return VariableDie; } -void DwarfDebug::addPubTypes(DISubprogram SP) { +void CompileUnit::addPubTypes(DISubprogram SP) { DICompositeType SPTy = SP.getType(); unsigned SPTag = SPTy.getTag(); if (SPTag != dwarf::DW_TAG_subroutine_type) @@ -1789,9 +764,8 @@ void DwarfDebug::addPubTypes(DISubprogram SP) { DICompositeType CATy = getDICompositeType(ATy); if (DIDescriptor(CATy).Verify() && !CATy.getName().empty() && !CATy.isForwardDecl()) { - CompileUnit *TheCU = getCompileUnit(CATy); - if (DIEEntry *Entry = TheCU->getDIEEntry(CATy)) - TheCU->addGlobalType(CATy.getName(), Entry->getEntry()); + if (DIEEntry *Entry = getDIEEntry(CATy)) + addGlobalType(CATy.getName(), Entry->getEntry()); } } } @@ -1802,6 +776,14 @@ DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) { return NULL; SmallVector Children; + + // Collect arguments for current function. + if (Scope == CurrentFnDbgScope) + for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i) + if (DbgVariable *ArgDV = CurrentFnArguments[i]) + if (DIE *Arg = constructVariableDIE(ArgDV, Scope)) + Children.push_back(Arg); + // Collect lexical scope childrens first. const SmallVector &Variables = Scope->getDbgVariables(); for (unsigned i = 0, N = Variables.size(); i < N; ++i) @@ -1841,7 +823,7 @@ DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) { ScopeDIE->addChild(*I); if (DS.isSubprogram()) - addPubTypes(DISubprogram(DS)); + getCompileUnit(DS)->addPubTypes(DISubprogram(DS)); return ScopeDIE; } @@ -1851,10 +833,21 @@ DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) { /// in the SourceIds map. This can update DirectoryNames and SourceFileNames /// maps as well. -unsigned DwarfDebug::GetOrCreateSourceID(StringRef FileName){ +unsigned DwarfDebug::GetOrCreateSourceID(StringRef FileName, + StringRef DirName) { // If FE did not provide a file name, then assume stdin. if (FileName.empty()) - return GetOrCreateSourceID(""); + return GetOrCreateSourceID("", StringRef()); + + // MCStream expects full path name as filename. + if (!DirName.empty() && !FileName.startswith("/")) { + std::string FullPathName(DirName.data()); + if (!DirName.endswith("/")) + FullPathName += "/"; + FullPathName += FileName.data(); + // Here FullPathName will be copied into StringMap by GetOrCreateSourceID. + return GetOrCreateSourceID(StringRef(FullPathName), StringRef()); + } StringMapEntry &Entry = SourceIdMap.GetOrCreateValue(FileName); if (Entry.getValue()) @@ -1864,19 +857,18 @@ unsigned DwarfDebug::GetOrCreateSourceID(StringRef FileName){ Entry.setValue(SrcId); // Print out a .file directive to specify files for .loc directives. - Asm->OutStreamer.EmitDwarfFileDirective(SrcId, FileName); + Asm->OutStreamer.EmitDwarfFileDirective(SrcId, Entry.getKey()); return SrcId; } /// getOrCreateNameSpace - Create a DIE for DINameSpace. -DIE *DwarfDebug::getOrCreateNameSpace(DINameSpace NS) { - CompileUnit *TheCU = getCompileUnit(NS); - DIE *NDie = TheCU->getDIE(NS); +DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) { + DIE *NDie = getDIE(NS); if (NDie) return NDie; NDie = new DIE(dwarf::DW_TAG_namespace); - TheCU->insertDIE(NS, NDie); + insertDIE(NS, NDie); if (!NS.getName().empty()) addString(NDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, NS.getName()); addSourceLine(NDie, NS); @@ -1890,40 +882,40 @@ void DwarfDebug::constructCompileUnit(const MDNode *N) { DICompileUnit DIUnit(N); StringRef FN = DIUnit.getFilename(); StringRef Dir = DIUnit.getDirectory(); - unsigned ID = GetOrCreateSourceID(FN); + unsigned ID = GetOrCreateSourceID(FN, Dir); DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string, - DIUnit.getProducer()); - addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - DIUnit.getLanguage()); - addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); + CompileUnit *NewCU = new CompileUnit(ID, Die, Asm, this); + NewCU->addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string, + DIUnit.getProducer()); + NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + DIUnit.getLanguage()); + NewCU->addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); // Use DW_AT_entry_pc instead of DW_AT_low_pc/DW_AT_high_pc pair. This // simplifies debug range entries. - addUInt(Die, dwarf::DW_AT_entry_pc, dwarf::DW_FORM_addr, 0); + NewCU->addUInt(Die, dwarf::DW_AT_entry_pc, dwarf::DW_FORM_addr, 0); // DW_AT_stmt_list is a offset of line number information for this // compile unit in debug_line section. if (Asm->MAI->doesDwarfUsesAbsoluteLabelForStmtList()) - addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_addr, - Asm->GetTempSymbol("section_line")); + NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("section_line")); else - addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); + NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); if (!Dir.empty()) - addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir); + NewCU->addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir); if (DIUnit.isOptimized()) - addUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); + NewCU->addUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); StringRef Flags = DIUnit.getFlags(); if (!Flags.empty()) - addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags); - + NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags); + unsigned RVer = DIUnit.getRunTimeVersion(); if (RVer) - addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, + NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, dwarf::DW_FORM_data1, RVer); - CompileUnit *NewCU = new CompileUnit(ID, Die); if (!FirstCU) FirstCU = NewCU; CUMap.insert(std::make_pair(N, NewCU)); @@ -2019,14 +1011,15 @@ void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) { bool isGlobalVariable = GV.getGlobal() != NULL; // Add name. - addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, - GV.getDisplayName()); + TheCU->addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, + GV.getDisplayName()); StringRef LinkageName = GV.getLinkageName(); if (!LinkageName.empty() && isGlobalVariable) - addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, - getRealLinkageName(LinkageName)); + TheCU->addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name, + dwarf::DW_FORM_string, + getRealLinkageName(LinkageName)); // Add type. - addType(VariableDIE, GTy); + TheCU->addType(VariableDIE, GTy); if (GTy.isCompositeType() && !GTy.getName().empty() && !GTy.isForwardDecl()) { DIEEntry *Entry = TheCU->getDIEEntry(GTy); @@ -2035,22 +1028,22 @@ void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) { } // Add scoping info. if (!GV.isLocalToUnit()) { - addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + TheCU->addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); // Expose as global. TheCU->addGlobal(GV.getName(), VariableDIE); } // Add line number info. - addSourceLine(VariableDIE, GV); + TheCU->addSourceLine(VariableDIE, GV); // Add to map. TheCU->insertDIE(N, VariableDIE); // Add to context owner. DIDescriptor GVContext = GV.getContext(); - addToContextOwner(VariableDIE, GVContext); + TheCU->addToContextOwner(VariableDIE, GVContext); // Add location. if (isGlobalVariable) { DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - addLabel(Block, 0, dwarf::DW_FORM_udata, + TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata, Asm->Mang->getSymbol(GV.getGlobal())); // Do not create specification DIE if context is either compile unit // or a subprogram. @@ -2058,28 +1051,28 @@ void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) { !GVContext.isFile() && !isSubprogramContext(GVContext)) { // Create specification DIE. DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable); - addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, + TheCU->addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, VariableDIE); - addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); - addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + TheCU->addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); + TheCU->addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); TheCU->addDie(VariableSpecDIE); } else { - addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); + TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); } } else if (ConstantInt *CI = dyn_cast_or_null(GV.getConstant())) - addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy)); + TheCU->addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy)); else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) { // GV is a merged global. DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - addLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->Mang->getSymbol(cast(CE->getOperand(0)))); + TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getSymbol(cast(CE->getOperand(0)))); ConstantInt *CII = cast(CE->getOperand(2)); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - addUInt(Block, 0, dwarf::DW_FORM_udata, CII->getZExtValue()); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); - addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); + TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + TheCU->addUInt(Block, 0, dwarf::DW_FORM_udata, CII->getZExtValue()); + TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); } return; @@ -2105,7 +1098,7 @@ void DwarfDebug::constructSubprogramDIE(const MDNode *N) { TheCU->insertDIE(N, SubprogramDie); // Add to context owner. - addToContextOwner(SubprogramDie, SP.getContext()); + TheCU->addToContextOwner(SubprogramDie, SP.getContext()); // Expose as global. TheCU->addGlobal(SP.getName(), SubprogramDie); @@ -2160,12 +1153,16 @@ void DwarfDebug::beginModule(Module *M) { //getOrCreateTypeDIE if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum")) - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) - getOrCreateTypeDIE(DIType(NMD->getOperand(i))); + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIType Ty(NMD->getOperand(i)); + getCompileUnit(Ty)->getOrCreateTypeDIE(Ty); + } if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty")) - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) - getOrCreateTypeDIE(DIType(NMD->getOperand(i))); + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIType Ty(NMD->getOperand(i)); + getCompileUnit(Ty)->getOrCreateTypeDIE(Ty); + } // Prime section data. SectionMap.insert(Asm->getObjFileLowering().getTextSection()); @@ -2216,7 +1213,7 @@ void DwarfDebug::endModule() { for (SmallPtrSet::iterator AI = InlinedSubprogramDIEs.begin(), AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) { DIE *ISP = *AI; - addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); + FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); } for (DenseMap::iterator CI = ContainingTypeMap.begin(), @@ -2226,7 +1223,8 @@ void DwarfDebug::endModule() { if (!N) continue; DIE *NDie = getCompileUnit(N)->getDIE(N); if (!NDie) continue; - addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie); + getCompileUnit(N)->addDIEEntry(SPDie, dwarf::DW_AT_containing_type, + dwarf::DW_FORM_ref4, NDie); } // Standard sections final addresses. @@ -2309,6 +1307,30 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var, return AbsDbgVariable; } +/// addCurrentFnArgument - If Var is an current function argument that add +/// it in CurrentFnArguments list. +bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, + DbgVariable *Var, DbgScope *Scope) { + if (Scope != CurrentFnDbgScope) + return false; + DIVariable DV = Var->getVariable(); + if (DV.getTag() != dwarf::DW_TAG_arg_variable) + return false; + unsigned ArgNo = DV.getArgNumber(); + if (ArgNo == 0) + return false; + + size_t Size = CurrentFnArguments.size(); + if (Size == 0) + CurrentFnArguments.resize(MF->getFunction()->arg_size()); + // llvm::Function argument size is not good indicator of how many + // arguments does the function have at source level. + if (ArgNo > Size) + CurrentFnArguments.resize(ArgNo * 2); + CurrentFnArguments[ArgNo - 1] = Var; + return true; +} + /// collectVariableInfoFromMMITable - Collect variable information from /// side table maintained by MMI. void @@ -2337,7 +1359,8 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF, DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second); DbgVariable *RegVar = new DbgVariable(DV); recordVariableFrameIndex(RegVar, VP.first); - Scope->addVariable(RegVar); + if (!addCurrentFnArgument(MF, RegVar, Scope)) + Scope->addVariable(RegVar); if (AbsDbgVariable) { recordVariableFrameIndex(AbsDbgVariable, VP.first); VarToAbstractVarMap[RegVar] = AbsDbgVariable; @@ -2349,9 +1372,9 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF, /// DBG_VALUE instruction, is in a defined reg. static bool isDbgValueInDefinedReg(const MachineInstr *MI) { assert (MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!"); - if (MI->getOperand(0).isReg() && MI->getOperand(0).getReg()) - return true; - return false; + return MI->getNumOperands() == 3 && + MI->getOperand(0).isReg() && MI->getOperand(0).getReg() && + MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0; } /// collectVariableInfo - Populate DbgScope entries with variables' info. @@ -2362,41 +1385,21 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, /// collection info from MMI table. collectVariableInfoFromMMITable(MF, Processed); - SmallVector DbgValues; - // Collect variable information from DBG_VALUE machine instructions; - for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); - I != E; ++I) - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - const MachineInstr *MInsn = II; - if (!MInsn->isDebugValue()) - continue; - DbgValues.push_back(MInsn); - } - - // This is a collection of DBV_VALUE instructions describing same variable. - SmallVector MultipleValues; - for(SmallVector::iterator I = DbgValues.begin(), - E = DbgValues.end(); I != E; ++I) { - const MachineInstr *MInsn = *I; - MultipleValues.clear(); - if (isDbgValueInDefinedReg(MInsn)) - MultipleValues.push_back(MInsn); - DIVariable DV(MInsn->getOperand(MInsn->getNumOperands() - 1).getMetadata()); - if (Processed.count(DV) != 0) + for (SmallVectorImpl::const_iterator + UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI != UVE; + ++UVI) { + const MDNode *Var = *UVI; + if (Processed.count(Var)) continue; - const MachineInstr *PrevMI = MInsn; - for (SmallVector::iterator MI = I+1, - ME = DbgValues.end(); MI != ME; ++MI) { - const MDNode *Var = - (*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata(); - if (Var == DV && - !PrevMI->isIdenticalTo(*MI)) - MultipleValues.push_back(*MI); - PrevMI = *MI; - } + // History contains relevant DBG_VALUE instructions for Var and instructions + // clobbering it. + SmallVectorImpl &History = DbgValues[Var]; + if (History.empty()) + continue; + const MachineInstr *MInsn = History.front(); + DIVariable DV(Var); DbgScope *Scope = NULL; if (DV.getTag() == dwarf::DW_TAG_arg_variable && DISubprogram(DV.getContext()).describes(MF->getFunction())) @@ -2408,32 +1411,29 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, continue; Processed.insert(DV); + assert(MInsn->isDebugValue() && "History must begin with debug value"); DbgVariable *RegVar = new DbgVariable(DV); - Scope->addVariable(RegVar); + if (!addCurrentFnArgument(MF, RegVar, Scope)) + Scope->addVariable(RegVar); if (DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc())) { DbgVariableToDbgInstMap[AbsVar] = MInsn; VarToAbstractVarMap[RegVar] = AbsVar; } - if (MultipleValues.size() <= 1) { + + // Simple ranges that are fully coalesced. + if (History.size() <= 1 || (History.size() == 2 && + MInsn->isIdenticalTo(History.back()))) { DbgVariableToDbgInstMap[RegVar] = MInsn; continue; } // handle multiple DBG_VALUE instructions describing one variable. - if (DotDebugLocEntries.empty()) - RegVar->setDotDebugLocOffset(0); - else - RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); - const MachineInstr *Begin = NULL; - const MachineInstr *End = NULL; - for (SmallVector::iterator - MVI = MultipleValues.begin(), MVE = MultipleValues.end(); - MVI != MVE; ++MVI) { - if (!Begin) { - Begin = *MVI; - continue; - } - End = *MVI; + RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); + + for (SmallVectorImpl::const_iterator + HI = History.begin(), HE = History.end(); HI != HE; ++HI) { + const MachineInstr *Begin = *HI; + assert(Begin->isDebugValue() && "Invalid History entry"); MachineLocation MLoc; if (Begin->getNumOperands() == 3) { if (Begin->getOperand(0).isReg() && Begin->getOperand(1).isImm()) @@ -2441,25 +1441,32 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, } else MLoc = Asm->getDebugValueLocation(Begin); - const MCSymbol *FLabel = getLabelBeforeInsn(Begin); - const MCSymbol *SLabel = getLabelBeforeInsn(End); - if (MLoc.getReg()) - DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc)); + // FIXME: emitDebugLoc only understands registers. + if (!MLoc.getReg()) + continue; - Begin = End; - if (MVI + 1 == MVE) { - // If End is the last instruction then its value is valid - // until the end of the funtion. - MachineLocation EMLoc; - if (End->getNumOperands() == 3) { - if (End->getOperand(0).isReg() && Begin->getOperand(1).isImm()) - EMLoc.set(Begin->getOperand(0).getReg(), Begin->getOperand(1).getImm()); - } else - EMLoc = Asm->getDebugValueLocation(End); - if (EMLoc.getReg()) - DotDebugLocEntries. - push_back(DotDebugLocEntry(SLabel, FunctionEndSym, EMLoc)); + // Compute the range for a register location. + const MCSymbol *FLabel = getLabelBeforeInsn(Begin); + const MCSymbol *SLabel = 0; + + if (HI + 1 == HE) + // If Begin is the last instruction in History then its value is valid + // until the end of the function. + SLabel = FunctionEndSym; + else { + const MachineInstr *End = HI[1]; + if (End->isDebugValue()) + SLabel = getLabelBeforeInsn(End); + else { + // End is a normal instruction clobbering the range. + SLabel = getLabelAfterInsn(End); + assert(SLabel && "Forgot label after clobber instruction"); + ++HI; + } } + + // The value is valid until the next DBG_VALUE or clobber. + DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc, Var)); } DotDebugLocEntries.push_back(DotDebugLocEntry()); } @@ -2480,66 +1487,74 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, /// getLabelBeforeInsn - Return Label preceding the instruction. const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) { - DenseMap::iterator I = - LabelsBeforeInsn.find(MI); - if (I == LabelsBeforeInsn.end()) - // FunctionBeginSym always preceeds all the instruction in current function. - return FunctionBeginSym; - return I->second; + MCSymbol *Label = LabelsBeforeInsn.lookup(MI); + assert(Label && "Didn't insert label before instruction"); + return Label; } /// getLabelAfterInsn - Return Label immediately following the instruction. const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { - DenseMap::iterator I = - LabelsAfterInsn.find(MI); - if (I == LabelsAfterInsn.end()) - return NULL; - return I->second; + return LabelsAfterInsn.lookup(MI); } /// beginInstruction - Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { - if (InsnNeedsLabel.count(MI) == 0) { - LabelsBeforeInsn[MI] = PrevLabel; - return; + // Check if source location changes, but ignore DBG_VALUE locations. + if (!MI->isDebugValue()) { + DebugLoc DL = MI->getDebugLoc(); + if (DL != PrevInstLoc && (!DL.isUnknown() || UnknownLocations)) { + PrevInstLoc = DL; + if (!DL.isUnknown()) { + const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext()); + recordSourceLine(DL.getLine(), DL.getCol(), Scope); + } else + recordSourceLine(0, 0, 0); + } } - // Check location. - DebugLoc DL = MI->getDebugLoc(); - if (!DL.isUnknown()) { - const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext()); - PrevLabel = recordSourceLine(DL.getLine(), DL.getCol(), Scope); - PrevInstLoc = DL; - LabelsBeforeInsn[MI] = PrevLabel; - return; - } + // Insert labels where requested. + DenseMap::iterator I = + LabelsBeforeInsn.find(MI); - // If location is unknown then use temp label for this DBG_VALUE - // instruction. - if (MI->isDebugValue()) { + // No label needed. + if (I == LabelsBeforeInsn.end()) + return; + + // Label already assigned. + if (I->second) + return; + + if (!PrevLabel) { PrevLabel = MMI->getContext().CreateTempSymbol(); Asm->OutStreamer.EmitLabel(PrevLabel); - LabelsBeforeInsn[MI] = PrevLabel; - return; } - - if (UnknownLocations) { - PrevLabel = recordSourceLine(0, 0, 0); - LabelsBeforeInsn[MI] = PrevLabel; - return; - } - - assert (0 && "Instruction is not processed!"); + I->second = PrevLabel; } /// endInstruction - Process end of an instruction. void DwarfDebug::endInstruction(const MachineInstr *MI) { - if (InsnsEndScopeSet.count(MI) != 0) { - // Emit a label if this instruction ends a scope. - MCSymbol *Label = MMI->getContext().CreateTempSymbol(); - Asm->OutStreamer.EmitLabel(Label); - LabelsAfterInsn[MI] = Label; + // Don't create a new label after DBG_VALUE instructions. + // They don't generate code. + if (!MI->isDebugValue()) + PrevLabel = 0; + + DenseMap::iterator I = + LabelsAfterInsn.find(MI); + + // No label needed. + if (I == LabelsAfterInsn.end()) + return; + + // Label already assigned. + if (I->second) + return; + + // We need a label after this instruction. + if (!PrevLabel) { + PrevLabel = MMI->getContext().CreateTempSymbol(); + Asm->OutStreamer.EmitLabel(PrevLabel); } + I->second = PrevLabel; } /// getOrCreateDbgScope - Create DbgScope for the scope. @@ -2799,7 +1814,8 @@ void DwarfDebug::identifyScopeMarkers() { RE = Ranges.end(); RI != RE; ++RI) { assert(RI->first && "DbgRange does not have first instruction!"); assert(RI->second && "DbgRange does not have second instruction!"); - InsnsEndScopeSet.insert(RI->second); + requestLabelBeforeInsn(RI->first); + requestLabelAfterInsn(RI->second); } } } @@ -2877,45 +1893,145 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { recordSourceLine(Line, Col, TheScope); + assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned"); + /// ProcessedArgs - Collection of arguments already processed. SmallPtrSet ProcessedArgs; - DebugLoc PrevLoc; + const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); + + /// LiveUserVar - Map physreg numbers to the MDNode they contain. + std::vector LiveUserVar(TRI->getNumRegs()); + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); - I != E; ++I) + I != E; ++I) { + bool AtBlockEntry = true; for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { const MachineInstr *MI = II; - DebugLoc DL = MI->getDebugLoc(); + if (MI->isDebugValue()) { assert (MI->getNumOperands() > 1 && "Invalid machine instruction!"); - DIVariable DV(MI->getOperand(MI->getNumOperands() - 1).getMetadata()); - if (!DV.Verify()) continue; - // If DBG_VALUE is for a local variable then it needs a label. - if (DV.getTag() != dwarf::DW_TAG_arg_variable) - InsnNeedsLabel.insert(MI); - // DBG_VALUE for inlined functions argument needs a label. - else if (!DISubprogram(getDISubprogram(DV.getContext())). - describes(MF->getFunction())) - InsnNeedsLabel.insert(MI); - // DBG_VALUE indicating argument location change needs a label. - else if (!ProcessedArgs.insert(DV)) - InsnNeedsLabel.insert(MI); + + // Keep track of user variables. + const MDNode *Var = + MI->getOperand(MI->getNumOperands() - 1).getMetadata(); + + // Variable is in a register, we need to check for clobbers. + if (isDbgValueInDefinedReg(MI)) + LiveUserVar[MI->getOperand(0).getReg()] = Var; + + // Check the history of this variable. + SmallVectorImpl &History = DbgValues[Var]; + if (History.empty()) { + UserVariables.push_back(Var); + // The first mention of a function argument gets the FunctionBeginSym + // label, so arguments are visible when breaking at function entry. + DIVariable DV(Var); + if (DV.Verify() && DV.getTag() == dwarf::DW_TAG_arg_variable && + DISubprogram(getDISubprogram(DV.getContext())) + .describes(MF->getFunction())) + LabelsBeforeInsn[MI] = FunctionBeginSym; + } else { + // We have seen this variable before. Try to coalesce DBG_VALUEs. + const MachineInstr *Prev = History.back(); + if (Prev->isDebugValue()) { + // Coalesce identical entries at the end of History. + if (History.size() >= 2 && + Prev->isIdenticalTo(History[History.size() - 2])) + History.pop_back(); + + // Terminate old register assignments that don't reach MI; + MachineFunction::const_iterator PrevMBB = Prev->getParent(); + if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB) != I) && + isDbgValueInDefinedReg(Prev)) { + // Previous register assignment needs to terminate at the end of + // its basic block. + MachineBasicBlock::const_iterator LastMI = + PrevMBB->getLastNonDebugInstr(); + if (LastMI == PrevMBB->end()) + // Drop DBG_VALUE for empty range. + History.pop_back(); + else { + // Terminate after LastMI. + History.push_back(LastMI); + } + } + } + } + History.push_back(MI); } else { - // If location is unknown then instruction needs a location only if - // UnknownLocations flag is set. - if (DL.isUnknown()) { - if (UnknownLocations && !PrevLoc.isUnknown()) - InsnNeedsLabel.insert(MI); - } else if (DL != PrevLoc) - // Otherwise, instruction needs a location only if it is new location. - InsnNeedsLabel.insert(MI); + // Not a DBG_VALUE instruction. + if (!MI->isLabel()) + AtBlockEntry = false; + + // Check if the instruction clobbers any registers with debug vars. + for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(), + MOE = MI->operands_end(); MOI != MOE; ++MOI) { + if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg()) + continue; + for (const unsigned *AI = TRI->getOverlaps(MOI->getReg()); + unsigned Reg = *AI; ++AI) { + const MDNode *Var = LiveUserVar[Reg]; + if (!Var) + continue; + // Reg is now clobbered. + LiveUserVar[Reg] = 0; + + // Was MD last defined by a DBG_VALUE referring to Reg? + DbgValueHistoryMap::iterator HistI = DbgValues.find(Var); + if (HistI == DbgValues.end()) + continue; + SmallVectorImpl &History = HistI->second; + if (History.empty()) + continue; + const MachineInstr *Prev = History.back(); + // Sanity-check: Register assignments are terminated at the end of + // their block. + if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent()) + continue; + // Is the variable still in Reg? + if (!isDbgValueInDefinedReg(Prev) || + Prev->getOperand(0).getReg() != Reg) + continue; + // Var is clobbered. Make sure the next instruction gets a label. + History.push_back(MI); + } + } } - - if (!DL.isUnknown() || UnknownLocations) - PrevLoc = DL; } + } + for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end(); + I != E; ++I) { + SmallVectorImpl &History = I->second; + if (History.empty()) + continue; + + // Make sure the final register assignments are terminated. + const MachineInstr *Prev = History.back(); + if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) { + const MachineBasicBlock *PrevMBB = Prev->getParent(); + MachineBasicBlock::const_iterator LastMI = PrevMBB->getLastNonDebugInstr(); + if (LastMI == PrevMBB->end()) + // Drop DBG_VALUE for empty range. + History.pop_back(); + else { + // Terminate after LastMI. + History.push_back(LastMI); + } + } + // Request labels for the full history. + for (unsigned i = 0, e = History.size(); i != e; ++i) { + const MachineInstr *MI = History[i]; + if (MI->isDebugValue()) + requestLabelBeforeInsn(MI); + else + requestLabelAfterInsn(MI); + } + } + + PrevInstLoc = DebugLoc(); PrevLabel = FunctionBeginSym; } @@ -2963,8 +2079,9 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { DIE *CurFnDIE = constructScopeDIE(CurrentFnDbgScope); if (!DisableFramePointerElim(*MF)) - addUInt(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr, - dwarf::DW_FORM_flag, 1); + getCompileUnit(CurrentFnDbgScope->getScopeNode())->addUInt(CurFnDIE, + dwarf::DW_AT_APPLE_omit_frame_ptr, + dwarf::DW_FORM_flag, 1); DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(), @@ -2973,12 +2090,13 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Clear debug info CurrentFnDbgScope = NULL; - InsnNeedsLabel.clear(); + DeleteContainerPointers(CurrentFnArguments); DbgVariableToFrameIndexMap.clear(); VarToAbstractVarMap.clear(); DbgVariableToDbgInstMap.clear(); DeleteContainerSeconds(DbgScopeMap); - InsnsEndScopeSet.clear(); + UserVariables.clear(); + DbgValues.clear(); ConcreteScopes.clear(); DeleteContainerSeconds(AbstractScopes); AbstractScopesList.clear(); @@ -3029,10 +2147,9 @@ DbgScope *DwarfDebug::findDbgScope(const MachineInstr *MInsn) { /// recordSourceLine - Register a source line with debug info. Returns the /// unique label that was emitted and which provides correspondence to /// the source line list. -MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, - const MDNode *S) { +void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S){ StringRef Fn; - + StringRef Dir; unsigned Src = 1; if (S) { DIDescriptor Scope(S); @@ -3040,27 +2157,26 @@ MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, if (Scope.isCompileUnit()) { DICompileUnit CU(S); Fn = CU.getFilename(); + Dir = CU.getDirectory(); } else if (Scope.isFile()) { DIFile F(S); Fn = F.getFilename(); + Dir = F.getDirectory(); } else if (Scope.isSubprogram()) { DISubprogram SP(S); Fn = SP.getFilename(); + Dir = SP.getDirectory(); } else if (Scope.isLexicalBlock()) { DILexicalBlock DB(S); Fn = DB.getFilename(); + Dir = DB.getDirectory(); } else assert(0 && "Unexpected scope info"); - Src = GetOrCreateSourceID(Fn); + Src = GetOrCreateSourceID(Fn, Dir); } - Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, DWARF2_FLAG_IS_STMT, - 0, 0); - - MCSymbol *Label = MMI->getContext().CreateTempSymbol(); - Asm->OutStreamer.EmitLabel(Label); - return Label; + 0, 0, Fn); } //===----------------------------------------------------------------------===// @@ -3118,17 +2234,15 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { /// computeSizeAndOffsets - Compute the size and offset of all the DIEs. /// void DwarfDebug::computeSizeAndOffsets() { - unsigned PrevOffset = 0; for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { // Compute size of compile unit header. - static unsigned Offset = PrevOffset + + unsigned Offset = sizeof(int32_t) + // Length of Compilation Unit Info sizeof(int16_t) + // DWARF version number sizeof(int32_t) + // Offset Into Abbrev. Section sizeof(int8_t); // Pointer Size (in bytes) computeSizeAndOffset(I->second->getCUDie(), Offset, true); - PrevOffset = Offset; } } @@ -3289,8 +2403,7 @@ void DwarfDebug::emitDebugInfo() { unsigned ContentSize = Die->getSize() + sizeof(int16_t) + // DWARF version number sizeof(int32_t) + // Offset Into Abbrev. Section - sizeof(int8_t) + // Pointer Size (in bytes) - sizeof(int32_t); // FIXME - extra pad for gdb bug. + sizeof(int8_t); // Pointer Size (in bytes) Asm->OutStreamer.AddComment("Length of Compilation Unit Info"); Asm->EmitInt32(ContentSize); @@ -3303,12 +2416,6 @@ void DwarfDebug::emitDebugInfo() { Asm->EmitInt8(Asm->getTargetData().getPointerSize()); emitDIE(Die); - // FIXME - extra padding for gdb bug. - Asm->OutStreamer.AddComment("4 extra padding bytes for GDB"); - Asm->EmitInt8(0); - Asm->EmitInt8(0); - Asm->EmitInt8(0); - Asm->EmitInt8(0); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_end", TheCU->getID())); } } @@ -3614,32 +2721,38 @@ void DwarfDebug::emitDebugLoc() { } else { Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size, 0); Asm->OutStreamer.EmitSymbolValue(Entry.End, Size, 0); - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); - unsigned Reg = RI->getDwarfRegNum(Entry.Loc.getReg(), false); - if (int Offset = Entry.Loc.getOffset()) { - // If the value is at a certain offset from frame register then - // use DW_OP_fbreg. - unsigned OffsetSize = Offset ? MCAsmInfo::getSLEB128Size(Offset) : 1; + DIVariable DV(Entry.Variable); + if (DV.hasComplexAddress()) { + unsigned N = DV.getNumAddrElements(); + unsigned i = 0; Asm->OutStreamer.AddComment("Loc expr size"); - Asm->EmitInt16(1 + OffsetSize); - Asm->OutStreamer.AddComment( - dwarf::OperationEncodingString(dwarf::DW_OP_fbreg)); - Asm->EmitInt8(dwarf::DW_OP_fbreg); - Asm->OutStreamer.AddComment("Offset"); - Asm->EmitSLEB128(Offset); - } else { - if (Reg < 32) { - Asm->OutStreamer.AddComment("Loc expr size"); - Asm->EmitInt16(1); - Asm->OutStreamer.AddComment( - dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg)); - Asm->EmitInt8(dwarf::DW_OP_reg0 + Reg); + if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { + // If first address element is OpPlus then emit + // DW_OP_breg + Offset instead of DW_OP_reg + Offset. + MachineLocation Loc(Entry.Loc.getReg(), DV.getAddrElement(1)); + Asm->EmitInt16(Asm->getDwarfRegOpSize(Loc) + N - 2); + Asm->EmitDwarfRegOp(Loc); +// Asm->EmitULEB128(DV.getAddrElement(1)); + i = 2; } else { - Asm->OutStreamer.AddComment("Loc expr size"); - Asm->EmitInt16(1 + MCAsmInfo::getULEB128Size(Reg)); - Asm->EmitInt8(dwarf::DW_OP_regx); - Asm->EmitULEB128(Reg); + Asm->EmitInt16(Asm->getDwarfRegOpSize(Entry.Loc) + N); + Asm->EmitDwarfRegOp(Entry.Loc); } + + // Emit remaining complex address elements. + for (; i < N; ++i) { + uint64_t Element = DV.getAddrElement(i); + if (Element == DIBuilder::OpPlus) { + Asm->EmitInt8(dwarf::DW_OP_plus_uconst); + Asm->EmitULEB128(DV.getAddrElement(++i)); + } else if (Element == DIBuilder::OpDeref) + Asm->EmitInt8(dwarf::DW_OP_deref); + else llvm_unreachable("unknown Opcode found in complex address"); + } + } else { + Asm->OutStreamer.AddComment("Loc expr size"); + Asm->EmitInt16(Asm->getDwarfRegOpSize(Entry.Loc)); + Asm->EmitDwarfRegOp(Entry.Loc); } } } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index 7df0510fbfba..25f2675d40f0 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -16,6 +16,7 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Analysis/DebugInfo.h" #include "DIE.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -40,21 +41,6 @@ class DIE; class DIEBlock; class DIEEntry; -class DIEnumerator; -class DIDescriptor; -class DIVariable; -class DIGlobal; -class DIGlobalVariable; -class DISubprogram; -class DIBasicType; -class DIDerivedType; -class DIType; -class DINameSpace; -class DISubrange; -class DICompositeType; -class DITemplateTypeParameter; -class DITemplateValueParameter; - //===----------------------------------------------------------------------===// /// SrcLineInfo - This class is used to record source line correspondence. /// @@ -80,10 +66,12 @@ typedef struct DotDebugLocEntry { const MCSymbol *Begin; const MCSymbol *End; MachineLocation Loc; + const MDNode *Variable; bool Merged; - DotDebugLocEntry() : Begin(0), End(0), Merged(false) {} - DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L) - : Begin(B), End(E), Loc(L), Merged(false) {} + DotDebugLocEntry() : Begin(0), End(0), Variable(0), Merged(false) {} + DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L, + const MDNode *V) + : Begin(B), End(E), Loc(L), Variable(V), Merged(false) {} /// Empty entries are also used as a trigger to emit temp label. Such /// labels are referenced is used to find debug_loc offset for a given DIE. bool isEmpty() { return Begin == 0 && End == 0; } @@ -96,6 +84,43 @@ typedef struct DotDebugLocEntry { } } DotDebugLocEntry; +//===----------------------------------------------------------------------===// +/// DbgVariable - This class is used to track local variable information. +/// +class DbgVariable { + DIVariable Var; // Variable Descriptor. + DIE *TheDIE; // Variable DIE. + unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries. +public: + // AbsVar may be NULL. + DbgVariable(DIVariable V) : Var(V), TheDIE(0), DotDebugLocOffset(~0U) {} + + // Accessors. + DIVariable getVariable() const { return Var; } + void setDIE(DIE *D) { TheDIE = D; } + DIE *getDIE() const { return TheDIE; } + void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } + unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; } + StringRef getName() const { return Var.getName(); } + unsigned getTag() const { return Var.getTag(); } + bool variableHasComplexAddress() const { + assert(Var.Verify() && "Invalid complex DbgVariable!"); + return Var.hasComplexAddress(); + } + bool isBlockByrefVariable() const { + assert(Var.Verify() && "Invalid complex DbgVariable!"); + return Var.isBlockByrefVariable(); + } + unsigned getNumAddrElements() const { + assert(Var.Verify() && "Invalid complex DbgVariable!"); + return Var.getNumAddrElements(); + } + uint64_t getAddrElement(unsigned i) const { + return Var.getAddrElement(i); + } + DIType getType() const; +}; + class DwarfDebug { /// Asm - Target of Dwarf emission. AsmPrinter *Asm; @@ -122,12 +147,6 @@ class DwarfDebug { /// id mapped to a unique id. StringMap SourceIdMap; - /// DIEBlocks - A list of all the DIEBlocks in use. - std::vector DIEBlocks; - - // DIEValueAllocator - All DIEValues are allocated through this allocator. - BumpPtrAllocator DIEValueAllocator; - /// StringPool - A String->Symbol mapping of strings used by indirect /// references. StringMap > StringPool; @@ -139,10 +158,13 @@ class DwarfDebug { /// UniqueVector SectionMap; - // CurrentFnDbgScope - Top level scope for the current function. - // + /// CurrentFnDbgScope - Top level scope for the current function. + /// DbgScope *CurrentFnDbgScope; + /// CurrentFnArguments - List of Arguments (DbgValues) for current function. + SmallVector CurrentFnArguments; + /// DbgScopeMap - Tracks the scopes in the current function. Owns the /// contained DbgScope*s. /// @@ -195,10 +217,6 @@ class DwarfDebug { /// corresponds to the MDNode mapped with the subprogram DIE. DenseMap ContainingTypeMap; - typedef SmallVector ScopeVector; - - SmallPtrSet InsnsEndScopeSet; - /// InlineInfo - Keep track of inlined functions and their location. This /// information is used to populate debug_inlined section. typedef std::pair InlineInfoLabels; @@ -217,9 +235,16 @@ class DwarfDebug { /// instruction. DenseMap LabelsAfterInsn; - /// insnNeedsLabel - Collection of instructions that need a label to mark - /// a debuggging information entity. - SmallPtrSet InsnNeedsLabel; + /// UserVariables - Every user variable mentioned by a DBG_VALUE instruction + /// in order of appearance. + SmallVector UserVariables; + + /// DbgValues - For each user variable, keep a list of DBG_VALUE + /// instructions in order. The list can also contain normal instructions that + /// clobber the previous DBG_VALUE. + typedef DenseMap > + DbgValueHistoryMap; + DbgValueHistoryMap DbgValues; SmallVector DebugRangeSymbols; @@ -238,6 +263,9 @@ class DwarfDebug { std::vector DebugFrames; + // DIEValueAllocator - All DIEValues are allocated through this allocator. + BumpPtrAllocator DIEValueAllocator; + // Section Symbols: these are assembler temporary labels that are emitted at // the beginning of each supported dwarf section. These are used to form // section offsets and are created by EmitSectionLabels. @@ -246,150 +274,12 @@ class DwarfDebug { MCSymbol *DwarfDebugLocSectionSym; MCSymbol *FunctionBeginSym, *FunctionEndSym; - DIEInteger *DIEIntegerOne; private: - /// getNumSourceIds - Return the number of unique source ids. - unsigned getNumSourceIds() const { - return SourceIdMap.size(); - } - /// assignAbbrevNumber - Define a unique number for the abbreviation. /// void assignAbbrevNumber(DIEAbbrev &Abbrev); - /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug - /// information entry. - DIEEntry *createDIEEntry(DIE *Entry); - - /// addUInt - Add an unsigned integer attribute data and value. - /// - void addUInt(DIE *Die, unsigned Attribute, unsigned Form, uint64_t Integer); - - /// addSInt - Add an signed integer attribute data and value. - /// - void addSInt(DIE *Die, unsigned Attribute, unsigned Form, int64_t Integer); - - /// addString - Add a string attribute data and value. - /// - void addString(DIE *Die, unsigned Attribute, unsigned Form, - const StringRef Str); - - /// addLabel - Add a Dwarf label attribute data and value. - /// - void addLabel(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Label); - - /// addDelta - Add a label delta attribute data and value. - /// - void addDelta(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Hi, const MCSymbol *Lo); - - /// addDIEEntry - Add a DIE attribute data and value. - /// - void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry); - - /// addBlock - Add block data. - /// - void addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block); - - /// addSourceLine - Add location information to specified debug information - /// entry. - void addSourceLine(DIE *Die, DIVariable V); - void addSourceLine(DIE *Die, DIGlobalVariable G); - void addSourceLine(DIE *Die, DISubprogram SP); - void addSourceLine(DIE *Die, DIType Ty); - void addSourceLine(DIE *Die, DINameSpace NS); - - /// addAddress - Add an address attribute to a die based on the location - /// provided. - void addAddress(DIE *Die, unsigned Attribute, - const MachineLocation &Location); - - /// addRegisterAddress - Add register location entry in variable DIE. - bool addRegisterAddress(DIE *Die, const MachineOperand &MO); - - /// addConstantValue - Add constant value entry in variable DIE. - bool addConstantValue(DIE *Die, const MachineOperand &MO); - bool addConstantValue(DIE *Die, ConstantInt *CI, bool Unsigned); - - /// addConstantFPValue - Add constant value entry in variable DIE. - bool addConstantFPValue(DIE *Die, const MachineOperand &MO); - - /// addComplexAddress - Start with the address based on the location provided, - /// and generate the DWARF information necessary to find the actual variable - /// (navigating the extra location information encoded in the type) based on - /// the starting location. Add the DWARF information to the die. - /// - void addComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, - const MachineLocation &Location); - - // FIXME: Should be reformulated in terms of addComplexAddress. - /// addBlockByrefAddress - Start with the address based on the location - /// provided, and generate the DWARF information necessary to find the - /// actual Block variable (navigating the Block struct) based on the - /// starting location. Add the DWARF information to the die. Obsolete, - /// please use addComplexAddress instead. - /// - void addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, - const MachineLocation &Location); - - /// addVariableAddress - Add DW_AT_location attribute for a DbgVariable based - /// on provided frame index. - void addVariableAddress(DbgVariable *&DV, DIE *Die, int64_t FI); - - /// addToContextOwner - Add Die into the list of its context owner's children. - void addToContextOwner(DIE *Die, DIDescriptor Context); - - /// addType - Add a new type attribute to the specified entity. - void addType(DIE *Entity, DIType Ty); - - - /// getOrCreateNameSpace - Create a DIE for DINameSpace. - DIE *getOrCreateNameSpace(DINameSpace NS); - - /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the - /// given DIType. - DIE *getOrCreateTypeDIE(DIType Ty); - - /// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE - /// for the given DITemplateTypeParameter. - DIE *getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP); - - /// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE - /// for the given DITemplateValueParameter. - DIE *getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TVP); - - void addPubTypes(DISubprogram SP); - - /// constructTypeDIE - Construct basic type die from DIBasicType. - void constructTypeDIE(DIE &Buffer, - DIBasicType BTy); - - /// constructTypeDIE - Construct derived type die from DIDerivedType. - void constructTypeDIE(DIE &Buffer, - DIDerivedType DTy); - - /// constructTypeDIE - Construct type DIE from DICompositeType. - void constructTypeDIE(DIE &Buffer, - DICompositeType CTy); - - /// constructSubrangeDIE - Construct subrange DIE from DISubrange. - void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy); - - /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. - void constructArrayTypeDIE(DIE &Buffer, - DICompositeType *CTy); - - /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. - DIE *constructEnumTypeDIE(DIEnumerator ETy); - - /// createMemberDIE - Create new member DIE. - DIE *createMemberDIE(DIDerivedType DT); - - /// createSubprogramDIE - Create new DIE using SP. - DIE *createSubprogramDIE(DISubprogram SP); - /// getOrCreateDbgScope - Create DbgScope for the scope. DbgScope *getOrCreateDbgScope(const MDNode *Scope, const MDNode *InlinedAt); @@ -504,11 +394,6 @@ class DwarfDebug { /// inlining instance. void emitDebugInlineInfo(); - /// GetOrCreateSourceID - Look up the source id with the given directory and - /// source file names. If none currently exists, create a new id and insert it - /// in the SourceIds map. - unsigned GetOrCreateSourceID(StringRef FullName); - /// constructCompileUnit - Create new CompileUnit for the given /// metadata node with tag DW_TAG_compile_unit. void constructCompileUnit(const MDNode *N); @@ -525,7 +410,7 @@ class DwarfDebug { /// recordSourceLine - Register a source line with debug info. Returns the /// unique label that was emitted and which provides correspondence to /// the source line list. - MCSymbol *recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope); + void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope); /// recordVariableFrameIndex - Record a variable's index. void recordVariableFrameIndex(const DbgVariable *V, int Index); @@ -546,6 +431,11 @@ class DwarfDebug { /// and collect DbgScopes. Return true, if atleast one scope was found. bool extractScopeInformation(); + /// addCurrentFnArgument - If Var is an current function argument that add + /// it in CurrentFnArguments list. + bool addCurrentFnArgument(const MachineFunction *MF, + DbgVariable *Var, DbgScope *Scope); + /// collectVariableInfo - Populate DbgScope entries with variables' info. void collectVariableInfo(const MachineFunction *, SmallPtrSet &ProcessedVars); @@ -554,6 +444,23 @@ class DwarfDebug { /// side table maintained by MMI. void collectVariableInfoFromMMITable(const MachineFunction * MF, SmallPtrSet &P); + + /// requestLabelBeforeInsn - Ensure that a label will be emitted before MI. + void requestLabelBeforeInsn(const MachineInstr *MI) { + LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol*)0)); + } + + /// getLabelBeforeInsn - Return Label preceding the instruction. + const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); + + /// requestLabelAfterInsn - Ensure that a label will be emitted after MI. + void requestLabelAfterInsn(const MachineInstr *MI) { + LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol*)0)); + } + + /// getLabelAfterInsn - Return Label immediately following the instruction. + const MCSymbol *getLabelAfterInsn(const MachineInstr *MI); + public: //===--------------------------------------------------------------------===// // Main entry points. @@ -577,17 +484,19 @@ class DwarfDebug { /// void endFunction(const MachineFunction *MF); - /// getLabelBeforeInsn - Return Label preceding the instruction. - const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); - - /// getLabelAfterInsn - Return Label immediately following the instruction. - const MCSymbol *getLabelAfterInsn(const MachineInstr *MI); - /// beginInstruction - Process beginning of an instruction. void beginInstruction(const MachineInstr *MI); /// endInstruction - Prcess end of an instruction. void endInstruction(const MachineInstr *MI); + + /// GetOrCreateSourceID - Look up the source id with the given directory and + /// source file names. If none currently exists, create a new id and insert it + /// in the SourceIds map. + unsigned GetOrCreateSourceID(StringRef DirName, StringRef FullName); + + /// createSubprogramDIE - Create new DIE using SP. + DIE *createSubprogramDIE(DISubprogram SP); }; } // End of namespace llvm diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.h index a172e53f8ac7..f11164122cc4 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.h @@ -140,17 +140,18 @@ class DwarfException { }; class DwarfCFIException : public DwarfException { - /// shouldEmitTable - Per-function flag to indicate if EH tables should - /// be emitted. - bool shouldEmitTable; + /// shouldEmitPersonality - Per-function flag to indicate if .cfi_personality + /// should be emitted. + bool shouldEmitPersonality; + + /// shouldEmitLSDA - Per-function flag to indicate if .cfi_lsda + /// should be emitted. + bool shouldEmitLSDA; /// shouldEmitMoves - Per-function flag to indicate if frame moves info /// should be emitted. bool shouldEmitMoves; - /// shouldEmitTableModule - Per-module flag to indicate if EH tables - /// should be emitted. - bool shouldEmitTableModule; public: //===--------------------------------------------------------------------===// // Main entry points. @@ -237,6 +238,38 @@ class DwarfTableException : public DwarfException { virtual void EndFunction(); }; + +class ARMException : public DwarfException { + /// shouldEmitTable - Per-function flag to indicate if EH tables should + /// be emitted. + bool shouldEmitTable; + + /// shouldEmitMoves - Per-function flag to indicate if frame moves info + /// should be emitted. + bool shouldEmitMoves; + + /// shouldEmitTableModule - Per-module flag to indicate if EH tables + /// should be emitted. + bool shouldEmitTableModule; +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + ARMException(AsmPrinter *A); + virtual ~ARMException(); + + /// EndModule - Emit all exception information that should come after the + /// content. + virtual void EndModule(); + + /// BeginFunction - Gather pre-function exception information. Assumes being + /// emitted immediately after the function entry point. + virtual void BeginFunction(const MachineFunction *MF); + + /// EndFunction - Gather and emit post-function exception information. + virtual void EndFunction(); +}; + } // End of namespace llvm #endif diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfTableException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfTableException.cpp index 751901183cd0..b50d8bd3cecc 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfTableException.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfTableException.cpp @@ -92,7 +92,7 @@ void DwarfTableException::EmitCIE(const Function *PersonalityFn, unsigned Index) // personality function reference: unsigned LSDAEncoding = TLOF.getLSDAEncoding(); - unsigned FDEEncoding = TLOF.getFDEEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(false); unsigned PerEncoding = TLOF.getPersonalityEncoding(); char Augmentation[6] = { 0 }; @@ -168,7 +168,7 @@ void DwarfTableException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); unsigned LSDAEncoding = TLOF.getLSDAEncoding(); - unsigned FDEEncoding = TLOF.getFDEEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(false); Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); diff --git a/contrib/llvm/lib/CodeGen/BranchFolding.cpp b/contrib/llvm/lib/CodeGen/BranchFolding.cpp index 78a87431feaa..77043406bc85 100644 --- a/contrib/llvm/lib/CodeGen/BranchFolding.cpp +++ b/contrib/llvm/lib/CodeGen/BranchFolding.cpp @@ -1048,7 +1048,7 @@ bool BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) { // AnalyzeBranch. if (PriorCond.empty() && !PriorTBB && MBB->pred_size() == 1 && PrevBB.succ_size() == 1 && - !MBB->hasAddressTaken()) { + !MBB->hasAddressTaken() && !MBB->isLandingPad()) { DEBUG(dbgs() << "\nMerging into block: " << PrevBB << "From MBB: " << *MBB); PrevBB.splice(PrevBB.end(), MBB, MBB->begin(), MBB->end()); diff --git a/contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp b/contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp index 76bb3d148b0b..e5894b8cca9d 100644 --- a/contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp +++ b/contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp @@ -87,8 +87,8 @@ static unsigned copyHint(const MachineInstr *mi, unsigned reg, } void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) { - MachineRegisterInfo &mri = mf_.getRegInfo(); - const TargetRegisterInfo &tri = *mf_.getTarget().getRegisterInfo(); + MachineRegisterInfo &mri = MF.getRegInfo(); + const TargetRegisterInfo &tri = *MF.getTarget().getRegisterInfo(); MachineBasicBlock *mbb = 0; MachineLoop *loop = 0; unsigned loopDepth = 0; @@ -103,6 +103,9 @@ void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) { // Don't recompute a target specific hint. bool noHint = mri.getRegAllocationHint(li.reg).first != 0; + // Don't recompute spill weight for an unspillable register. + bool Spillable = li.isSpillable(); + for (MachineRegisterInfo::reg_iterator I = mri.reg_begin(li.reg); MachineInstr *mi = I.skipInstruction();) { if (mi->isIdentityCopy() || mi->isImplicitDef() || mi->isDebugValue()) @@ -110,34 +113,37 @@ void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) { if (!visited.insert(mi)) continue; - // Get loop info for mi. - if (mi->getParent() != mbb) { - mbb = mi->getParent(); - loop = loops_.getLoopFor(mbb); - loopDepth = loop ? loop->getLoopDepth() : 0; - isExiting = loop ? loop->isLoopExiting(mbb) : false; + float weight = 1.0f; + if (Spillable) { + // Get loop info for mi. + if (mi->getParent() != mbb) { + mbb = mi->getParent(); + loop = Loops.getLoopFor(mbb); + loopDepth = loop ? loop->getLoopDepth() : 0; + isExiting = loop ? loop->isLoopExiting(mbb) : false; + } + + // Calculate instr weight. + bool reads, writes; + tie(reads, writes) = mi->readsWritesVirtualRegister(li.reg); + weight = LiveIntervals::getSpillWeight(writes, reads, loopDepth); + + // Give extra weight to what looks like a loop induction variable update. + if (writes && isExiting && LIS.isLiveOutOfMBB(li, mbb)) + weight *= 3; + + totalWeight += weight; } - // Calculate instr weight. - bool reads, writes; - tie(reads, writes) = mi->readsWritesVirtualRegister(li.reg); - float weight = LiveIntervals::getSpillWeight(writes, reads, loopDepth); - - // Give extra weight to what looks like a loop induction variable update. - if (writes && isExiting && lis_.isLiveOutOfMBB(li, mbb)) - weight *= 3; - - totalWeight += weight; - // Get allocation hints from copies. if (noHint || !mi->isCopy()) continue; unsigned hint = copyHint(mi, li.reg, tri, mri); if (!hint) continue; - float hweight = hint_[hint] += weight; + float hweight = Hint[hint] += weight; if (TargetRegisterInfo::isPhysicalRegister(hint)) { - if (hweight > bestPhys && lis_.isAllocatable(hint)) + if (hweight > bestPhys && LIS.isAllocatable(hint)) bestPhys = hweight, hintPhys = hint; } else { if (hweight > bestVirt) @@ -145,15 +151,19 @@ void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) { } } - hint_.clear(); + Hint.clear(); // Always prefer the physreg hint. if (unsigned hint = hintPhys ? hintPhys : hintVirt) { mri.setRegAllocationHint(li.reg, 0, hint); - // Weakly boost the spill weifght of hinted registers. + // Weakly boost the spill weight of hinted registers. totalWeight *= 1.01F; } + // If the live interval was already unspillable, leave it that way. + if (!Spillable) + return; + // Mark li as unspillable if all live ranges are tiny. if (li.isZeroLength()) { li.markNotSpillable(); @@ -166,8 +176,7 @@ void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) { // FIXME: this gets much more complicated once we support non-trivial // re-materialization. bool isLoad = false; - SmallVector spillIs; - if (lis_.isReMaterializable(li, spillIs, isLoad)) { + if (LIS.isReMaterializable(li, 0, isLoad)) { if (isLoad) totalWeight *= 0.9F; else @@ -178,50 +187,29 @@ void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) { } void VirtRegAuxInfo::CalculateRegClass(unsigned reg) { - MachineRegisterInfo &mri = mf_.getRegInfo(); - const TargetRegisterInfo *tri = mf_.getTarget().getRegisterInfo(); - const TargetRegisterClass *orc = mri.getRegClass(reg); - SmallPtrSet rcs; + MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); + const TargetRegisterClass *OldRC = MRI.getRegClass(reg); + const TargetRegisterClass *NewRC = TRI->getLargestLegalSuperClass(OldRC); - for (MachineRegisterInfo::reg_nodbg_iterator I = mri.reg_nodbg_begin(reg), - E = mri.reg_nodbg_end(); I != E; ++I) { - // The targets don't have accurate enough regclass descriptions that we can - // handle subregs. We need something similar to - // TRI::getMatchingSuperRegClass, but returning a super class instead of a - // sub class. - if (I.getOperand().getSubReg()) { - DEBUG(dbgs() << "Cannot handle subregs: " << I.getOperand() << '\n'); + // Stop early if there is no room to grow. + if (NewRC == OldRC) + return; + + // Accumulate constraints from all uses. + for (MachineRegisterInfo::reg_nodbg_iterator I = MRI.reg_nodbg_begin(reg), + E = MRI.reg_nodbg_end(); I != E; ++I) { + // TRI doesn't have accurate enough information to model this yet. + if (I.getOperand().getSubReg()) + return; + const TargetRegisterClass *OpRC = + I->getDesc().getRegClass(I.getOperandNo(), TRI); + if (OpRC) + NewRC = getCommonSubClass(NewRC, OpRC); + if (!NewRC || NewRC == OldRC) return; - } - if (const TargetRegisterClass *rc = - I->getDesc().getRegClass(I.getOperandNo(), tri)) - rcs.insert(rc); } - - // If we found no regclass constraints, just leave reg as is. - // In theory, we could inflate to the largest superclass of reg's existing - // class, but that might not be legal for the current cpu setting. - // This could happen if reg is only used by COPY instructions, so we may need - // to improve on this. - if (rcs.empty()) { - return; - } - - // Compute the intersection of all classes in rcs. - // This ought to be independent of iteration order, but if the target register - // classes don't form a proper algebra, it is possible to get different - // results. The solution is to make sure the intersection of any two register - // classes is also a register class or the null set. - const TargetRegisterClass *rc = 0; - for (SmallPtrSet::iterator I = rcs.begin(), - E = rcs.end(); I != E; ++I) { - rc = rc ? getCommonSubClass(rc, *I) : *I; - assert(rc && "Incompatible regclass constraints found"); - } - - if (rc == orc) - return; - DEBUG(dbgs() << "Inflating " << orc->getName() << ':' << PrintReg(reg) - << " to " << rc->getName() <<".\n"); - mri.setRegClass(reg, rc); + DEBUG(dbgs() << "Inflating " << OldRC->getName() << ':' << PrintReg(reg) + << " to " << NewRC->getName() <<".\n"); + MRI.setRegClass(reg, NewRC); } diff --git a/contrib/llvm/lib/CodeGen/CallingConvLower.cpp b/contrib/llvm/lib/CodeGen/CallingConvLower.cpp index 2ad80b4d3a75..bfb6ba10234f 100644 --- a/contrib/llvm/lib/CodeGen/CallingConvLower.cpp +++ b/contrib/llvm/lib/CodeGen/CallingConvLower.cpp @@ -19,15 +19,18 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetLowering.h" using namespace llvm; CCState::CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &tm, SmallVector &locs, LLVMContext &C) : CallingConv(CC), IsVarArg(isVarArg), TM(tm), - TRI(*TM.getRegisterInfo()), Locs(locs), Context(C) { + TRI(*TM.getRegisterInfo()), Locs(locs), Context(C), + CallOrPrologue(Invalid) { // No stack is used. StackOffset = 0; + clearFirstByValReg(); UsedRegs.resize((TRI.getNumRegs()+31)/32); } @@ -44,8 +47,8 @@ void CCState::HandleByVal(unsigned ValNo, MVT ValVT, Size = MinSize; if (MinAlign > (int)Align) Align = MinAlign; + TM.getTargetLowering()->HandleByVal(const_cast(this), Size); unsigned Offset = AllocateStack(Size, Align); - addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); } @@ -155,7 +158,7 @@ void CCState::AnalyzeCallResult(const SmallVectorImpl &Ins, if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this)) { #ifndef NDEBUG dbgs() << "Call result #" << i << " has unhandled type " - << EVT(VT).getEVTString(); + << EVT(VT).getEVTString() << "\n"; #endif llvm_unreachable(0); } diff --git a/contrib/llvm/lib/CodeGen/CodePlacementOpt.cpp b/contrib/llvm/lib/CodeGen/CodePlacementOpt.cpp index 91a9536e7757..270c337ef67e 100644 --- a/contrib/llvm/lib/CodeGen/CodePlacementOpt.cpp +++ b/contrib/llvm/lib/CodeGen/CodePlacementOpt.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file implements the pass that optimize code placement and align loop -// headers to target specific alignment boundary. +// This file implements the pass that optimizes code placement and aligns loop +// headers to target-specific alignment boundaries. // //===----------------------------------------------------------------------===// @@ -40,7 +40,7 @@ namespace { virtual bool runOnMachineFunction(MachineFunction &MF); virtual const char *getPassName() const { - return "Code Placement Optimizater"; + return "Code Placement Optimizer"; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { @@ -254,7 +254,7 @@ bool CodePlacementOpt::MoveDiscontiguousLoopBlocks(MachineFunction &MF, // Determine a position to move orphaned loop blocks to. If TopMBB is not // entered via fallthrough and BotMBB is exited via fallthrough, prepend them - // to the top of the loop to avoid loosing that fallthrough. Otherwise append + // to the top of the loop to avoid losing that fallthrough. Otherwise append // them to the bottom, even if it previously had a fallthrough, on the theory // that it's worth an extra branch to keep the loop contiguous. MachineFunction::iterator InsertPt = diff --git a/contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp index 0ebb5b0db70e..34b1a396bb72 100644 --- a/contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp +++ b/contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp @@ -93,7 +93,8 @@ namespace { /// with the eh.exception call. This recursively looks past instructions /// which don't change the EH pointer value, like casts or PHI nodes. bool FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke, - SmallPtrSet &SelCalls); + SmallPtrSet &SelCalls, + SmallPtrSet &SeenPHIs); public: static char ID; // Pass identification, replacement for typeid. @@ -199,8 +200,8 @@ bool DwarfEHPrepare::CleanupSelectors(SmallPtrSet &Sels) { /// change the EH pointer value, like casts or PHI nodes. bool DwarfEHPrepare::FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke, - SmallPtrSet &SelCalls) { - SmallPtrSet SeenPHIs; + SmallPtrSet &SelCalls, + SmallPtrSet &SeenPHIs) { bool Changed = false; for (Value::use_iterator @@ -215,11 +216,11 @@ DwarfEHPrepare::FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke, if (Invoke->getCalledFunction() == URoR) URoRInvoke = true; } else if (CastInst *CI = dyn_cast(II)) { - Changed |= FindSelectorAndURoR(CI, URoRInvoke, SelCalls); + Changed |= FindSelectorAndURoR(CI, URoRInvoke, SelCalls, SeenPHIs); } else if (PHINode *PN = dyn_cast(II)) { if (SeenPHIs.insert(PN)) // Don't process a PHI node more than once. - Changed |= FindSelectorAndURoR(PN, URoRInvoke, SelCalls); + Changed |= FindSelectorAndURoR(PN, URoRInvoke, SelCalls, SeenPHIs); } } @@ -294,7 +295,8 @@ bool DwarfEHPrepare::HandleURoRInvokes() { bool URoRInvoke = false; SmallPtrSet SelCalls; - Changed |= FindSelectorAndURoR(EHPtr, URoRInvoke, SelCalls); + SmallPtrSet SeenPHIs; + Changed |= FindSelectorAndURoR(EHPtr, URoRInvoke, SelCalls, SeenPHIs); if (URoRInvoke) { // This EH pointer is being used by an invoke of an URoR instruction and @@ -437,8 +439,9 @@ bool DwarfEHPrepare::NormalizeLandingPads() { if (InVal == 0) { // Different unwind edges have different values. Create a new PHI node // in NewBB. - PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName()+".unwind", - NewBB); + PHINode *NewPN = PHINode::Create(PN->getType(), + PN->getNumIncomingValues(), + PN->getName()+".unwind", NewBB); // Add an entry for each unwind edge, using the value from the old PHI. for (pred_iterator PI = PB; PI != PE; ++PI) NewPN->addIncoming(PN->getIncomingValueForBlock(*PI), *PI); diff --git a/contrib/llvm/lib/CodeGen/ELF.h b/contrib/llvm/lib/CodeGen/ELF.h index e08feeb27539..5b634682cc87 100644 --- a/contrib/llvm/lib/CodeGen/ELF.h +++ b/contrib/llvm/lib/CodeGen/ELF.h @@ -173,7 +173,7 @@ namespace llvm { unsigned Offset; // sh_offset - Offset from the file start unsigned Size; // sh_size - The section size. unsigned Link; // sh_link - Section header table index link. - unsigned Info; // sh_info - Auxillary information. + unsigned Info; // sh_info - Auxiliary information. unsigned Align; // sh_addralign - Alignment of section. unsigned EntSize; // sh_entsize - Size of entries in the section e diff --git a/contrib/llvm/lib/CodeGen/ELFWriter.cpp b/contrib/llvm/lib/CodeGen/ELFWriter.cpp index 0fd1e8e83bd7..fa2319bff704 100644 --- a/contrib/llvm/lib/CodeGen/ELFWriter.cpp +++ b/contrib/llvm/lib/CodeGen/ELFWriter.cpp @@ -77,7 +77,7 @@ ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm) // Create the object code emitter object for this target. ElfCE = new ELFCodeEmitter(*this); - // Inital number of sections + // Initial number of sections NumSections = 0; } @@ -660,19 +660,21 @@ bool ELFWriter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { /// EmitXXStructorList - Emit the ctor or dtor list. This just emits out the /// function pointers, ignoring the init priority. void ELFWriter::EmitXXStructorList(Constant *List, ELFSection &Xtor) { - // Should be an array of '{ int, void ()* }' structs. The first value is the + // Should be an array of '{ i32, void ()* }' structs. The first value is the // init priority, which we ignore. - if (!isa(List)) return; + if (List->isNullValue()) return; ConstantArray *InitList = cast(List); - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) - if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ - if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + if (InitList->getOperand(i)->isNullValue()) + continue; + ConstantStruct *CS = cast(InitList->getOperand(i)); - if (CS->getOperand(1)->isNullValue()) - return; // Found a null terminator, exit printing. - // Emit the function pointer. - EmitGlobalConstant(CS->getOperand(1), Xtor); - } + if (CS->getOperand(1)->isNullValue()) + continue; + + // Emit the function pointer. + EmitGlobalConstant(CS->getOperand(1), Xtor); + } } bool ELFWriter::runOnMachineFunction(MachineFunction &MF) { diff --git a/contrib/llvm/lib/CodeGen/EdgeBundles.cpp b/contrib/llvm/lib/CodeGen/EdgeBundles.cpp index aed8bc947991..646e01407a4f 100644 --- a/contrib/llvm/lib/CodeGen/EdgeBundles.cpp +++ b/contrib/llvm/lib/CodeGen/EdgeBundles.cpp @@ -53,6 +53,19 @@ bool EdgeBundles::runOnMachineFunction(MachineFunction &mf) { EC.compress(); if (ViewEdgeBundles) view(); + + // Compute the reverse mapping. + Blocks.clear(); + Blocks.resize(getNumBundles()); + + for (unsigned i = 0, e = MF->getNumBlockIDs(); i != e; ++i) { + unsigned b0 = getBundle(i, 0); + unsigned b1 = getBundle(i, 1); + Blocks[b0].push_back(i); + if (b1 != b0) + Blocks[b1].push_back(i); + } + return false; } @@ -82,5 +95,3 @@ raw_ostream &llvm::WriteGraph(raw_ostream &O, const EdgeBundles &G, O << "}\n"; return O; } - - diff --git a/contrib/llvm/lib/CodeGen/ExpandISelPseudos.cpp b/contrib/llvm/lib/CodeGen/ExpandISelPseudos.cpp index b5ec303f5d93..ebc2fc91efa3 100644 --- a/contrib/llvm/lib/CodeGen/ExpandISelPseudos.cpp +++ b/contrib/llvm/lib/CodeGen/ExpandISelPseudos.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// Expand Psuedo-instructions produced by ISel. These are usually to allow +// Expand Pseudo-instructions produced by ISel. These are usually to allow // the expansion to contain control flow, such as a conditional move // implemented with a conditional branch and a phi, or an atomic operation // implemented with a loop. diff --git a/contrib/llvm/lib/CodeGen/IfConversion.cpp b/contrib/llvm/lib/CodeGen/IfConversion.cpp index db53b0473a9a..790200b8df5f 100644 --- a/contrib/llvm/lib/CodeGen/IfConversion.cpp +++ b/contrib/llvm/lib/CodeGen/IfConversion.cpp @@ -27,7 +27,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" @@ -146,10 +145,6 @@ namespace { : BBI(b), Kind(k), NeedSubsumption(s), NumDups(d), NumDups2(d2) {} }; - /// Roots - Basic blocks that do not have successors. These are the starting - /// points of Graph traversal. - std::vector Roots; - /// BBAnalysis - Results of if-conversion feasibility analysis indexed by /// basic block number. std::vector BBAnalysis; @@ -287,11 +282,6 @@ bool IfConverter::runOnMachineFunction(MachineFunction &MF) { MF.RenumberBlocks(); BBAnalysis.resize(MF.getNumBlockIDs()); - // Look for root nodes, i.e. blocks without successors. - for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) - if (I->succ_empty()) - Roots.push_back(I); - std::vector Tokens; MadeChange = false; unsigned NumIfCvts = NumSimple + NumSimpleFalse + NumTriangle + @@ -406,7 +396,6 @@ bool IfConverter::runOnMachineFunction(MachineFunction &MF) { } Tokens.clear(); - Roots.clear(); BBAnalysis.clear(); if (MadeChange && IfCvtBranchFold) { @@ -924,13 +913,9 @@ IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB, /// candidates. void IfConverter::AnalyzeBlocks(MachineFunction &MF, std::vector &Tokens) { - std::set Visited; - for (unsigned i = 0, e = Roots.size(); i != e; ++i) { - for (idf_ext_iterator I=idf_ext_begin(Roots[i],Visited), - E = idf_ext_end(Roots[i], Visited); I != E; ++I) { - MachineBasicBlock *BB = *I; - AnalyzeBlock(BB, Tokens); - } + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { + MachineBasicBlock *BB = I; + AnalyzeBlock(BB, Tokens); } // Sort to favor more complex ifcvt scheme. diff --git a/contrib/llvm/lib/CodeGen/InlineSpiller.cpp b/contrib/llvm/lib/CodeGen/InlineSpiller.cpp index 38e6c8590269..b1a33a6afa42 100644 --- a/contrib/llvm/lib/CodeGen/InlineSpiller.cpp +++ b/contrib/llvm/lib/CodeGen/InlineSpiller.cpp @@ -19,41 +19,75 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -static cl::opt -VerifySpills("verify-spills", cl::desc("Verify after each spill/split")); - namespace { class InlineSpiller : public Spiller { - MachineFunctionPass &pass_; - MachineFunction &mf_; - LiveIntervals &lis_; - LiveStacks &lss_; - AliasAnalysis *aa_; - VirtRegMap &vrm_; - MachineFrameInfo &mfi_; - MachineRegisterInfo &mri_; - const TargetInstrInfo &tii_; - const TargetRegisterInfo &tri_; - const BitVector reserved_; + MachineFunctionPass &Pass; + MachineFunction &MF; + LiveIntervals &LIS; + LiveStacks &LSS; + AliasAnalysis *AA; + MachineDominatorTree &MDT; + MachineLoopInfo &Loops; + VirtRegMap &VRM; + MachineFrameInfo &MFI; + MachineRegisterInfo &MRI; + const TargetInstrInfo &TII; + const TargetRegisterInfo &TRI; // Variables that are valid during spill(), but used by multiple methods. - LiveRangeEdit *edit_; - const TargetRegisterClass *rc_; - int stackSlot_; + LiveRangeEdit *Edit; + LiveInterval *StackInt; + int StackSlot; + unsigned Original; + + // All registers to spill to StackSlot, including the main register. + SmallVector RegsToSpill; + + // All COPY instructions to/from snippets. + // They are ignored since both operands refer to the same stack slot. + SmallPtrSet SnippetCopies; // Values that failed to remat at some point. - SmallPtrSet usedValues_; + SmallPtrSet UsedValues; + + // Information about a value that was defined by a copy from a sibling + // register. + struct SibValueInfo { + // True when all reaching defs were reloads: No spill is necessary. + bool AllDefsAreReloads; + + // The preferred register to spill. + unsigned SpillReg; + + // The value of SpillReg that should be spilled. + VNInfo *SpillVNI; + + // A defining instruction that is not a sibling copy or a reload, or NULL. + // This can be used as a template for rematerialization. + MachineInstr *DefMI; + + SibValueInfo(unsigned Reg, VNInfo *VNI) + : AllDefsAreReloads(false), SpillReg(Reg), SpillVNI(VNI), DefMI(0) {} + }; + + // Values in RegsToSpill defined by sibling copies. + typedef DenseMap SibValueMap; + SibValueMap SibValues; + + // Dead defs generated during spilling. + SmallVector DeadDefs; ~InlineSpiller() {} @@ -61,34 +95,52 @@ class InlineSpiller : public Spiller { InlineSpiller(MachineFunctionPass &pass, MachineFunction &mf, VirtRegMap &vrm) - : pass_(pass), - mf_(mf), - lis_(pass.getAnalysis()), - lss_(pass.getAnalysis()), - aa_(&pass.getAnalysis()), - vrm_(vrm), - mfi_(*mf.getFrameInfo()), - mri_(mf.getRegInfo()), - tii_(*mf.getTarget().getInstrInfo()), - tri_(*mf.getTarget().getRegisterInfo()), - reserved_(tri_.getReservedRegs(mf_)) {} - - void spill(LiveInterval *li, - SmallVectorImpl &newIntervals, - const SmallVectorImpl &spillIs); + : Pass(pass), + MF(mf), + LIS(pass.getAnalysis()), + LSS(pass.getAnalysis()), + AA(&pass.getAnalysis()), + MDT(pass.getAnalysis()), + Loops(pass.getAnalysis()), + VRM(vrm), + MFI(*mf.getFrameInfo()), + MRI(mf.getRegInfo()), + TII(*mf.getTarget().getInstrInfo()), + TRI(*mf.getTarget().getRegisterInfo()) {} void spill(LiveRangeEdit &); private: - bool reMaterializeFor(MachineBasicBlock::iterator MI); + bool isSnippet(const LiveInterval &SnipLI); + void collectRegsToSpill(); + + bool isRegToSpill(unsigned Reg) { + return std::find(RegsToSpill.begin(), + RegsToSpill.end(), Reg) != RegsToSpill.end(); + } + + bool isSibling(unsigned Reg); + MachineInstr *traceSiblingValue(unsigned, VNInfo*, VNInfo*); + void analyzeSiblingValues(); + + bool hoistSpill(LiveInterval &SpillLI, MachineInstr *CopyMI); + void eliminateRedundantSpills(LiveInterval &LI, VNInfo *VNI); + + void markValueUsed(LiveInterval*, VNInfo*); + bool reMaterializeFor(LiveInterval&, MachineBasicBlock::iterator MI); void reMaterializeAll(); - bool coalesceStackAccess(MachineInstr *MI); + bool coalesceStackAccess(MachineInstr *MI, unsigned Reg); bool foldMemoryOperand(MachineBasicBlock::iterator MI, const SmallVectorImpl &Ops, MachineInstr *LoadMI = 0); - void insertReload(LiveInterval &NewLI, MachineBasicBlock::iterator MI); - void insertSpill(LiveInterval &NewLI, MachineBasicBlock::iterator MI); + void insertReload(LiveInterval &NewLI, SlotIndex, + MachineBasicBlock::iterator MI); + void insertSpill(LiveInterval &NewLI, const LiveInterval &OldLI, + SlotIndex, MachineBasicBlock::iterator MI); + + void spillAroundUses(unsigned Reg); + void spillAll(); }; } @@ -96,45 +148,489 @@ namespace llvm { Spiller *createInlineSpiller(MachineFunctionPass &pass, MachineFunction &mf, VirtRegMap &vrm) { - if (VerifySpills) - mf.verify(&pass, "When creating inline spiller"); return new InlineSpiller(pass, mf, vrm); } } -/// reMaterializeFor - Attempt to rematerialize before MI instead of reloading. -bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) { - SlotIndex UseIdx = lis_.getInstructionIndex(MI).getUseIndex(); - VNInfo *OrigVNI = edit_->getParent().getVNInfoAt(UseIdx); +//===----------------------------------------------------------------------===// +// Snippets +//===----------------------------------------------------------------------===// - if (!OrigVNI) { +// When spilling a virtual register, we also spill any snippets it is connected +// to. The snippets are small live ranges that only have a single real use, +// leftovers from live range splitting. Spilling them enables memory operand +// folding or tightens the live range around the single use. +// +// This minimizes register pressure and maximizes the store-to-load distance for +// spill slots which can be important in tight loops. + +/// isFullCopyOf - If MI is a COPY to or from Reg, return the other register, +/// otherwise return 0. +static unsigned isFullCopyOf(const MachineInstr *MI, unsigned Reg) { + if (!MI->isCopy()) + return 0; + if (MI->getOperand(0).getSubReg() != 0) + return 0; + if (MI->getOperand(1).getSubReg() != 0) + return 0; + if (MI->getOperand(0).getReg() == Reg) + return MI->getOperand(1).getReg(); + if (MI->getOperand(1).getReg() == Reg) + return MI->getOperand(0).getReg(); + return 0; +} + +/// isSnippet - Identify if a live interval is a snippet that should be spilled. +/// It is assumed that SnipLI is a virtual register with the same original as +/// Edit->getReg(). +bool InlineSpiller::isSnippet(const LiveInterval &SnipLI) { + unsigned Reg = Edit->getReg(); + + // A snippet is a tiny live range with only a single instruction using it + // besides copies to/from Reg or spills/fills. We accept: + // + // %snip = COPY %Reg / FILL fi# + // %snip = USE %snip + // %Reg = COPY %snip / SPILL %snip, fi# + // + if (SnipLI.getNumValNums() > 2 || !LIS.intervalIsInOneMBB(SnipLI)) + return false; + + MachineInstr *UseMI = 0; + + // Check that all uses satisfy our criteria. + for (MachineRegisterInfo::reg_nodbg_iterator + RI = MRI.reg_nodbg_begin(SnipLI.reg); + MachineInstr *MI = RI.skipInstruction();) { + + // Allow copies to/from Reg. + if (isFullCopyOf(MI, Reg)) + continue; + + // Allow stack slot loads. + int FI; + if (SnipLI.reg == TII.isLoadFromStackSlot(MI, FI) && FI == StackSlot) + continue; + + // Allow stack slot stores. + if (SnipLI.reg == TII.isStoreToStackSlot(MI, FI) && FI == StackSlot) + continue; + + // Allow a single additional instruction. + if (UseMI && MI != UseMI) + return false; + UseMI = MI; + } + return true; +} + +/// collectRegsToSpill - Collect live range snippets that only have a single +/// real use. +void InlineSpiller::collectRegsToSpill() { + unsigned Reg = Edit->getReg(); + + // Main register always spills. + RegsToSpill.assign(1, Reg); + SnippetCopies.clear(); + + // Snippets all have the same original, so there can't be any for an original + // register. + if (Original == Reg) + return; + + for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Reg); + MachineInstr *MI = RI.skipInstruction();) { + unsigned SnipReg = isFullCopyOf(MI, Reg); + if (!isSibling(SnipReg)) + continue; + LiveInterval &SnipLI = LIS.getInterval(SnipReg); + if (!isSnippet(SnipLI)) + continue; + SnippetCopies.insert(MI); + if (!isRegToSpill(SnipReg)) + RegsToSpill.push_back(SnipReg); + + DEBUG(dbgs() << "\talso spill snippet " << SnipLI << '\n'); + } +} + + +//===----------------------------------------------------------------------===// +// Sibling Values +//===----------------------------------------------------------------------===// + +// After live range splitting, some values to be spilled may be defined by +// copies from sibling registers. We trace the sibling copies back to the +// original value if it still exists. We need it for rematerialization. +// +// Even when the value can't be rematerialized, we still want to determine if +// the value has already been spilled, or we may want to hoist the spill from a +// loop. + +bool InlineSpiller::isSibling(unsigned Reg) { + return TargetRegisterInfo::isVirtualRegister(Reg) && + VRM.getOriginal(Reg) == Original; +} + +/// traceSiblingValue - Trace a value that is about to be spilled back to the +/// real defining instructions by looking through sibling copies. Always stay +/// within the range of OrigVNI so the registers are known to carry the same +/// value. +/// +/// Determine if the value is defined by all reloads, so spilling isn't +/// necessary - the value is already in the stack slot. +/// +/// Return a defining instruction that may be a candidate for rematerialization. +/// +MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI, + VNInfo *OrigVNI) { + DEBUG(dbgs() << "Tracing value " << PrintReg(UseReg) << ':' + << UseVNI->id << '@' << UseVNI->def << '\n'); + SmallPtrSet Visited; + SmallVector, 8> WorkList; + WorkList.push_back(std::make_pair(UseReg, UseVNI)); + + // Best spill candidate seen so far. This must dominate UseVNI. + SibValueInfo SVI(UseReg, UseVNI); + MachineBasicBlock *UseMBB = LIS.getMBBFromIndex(UseVNI->def); + unsigned SpillDepth = Loops.getLoopDepth(UseMBB); + bool SeenOrigPHI = false; // Original PHI met. + + do { + unsigned Reg; + VNInfo *VNI; + tie(Reg, VNI) = WorkList.pop_back_val(); + if (!Visited.insert(VNI)) + continue; + + // Is this value a better spill candidate? + if (!isRegToSpill(Reg)) { + MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def); + if (MBB != UseMBB && MDT.dominates(MBB, UseMBB)) { + // This is a valid spill location dominating UseVNI. + // Prefer to spill at a smaller loop depth. + unsigned Depth = Loops.getLoopDepth(MBB); + if (Depth < SpillDepth) { + DEBUG(dbgs() << " spill depth " << Depth << ": " << PrintReg(Reg) + << ':' << VNI->id << '@' << VNI->def << '\n'); + SVI.SpillReg = Reg; + SVI.SpillVNI = VNI; + SpillDepth = Depth; + } + } + } + + // Trace through PHI-defs created by live range splitting. + if (VNI->isPHIDef()) { + if (VNI->def == OrigVNI->def) { + DEBUG(dbgs() << " orig phi value " << PrintReg(Reg) << ':' + << VNI->id << '@' << VNI->def << '\n'); + SeenOrigPHI = true; + continue; + } + // Get values live-out of predecessors. + LiveInterval &LI = LIS.getInterval(Reg); + MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def); + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + VNInfo *PVNI = LI.getVNInfoAt(LIS.getMBBEndIdx(*PI).getPrevSlot()); + if (PVNI) + WorkList.push_back(std::make_pair(Reg, PVNI)); + } + continue; + } + + MachineInstr *MI = LIS.getInstructionFromIndex(VNI->def); + assert(MI && "Missing def"); + + // Trace through sibling copies. + if (unsigned SrcReg = isFullCopyOf(MI, Reg)) { + if (isSibling(SrcReg)) { + LiveInterval &SrcLI = LIS.getInterval(SrcReg); + VNInfo *SrcVNI = SrcLI.getVNInfoAt(VNI->def.getUseIndex()); + assert(SrcVNI && "Copy from non-existing value"); + DEBUG(dbgs() << " copy of " << PrintReg(SrcReg) << ':' + << SrcVNI->id << '@' << SrcVNI->def << '\n'); + WorkList.push_back(std::make_pair(SrcReg, SrcVNI)); + continue; + } + } + + // Track reachable reloads. + int FI; + if (Reg == TII.isLoadFromStackSlot(MI, FI) && FI == StackSlot) { + DEBUG(dbgs() << " reload " << PrintReg(Reg) << ':' + << VNI->id << "@" << VNI->def << '\n'); + SVI.AllDefsAreReloads = true; + continue; + } + + // We have an 'original' def. Don't record trivial cases. + if (VNI == UseVNI) { + DEBUG(dbgs() << "Not a sibling copy.\n"); + return MI; + } + + // Potential remat candidate. + DEBUG(dbgs() << " def " << PrintReg(Reg) << ':' + << VNI->id << '@' << VNI->def << '\t' << *MI); + SVI.DefMI = MI; + } while (!WorkList.empty()); + + if (SeenOrigPHI || SVI.DefMI) + SVI.AllDefsAreReloads = false; + + DEBUG({ + if (SVI.AllDefsAreReloads) + dbgs() << "All defs are reloads.\n"; + else + dbgs() << "Prefer to spill " << PrintReg(SVI.SpillReg) << ':' + << SVI.SpillVNI->id << '@' << SVI.SpillVNI->def << '\n'; + }); + SibValues.insert(std::make_pair(UseVNI, SVI)); + return SVI.DefMI; +} + +/// analyzeSiblingValues - Trace values defined by sibling copies back to +/// something that isn't a sibling copy. +/// +/// Keep track of values that may be rematerializable. +void InlineSpiller::analyzeSiblingValues() { + SibValues.clear(); + + // No siblings at all? + if (Edit->getReg() == Original) + return; + + LiveInterval &OrigLI = LIS.getInterval(Original); + for (unsigned i = 0, e = RegsToSpill.size(); i != e; ++i) { + unsigned Reg = RegsToSpill[i]; + LiveInterval &LI = LIS.getInterval(Reg); + for (LiveInterval::const_vni_iterator VI = LI.vni_begin(), + VE = LI.vni_end(); VI != VE; ++VI) { + VNInfo *VNI = *VI; + if (VNI->isUnused()) + continue; + MachineInstr *DefMI = 0; + // Check possible sibling copies. + if (VNI->isPHIDef() || VNI->getCopy()) { + VNInfo *OrigVNI = OrigLI.getVNInfoAt(VNI->def); + if (OrigVNI->def != VNI->def) + DefMI = traceSiblingValue(Reg, VNI, OrigVNI); + } + if (!DefMI && !VNI->isPHIDef()) + DefMI = LIS.getInstructionFromIndex(VNI->def); + if (DefMI && Edit->checkRematerializable(VNI, DefMI, TII, AA)) { + DEBUG(dbgs() << "Value " << PrintReg(Reg) << ':' << VNI->id << '@' + << VNI->def << " may remat from " << *DefMI); + } + } + } +} + +/// hoistSpill - Given a sibling copy that defines a value to be spilled, insert +/// a spill at a better location. +bool InlineSpiller::hoistSpill(LiveInterval &SpillLI, MachineInstr *CopyMI) { + SlotIndex Idx = LIS.getInstructionIndex(CopyMI); + VNInfo *VNI = SpillLI.getVNInfoAt(Idx.getDefIndex()); + assert(VNI && VNI->def == Idx.getDefIndex() && "Not defined by copy"); + SibValueMap::iterator I = SibValues.find(VNI); + if (I == SibValues.end()) + return false; + + const SibValueInfo &SVI = I->second; + + // Let the normal folding code deal with the boring case. + if (!SVI.AllDefsAreReloads && SVI.SpillVNI == VNI) + return false; + + // SpillReg may have been deleted by remat and DCE. + if (!LIS.hasInterval(SVI.SpillReg)) { + DEBUG(dbgs() << "Stale interval: " << PrintReg(SVI.SpillReg) << '\n'); + SibValues.erase(I); + return false; + } + + LiveInterval &SibLI = LIS.getInterval(SVI.SpillReg); + if (!SibLI.containsValue(SVI.SpillVNI)) { + DEBUG(dbgs() << "Stale value: " << PrintReg(SVI.SpillReg) << '\n'); + SibValues.erase(I); + return false; + } + + // Conservatively extend the stack slot range to the range of the original + // value. We may be able to do better with stack slot coloring by being more + // careful here. + assert(StackInt && "No stack slot assigned yet."); + LiveInterval &OrigLI = LIS.getInterval(Original); + VNInfo *OrigVNI = OrigLI.getVNInfoAt(Idx); + StackInt->MergeValueInAsValue(OrigLI, OrigVNI, StackInt->getValNumInfo(0)); + DEBUG(dbgs() << "\tmerged orig valno " << OrigVNI->id << ": " + << *StackInt << '\n'); + + // Already spilled everywhere. + if (SVI.AllDefsAreReloads) + return true; + + // We are going to spill SVI.SpillVNI immediately after its def, so clear out + // any later spills of the same value. + eliminateRedundantSpills(SibLI, SVI.SpillVNI); + + MachineBasicBlock *MBB = LIS.getMBBFromIndex(SVI.SpillVNI->def); + MachineBasicBlock::iterator MII; + if (SVI.SpillVNI->isPHIDef()) + MII = MBB->SkipPHIsAndLabels(MBB->begin()); + else { + MachineInstr *DefMI = LIS.getInstructionFromIndex(SVI.SpillVNI->def); + assert(DefMI && "Defining instruction disappeared"); + MII = DefMI; + ++MII; + } + // Insert spill without kill flag immediately after def. + TII.storeRegToStackSlot(*MBB, MII, SVI.SpillReg, false, StackSlot, + MRI.getRegClass(SVI.SpillReg), &TRI); + --MII; // Point to store instruction. + LIS.InsertMachineInstrInMaps(MII); + VRM.addSpillSlotUse(StackSlot, MII); + DEBUG(dbgs() << "\thoisted: " << SVI.SpillVNI->def << '\t' << *MII); + return true; +} + +/// eliminateRedundantSpills - SLI:VNI is known to be on the stack. Remove any +/// redundant spills of this value in SLI.reg and sibling copies. +void InlineSpiller::eliminateRedundantSpills(LiveInterval &SLI, VNInfo *VNI) { + assert(VNI && "Missing value"); + SmallVector, 8> WorkList; + WorkList.push_back(std::make_pair(&SLI, VNI)); + assert(StackInt && "No stack slot assigned yet."); + + do { + LiveInterval *LI; + tie(LI, VNI) = WorkList.pop_back_val(); + unsigned Reg = LI->reg; + DEBUG(dbgs() << "Checking redundant spills for " + << VNI->id << '@' << VNI->def << " in " << *LI << '\n'); + + // Regs to spill are taken care of. + if (isRegToSpill(Reg)) + continue; + + // Add all of VNI's live range to StackInt. + StackInt->MergeValueInAsValue(*LI, VNI, StackInt->getValNumInfo(0)); + DEBUG(dbgs() << "Merged to stack int: " << *StackInt << '\n'); + + // Find all spills and copies of VNI. + for (MachineRegisterInfo::use_nodbg_iterator UI = MRI.use_nodbg_begin(Reg); + MachineInstr *MI = UI.skipInstruction();) { + if (!MI->isCopy() && !MI->getDesc().mayStore()) + continue; + SlotIndex Idx = LIS.getInstructionIndex(MI); + if (LI->getVNInfoAt(Idx) != VNI) + continue; + + // Follow sibling copies down the dominator tree. + if (unsigned DstReg = isFullCopyOf(MI, Reg)) { + if (isSibling(DstReg)) { + LiveInterval &DstLI = LIS.getInterval(DstReg); + VNInfo *DstVNI = DstLI.getVNInfoAt(Idx.getDefIndex()); + assert(DstVNI && "Missing defined value"); + assert(DstVNI->def == Idx.getDefIndex() && "Wrong copy def slot"); + WorkList.push_back(std::make_pair(&DstLI, DstVNI)); + } + continue; + } + + // Erase spills. + int FI; + if (Reg == TII.isStoreToStackSlot(MI, FI) && FI == StackSlot) { + DEBUG(dbgs() << "Redundant spill " << Idx << '\t' << *MI); + // eliminateDeadDefs won't normally remove stores, so switch opcode. + MI->setDesc(TII.get(TargetOpcode::KILL)); + DeadDefs.push_back(MI); + } + } + } while (!WorkList.empty()); +} + + +//===----------------------------------------------------------------------===// +// Rematerialization +//===----------------------------------------------------------------------===// + +/// markValueUsed - Remember that VNI failed to rematerialize, so its defining +/// instruction cannot be eliminated. See through snippet copies +void InlineSpiller::markValueUsed(LiveInterval *LI, VNInfo *VNI) { + SmallVector, 8> WorkList; + WorkList.push_back(std::make_pair(LI, VNI)); + do { + tie(LI, VNI) = WorkList.pop_back_val(); + if (!UsedValues.insert(VNI)) + continue; + + if (VNI->isPHIDef()) { + MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def); + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + VNInfo *PVNI = LI->getVNInfoAt(LIS.getMBBEndIdx(*PI).getPrevSlot()); + if (PVNI) + WorkList.push_back(std::make_pair(LI, PVNI)); + } + continue; + } + + // Follow snippet copies. + MachineInstr *MI = LIS.getInstructionFromIndex(VNI->def); + if (!SnippetCopies.count(MI)) + continue; + LiveInterval &SnipLI = LIS.getInterval(MI->getOperand(1).getReg()); + assert(isRegToSpill(SnipLI.reg) && "Unexpected register in copy"); + VNInfo *SnipVNI = SnipLI.getVNInfoAt(VNI->def.getUseIndex()); + assert(SnipVNI && "Snippet undefined before copy"); + WorkList.push_back(std::make_pair(&SnipLI, SnipVNI)); + } while (!WorkList.empty()); +} + +/// reMaterializeFor - Attempt to rematerialize before MI instead of reloading. +bool InlineSpiller::reMaterializeFor(LiveInterval &VirtReg, + MachineBasicBlock::iterator MI) { + SlotIndex UseIdx = LIS.getInstructionIndex(MI).getUseIndex(); + VNInfo *ParentVNI = VirtReg.getVNInfoAt(UseIdx); + + if (!ParentVNI) { DEBUG(dbgs() << "\tadding flags: "); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isUse() && MO.getReg() == edit_->getReg()) + if (MO.isReg() && MO.isUse() && MO.getReg() == VirtReg.reg) MO.setIsUndef(); } DEBUG(dbgs() << UseIdx << '\t' << *MI); return true; } - LiveRangeEdit::Remat RM(OrigVNI); - if (!edit_->canRematerializeAt(RM, UseIdx, false, lis_)) { - usedValues_.insert(OrigVNI); + if (SnippetCopies.count(MI)) + return false; + + // Use an OrigVNI from traceSiblingValue when ParentVNI is a sibling copy. + LiveRangeEdit::Remat RM(ParentVNI); + SibValueMap::const_iterator SibI = SibValues.find(ParentVNI); + if (SibI != SibValues.end()) + RM.OrigMI = SibI->second.DefMI; + if (!Edit->canRematerializeAt(RM, UseIdx, false, LIS)) { + markValueUsed(&VirtReg, ParentVNI); DEBUG(dbgs() << "\tcannot remat for " << UseIdx << '\t' << *MI); return false; } - // If the instruction also writes edit_->getReg(), it had better not require - // the same register for uses and defs. + // If the instruction also writes VirtReg.reg, it had better not require the + // same register for uses and defs. bool Reads, Writes; SmallVector Ops; - tie(Reads, Writes) = MI->readsWritesVirtualRegister(edit_->getReg(), &Ops); + tie(Reads, Writes) = MI->readsWritesVirtualRegister(VirtReg.reg, &Ops); if (Writes) { for (unsigned i = 0, e = Ops.size(); i != e; ++i) { MachineOperand &MO = MI->getOperand(Ops[i]); if (MO.isUse() ? MI->isRegTiedToDefOperand(Ops[i]) : MO.getSubReg()) { - usedValues_.insert(OrigVNI); + markValueUsed(&VirtReg, ParentVNI); DEBUG(dbgs() << "\tcannot remat tied reg: " << UseIdx << '\t' << *MI); return false; } @@ -145,35 +641,31 @@ bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) { // fold a load into the instruction. That avoids allocating a new register. if (RM.OrigMI->getDesc().canFoldAsLoad() && foldMemoryOperand(MI, Ops, RM.OrigMI)) { - edit_->markRematerialized(RM.ParentVNI); + Edit->markRematerialized(RM.ParentVNI); return true; } // Alocate a new register for the remat. - LiveInterval &NewLI = edit_->create(mri_, lis_, vrm_); + LiveInterval &NewLI = Edit->createFrom(Original, LIS, VRM); NewLI.markNotSpillable(); - // Rematting for a copy: Set allocation hint to be the destination register. - if (MI->isCopy()) - mri_.setRegAllocationHint(NewLI.reg, 0, MI->getOperand(0).getReg()); - // Finally we can rematerialize OrigMI before MI. - SlotIndex DefIdx = edit_->rematerializeAt(*MI->getParent(), MI, NewLI.reg, RM, - lis_, tii_, tri_); + SlotIndex DefIdx = Edit->rematerializeAt(*MI->getParent(), MI, NewLI.reg, RM, + LIS, TII, TRI); DEBUG(dbgs() << "\tremat: " << DefIdx << '\t' - << *lis_.getInstructionFromIndex(DefIdx)); + << *LIS.getInstructionFromIndex(DefIdx)); // Replace operands for (unsigned i = 0, e = Ops.size(); i != e; ++i) { MachineOperand &MO = MI->getOperand(Ops[i]); - if (MO.isReg() && MO.isUse() && MO.getReg() == edit_->getReg()) { + if (MO.isReg() && MO.isUse() && MO.getReg() == VirtReg.reg) { MO.setReg(NewLI.reg); MO.setIsKill(); } } DEBUG(dbgs() << "\t " << UseIdx << '\t' << *MI); - VNInfo *DefVNI = NewLI.getNextValue(DefIdx, 0, lis_.getVNInfoAllocator()); + VNInfo *DefVNI = NewLI.getNextValue(DefIdx, 0, LIS.getVNInfoAllocator()); NewLI.addRange(LiveRange(DefIdx, UseIdx.getDefIndex(), DefVNI)); DEBUG(dbgs() << "\tinterval: " << NewLI << '\n'); return true; @@ -182,75 +674,85 @@ bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) { /// reMaterializeAll - Try to rematerialize as many uses as possible, /// and trim the live ranges after. void InlineSpiller::reMaterializeAll() { - // Do a quick scan of the interval values to find if any are remattable. - if (!edit_->anyRematerializable(lis_, tii_, aa_)) + // analyzeSiblingValues has already tested all relevant defining instructions. + if (!Edit->anyRematerializable(LIS, TII, AA)) return; - usedValues_.clear(); + UsedValues.clear(); - // Try to remat before all uses of edit_->getReg(). + // Try to remat before all uses of snippets. bool anyRemat = false; - for (MachineRegisterInfo::use_nodbg_iterator - RI = mri_.use_nodbg_begin(edit_->getReg()); - MachineInstr *MI = RI.skipInstruction();) - anyRemat |= reMaterializeFor(MI); - + for (unsigned i = 0, e = RegsToSpill.size(); i != e; ++i) { + unsigned Reg = RegsToSpill[i]; + LiveInterval &LI = LIS.getInterval(Reg); + for (MachineRegisterInfo::use_nodbg_iterator + RI = MRI.use_nodbg_begin(Reg); + MachineInstr *MI = RI.skipInstruction();) + anyRemat |= reMaterializeFor(LI, MI); + } if (!anyRemat) return; // Remove any values that were completely rematted. - bool anyRemoved = false; - for (LiveInterval::vni_iterator I = edit_->getParent().vni_begin(), - E = edit_->getParent().vni_end(); I != E; ++I) { - VNInfo *VNI = *I; - if (VNI->hasPHIKill() || !edit_->didRematerialize(VNI) || - usedValues_.count(VNI)) - continue; - MachineInstr *DefMI = lis_.getInstructionFromIndex(VNI->def); - DEBUG(dbgs() << "\tremoving dead def: " << VNI->def << '\t' << *DefMI); - lis_.RemoveMachineInstrFromMaps(DefMI); - vrm_.RemoveMachineInstrFromMaps(DefMI); - DefMI->eraseFromParent(); - VNI->def = SlotIndex(); - anyRemoved = true; - } - - if (!anyRemoved) - return; - - // Removing values may cause debug uses where parent is not live. - for (MachineRegisterInfo::use_iterator RI = mri_.use_begin(edit_->getReg()); - MachineInstr *MI = RI.skipInstruction();) { - if (!MI->isDebugValue()) - continue; - // Try to preserve the debug value if parent is live immediately after it. - MachineBasicBlock::iterator NextMI = MI; - ++NextMI; - if (NextMI != MI->getParent()->end() && !lis_.isNotInMIMap(NextMI)) { - SlotIndex Idx = lis_.getInstructionIndex(NextMI); - VNInfo *VNI = edit_->getParent().getVNInfoAt(Idx); - if (VNI && (VNI->hasPHIKill() || usedValues_.count(VNI))) + for (unsigned i = 0, e = RegsToSpill.size(); i != e; ++i) { + unsigned Reg = RegsToSpill[i]; + LiveInterval &LI = LIS.getInterval(Reg); + for (LiveInterval::vni_iterator I = LI.vni_begin(), E = LI.vni_end(); + I != E; ++I) { + VNInfo *VNI = *I; + if (VNI->isUnused() || VNI->isPHIDef() || UsedValues.count(VNI)) continue; + MachineInstr *MI = LIS.getInstructionFromIndex(VNI->def); + MI->addRegisterDead(Reg, &TRI); + if (!MI->allDefsAreDead()) + continue; + DEBUG(dbgs() << "All defs dead: " << *MI); + DeadDefs.push_back(MI); } - DEBUG(dbgs() << "Removing debug info due to remat:" << "\t" << *MI); - MI->eraseFromParent(); } + + // Eliminate dead code after remat. Note that some snippet copies may be + // deleted here. + if (DeadDefs.empty()) + return; + DEBUG(dbgs() << "Remat created " << DeadDefs.size() << " dead defs.\n"); + Edit->eliminateDeadDefs(DeadDefs, LIS, VRM, TII); + + // Get rid of deleted and empty intervals. + for (unsigned i = RegsToSpill.size(); i != 0; --i) { + unsigned Reg = RegsToSpill[i-1]; + if (!LIS.hasInterval(Reg)) { + RegsToSpill.erase(RegsToSpill.begin() + (i - 1)); + continue; + } + LiveInterval &LI = LIS.getInterval(Reg); + if (!LI.empty()) + continue; + Edit->eraseVirtReg(Reg, LIS); + RegsToSpill.erase(RegsToSpill.begin() + (i - 1)); + } + DEBUG(dbgs() << RegsToSpill.size() << " registers to spill after remat.\n"); } -/// If MI is a load or store of stackSlot_, it can be removed. -bool InlineSpiller::coalesceStackAccess(MachineInstr *MI) { + +//===----------------------------------------------------------------------===// +// Spilling +//===----------------------------------------------------------------------===// + +/// If MI is a load or store of StackSlot, it can be removed. +bool InlineSpiller::coalesceStackAccess(MachineInstr *MI, unsigned Reg) { int FI = 0; - unsigned reg; - if (!(reg = tii_.isLoadFromStackSlot(MI, FI)) && - !(reg = tii_.isStoreToStackSlot(MI, FI))) + unsigned InstrReg; + if (!(InstrReg = TII.isLoadFromStackSlot(MI, FI)) && + !(InstrReg = TII.isStoreToStackSlot(MI, FI))) return false; // We have a stack access. Is it the right register and slot? - if (reg != edit_->getReg() || FI != stackSlot_) + if (InstrReg != Reg || FI != StackSlot) return false; DEBUG(dbgs() << "Coalescing stack access: " << *MI); - lis_.RemoveMachineInstrFromMaps(MI); + LIS.RemoveMachineInstrFromMaps(MI); MI->eraseFromParent(); return true; } @@ -283,13 +785,13 @@ bool InlineSpiller::foldMemoryOperand(MachineBasicBlock::iterator MI, } MachineInstr *FoldMI = - LoadMI ? tii_.foldMemoryOperand(MI, FoldOps, LoadMI) - : tii_.foldMemoryOperand(MI, FoldOps, stackSlot_); + LoadMI ? TII.foldMemoryOperand(MI, FoldOps, LoadMI) + : TII.foldMemoryOperand(MI, FoldOps, StackSlot); if (!FoldMI) return false; - lis_.ReplaceMachineInstrInMaps(MI, FoldMI); + LIS.ReplaceMachineInstrInMaps(MI, FoldMI); if (!LoadMI) - vrm_.addSpillSlotUse(stackSlot_, FoldMI); + VRM.addSpillSlotUse(StackSlot, FoldMI); MI->eraseFromParent(); DEBUG(dbgs() << "\tfolded: " << *FoldMI); return true; @@ -297,84 +799,40 @@ bool InlineSpiller::foldMemoryOperand(MachineBasicBlock::iterator MI, /// insertReload - Insert a reload of NewLI.reg before MI. void InlineSpiller::insertReload(LiveInterval &NewLI, + SlotIndex Idx, MachineBasicBlock::iterator MI) { MachineBasicBlock &MBB = *MI->getParent(); - SlotIndex Idx = lis_.getInstructionIndex(MI).getDefIndex(); - tii_.loadRegFromStackSlot(MBB, MI, NewLI.reg, stackSlot_, rc_, &tri_); + TII.loadRegFromStackSlot(MBB, MI, NewLI.reg, StackSlot, + MRI.getRegClass(NewLI.reg), &TRI); --MI; // Point to load instruction. - SlotIndex LoadIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex(); - vrm_.addSpillSlotUse(stackSlot_, MI); + SlotIndex LoadIdx = LIS.InsertMachineInstrInMaps(MI).getDefIndex(); + VRM.addSpillSlotUse(StackSlot, MI); DEBUG(dbgs() << "\treload: " << LoadIdx << '\t' << *MI); VNInfo *LoadVNI = NewLI.getNextValue(LoadIdx, 0, - lis_.getVNInfoAllocator()); + LIS.getVNInfoAllocator()); NewLI.addRange(LiveRange(LoadIdx, Idx, LoadVNI)); } /// insertSpill - Insert a spill of NewLI.reg after MI. -void InlineSpiller::insertSpill(LiveInterval &NewLI, - MachineBasicBlock::iterator MI) { +void InlineSpiller::insertSpill(LiveInterval &NewLI, const LiveInterval &OldLI, + SlotIndex Idx, MachineBasicBlock::iterator MI) { MachineBasicBlock &MBB = *MI->getParent(); - - // Get the defined value. It could be an early clobber so keep the def index. - SlotIndex Idx = lis_.getInstructionIndex(MI).getDefIndex(); - VNInfo *VNI = edit_->getParent().getVNInfoAt(Idx); - assert(VNI && VNI->def.getDefIndex() == Idx && "Inconsistent VNInfo"); - Idx = VNI->def; - - tii_.storeRegToStackSlot(MBB, ++MI, NewLI.reg, true, stackSlot_, rc_, &tri_); + TII.storeRegToStackSlot(MBB, ++MI, NewLI.reg, true, StackSlot, + MRI.getRegClass(NewLI.reg), &TRI); --MI; // Point to store instruction. - SlotIndex StoreIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex(); - vrm_.addSpillSlotUse(stackSlot_, MI); + SlotIndex StoreIdx = LIS.InsertMachineInstrInMaps(MI).getDefIndex(); + VRM.addSpillSlotUse(StackSlot, MI); DEBUG(dbgs() << "\tspilled: " << StoreIdx << '\t' << *MI); - VNInfo *StoreVNI = NewLI.getNextValue(Idx, 0, lis_.getVNInfoAllocator()); + VNInfo *StoreVNI = NewLI.getNextValue(Idx, 0, LIS.getVNInfoAllocator()); NewLI.addRange(LiveRange(Idx, StoreIdx, StoreVNI)); } -void InlineSpiller::spill(LiveInterval *li, - SmallVectorImpl &newIntervals, - const SmallVectorImpl &spillIs) { - LiveRangeEdit edit(*li, newIntervals, spillIs); - spill(edit); - if (VerifySpills) - mf_.verify(&pass_, "After inline spill"); -} +/// spillAroundUses - insert spill code around each use of Reg. +void InlineSpiller::spillAroundUses(unsigned Reg) { + LiveInterval &OldLI = LIS.getInterval(Reg); -void InlineSpiller::spill(LiveRangeEdit &edit) { - edit_ = &edit; - assert(!TargetRegisterInfo::isStackSlot(edit.getReg()) - && "Trying to spill a stack slot."); - DEBUG(dbgs() << "Inline spilling " - << mri_.getRegClass(edit.getReg())->getName() - << ':' << edit.getParent() << "\nFrom original " - << PrintReg(vrm_.getOriginal(edit.getReg())) << '\n'); - assert(edit.getParent().isSpillable() && - "Attempting to spill already spilled value."); - - reMaterializeAll(); - - // Remat may handle everything. - if (edit_->getParent().empty()) - return; - - rc_ = mri_.getRegClass(edit.getReg()); - - // Share a stack slot among all descendants of Orig. - unsigned Orig = vrm_.getOriginal(edit.getReg()); - stackSlot_ = vrm_.getStackSlot(Orig); - if (stackSlot_ == VirtRegMap::NO_STACK_SLOT) - stackSlot_ = vrm_.assignVirt2StackSlot(Orig); - - if (Orig != edit.getReg()) - vrm_.assignVirt2StackSlot(edit.getReg(), stackSlot_); - - // Update LiveStacks now that we are committed to spilling. - LiveInterval &stacklvr = lss_.getOrCreateInterval(stackSlot_, rc_); - if (!stacklvr.hasAtLeastOneValue()) - stacklvr.getNextValue(SlotIndex(), 0, lss_.getVNInfoAllocator()); - stacklvr.MergeRangesInAsValue(edit_->getParent(), stacklvr.getValNumInfo(0)); - - // Iterate over instructions using register. - for (MachineRegisterInfo::reg_iterator RI = mri_.reg_begin(edit.getReg()); + // Iterate over instructions using Reg. + for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Reg); MachineInstr *MI = RI.skipInstruction();) { // Debug values are not allowed to affect codegen. @@ -383,7 +841,7 @@ void InlineSpiller::spill(LiveRangeEdit &edit) { uint64_t Offset = MI->getOperand(1).getImm(); const MDNode *MDPtr = MI->getOperand(2).getMetadata(); DebugLoc DL = MI->getDebugLoc(); - if (MachineInstr *NewDV = tii_.emitFrameIndexDebugValue(mf_, stackSlot_, + if (MachineInstr *NewDV = TII.emitFrameIndexDebugValue(MF, StackSlot, Offset, MDPtr, DL)) { DEBUG(dbgs() << "Modifying debug info due to spill:" << "\t" << *MI); MachineBasicBlock *MBB = MI->getParent(); @@ -395,14 +853,44 @@ void InlineSpiller::spill(LiveRangeEdit &edit) { continue; } + // Ignore copies to/from snippets. We'll delete them. + if (SnippetCopies.count(MI)) + continue; + // Stack slot accesses may coalesce away. - if (coalesceStackAccess(MI)) + if (coalesceStackAccess(MI, Reg)) continue; // Analyze instruction. bool Reads, Writes; SmallVector Ops; - tie(Reads, Writes) = MI->readsWritesVirtualRegister(edit.getReg(), &Ops); + tie(Reads, Writes) = MI->readsWritesVirtualRegister(Reg, &Ops); + + // Find the slot index where this instruction reads and writes OldLI. + // This is usually the def slot, except for tied early clobbers. + SlotIndex Idx = LIS.getInstructionIndex(MI).getDefIndex(); + if (VNInfo *VNI = OldLI.getVNInfoAt(Idx.getUseIndex())) + if (SlotIndex::isSameInstr(Idx, VNI->def)) + Idx = VNI->def; + + // Check for a sibling copy. + unsigned SibReg = isFullCopyOf(MI, Reg); + if (SibReg && isSibling(SibReg)) { + if (Writes) { + // Hoist the spill of a sib-reg copy. + if (hoistSpill(OldLI, MI)) { + // This COPY is now dead, the value is already in the stack slot. + MI->getOperand(0).setIsDead(); + DeadDefs.push_back(MI); + continue; + } + } else { + // This is a reload for a sib-reg copy. Drop spills downstream. + LiveInterval &SibLI = LIS.getInterval(SibReg); + eliminateRedundantSpills(SibLI, SibLI.getVNInfoAt(Idx)); + // The COPY will fold to a reload below. + } + } // Attempt to fold memory ops. if (foldMemoryOperand(MI, Ops)) @@ -410,11 +898,11 @@ void InlineSpiller::spill(LiveRangeEdit &edit) { // Allocate interval around instruction. // FIXME: Infer regclass from instruction alone. - LiveInterval &NewLI = edit.create(mri_, lis_, vrm_); + LiveInterval &NewLI = Edit->createFrom(Reg, LIS, VRM); NewLI.markNotSpillable(); if (Reads) - insertReload(NewLI, MI); + insertReload(NewLI, Idx, MI); // Rewrite instruction operands. bool hasLiveDef = false; @@ -429,11 +917,84 @@ void InlineSpiller::spill(LiveRangeEdit &edit) { hasLiveDef = true; } } + DEBUG(dbgs() << "\trewrite: " << Idx << '\t' << *MI); // FIXME: Use a second vreg if instruction has no tied ops. if (Writes && hasLiveDef) - insertSpill(NewLI, MI); + insertSpill(NewLI, OldLI, Idx, MI); DEBUG(dbgs() << "\tinterval: " << NewLI << '\n'); } } + +/// spillAll - Spill all registers remaining after rematerialization. +void InlineSpiller::spillAll() { + // Update LiveStacks now that we are committed to spilling. + if (StackSlot == VirtRegMap::NO_STACK_SLOT) { + StackSlot = VRM.assignVirt2StackSlot(Original); + StackInt = &LSS.getOrCreateInterval(StackSlot, MRI.getRegClass(Original)); + StackInt->getNextValue(SlotIndex(), 0, LSS.getVNInfoAllocator()); + } else + StackInt = &LSS.getInterval(StackSlot); + + if (Original != Edit->getReg()) + VRM.assignVirt2StackSlot(Edit->getReg(), StackSlot); + + assert(StackInt->getNumValNums() == 1 && "Bad stack interval values"); + for (unsigned i = 0, e = RegsToSpill.size(); i != e; ++i) + StackInt->MergeRangesInAsValue(LIS.getInterval(RegsToSpill[i]), + StackInt->getValNumInfo(0)); + DEBUG(dbgs() << "Merged spilled regs: " << *StackInt << '\n'); + + // Spill around uses of all RegsToSpill. + for (unsigned i = 0, e = RegsToSpill.size(); i != e; ++i) + spillAroundUses(RegsToSpill[i]); + + // Hoisted spills may cause dead code. + if (!DeadDefs.empty()) { + DEBUG(dbgs() << "Eliminating " << DeadDefs.size() << " dead defs\n"); + Edit->eliminateDeadDefs(DeadDefs, LIS, VRM, TII); + } + + // Finally delete the SnippetCopies. + for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Edit->getReg()); + MachineInstr *MI = RI.skipInstruction();) { + assert(SnippetCopies.count(MI) && "Remaining use wasn't a snippet copy"); + // FIXME: Do this with a LiveRangeEdit callback. + VRM.RemoveMachineInstrFromMaps(MI); + LIS.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + } + + // Delete all spilled registers. + for (unsigned i = 0, e = RegsToSpill.size(); i != e; ++i) + Edit->eraseVirtReg(RegsToSpill[i], LIS); +} + +void InlineSpiller::spill(LiveRangeEdit &edit) { + Edit = &edit; + assert(!TargetRegisterInfo::isStackSlot(edit.getReg()) + && "Trying to spill a stack slot."); + // Share a stack slot among all descendants of Original. + Original = VRM.getOriginal(edit.getReg()); + StackSlot = VRM.getStackSlot(Original); + StackInt = 0; + + DEBUG(dbgs() << "Inline spilling " + << MRI.getRegClass(edit.getReg())->getName() + << ':' << edit.getParent() << "\nFrom original " + << LIS.getInterval(Original) << '\n'); + assert(edit.getParent().isSpillable() && + "Attempting to spill already spilled value."); + assert(DeadDefs.empty() && "Previous spill didn't remove dead defs"); + + collectRegsToSpill(); + analyzeSiblingValues(); + reMaterializeAll(); + + // Remat may handle everything. + if (!RegsToSpill.empty()) + spillAll(); + + Edit->calculateRegClassAndHint(MF, LIS, Loops); +} diff --git a/contrib/llvm/lib/CodeGen/InterferenceCache.cpp b/contrib/llvm/lib/CodeGen/InterferenceCache.cpp new file mode 100644 index 000000000000..b1014a97fa03 --- /dev/null +++ b/contrib/llvm/lib/CodeGen/InterferenceCache.cpp @@ -0,0 +1,155 @@ +//===-- InterferenceCache.h - Caching per-block interference ---*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// InterferenceCache remembers per-block interference in LiveIntervalUnions. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "InterferenceCache.h" +#include "llvm/Target/TargetRegisterInfo.h" + +using namespace llvm; + +void InterferenceCache::init(MachineFunction *mf, + LiveIntervalUnion *liuarray, + SlotIndexes *indexes, + const TargetRegisterInfo *tri) { + MF = mf; + LIUArray = liuarray; + TRI = tri; + PhysRegEntries.assign(TRI->getNumRegs(), 0); + for (unsigned i = 0; i != CacheEntries; ++i) + Entries[i].clear(mf, indexes); +} + +InterferenceCache::Entry *InterferenceCache::get(unsigned PhysReg) { + unsigned E = PhysRegEntries[PhysReg]; + if (E < CacheEntries && Entries[E].getPhysReg() == PhysReg) { + if (!Entries[E].valid(LIUArray, TRI)) + Entries[E].revalidate(); + return &Entries[E]; + } + // No valid entry exists, pick the next round-robin entry. + E = RoundRobin; + if (++RoundRobin == CacheEntries) + RoundRobin = 0; + Entries[E].reset(PhysReg, LIUArray, TRI, MF); + PhysRegEntries[PhysReg] = E; + return &Entries[E]; +} + +/// revalidate - LIU contents have changed, update tags. +void InterferenceCache::Entry::revalidate() { + // Invalidate all block entries. + ++Tag; + // Invalidate all iterators. + PrevPos = SlotIndex(); + for (unsigned i = 0, e = Aliases.size(); i != e; ++i) + Aliases[i].second = Aliases[i].first->getTag(); +} + +void InterferenceCache::Entry::reset(unsigned physReg, + LiveIntervalUnion *LIUArray, + const TargetRegisterInfo *TRI, + const MachineFunction *MF) { + // LIU's changed, invalidate cache. + ++Tag; + PhysReg = physReg; + Blocks.resize(MF->getNumBlockIDs()); + Aliases.clear(); + for (const unsigned *AS = TRI->getOverlaps(PhysReg); *AS; ++AS) { + LiveIntervalUnion *LIU = LIUArray + *AS; + Aliases.push_back(std::make_pair(LIU, LIU->getTag())); + } + + // Reset iterators. + PrevPos = SlotIndex(); + unsigned e = Aliases.size(); + Iters.resize(e); + for (unsigned i = 0; i != e; ++i) + Iters[i].setMap(Aliases[i].first->getMap()); +} + +bool InterferenceCache::Entry::valid(LiveIntervalUnion *LIUArray, + const TargetRegisterInfo *TRI) { + unsigned i = 0, e = Aliases.size(); + for (const unsigned *AS = TRI->getOverlaps(PhysReg); *AS; ++AS, ++i) { + LiveIntervalUnion *LIU = LIUArray + *AS; + if (i == e || Aliases[i].first != LIU) + return false; + if (LIU->changedSince(Aliases[i].second)) + return false; + } + return i == e; +} + +void InterferenceCache::Entry::update(unsigned MBBNum) { + SlotIndex Start, Stop; + tie(Start, Stop) = Indexes->getMBBRange(MBBNum); + + // Use advanceTo only when possible. + if (PrevPos != Start) { + if (!PrevPos.isValid() || Start < PrevPos) + for (unsigned i = 0, e = Iters.size(); i != e; ++i) + Iters[i].find(Start); + else + for (unsigned i = 0, e = Iters.size(); i != e; ++i) + Iters[i].advanceTo(Start); + PrevPos = Start; + } + + MachineFunction::const_iterator MFI = MF->getBlockNumbered(MBBNum); + BlockInterference *BI = &Blocks[MBBNum]; + for (;;) { + BI->Tag = Tag; + BI->First = BI->Last = SlotIndex(); + + // Check for first interference. + for (unsigned i = 0, e = Iters.size(); i != e; ++i) { + Iter &I = Iters[i]; + if (!I.valid()) + continue; + SlotIndex StartI = I.start(); + if (StartI >= Stop) + continue; + if (!BI->First.isValid() || StartI < BI->First) + BI->First = StartI; + } + + PrevPos = Stop; + if (BI->First.isValid()) + break; + + // No interference in this block? Go ahead and precompute the next block. + if (++MFI == MF->end()) + return; + MBBNum = MFI->getNumber(); + BI = &Blocks[MBBNum]; + if (BI->Tag == Tag) + return; + tie(Start, Stop) = Indexes->getMBBRange(MBBNum); + } + + // Check for last interference in block. + for (unsigned i = 0, e = Iters.size(); i != e; ++i) { + Iter &I = Iters[i]; + if (!I.valid() || I.start() >= Stop) + continue; + I.advanceTo(Stop); + bool Backup = !I.valid() || I.start() >= Stop; + if (Backup) + --I; + SlotIndex StopI = I.stop(); + if (!BI->Last.isValid() || StopI > BI->Last) + BI->Last = StopI; + if (Backup) + ++I; + } +} diff --git a/contrib/llvm/lib/CodeGen/InterferenceCache.h b/contrib/llvm/lib/CodeGen/InterferenceCache.h new file mode 100644 index 000000000000..6c36fa4021fb --- /dev/null +++ b/contrib/llvm/lib/CodeGen/InterferenceCache.h @@ -0,0 +1,163 @@ +//===-- InterferenceCache.h - Caching per-block interference ---*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// InterferenceCache remembers per-block interference in LiveIntervalUnions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_INTERFERENCECACHE +#define LLVM_CODEGEN_INTERFERENCECACHE + +#include "LiveIntervalUnion.h" + +namespace llvm { + +class InterferenceCache { + const TargetRegisterInfo *TRI; + LiveIntervalUnion *LIUArray; + SlotIndexes *Indexes; + MachineFunction *MF; + + /// BlockInterference - information about the interference in a single basic + /// block. + struct BlockInterference { + BlockInterference() : Tag(0) {} + unsigned Tag; + SlotIndex First; + SlotIndex Last; + }; + + /// Entry - A cache entry containing interference information for all aliases + /// of PhysReg in all basic blocks. + class Entry { + /// PhysReg - The register currently represented. + unsigned PhysReg; + + /// Tag - Cache tag is changed when any of the underlying LiveIntervalUnions + /// change. + unsigned Tag; + + /// MF - The current function. + MachineFunction *MF; + + /// Indexes - Mapping block numbers to SlotIndex ranges. + SlotIndexes *Indexes; + + /// PrevPos - The previous position the iterators were moved to. + SlotIndex PrevPos; + + /// AliasTags - A LiveIntervalUnion pointer and tag for each alias of + /// PhysReg. + SmallVector, 8> Aliases; + + typedef LiveIntervalUnion::SegmentIter Iter; + + /// Iters - an iterator for each alias + SmallVector Iters; + + /// Blocks - Interference for each block in the function. + SmallVector Blocks; + + /// update - Recompute Blocks[MBBNum] + void update(unsigned MBBNum); + + public: + Entry() : PhysReg(0), Tag(0), Indexes(0) {} + + void clear(MachineFunction *mf, SlotIndexes *indexes) { + PhysReg = 0; + MF = mf; + Indexes = indexes; + } + + unsigned getPhysReg() const { return PhysReg; } + + void revalidate(); + + /// valid - Return true if this is a valid entry for physReg. + bool valid(LiveIntervalUnion *LIUArray, const TargetRegisterInfo *TRI); + + /// reset - Initialize entry to represent physReg's aliases. + void reset(unsigned physReg, + LiveIntervalUnion *LIUArray, + const TargetRegisterInfo *TRI, + const MachineFunction *MF); + + /// get - Return an up to date BlockInterference. + BlockInterference *get(unsigned MBBNum) { + if (Blocks[MBBNum].Tag != Tag) + update(MBBNum); + return &Blocks[MBBNum]; + } + }; + + // We don't keep a cache entry for every physical register, that would use too + // much memory. Instead, a fixed number of cache entries are used in a round- + // robin manner. + enum { CacheEntries = 32 }; + + // Point to an entry for each physreg. The entry pointed to may not be up to + // date, and it may have been reused for a different physreg. + SmallVector PhysRegEntries; + + // Next round-robin entry to be picked. + unsigned RoundRobin; + + // The actual cache entries. + Entry Entries[CacheEntries]; + + // get - Get a valid entry for PhysReg. + Entry *get(unsigned PhysReg); + +public: + InterferenceCache() : TRI(0), LIUArray(0), Indexes(0), MF(0), RoundRobin(0) {} + + /// init - Prepare cache for a new function. + void init(MachineFunction*, LiveIntervalUnion*, SlotIndexes*, + const TargetRegisterInfo *); + + /// Cursor - The primary query interface for the block interference cache. + class Cursor { + Entry *CacheEntry; + BlockInterference *Current; + public: + /// Cursor - Create a cursor for the interference allocated to PhysReg and + /// all its aliases. + Cursor(InterferenceCache &Cache, unsigned PhysReg) + : CacheEntry(Cache.get(PhysReg)), Current(0) {} + + /// moveTo - Move cursor to basic block MBBNum. + void moveToBlock(unsigned MBBNum) { + Current = CacheEntry->get(MBBNum); + } + + /// hasInterference - Return true if the current block has any interference. + bool hasInterference() { + return Current->First.isValid(); + } + + /// first - Return the starting index of the first interfering range in the + /// current block. + SlotIndex first() { + return Current->First; + } + + /// last - Return the ending index of the last interfering range in the + /// current block. + SlotIndex last() { + return Current->Last; + } + }; + + friend class Cursor; +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp index 80dfc763af69..e1dad2efa98f 100644 --- a/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -98,12 +98,6 @@ static cl::opt EnableFastISelOption("fast-isel", cl::Hidden, cl::desc("Enable the \"fast\" instruction selector")); -// Enable or disable an experimental optimization to split GEPs -// and run a special GVN pass which does not examine loads, in -// an effort to factor out redundancy implicit in complex GEPs. -static cl::opt EnableSplitGEPGVN("split-gep-gvn", cl::Hidden, - cl::desc("Split GEPs and run no-load GVN")); - LLVMTargetMachine::LLVMTargetMachine(const Target &T, const std::string &Triple) : TargetMachine(T), TargetTriple(Triple) { @@ -132,6 +126,9 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, return true; assert(Context != 0 && "Failed to get MCContext"); + if (hasMCSaveTempLabels()) + Context->setAllowTemporaryLabels(false); + const MCAsmInfo &MAI = *getMCAsmInfo(); OwningPtr AsmStreamer; @@ -139,7 +136,7 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, default: return true; case CGFT_AssemblyFile: { MCInstPrinter *InstPrinter = - getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI); + getTarget().createMCInstPrinter(*this, MAI.getAssemblerDialect(), MAI); // Create a code emitter if asked to show the encoding. MCCodeEmitter *MCE = 0; @@ -152,6 +149,7 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, MCStreamer *S = getTarget().createAsmStreamer(*Context, Out, getVerboseAsm(), hasMCUseLoc(), + hasMCUseCFI(), InstPrinter, MCE, TAB, ShowMCInst); @@ -230,11 +228,40 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, /// bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, + raw_ostream &Out, CodeGenOpt::Level OptLevel, bool DisableVerify) { // Add common CodeGen passes. if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Ctx)) return true; + + if (hasMCSaveTempLabels()) + Ctx->setAllowTemporaryLabels(false); + + // Create the code emitter for the target if it exists. If not, .o file + // emission fails. + MCCodeEmitter *MCE = getTarget().createCodeEmitter(*this, *Ctx); + TargetAsmBackend *TAB = getTarget().createAsmBackend(TargetTriple); + if (MCE == 0 || TAB == 0) + return true; + + OwningPtr AsmStreamer; + AsmStreamer.reset(getTarget().createObjectStreamer(TargetTriple, *Ctx, + *TAB, Out, MCE, + hasMCRelaxAll(), + hasMCNoExecStack())); + AsmStreamer.get()->InitSections(); + + // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. + FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer); + if (Printer == 0) + return true; + + // If successful, createAsmPrinter took ownership of AsmStreamer. + AsmStreamer.take(); + + PM.add(Printer); + // Make sure the code model is set. setCodeModelForJIT(); @@ -272,12 +299,6 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, if (!DisableVerify) PM.add(createVerifierPass()); - // Optionally, tun split-GEPs and no-load GVN. - if (EnableSplitGEPGVN) { - PM.add(createGEPSplitterPass()); - PM.add(createGVNPass(/*NoLoads=*/true)); - } - // Run loop strength reduction before anything else. if (OptLevel != CodeGenOpt::None && !DisableLSR) { PM.add(createLoopStrengthReducePass(getTargetLowering())); @@ -304,6 +325,7 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, // FALLTHROUGH case ExceptionHandling::DwarfCFI: case ExceptionHandling::DwarfTable: + case ExceptionHandling::ARM: PM.add(createDwarfEHPass(this)); break; case ExceptionHandling::None: diff --git a/contrib/llvm/lib/CodeGen/LiveDebugVariables.cpp b/contrib/llvm/lib/CodeGen/LiveDebugVariables.cpp index 853ec1ac7c13..8b214831d2cd 100644 --- a/contrib/llvm/lib/CodeGen/LiveDebugVariables.cpp +++ b/contrib/llvm/lib/CodeGen/LiveDebugVariables.cpp @@ -30,6 +30,7 @@ #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -76,6 +77,7 @@ typedef IntervalMap LocMap; /// held by the same virtual register. The equivalence class is the transitive /// closure of that relation. namespace { +class LDVImpl; class UserValue { const MDNode *variable; ///< The debug info variable we are part of. unsigned offset; ///< Byte offset into variable. @@ -99,10 +101,6 @@ class UserValue { void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo, LiveIntervals &LIS, const TargetInstrInfo &TII); - /// insertDebugKill - Insert an undef DBG_VALUE into MBB at Idx. - void insertDebugKill(MachineBasicBlock *MBB, SlotIndex Idx, - LiveIntervals &LIS, const TargetInstrInfo &TII); - public: /// UserValue - Create a new UserValue. UserValue(const MDNode *var, unsigned o, DebugLoc L, @@ -146,17 +144,31 @@ class UserValue { /// getLocationNo - Return the location number that matches Loc. unsigned getLocationNo(const MachineOperand &LocMO) { - if (LocMO.isReg() && LocMO.getReg() == 0) - return ~0u; - for (unsigned i = 0, e = locations.size(); i != e; ++i) - if (LocMO.isIdenticalTo(locations[i])) - return i; + if (LocMO.isReg()) { + if (LocMO.getReg() == 0) + return ~0u; + // For register locations we dont care about use/def and other flags. + for (unsigned i = 0, e = locations.size(); i != e; ++i) + if (locations[i].isReg() && + locations[i].getReg() == LocMO.getReg() && + locations[i].getSubReg() == LocMO.getSubReg()) + return i; + } else + for (unsigned i = 0, e = locations.size(); i != e; ++i) + if (LocMO.isIdenticalTo(locations[i])) + return i; locations.push_back(LocMO); // We are storing a MachineOperand outside a MachineInstr. locations.back().clearParent(); + // Don't store def operands. + if (locations.back().isReg()) + locations.back().setIsUse(); return locations.size() - 1; } + /// mapVirtRegs - Ensure that all virtual register locations are mapped. + void mapVirtRegs(LDVImpl *LDV); + /// addDef - Add a definition point to this value. void addDef(SlotIndex Idx, const MachineOperand &LocMO) { // Add a singular (Idx,Idx) -> Loc mapping. @@ -168,19 +180,36 @@ class UserValue { /// extendDef - Extend the current definition as far as possible down the /// dominator tree. Stop when meeting an existing def or when leaving the live /// range of VNI. + /// End points where VNI is no longer live are added to Kills. /// @param Idx Starting point for the definition. /// @param LocNo Location number to propagate. /// @param LI Restrict liveness to where LI has the value VNI. May be null. /// @param VNI When LI is not null, this is the value to restrict to. + /// @param Kills Append end points of VNI's live range to Kills. /// @param LIS Live intervals analysis. /// @param MDT Dominator tree. void extendDef(SlotIndex Idx, unsigned LocNo, LiveInterval *LI, const VNInfo *VNI, + SmallVectorImpl *Kills, LiveIntervals &LIS, MachineDominatorTree &MDT); + /// addDefsFromCopies - The value in LI/LocNo may be copies to other + /// registers. Determine if any of the copies are available at the kill + /// points, and add defs if possible. + /// @param LI Scan for copies of the value in LI->reg. + /// @param LocNo Location number of LI->reg. + /// @param Kills Points where the range of LocNo could be extended. + /// @param NewDefs Append (Idx, LocNo) of inserted defs here. + void addDefsFromCopies(LiveInterval *LI, unsigned LocNo, + const SmallVectorImpl &Kills, + SmallVectorImpl > &NewDefs, + MachineRegisterInfo &MRI, + LiveIntervals &LIS); + /// computeIntervals - Compute the live intervals of all locations after /// collecting all their def points. - void computeIntervals(LiveIntervals &LIS, MachineDominatorTree &MDT); + void computeIntervals(MachineRegisterInfo &MRI, + LiveIntervals &LIS, MachineDominatorTree &MDT); /// renameRegister - Update locations to rewrite OldReg as NewReg:SubIdx. void renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx, @@ -230,9 +259,6 @@ class LDVImpl { /// lookupVirtReg - Find the EC leader for VirtReg or null. UserValue *lookupVirtReg(unsigned VirtReg); - /// mapVirtReg - Map virtual register to an equivalence class. - void mapVirtReg(unsigned VirtReg, UserValue *EC); - /// handleDebugValue - Add DBG_VALUE instruction to our maps. /// @param MI DBG_VALUE instruction /// @param Idx Last valid SLotIndex before instruction. @@ -261,7 +287,10 @@ class LDVImpl { userVarMap.clear(); } - /// renameRegister - Replace all references to OldReg wiht NewReg:SubIdx. + /// mapVirtReg - Map virtual register to an equivalence class. + void mapVirtReg(unsigned VirtReg, UserValue *EC); + + /// renameRegister - Replace all references to OldReg with NewReg:SubIdx. void renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx); /// emitDebugVariables - Recreate DBG_VALUE instruction from data structures. @@ -322,6 +351,13 @@ void UserValue::coalesceLocation(unsigned LocNo) { } } +void UserValue::mapVirtRegs(LDVImpl *LDV) { + for (unsigned i = 0, e = locations.size(); i != e; ++i) + if (locations[i].isReg() && + TargetRegisterInfo::isVirtualRegister(locations[i].getReg())) + LDV->mapVirtReg(locations[i].getReg(), this); +} + UserValue *LDVImpl::getUserValue(const MDNode *Var, unsigned Offset, DebugLoc DL) { UserValue *&Leader = userVarMap[Var]; @@ -363,14 +399,6 @@ bool LDVImpl::handleDebugValue(MachineInstr *MI, SlotIndex Idx) { unsigned Offset = MI->getOperand(1).getImm(); const MDNode *Var = MI->getOperand(2).getMetadata(); UserValue *UV = getUserValue(Var, Offset, MI->getDebugLoc()); - - // If the location is a virtual register, make sure it is mapped. - if (MI->getOperand(0).isReg()) { - unsigned Reg = MI->getOperand(0).getReg(); - if (TargetRegisterInfo::isVirtualRegister(Reg)) - mapVirtReg(Reg, UV); - } - UV->addDef(Idx, MI->getOperand(0)); return true; } @@ -405,6 +433,7 @@ bool LDVImpl::collectDebugValues(MachineFunction &mf) { void UserValue::extendDef(SlotIndex Idx, unsigned LocNo, LiveInterval *LI, const VNInfo *VNI, + SmallVectorImpl *Kills, LiveIntervals &LIS, MachineDominatorTree &MDT) { SmallVector Todo; Todo.push_back(Idx); @@ -419,8 +448,11 @@ void UserValue::extendDef(SlotIndex Idx, unsigned LocNo, bool ToEnd = true; if (LI && VNI) { LiveRange *Range = LI->getLiveRangeContaining(Start); - if (!Range || Range->valno != VNI) + if (!Range || Range->valno != VNI) { + if (Kills) + Kills->push_back(Start); continue; + } if (Range->end < Stop) Stop = Range->end, ToEnd = false; } @@ -438,6 +470,9 @@ void UserValue::extendDef(SlotIndex Idx, unsigned LocNo, // Limited by the next def. if (I.valid() && I.start() < Stop) Stop = I.start(), ToEnd = false; + // Limited by VNI's live range. + else if (!ToEnd && Kills) + Kills->push_back(Stop); if (Start >= Stop) continue; @@ -455,7 +490,82 @@ void UserValue::extendDef(SlotIndex Idx, unsigned LocNo, } void -UserValue::computeIntervals(LiveIntervals &LIS, MachineDominatorTree &MDT) { +UserValue::addDefsFromCopies(LiveInterval *LI, unsigned LocNo, + const SmallVectorImpl &Kills, + SmallVectorImpl > &NewDefs, + MachineRegisterInfo &MRI, LiveIntervals &LIS) { + if (Kills.empty()) + return; + // Don't track copies from physregs, there are too many uses. + if (!TargetRegisterInfo::isVirtualRegister(LI->reg)) + return; + + // Collect all the (vreg, valno) pairs that are copies of LI. + SmallVector, 8> CopyValues; + for (MachineRegisterInfo::use_nodbg_iterator + UI = MRI.use_nodbg_begin(LI->reg), + UE = MRI.use_nodbg_end(); UI != UE; ++UI) { + // Copies of the full value. + if (UI.getOperand().getSubReg() || !UI->isCopy()) + continue; + MachineInstr *MI = &*UI; + unsigned DstReg = MI->getOperand(0).getReg(); + + // Don't follow copies to physregs. These are usually setting up call + // arguments, and the argument registers are always call clobbered. We are + // better off in the source register which could be a callee-saved register, + // or it could be spilled. + if (!TargetRegisterInfo::isVirtualRegister(DstReg)) + continue; + + // Is LocNo extended to reach this copy? If not, another def may be blocking + // it, or we are looking at a wrong value of LI. + SlotIndex Idx = LIS.getInstructionIndex(MI); + LocMap::iterator I = locInts.find(Idx.getUseIndex()); + if (!I.valid() || I.value() != LocNo) + continue; + + if (!LIS.hasInterval(DstReg)) + continue; + LiveInterval *DstLI = &LIS.getInterval(DstReg); + const VNInfo *DstVNI = DstLI->getVNInfoAt(Idx.getDefIndex()); + assert(DstVNI && DstVNI->def == Idx.getDefIndex() && "Bad copy value"); + CopyValues.push_back(std::make_pair(DstLI, DstVNI)); + } + + if (CopyValues.empty()) + return; + + DEBUG(dbgs() << "Got " << CopyValues.size() << " copies of " << *LI << '\n'); + + // Try to add defs of the copied values for each kill point. + for (unsigned i = 0, e = Kills.size(); i != e; ++i) { + SlotIndex Idx = Kills[i]; + for (unsigned j = 0, e = CopyValues.size(); j != e; ++j) { + LiveInterval *DstLI = CopyValues[j].first; + const VNInfo *DstVNI = CopyValues[j].second; + if (DstLI->getVNInfoAt(Idx) != DstVNI) + continue; + // Check that there isn't already a def at Idx + LocMap::iterator I = locInts.find(Idx); + if (I.valid() && I.start() <= Idx) + continue; + DEBUG(dbgs() << "Kill at " << Idx << " covered by valno #" + << DstVNI->id << " in " << *DstLI << '\n'); + MachineInstr *CopyMI = LIS.getInstructionFromIndex(DstVNI->def); + assert(CopyMI && CopyMI->isCopy() && "Bad copy value"); + unsigned LocNo = getLocationNo(CopyMI->getOperand(0)); + I.insert(Idx, Idx.getNextSlot(), LocNo); + NewDefs.push_back(std::make_pair(Idx, LocNo)); + break; + } + } +} + +void +UserValue::computeIntervals(MachineRegisterInfo &MRI, + LiveIntervals &LIS, + MachineDominatorTree &MDT) { SmallVector, 16> Defs; // Collect all defs to be extended (Skipping undefs). @@ -463,7 +573,8 @@ UserValue::computeIntervals(LiveIntervals &LIS, MachineDominatorTree &MDT) { if (I.value() != ~0u) Defs.push_back(std::make_pair(I.start(), I.value())); - for (unsigned i = 0, e = Defs.size(); i != e; ++i) { + // Extend all defs, and possibly add new ones along the way. + for (unsigned i = 0; i != Defs.size(); ++i) { SlotIndex Idx = Defs[i].first; unsigned LocNo = Defs[i].second; const MachineOperand &Loc = locations[LocNo]; @@ -472,9 +583,11 @@ UserValue::computeIntervals(LiveIntervals &LIS, MachineDominatorTree &MDT) { if (Loc.isReg() && LIS.hasInterval(Loc.getReg())) { LiveInterval *LI = &LIS.getInterval(Loc.getReg()); const VNInfo *VNI = LI->getVNInfoAt(Idx); - extendDef(Idx, LocNo, LI, VNI, LIS, MDT); + SmallVector Kills; + extendDef(Idx, LocNo, LI, VNI, &Kills, LIS, MDT); + addDefsFromCopies(LI, LocNo, Kills, Defs, MRI, LIS); } else - extendDef(Idx, LocNo, 0, 0, LIS, MDT); + extendDef(Idx, LocNo, 0, 0, 0, LIS, MDT); } // Finally, erase all the undefs. @@ -486,8 +599,10 @@ UserValue::computeIntervals(LiveIntervals &LIS, MachineDominatorTree &MDT) { } void LDVImpl::computeIntervals() { - for (unsigned i = 0, e = userValues.size(); i != e; ++i) - userValues[i]->computeIntervals(*LIS, *MDT); + for (unsigned i = 0, e = userValues.size(); i != e; ++i) { + userValues[i]->computeIntervals(MF->getRegInfo(), *LIS, *MDT); + userValues[i]->mapVirtRegs(this); + } } bool LDVImpl::runOnMachineFunction(MachineFunction &mf) { @@ -640,13 +755,6 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, .addOperand(Loc).addImm(offset).addMetadata(variable); } -void UserValue::insertDebugKill(MachineBasicBlock *MBB, SlotIndex Idx, - LiveIntervals &LIS, const TargetInstrInfo &TII) { - MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS); - BuildMI(*MBB, I, findDebugLoc(), TII.get(TargetOpcode::DBG_VALUE)).addReg(0) - .addImm(offset).addMetadata(variable); -} - void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, const TargetInstrInfo &TII) { MachineFunction::iterator MFEnd = VRM->getMachineFunction().end(); @@ -678,12 +786,6 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, break; ++I; - if (Stop == MBBEnd) - continue; - // The current interval ends before MBB. - // Insert a kill if there is a gap. - if (!I.valid() || I.start() > Stop) - insertDebugKill(MBB, Stop, LIS, TII); } } diff --git a/contrib/llvm/lib/CodeGen/LiveInterval.cpp b/contrib/llvm/lib/CodeGen/LiveInterval.cpp index c2dbd6ab75a1..cfade24b8d87 100644 --- a/contrib/llvm/lib/CodeGen/LiveInterval.cpp +++ b/contrib/llvm/lib/CodeGen/LiveInterval.cpp @@ -30,19 +30,22 @@ #include using namespace llvm; -// CompEnd - Compare LiveRange ends. -namespace { -struct CompEnd { - bool operator()(const LiveRange &A, const LiveRange &B) const { - return A.end < B.end; - } -}; -} - LiveInterval::iterator LiveInterval::find(SlotIndex Pos) { - assert(Pos.isValid() && "Cannot search for an invalid index"); - return std::upper_bound(begin(), end(), LiveRange(SlotIndex(), Pos, 0), - CompEnd()); + // This algorithm is basically std::upper_bound. + // Unfortunately, std::upper_bound cannot be used with mixed types until we + // adopt C++0x. Many libraries can do it, but not all. + if (empty() || Pos >= endIndex()) + return end(); + iterator I = begin(); + size_t Len = ranges.size(); + do { + size_t Mid = Len >> 1; + if (Pos < I[Mid].end) + Len = Mid; + else + I += Mid + 1, Len -= Mid + 1; + } while (Len); + return I; } /// killedInRange - Return true if the interval has kills in [Start,End). @@ -291,6 +294,22 @@ LiveInterval::addRangeFrom(LiveRange LR, iterator From) { return ranges.insert(it, LR); } +/// extendInBlock - If this interval is live before UseIdx in the basic +/// block that starts at StartIdx, extend it to be live at UseIdx and return +/// the value. If there is no live range before UseIdx, return NULL. +VNInfo *LiveInterval::extendInBlock(SlotIndex StartIdx, SlotIndex UseIdx) { + if (empty()) + return 0; + iterator I = std::upper_bound(begin(), end(), UseIdx); + if (I == begin()) + return 0; + --I; + if (I->end <= StartIdx) + return 0; + if (I->end <= UseIdx) + extendIntervalEndTo(I, UseIdx.getNextSlot()); + return I->valno; +} /// removeRange - Remove the specified range from this interval. Note that /// the range must be in a single LiveRange in its entirety. @@ -476,60 +495,19 @@ void LiveInterval::MergeRangesInAsValue(const LiveInterval &RHS, void LiveInterval::MergeValueInAsValue( const LiveInterval &RHS, const VNInfo *RHSValNo, VNInfo *LHSValNo) { - SmallVector ReplacedValNos; - iterator IP = begin(); + // TODO: Make this more efficient. + iterator InsertPos = begin(); for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { - assert(I->valno == RHS.getValNumInfo(I->valno->id) && "Bad VNInfo"); if (I->valno != RHSValNo) continue; - SlotIndex Start = I->start, End = I->end; - IP = std::upper_bound(IP, end(), Start); - // If the start of this range overlaps with an existing liverange, trim it. - if (IP != begin() && IP[-1].end > Start) { - if (IP[-1].valno != LHSValNo) { - ReplacedValNos.push_back(IP[-1].valno); - IP[-1].valno = LHSValNo; // Update val#. - } - Start = IP[-1].end; - // Trimmed away the whole range? - if (Start >= End) continue; - } - // If the end of this range overlaps with an existing liverange, trim it. - if (IP != end() && End > IP->start) { - if (IP->valno != LHSValNo) { - ReplacedValNos.push_back(IP->valno); - IP->valno = LHSValNo; // Update val#. - } - End = IP->start; - // If this trimmed away the whole range, ignore it. - if (Start == End) continue; - } - // Map the valno in the other live range to the current live range. - IP = addRangeFrom(LiveRange(Start, End, LHSValNo), IP); - } - - - SmallSet Seen; - for (unsigned i = 0, e = ReplacedValNos.size(); i != e; ++i) { - VNInfo *V1 = ReplacedValNos[i]; - if (Seen.insert(V1)) { - bool isDead = true; - for (const_iterator I = begin(), E = end(); I != E; ++I) - if (I->valno == V1) { - isDead = false; - break; - } - if (isDead) { - // Now that V1 is dead, remove it. - markValNoForDeletion(V1); - } - } + LiveRange Tmp = *I; + Tmp.valno = LHSValNo; + InsertPos = addRangeFrom(Tmp, InsertPos); } } - /// MergeValueNumberInto - This method is called when two value nubmers /// are found to be equivalent. This eliminates V1, replacing all /// LiveRanges with the V1 value number with the V2 value number. This can @@ -700,8 +678,8 @@ void LiveRange::print(raw_ostream &os) const { unsigned ConnectedVNInfoEqClasses::Classify(const LiveInterval *LI) { // Create initial equivalence classes. - eqClass_.clear(); - eqClass_.grow(LI->getNumValNums()); + EqClass.clear(); + EqClass.grow(LI->getNumValNums()); const VNInfo *used = 0, *unused = 0; @@ -712,48 +690,65 @@ unsigned ConnectedVNInfoEqClasses::Classify(const LiveInterval *LI) { // Group all unused values into one class. if (VNI->isUnused()) { if (unused) - eqClass_.join(unused->id, VNI->id); + EqClass.join(unused->id, VNI->id); unused = VNI; continue; } used = VNI; if (VNI->isPHIDef()) { - const MachineBasicBlock *MBB = lis_.getMBBFromIndex(VNI->def); + const MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def); assert(MBB && "Phi-def has no defining MBB"); // Connect to values live out of predecessors. for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PE = MBB->pred_end(); PI != PE; ++PI) if (const VNInfo *PVNI = - LI->getVNInfoAt(lis_.getMBBEndIdx(*PI).getPrevSlot())) - eqClass_.join(VNI->id, PVNI->id); + LI->getVNInfoAt(LIS.getMBBEndIdx(*PI).getPrevSlot())) + EqClass.join(VNI->id, PVNI->id); } else { // Normal value defined by an instruction. Check for two-addr redef. // FIXME: This could be coincidental. Should we really check for a tied // operand constraint? // Note that VNI->def may be a use slot for an early clobber def. if (const VNInfo *UVNI = LI->getVNInfoAt(VNI->def.getPrevSlot())) - eqClass_.join(VNI->id, UVNI->id); + EqClass.join(VNI->id, UVNI->id); } } // Lump all the unused values in with the last used value. if (used && unused) - eqClass_.join(used->id, unused->id); + EqClass.join(used->id, unused->id); - eqClass_.compress(); - return eqClass_.getNumClasses(); + EqClass.compress(); + return EqClass.getNumClasses(); } -void ConnectedVNInfoEqClasses::Distribute(LiveInterval *LIV[]) { +void ConnectedVNInfoEqClasses::Distribute(LiveInterval *LIV[], + MachineRegisterInfo &MRI) { assert(LIV[0] && "LIV[0] must be set"); LiveInterval &LI = *LIV[0]; - // First move runs to new intervals. + // Rewrite instructions. + for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(LI.reg), + RE = MRI.reg_end(); RI != RE;) { + MachineOperand &MO = RI.getOperand(); + MachineInstr *MI = MO.getParent(); + ++RI; + if (MO.isUse() && MO.isUndef()) + continue; + // DBG_VALUE instructions should have been eliminated earlier. + SlotIndex Idx = LIS.getInstructionIndex(MI); + Idx = MO.isUse() ? Idx.getUseIndex() : Idx.getDefIndex(); + const VNInfo *VNI = LI.getVNInfoAt(Idx); + assert(VNI && "Interval not live at use."); + MO.setReg(LIV[getEqClass(VNI)]->reg); + } + + // Move runs to new intervals. LiveInterval::iterator J = LI.begin(), E = LI.end(); - while (J != E && eqClass_[J->valno->id] == 0) + while (J != E && EqClass[J->valno->id] == 0) ++J; for (LiveInterval::iterator I = J; I != E; ++I) { - if (unsigned eq = eqClass_[I->valno->id]) { + if (unsigned eq = EqClass[I->valno->id]) { assert((LIV[eq]->empty() || LIV[eq]->expiredAt(I->start)) && "New intervals should be empty"); LIV[eq]->ranges.push_back(*I); @@ -764,11 +759,11 @@ void ConnectedVNInfoEqClasses::Distribute(LiveInterval *LIV[]) { // Transfer VNInfos to their new owners and renumber them. unsigned j = 0, e = LI.getNumValNums(); - while (j != e && eqClass_[j] == 0) + while (j != e && EqClass[j] == 0) ++j; for (unsigned i = j; i != e; ++i) { VNInfo *VNI = LI.getValNumInfo(i); - if (unsigned eq = eqClass_[i]) { + if (unsigned eq = EqClass[i]) { VNI->id = LIV[eq]->getNumValNums(); LIV[eq]->valnos.push_back(VNI); } else { diff --git a/contrib/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp b/contrib/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp index aef5b5f77e78..9257191f7fc0 100644 --- a/contrib/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/contrib/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -572,19 +572,12 @@ void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB, if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) handleVirtualRegisterDef(MBB, MI, MIIdx, MO, MOIdx, getOrCreateInterval(MO.getReg())); - else if (allocatableRegs_[MO.getReg()]) { + else { MachineInstr *CopyMI = NULL; if (MI->isCopyLike()) CopyMI = MI; handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, getOrCreateInterval(MO.getReg()), CopyMI); - // Def of a register also defines its sub-registers. - for (const unsigned* AS = tri_->getSubRegisters(MO.getReg()); *AS; ++AS) - // If MI also modifies the sub-register explicitly, avoid processing it - // more than once. Do not pass in TRI here so it checks for exact match. - if (!MI->definesRegister(*AS)) - handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, - getOrCreateInterval(*AS), 0); } } @@ -645,7 +638,7 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB, end = MIIdx.getStoreIndex(); } else { DEBUG(dbgs() << " live through"); - end = baseIndex; + end = getMBBEndIdx(MBB); } } @@ -746,7 +739,8 @@ LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) { /// shrinkToUses - After removing some uses of a register, shrink its live /// range to just the remaining uses. This method does not compute reaching /// defs for new uses, and it doesn't remove dead defs. -void LiveIntervals::shrinkToUses(LiveInterval *li) { +bool LiveIntervals::shrinkToUses(LiveInterval *li, + SmallVectorImpl *dead) { DEBUG(dbgs() << "Shrink: " << *li << '\n'); assert(TargetRegisterInfo::isVirtualRegister(li->reg) && "Can't only shrink physical registers"); @@ -760,7 +754,15 @@ void LiveIntervals::shrinkToUses(LiveInterval *li) { continue; SlotIndex Idx = getInstructionIndex(UseMI).getUseIndex(); VNInfo *VNI = li->getVNInfoAt(Idx); - assert(VNI && "Live interval not live into reading instruction"); + if (!VNI) { + // This shouldn't happen: readsVirtualRegister returns true, but there is + // no live value. It is likely caused by a target getting flags + // wrong. + DEBUG(dbgs() << Idx << '\t' << *UseMI + << "Warning: Instr claims to read non-existent value in " + << *li << '\n'); + continue; + } if (VNI->def == Idx) { // Special case: An early-clobber tied operand reads and writes the // register one slot early. @@ -778,49 +780,47 @@ void LiveIntervals::shrinkToUses(LiveInterval *li) { VNInfo *VNI = *I; if (VNI->isUnused()) continue; + // We may eliminate PHI values, so recompute PHIKill flags. + VNI->setHasPHIKill(false); NewLI.addRange(LiveRange(VNI->def, VNI->def.getNextSlot(), VNI)); + + // A use tied to an early-clobber def ends at the load slot and isn't caught + // above. Catch it here instead. This probably only ever happens for inline + // assembly. + if (VNI->def.isUse()) + if (VNInfo *UVNI = li->getVNInfoAt(VNI->def.getLoadIndex())) + WorkList.push_back(std::make_pair(VNI->def.getLoadIndex(), UVNI)); } + // Keep track of the PHIs that are in use. + SmallPtrSet UsedPHIs; + // Extend intervals to reach all uses in WorkList. while (!WorkList.empty()) { SlotIndex Idx = WorkList.back().first; VNInfo *VNI = WorkList.back().second; WorkList.pop_back(); - - // Extend the live range for VNI to be live at Idx. - LiveInterval::iterator I = NewLI.find(Idx); - - // Already got it? - if (I != NewLI.end() && I->start <= Idx) { - assert(I->valno == VNI && "Unexpected existing value number"); - continue; - } - - // Is there already a live range in the block containing Idx? const MachineBasicBlock *MBB = getMBBFromIndex(Idx); SlotIndex BlockStart = getMBBStartIdx(MBB); - DEBUG(dbgs() << "Shrink: Use val#" << VNI->id << " at " << Idx - << " in BB#" << MBB->getNumber() << '@' << BlockStart); - if (I != NewLI.begin() && (--I)->end > BlockStart) { - assert(I->valno == VNI && "Wrong reaching def"); - DEBUG(dbgs() << " extend [" << I->start << ';' << I->end << ")\n"); - // Is this the first use of a PHIDef in its defining block? - if (VNI->isPHIDef() && I->end == VNI->def.getNextSlot()) { - // The PHI is live, make sure the predecessors are live-out. - for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), - PE = MBB->pred_end(); PI != PE; ++PI) { - SlotIndex Stop = getMBBEndIdx(*PI).getPrevSlot(); - VNInfo *PVNI = li->getVNInfoAt(Stop); - // A predecessor is not required to have a live-out value for a PHI. - if (PVNI) { - assert(PVNI->hasPHIKill() && "Missing hasPHIKill flag"); - WorkList.push_back(std::make_pair(Stop, PVNI)); - } + + // Extend the live range for VNI to be live at Idx. + if (VNInfo *ExtVNI = NewLI.extendInBlock(BlockStart, Idx)) { + (void)ExtVNI; + assert(ExtVNI == VNI && "Unexpected existing value number"); + // Is this a PHIDef we haven't seen before? + if (!VNI->isPHIDef() || VNI->def != BlockStart || !UsedPHIs.insert(VNI)) + continue; + // The PHI is live, make sure the predecessors are live-out. + for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + SlotIndex Stop = getMBBEndIdx(*PI).getPrevSlot(); + VNInfo *PVNI = li->getVNInfoAt(Stop); + // A predecessor is not required to have a live-out value for a PHI. + if (PVNI) { + PVNI->setHasPHIKill(true); + WorkList.push_back(std::make_pair(Stop, PVNI)); } } - - // Extend the live range in the block to include Idx. - NewLI.addRange(LiveRange(I->end, Idx.getNextSlot(), VNI)); continue; } @@ -838,6 +838,7 @@ void LiveIntervals::shrinkToUses(LiveInterval *li) { } // Handle dead values. + bool CanSeparate = false; for (LiveInterval::vni_iterator I = li->vni_begin(), E = li->vni_end(); I != E; ++I) { VNInfo *VNI = *I; @@ -847,21 +848,28 @@ void LiveIntervals::shrinkToUses(LiveInterval *li) { assert(LII != NewLI.end() && "Missing live range for PHI"); if (LII->end != VNI->def.getNextSlot()) continue; - if (!VNI->isPHIDef()) { + if (VNI->isPHIDef()) { // This is a dead PHI. Remove it. VNI->setIsUnused(true); NewLI.removeRange(*LII); + DEBUG(dbgs() << "Dead PHI at " << VNI->def << " may separate interval\n"); + CanSeparate = true; } else { // This is a dead def. Make sure the instruction knows. MachineInstr *MI = getInstructionFromIndex(VNI->def); assert(MI && "No instruction defining live value"); MI->addRegisterDead(li->reg, tri_); + if (dead && MI->allDefsAreDead()) { + DEBUG(dbgs() << "All defs dead: " << VNI->def << '\t' << *MI); + dead->push_back(MI); + } } } // Move the trimmed ranges back. li->ranges.swap(NewLI.ranges); - DEBUG(dbgs() << "Shrink: " << *li << '\n'); + DEBUG(dbgs() << "Shrunk: " << *li << '\n'); + return CanSeparate; } @@ -955,7 +963,7 @@ bool LiveIntervals::isValNoAvailableAt(const LiveInterval &li, MachineInstr *MI, bool LiveIntervals::isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, MachineInstr *MI, - const SmallVectorImpl &SpillIs, + const SmallVectorImpl *SpillIs, bool &isLoad) { if (DisableReMat) return false; @@ -982,9 +990,10 @@ LiveIntervals::isReMaterializable(const LiveInterval &li, // If a register operand of the re-materialized instruction is going to // be spilled next, then it's not legal to re-materialize this instruction. - for (unsigned i = 0, e = SpillIs.size(); i != e; ++i) - if (ImpUse == SpillIs[i]->reg) - return false; + if (SpillIs) + for (unsigned i = 0, e = SpillIs->size(); i != e; ++i) + if (ImpUse == (*SpillIs)[i]->reg) + return false; } return true; } @@ -993,16 +1002,15 @@ LiveIntervals::isReMaterializable(const LiveInterval &li, /// val# of the specified interval is re-materializable. bool LiveIntervals::isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, MachineInstr *MI) { - SmallVector Dummy1; bool Dummy2; - return isReMaterializable(li, ValNo, MI, Dummy1, Dummy2); + return isReMaterializable(li, ValNo, MI, 0, Dummy2); } /// isReMaterializable - Returns true if every definition of MI of every /// val# of the specified interval is re-materializable. bool LiveIntervals::isReMaterializable(const LiveInterval &li, - const SmallVectorImpl &SpillIs, + const SmallVectorImpl *SpillIs, bool &isLoad) { isLoad = false; for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end(); @@ -1499,7 +1507,7 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, // ... // def = ... // = use - // It's better to start a new interval to avoid artifically + // It's better to start a new interval to avoid artificially // extend the new interval. if (MI->readsWritesVirtualRegister(li.reg) == std::make_pair(false,true)) { @@ -1702,7 +1710,9 @@ LiveIntervals::getSpillWeight(bool isDef, bool isUse, unsigned loopDepth) { // overflow a float. This expression behaves like 10^d for small d, but is // more tempered for large d. At d=200 we get 6.7e33 which leaves a bit of // headroom before overflow. - float lc = std::pow(1 + (100.0f / (loopDepth+10)), (float)loopDepth); + // By the way, powf() might be unavailable here. For consistency, + // We may take pow(double,double). + float lc = std::pow(1 + (100.0 / (loopDepth + 10)), (double)loopDepth); return (isDef + isUse) * lc; } @@ -1715,7 +1725,7 @@ static void normalizeSpillWeights(std::vector &NewLIs) { std::vector LiveIntervals:: addIntervalsForSpills(const LiveInterval &li, - const SmallVectorImpl &SpillIs, + const SmallVectorImpl *SpillIs, const MachineLoopInfo *loopInfo, VirtRegMap &vrm) { assert(li.isSpillable() && "attempt to spill already spilled interval!"); diff --git a/contrib/llvm/lib/CodeGen/LiveIntervalUnion.cpp b/contrib/llvm/lib/CodeGen/LiveIntervalUnion.cpp index 205f28a0d65a..b67f96667bfd 100644 --- a/contrib/llvm/lib/CodeGen/LiveIntervalUnion.cpp +++ b/contrib/llvm/lib/CodeGen/LiveIntervalUnion.cpp @@ -35,12 +35,20 @@ void LiveIntervalUnion::unify(LiveInterval &VirtReg) { LiveInterval::iterator RegEnd = VirtReg.end(); SegmentIter SegPos = Segments.find(RegPos->start); - for (;;) { + while (SegPos.valid()) { SegPos.insert(RegPos->start, RegPos->end, &VirtReg); if (++RegPos == RegEnd) return; SegPos.advanceTo(RegPos->start); } + + // We have reached the end of Segments, so it is no longer necessary to search + // for the insertion position. + // It is faster to insert the end first. + --RegEnd; + SegPos.insert(RegEnd->start, RegEnd->end, &VirtReg); + for (; RegPos != RegEnd; ++RegPos, ++SegPos) + SegPos.insert(RegPos->start, RegPos->end, &VirtReg); } // Remove a live virtual register's segments from this union. @@ -168,6 +176,7 @@ LiveIntervalUnion::Query::firstInterference() { return FirstInterference; CheckedFirstInterference = true; InterferenceResult &IR = FirstInterference; + IR.LiveUnionI.setMap(LiveUnion->getMap()); // Quickly skip interference check for empty sets. if (VirtReg->empty() || LiveUnion->empty()) { @@ -176,10 +185,10 @@ LiveIntervalUnion::Query::firstInterference() { // VirtReg starts first, perform double binary search. IR.VirtRegI = VirtReg->find(LiveUnion->startIndex()); if (IR.VirtRegI != VirtReg->end()) - IR.LiveUnionI = LiveUnion->find(IR.VirtRegI->start); + IR.LiveUnionI.find(IR.VirtRegI->start); } else { // LiveUnion starts first, perform double binary search. - IR.LiveUnionI = LiveUnion->find(VirtReg->beginIndex()); + IR.LiveUnionI.find(VirtReg->beginIndex()); if (IR.LiveUnionI.valid()) IR.VirtRegI = VirtReg->find(IR.LiveUnionI.start()); else @@ -235,7 +244,7 @@ bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const { // // For comments on how to speed it up, see Query::findIntersection(). unsigned LiveIntervalUnion::Query:: -collectInterferingVRegs(unsigned MaxInterferingRegs) { +collectInterferingVRegs(unsigned MaxInterferingRegs, float MaxWeight) { InterferenceResult IR = firstInterference(); LiveInterval::iterator VirtRegEnd = VirtReg->end(); LiveInterval *RecentInterferingVReg = NULL; @@ -277,6 +286,11 @@ collectInterferingVRegs(unsigned MaxInterferingRegs) { // Cache the most recent interfering vreg to bypass isSeenInterference. RecentInterferingVReg = IR.LiveUnionI.value(); ++IR.LiveUnionI; + + // Stop collecting when the max weight is exceeded. + if (RecentInterferingVReg->weight >= MaxWeight) + return InterferingVRegs.size(); + continue; } // VirtRegI may have advanced far beyond LiveUnionI, diff --git a/contrib/llvm/lib/CodeGen/LiveIntervalUnion.h b/contrib/llvm/lib/CodeGen/LiveIntervalUnion.h index 6f9c5f4455e9..c83578e99c6c 100644 --- a/contrib/llvm/lib/CodeGen/LiveIntervalUnion.h +++ b/contrib/llvm/lib/CodeGen/LiveIntervalUnion.h @@ -95,6 +95,9 @@ class LiveIntervalUnion { // 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; @@ -163,10 +166,10 @@ class LiveIntervalUnion { bool CheckedFirstInterference; bool SeenAllInterferences; bool SeenUnspillableVReg; - unsigned Tag; + unsigned Tag, UserTag; public: - Query(): LiveUnion(), VirtReg() {} + Query(): LiveUnion(), VirtReg(), Tag(0), UserTag(0) {} Query(LiveInterval *VReg, LiveIntervalUnion *LIU): LiveUnion(LIU), VirtReg(VReg), CheckedFirstInterference(false), @@ -181,11 +184,13 @@ class LiveIntervalUnion { SeenAllInterferences = false; SeenUnspillableVReg = false; Tag = 0; + UserTag = 0; } - void init(LiveInterval *VReg, LiveIntervalUnion *LIU) { + void init(unsigned UTag, LiveInterval *VReg, LiveIntervalUnion *LIU) { assert(VReg && LIU && "Invalid arguments"); - if (VirtReg == VReg && LiveUnion == LIU && !LIU->changedSince(Tag)) { + if (UserTag == UTag && VirtReg == VReg && + LiveUnion == LIU && !LIU->changedSince(Tag)) { // Retain cached results, e.g. firstInterference. return; } @@ -193,6 +198,7 @@ class LiveIntervalUnion { LiveUnion = LIU; VirtReg = VReg; Tag = LIU->getTag(); + UserTag = UTag; } LiveInterval &virtReg() const { @@ -223,7 +229,8 @@ class LiveIntervalUnion { // 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); + unsigned collectInterferingVRegs(unsigned MaxInterferingRegs = UINT_MAX, + float MaxWeight = HUGE_VALF); // Was this virtual register visited during collectInterferingVRegs? bool isSeenInterference(LiveInterval *VReg) const; diff --git a/contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp b/contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp index 3bbda1c2e609..f8a3dbb5fd7b 100644 --- a/contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp +++ b/contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp @@ -11,24 +11,41 @@ // is spilled or split. //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "regalloc" #include "LiveRangeEdit.h" #include "VirtRegMap.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; -LiveInterval &LiveRangeEdit::create(MachineRegisterInfo &mri, - LiveIntervals &lis, - VirtRegMap &vrm) { - const TargetRegisterClass *RC = mri.getRegClass(getReg()); - unsigned VReg = mri.createVirtualRegister(RC); - vrm.grow(); - vrm.setIsSplitFromReg(VReg, vrm.getOriginal(getReg())); - LiveInterval &li = lis.getOrCreateInterval(VReg); - newRegs_.push_back(&li); - return li; +LiveInterval &LiveRangeEdit::createFrom(unsigned OldReg, + LiveIntervals &LIS, + VirtRegMap &VRM) { + MachineRegisterInfo &MRI = VRM.getRegInfo(); + unsigned VReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg)); + VRM.grow(); + VRM.setIsSplitFromReg(VReg, VRM.getOriginal(OldReg)); + LiveInterval &LI = LIS.getOrCreateInterval(VReg); + newRegs_.push_back(&LI); + return LI; +} + +bool LiveRangeEdit::checkRematerializable(VNInfo *VNI, + const MachineInstr *DefMI, + const TargetInstrInfo &tii, + AliasAnalysis *aa) { + assert(DefMI && "Missing instruction"); + scannedRemattable_ = true; + if (!tii.isTriviallyReMaterializable(DefMI, aa)) + return false; + remattable_.insert(VNI); + return true; } void LiveRangeEdit::scanRemattable(LiveIntervals &lis, @@ -42,8 +59,7 @@ void LiveRangeEdit::scanRemattable(LiveIntervals &lis, MachineInstr *DefMI = lis.getInstructionFromIndex(VNI->def); if (!DefMI) continue; - if (tii.isTriviallyReMaterializable(DefMI, aa)) - remattable_.insert(VNI); + checkRematerializable(VNI, DefMI, tii, aa); } scannedRemattable_ = true; } @@ -66,18 +82,16 @@ bool LiveRangeEdit::allUsesAvailableAt(const MachineInstr *OrigMI, UseIdx = UseIdx.getUseIndex(); for (unsigned i = 0, e = OrigMI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = OrigMI->getOperand(i); - if (!MO.isReg() || !MO.getReg() || MO.getReg() == getReg()) + if (!MO.isReg() || !MO.getReg() || MO.isDef()) continue; // Reserved registers are OK. if (MO.isUndef() || !lis.hasInterval(MO.getReg())) continue; - // We don't want to move any defs. - if (MO.isDef()) - return false; // We cannot depend on virtual registers in uselessRegs_. - for (unsigned ui = 0, ue = uselessRegs_.size(); ui != ue; ++ui) - if (uselessRegs_[ui]->reg == MO.getReg()) - return false; + if (uselessRegs_) + for (unsigned ui = 0, ue = uselessRegs_->size(); ui != ue; ++ui) + if ((*uselessRegs_)[ui]->reg == MO.getReg()) + return false; LiveInterval &li = lis.getInterval(MO.getReg()); const VNInfo *OVNI = li.getVNInfoAt(OrigIdx); @@ -99,16 +113,22 @@ bool LiveRangeEdit::canRematerializeAt(Remat &RM, if (!remattable_.count(RM.ParentVNI)) return false; - // No defining instruction. - RM.OrigMI = lis.getInstructionFromIndex(RM.ParentVNI->def); - assert(RM.OrigMI && "Defining instruction for remattable value disappeared"); + // No defining instruction provided. + SlotIndex DefIdx; + if (RM.OrigMI) + DefIdx = lis.getInstructionIndex(RM.OrigMI); + else { + DefIdx = RM.ParentVNI->def; + RM.OrigMI = lis.getInstructionFromIndex(DefIdx); + assert(RM.OrigMI && "No defining instruction for remattable value"); + } // If only cheap remats were requested, bail out early. if (cheapAsAMove && !RM.OrigMI->getDesc().isAsCheapAsAMove()) return false; // Verify that all used registers are available with the same values. - if (!allUsesAvailableAt(RM.OrigMI, RM.ParentVNI->def, UseIdx, lis)) + if (!allUsesAvailableAt(RM.OrigMI, DefIdx, UseIdx, lis)) return false; return true; @@ -120,10 +140,174 @@ SlotIndex LiveRangeEdit::rematerializeAt(MachineBasicBlock &MBB, const Remat &RM, LiveIntervals &lis, const TargetInstrInfo &tii, - const TargetRegisterInfo &tri) { + const TargetRegisterInfo &tri, + bool Late) { assert(RM.OrigMI && "Invalid remat"); tii.reMaterialize(MBB, MI, DestReg, 0, RM.OrigMI, tri); rematted_.insert(RM.ParentVNI); - return lis.InsertMachineInstrInMaps(--MI).getDefIndex(); + return lis.getSlotIndexes()->insertMachineInstrInMaps(--MI, Late) + .getDefIndex(); } +void LiveRangeEdit::eraseVirtReg(unsigned Reg, LiveIntervals &LIS) { + if (delegate_ && delegate_->LRE_CanEraseVirtReg(Reg)) + LIS.removeInterval(Reg); +} + +bool LiveRangeEdit::foldAsLoad(LiveInterval *LI, + SmallVectorImpl &Dead, + MachineRegisterInfo &MRI, + LiveIntervals &LIS, + const TargetInstrInfo &TII) { + MachineInstr *DefMI = 0, *UseMI = 0; + + // Check that there is a single def and a single use. + for (MachineRegisterInfo::reg_nodbg_iterator I = MRI.reg_nodbg_begin(LI->reg), + E = MRI.reg_nodbg_end(); I != E; ++I) { + MachineOperand &MO = I.getOperand(); + MachineInstr *MI = MO.getParent(); + if (MO.isDef()) { + if (DefMI && DefMI != MI) + return false; + if (!MI->getDesc().canFoldAsLoad()) + return false; + DefMI = MI; + } else if (!MO.isUndef()) { + if (UseMI && UseMI != MI) + return false; + // FIXME: Targets don't know how to fold subreg uses. + if (MO.getSubReg()) + return false; + UseMI = MI; + } + } + if (!DefMI || !UseMI) + return false; + + DEBUG(dbgs() << "Try to fold single def: " << *DefMI + << " into single use: " << *UseMI); + + SmallVector Ops; + if (UseMI->readsWritesVirtualRegister(LI->reg, &Ops).second) + return false; + + MachineInstr *FoldMI = TII.foldMemoryOperand(UseMI, Ops, DefMI); + if (!FoldMI) + return false; + DEBUG(dbgs() << " folded: " << *FoldMI); + LIS.ReplaceMachineInstrInMaps(UseMI, FoldMI); + UseMI->eraseFromParent(); + DefMI->addRegisterDead(LI->reg, 0); + Dead.push_back(DefMI); + return true; +} + +void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl &Dead, + LiveIntervals &LIS, VirtRegMap &VRM, + const TargetInstrInfo &TII) { + SetVector, + SmallPtrSet > ToShrink; + MachineRegisterInfo &MRI = VRM.getRegInfo(); + + for (;;) { + // Erase all dead defs. + while (!Dead.empty()) { + MachineInstr *MI = Dead.pop_back_val(); + assert(MI->allDefsAreDead() && "Def isn't really dead"); + SlotIndex Idx = LIS.getInstructionIndex(MI).getDefIndex(); + + // Never delete inline asm. + if (MI->isInlineAsm()) { + DEBUG(dbgs() << "Won't delete: " << Idx << '\t' << *MI); + continue; + } + + // Use the same criteria as DeadMachineInstructionElim. + bool SawStore = false; + if (!MI->isSafeToMove(&TII, 0, SawStore)) { + DEBUG(dbgs() << "Can't delete: " << Idx << '\t' << *MI); + continue; + } + + DEBUG(dbgs() << "Deleting dead def " << Idx << '\t' << *MI); + + // Check for live intervals that may shrink + for (MachineInstr::mop_iterator MOI = MI->operands_begin(), + MOE = MI->operands_end(); MOI != MOE; ++MOI) { + if (!MOI->isReg()) + continue; + unsigned Reg = MOI->getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + LiveInterval &LI = LIS.getInterval(Reg); + + // Shrink read registers, unless it is likely to be expensive and + // unlikely to change anything. We typically don't want to shrink the + // PIC base register that has lots of uses everywhere. + // Always shrink COPY uses that probably come from live range splitting. + if (MI->readsVirtualRegister(Reg) && + (MI->isCopy() || MOI->isDef() || MRI.hasOneNonDBGUse(Reg) || + LI.killedAt(Idx))) + ToShrink.insert(&LI); + + // Remove defined value. + if (MOI->isDef()) { + if (VNInfo *VNI = LI.getVNInfoAt(Idx)) { + if (delegate_) + delegate_->LRE_WillShrinkVirtReg(LI.reg); + LI.removeValNo(VNI); + if (LI.empty()) { + ToShrink.remove(&LI); + eraseVirtReg(Reg, LIS); + } + } + } + } + + if (delegate_) + delegate_->LRE_WillEraseInstruction(MI); + LIS.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + } + + if (ToShrink.empty()) + break; + + // Shrink just one live interval. Then delete new dead defs. + LiveInterval *LI = ToShrink.back(); + ToShrink.pop_back(); + if (foldAsLoad(LI, Dead, MRI, LIS, TII)) + continue; + if (delegate_) + delegate_->LRE_WillShrinkVirtReg(LI->reg); + if (!LIS.shrinkToUses(LI, &Dead)) + continue; + + // LI may have been separated, create new intervals. + LI->RenumberValues(LIS); + ConnectedVNInfoEqClasses ConEQ(LIS); + unsigned NumComp = ConEQ.Classify(LI); + if (NumComp <= 1) + continue; + DEBUG(dbgs() << NumComp << " components: " << *LI << '\n'); + SmallVector Dups(1, LI); + for (unsigned i = 1; i != NumComp; ++i) { + Dups.push_back(&createFrom(LI->reg, LIS, VRM)); + if (delegate_) + delegate_->LRE_DidCloneVirtReg(Dups.back()->reg, LI->reg); + } + ConEQ.Distribute(&Dups[0], MRI); + } +} + +void LiveRangeEdit::calculateRegClassAndHint(MachineFunction &MF, + LiveIntervals &LIS, + const MachineLoopInfo &Loops) { + VirtRegAuxInfo VRAI(MF, LIS, Loops); + for (iterator I = begin(), E = end(); I != E; ++I) { + LiveInterval &LI = **I; + VRAI.CalculateRegClass(LI.reg); + VRAI.CalculateWeightAndHint(LI); + } +} diff --git a/contrib/llvm/lib/CodeGen/LiveRangeEdit.h b/contrib/llvm/lib/CodeGen/LiveRangeEdit.h index 73f69ed63983..14d227e61957 100644 --- a/contrib/llvm/lib/CodeGen/LiveRangeEdit.h +++ b/contrib/llvm/lib/CodeGen/LiveRangeEdit.h @@ -25,13 +25,36 @@ namespace llvm { class AliasAnalysis; class LiveIntervals; +class MachineLoopInfo; class MachineRegisterInfo; class VirtRegMap; class LiveRangeEdit { +public: + /// Callback methods for LiveRangeEdit owners. + struct Delegate { + /// Called immediately before erasing a dead machine instruction. + virtual void LRE_WillEraseInstruction(MachineInstr *MI) {} + + /// Called when a virtual register is no longer used. Return false to defer + /// its deletion from LiveIntervals. + virtual bool LRE_CanEraseVirtReg(unsigned) { return true; } + + /// Called before shrinking the live range of a virtual register. + virtual void LRE_WillShrinkVirtReg(unsigned) {} + + /// Called after cloning a virtual register. + /// This is used for new registers representing connected components of Old. + virtual void LRE_DidCloneVirtReg(unsigned New, unsigned Old) {} + + virtual ~Delegate() {} + }; + +private: LiveInterval &parent_; SmallVectorImpl &newRegs_; - const SmallVectorImpl &uselessRegs_; + Delegate *const delegate_; + const SmallVectorImpl *uselessRegs_; /// firstNew_ - Index of the first register added to newRegs_. const unsigned firstNew_; @@ -41,11 +64,11 @@ class LiveRangeEdit { /// remattable_ - Values defined by remattable instructions as identified by /// tii.isTriviallyReMaterializable(). - SmallPtrSet remattable_; + SmallPtrSet remattable_; /// rematted_ - Values that were actually rematted, and so need to have their /// live range trimmed or entirely removed. - SmallPtrSet rematted_; + SmallPtrSet rematted_; /// scanRemattable - Identify the parent_ values that may rematerialize. void scanRemattable(LiveIntervals &lis, @@ -57,6 +80,11 @@ class LiveRangeEdit { bool allUsesAvailableAt(const MachineInstr *OrigMI, SlotIndex OrigIdx, SlotIndex UseIdx, LiveIntervals &lis); + /// foldAsLoad - If LI has a single use and a single def that can be folded as + /// a load, eliminate the register by folding the def into the use. + bool foldAsLoad(LiveInterval *LI, SmallVectorImpl &Dead, + MachineRegisterInfo&, LiveIntervals&, const TargetInstrInfo&); + public: /// Create a LiveRangeEdit for breaking down parent into smaller pieces. /// @param parent The register being spilled or split. @@ -66,9 +94,13 @@ class LiveRangeEdit { /// rematerializing values because they are about to be removed. LiveRangeEdit(LiveInterval &parent, SmallVectorImpl &newRegs, - const SmallVectorImpl &uselessRegs) - : parent_(parent), newRegs_(newRegs), uselessRegs_(uselessRegs), - firstNew_(newRegs.size()), scannedRemattable_(false) {} + Delegate *delegate = 0, + const SmallVectorImpl *uselessRegs = 0) + : parent_(parent), newRegs_(newRegs), + delegate_(delegate), + uselessRegs_(uselessRegs), + firstNew_(newRegs.size()), + scannedRemattable_(false) {} LiveInterval &getParent() const { return parent_; } unsigned getReg() const { return parent_.reg; } @@ -81,16 +113,33 @@ class LiveRangeEdit { bool empty() const { return size() == 0; } LiveInterval *get(unsigned idx) const { return newRegs_[idx+firstNew_]; } - /// create - Create a new register with the same class and stack slot as + /// FIXME: Temporary accessors until we can get rid of + /// LiveIntervals::AddIntervalsForSpills + SmallVectorImpl *getNewVRegs() { return &newRegs_; } + const SmallVectorImpl *getUselessVRegs() { + return uselessRegs_; + } + + /// createFrom - Create a new virtual register based on OldReg. + LiveInterval &createFrom(unsigned OldReg, LiveIntervals&, VirtRegMap&); + + /// create - Create a new register with the same class and original slot as /// parent. - LiveInterval &create(MachineRegisterInfo&, LiveIntervals&, VirtRegMap&); + LiveInterval &create(LiveIntervals &LIS, VirtRegMap &VRM) { + return createFrom(getReg(), LIS, VRM); + } /// anyRematerializable - Return true if any parent values may be /// rematerializable. - /// This function must be called before ny rematerialization is attempted. + /// This function must be called before any rematerialization is attempted. bool anyRematerializable(LiveIntervals&, const TargetInstrInfo&, AliasAnalysis*); + /// checkRematerializable - Manually add VNI to the list of rematerializable + /// values if DefMI may be rematerializable. + bool checkRematerializable(VNInfo *VNI, const MachineInstr *DefMI, + const TargetInstrInfo&, AliasAnalysis*); + /// Remat - Information needed to rematerialize at a specific location. struct Remat { VNInfo *ParentVNI; // parent_'s value at the remat location. @@ -116,18 +165,35 @@ class LiveRangeEdit { const Remat &RM, LiveIntervals&, const TargetInstrInfo&, - const TargetRegisterInfo&); + const TargetRegisterInfo&, + bool Late = false); /// markRematerialized - explicitly mark a value as rematerialized after doing /// it manually. - void markRematerialized(VNInfo *ParentVNI) { + void markRematerialized(const VNInfo *ParentVNI) { rematted_.insert(ParentVNI); } /// didRematerialize - Return true if ParentVNI was rematerialized anywhere. - bool didRematerialize(VNInfo *ParentVNI) const { + bool didRematerialize(const VNInfo *ParentVNI) const { return rematted_.count(ParentVNI); } + + /// eraseVirtReg - Notify the delegate that Reg is no longer in use, and try + /// to erase it from LIS. + void eraseVirtReg(unsigned Reg, LiveIntervals &LIS); + + /// eliminateDeadDefs - Try to delete machine instructions that are now dead + /// (allDefsAreDead returns true). This may cause live intervals to be trimmed + /// and further dead efs to be eliminated. + void eliminateDeadDefs(SmallVectorImpl &Dead, + LiveIntervals&, VirtRegMap&, + const TargetInstrInfo&); + + /// calculateRegClassAndHint - Recompute register class and hint for each new + /// register. + void calculateRegClassAndHint(MachineFunction&, LiveIntervals&, + const MachineLoopInfo&); }; } diff --git a/contrib/llvm/lib/CodeGen/LiveVariables.cpp b/contrib/llvm/lib/CodeGen/LiveVariables.cpp index dd43ef2530c1..20bad60dedda 100644 --- a/contrib/llvm/lib/CodeGen/LiveVariables.cpp +++ b/contrib/llvm/lib/CodeGen/LiveVariables.cpp @@ -107,9 +107,7 @@ void LiveVariables::MarkVirtRegAliveInBlock(VarInfo& VRInfo, // Mark the variable known alive in this bb VRInfo.AliveBlocks.set(BBNum); - for (MachineBasicBlock::const_pred_reverse_iterator PI = MBB->pred_rbegin(), - E = MBB->pred_rend(); PI != E; ++PI) - WorkList.push_back(*PI); + WorkList.insert(WorkList.end(), MBB->pred_rbegin(), MBB->pred_rend()); } void LiveVariables::MarkVirtRegAliveInBlock(VarInfo &VRInfo, @@ -707,7 +705,7 @@ bool LiveVariables::isLiveOut(unsigned Reg, const MachineBasicBlock &MBB) { // Loop over all of the successors of the basic block, checking to see if // the value is either live in the block, or if it is killed in the block. - std::vector OpSuccBlocks; + SmallVector OpSuccBlocks; for (MachineBasicBlock::const_succ_iterator SI = MBB.succ_begin(), E = MBB.succ_end(); SI != E; ++SI) { MachineBasicBlock *SuccMBB = *SI; diff --git a/contrib/llvm/lib/CodeGen/MachineBasicBlock.cpp b/contrib/llvm/lib/CodeGen/MachineBasicBlock.cpp index ccbff0af5b2c..57f3e34d0c5a 100644 --- a/contrib/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/contrib/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -363,8 +363,7 @@ void MachineBasicBlock::addPredecessor(MachineBasicBlock *pred) { } void MachineBasicBlock::removePredecessor(MachineBasicBlock *pred) { - std::vector::iterator I = - std::find(Predecessors.begin(), Predecessors.end(), pred); + pred_iterator I = std::find(Predecessors.begin(), Predecessors.end(), pred); assert(I != Predecessors.end() && "Pred is not a predecessor of this block!"); Predecessors.erase(I); } @@ -402,8 +401,7 @@ MachineBasicBlock::transferSuccessorsAndUpdatePHIs(MachineBasicBlock *fromMBB) { } bool MachineBasicBlock::isSuccessor(const MachineBasicBlock *MBB) const { - std::vector::const_iterator I = - std::find(Successors.begin(), Successors.end(), MBB); + const_succ_iterator I = std::find(Successors.begin(), Successors.end(), MBB); return I != Successors.end(); } diff --git a/contrib/llvm/lib/CodeGen/MachineCSE.cpp b/contrib/llvm/lib/CodeGen/MachineCSE.cpp index 07a7d27b019f..f97ccf65790f 100644 --- a/contrib/llvm/lib/CodeGen/MachineCSE.cpp +++ b/contrib/llvm/lib/CodeGen/MachineCSE.cpp @@ -365,6 +365,8 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { if (!FoundCSE) { // Look for trivial copy coalescing opportunities. if (PerformTrivialCoalescing(MI, MBB)) { + Changed = true; + // After coalescing MI itself may become a copy. if (MI->isCopyLike()) continue; @@ -379,10 +381,11 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { if (NewMI) { Commuted = true; FoundCSE = VNT.count(NewMI); - if (NewMI != MI) + if (NewMI != MI) { // New instruction. It doesn't need to be kept. NewMI->eraseFromParent(); - else if (!FoundCSE) + Changed = true; + } else if (!FoundCSE) // MI was changed but it didn't help, commute it back! (void)TII->commuteInstruction(MI); } @@ -450,6 +453,7 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { ++NumPhysCSEs; if (Commuted) ++NumCommutes; + Changed = true; } else { DEBUG(dbgs() << "*** Not profitable, avoid CSE!\n"); VNT.insert(MI, CurrVN++); diff --git a/contrib/llvm/lib/CodeGen/MachineInstr.cpp b/contrib/llvm/lib/CodeGen/MachineInstr.cpp index aa9ea61acec7..71df6f8b7701 100644 --- a/contrib/llvm/lib/CodeGen/MachineInstr.cpp +++ b/contrib/llvm/lib/CodeGen/MachineInstr.cpp @@ -441,6 +441,10 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) { OS << ")"; } + // Print nontemporal info. + if (MMO.isNonTemporal()) + OS << "(nontemporal)"; + return OS; } @@ -451,7 +455,8 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) { /// MachineInstr ctor - This constructor creates a dummy MachineInstr with /// TID NULL and no operands. MachineInstr::MachineInstr() - : TID(0), NumImplicitOps(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), + : TID(0), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), Parent(0) { // Make sure that we get added to a machine basicblock LeakDetector::addGarbageObject(this); @@ -470,7 +475,7 @@ void MachineInstr::addImplicitDefUseOperands() { /// implicit operands. It reserves space for the number of operands specified by /// the TargetInstrDesc. MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp) - : TID(&tid), NumImplicitOps(0), AsmPrinterFlags(0), + : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0) { if (!NoImp) NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); @@ -484,8 +489,8 @@ MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp) /// MachineInstr ctor - As above, but with a DebugLoc. MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl, bool NoImp) - : TID(&tid), NumImplicitOps(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), - Parent(0), debugLoc(dl) { + : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(dl) { if (!NoImp) NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); Operands.reserve(NumImplicitOps + TID->getNumOperands()); @@ -499,7 +504,7 @@ MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl, /// that the MachineInstr is created and added to the end of the specified /// basic block. MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid) - : TID(&tid), NumImplicitOps(0), AsmPrinterFlags(0), + : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0) { assert(MBB && "Cannot use inserting ctor with null basic block!"); NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); @@ -514,8 +519,8 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid) /// MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, const TargetInstrDesc &tid) - : TID(&tid), NumImplicitOps(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), - Parent(0), debugLoc(dl) { + : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(dl) { assert(MBB && "Cannot use inserting ctor with null basic block!"); NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); Operands.reserve(NumImplicitOps + TID->getNumOperands()); @@ -528,7 +533,7 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, /// MachineInstr ctor - Copies MachineInstr arg exactly /// MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) - : TID(&MI.getDesc()), NumImplicitOps(0), AsmPrinterFlags(0), + : TID(&MI.getDesc()), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), MemRefs(MI.MemRefs), MemRefsEnd(MI.MemRefsEnd), Parent(0), debugLoc(MI.getDebugLoc()) { Operands.reserve(MI.getNumOperands()); @@ -538,6 +543,9 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) addOperand(MI.getOperand(i)); NumImplicitOps = MI.NumImplicitOps; + // Copy all the flags. + Flags = MI.Flags; + // Set parent to null. Parent = 0; @@ -1417,6 +1425,14 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { } bool HaveSemi = false; + if (Flags) { + if (!HaveSemi) OS << ";"; HaveSemi = true; + OS << " flags: "; + + if (Flags & FrameSetup) + OS << "FrameSetup"; + } + if (!memoperands_empty()) { if (!HaveSemi) OS << ";"; HaveSemi = true; @@ -1447,13 +1463,14 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { } } + // Print debug location information. if (!debugLoc.isUnknown() && MF) { - if (!HaveSemi) OS << ";"; + if (!HaveSemi) OS << ";"; HaveSemi = true; OS << " dbg:"; printDebugLoc(debugLoc, MF, OS); } - OS << "\n"; + OS << '\n'; } bool MachineInstr::addRegisterKilled(unsigned IncomingReg, @@ -1530,13 +1547,8 @@ bool MachineInstr::addRegisterDead(unsigned IncomingReg, continue; if (Reg == IncomingReg) { - if (!Found) { - if (MO.isDead()) - // The register is already marked dead. - return true; - MO.setIsDead(); - Found = true; - } + MO.setIsDead(); + Found = true; } else if (hasAliases && MO.isDead() && TargetRegisterInfo::isPhysicalRegister(Reg)) { // There exists a super-register that's marked dead. diff --git a/contrib/llvm/lib/CodeGen/MachineLICM.cpp b/contrib/llvm/lib/CodeGen/MachineLICM.cpp index 443fc2d97bdf..b315702eef8f 100644 --- a/contrib/llvm/lib/CodeGen/MachineLICM.cpp +++ b/contrib/llvm/lib/CodeGen/MachineLICM.cpp @@ -39,7 +39,6 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" - using namespace llvm; STATISTIC(NumHoisted, @@ -169,6 +168,10 @@ namespace { /// bool IsLoopInvariantInst(MachineInstr &I); + /// HasAnyPHIUse - Return true if the specified register is used by any + /// phi node. + bool HasAnyPHIUse(unsigned Reg) const; + /// HasHighOperandLatency - Compute operand latency between a def of 'Reg' /// and an use in the current loop, return true if the target considered /// it 'high'. @@ -294,7 +297,7 @@ bool MachineLICM::runOnMachineFunction(MachineFunction &MF) { RegLimit.resize(NumRC); for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(), E = TRI->regclass_end(); I != E; ++I) - RegLimit[(*I)->getID()] = TLI->getRegPressureLimit(*I, MF); + RegLimit[(*I)->getID()] = TRI->getRegPressureLimit(*I, MF); } // Get our Loop information... @@ -758,18 +761,25 @@ bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) { } -/// HasPHIUses - Return true if the specified register has any PHI use. -static bool HasPHIUses(unsigned Reg, MachineRegisterInfo *MRI) { +/// HasAnyPHIUse - Return true if the specified register is used by any +/// phi node. +bool MachineLICM::HasAnyPHIUse(unsigned Reg) const { for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), UE = MRI->use_end(); UI != UE; ++UI) { MachineInstr *UseMI = &*UI; if (UseMI->isPHI()) return true; + // Look pass copies as well. + if (UseMI->isCopy()) { + unsigned Def = UseMI->getOperand(0).getReg(); + if (TargetRegisterInfo::isVirtualRegister(Def) && + HasAnyPHIUse(Def)) + return true; + } } return false; } - /// HasHighOperandLatency - Compute operand latency between a def of 'Reg' /// and an use in the current loop, return true if the target considered /// it 'high'. @@ -976,14 +986,13 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { return false; } - // If result(s) of this instruction is used by PHIs, then don't hoist it. - // The presence of joins makes it difficult for current register allocator - // implementation to perform remat. + // If result(s) of this instruction is used by PHIs outside of the loop, then + // don't hoist it if the instruction because it will introduce an extra copy. for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI.getOperand(i); if (!MO.isReg() || !MO.isDef()) continue; - if (HasPHIUses(MO.getReg(), MRI)) + if (HasAnyPHIUse(MO.getReg())) return false; } diff --git a/contrib/llvm/lib/CodeGen/MachineSink.cpp b/contrib/llvm/lib/CodeGen/MachineSink.cpp index 8a93a24287b6..916dff70a41e 100644 --- a/contrib/llvm/lib/CodeGen/MachineSink.cpp +++ b/contrib/llvm/lib/CodeGen/MachineSink.cpp @@ -265,8 +265,11 @@ bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) { if (MI->isDebugValue()) continue; - if (PerformTrivialForwardCoalescing(MI, &MBB)) + bool Joined = PerformTrivialForwardCoalescing(MI, &MBB); + if (Joined) { + MadeChange = true; continue; + } if (SinkInstruction(MI, SawStore)) ++NumSunk, MadeChange = true; diff --git a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp index 7351119f4728..f95f4112aeda 100644 --- a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp @@ -402,6 +402,11 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { SmallVector Cond; if (!TII->AnalyzeBranch(*const_cast(MBB), TBB, FBB, Cond)) { + // If the block branches directly to a landing pad successor, pretend that + // the landing pad is a normal block. + LandingPadSuccs.erase(TBB); + LandingPadSuccs.erase(FBB); + // Ok, AnalyzeBranch thinks it knows what's going on with this block. Let's // check whether its answers match up with reality. if (!TBB && !FBB) { @@ -602,9 +607,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { // Check Live Variables. if (MI->isDebugValue()) { // Liveness checks are not valid for debug values. - } else if (MO->isUndef()) { - // An doesn't refer to any register, so just skip it. - } else if (MO->isUse()) { + } else if (MO->isUse() && !MO->isUndef()) { regsLiveInButUnused.erase(Reg); bool isKill = false; @@ -612,13 +615,9 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { if (MI->isRegTiedToDefOperand(MONum, &defIdx)) { // A two-addr use counts as a kill if use and def are the same. unsigned DefReg = MI->getOperand(defIdx).getReg(); - if (Reg == DefReg) { + if (Reg == DefReg) isKill = true; - // And in that case an explicit kill flag is not allowed. - if (MO->isKill()) - report("Illegal kill flag on two-address instruction operand", - MO, MONum); - } else if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + else if (TargetRegisterInfo::isPhysicalRegister(Reg)) { report("Two-address instruction operands must be identical", MO, MONum); } @@ -675,8 +674,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { MInfo.vregsLiveIn.insert(std::make_pair(Reg, MI)); } } - } else { - assert(MO->isDef()); + } else if (MO->isDef()) { // Register defined. // TODO: verify that earlyclobber ops are not used. if (MO->isDead()) diff --git a/contrib/llvm/lib/CodeGen/PHIElimination.cpp b/contrib/llvm/lib/CodeGen/PHIElimination.cpp index 5f7cf582c960..af65f13bf065 100644 --- a/contrib/llvm/lib/CodeGen/PHIElimination.cpp +++ b/contrib/llvm/lib/CodeGen/PHIElimination.cpp @@ -28,12 +28,17 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include -#include using namespace llvm; +static cl::opt +DisableEdgeSplitting("disable-phi-elim-edge-splitting", cl::init(false), + cl::Hidden, cl::desc("Disable critical edge splitting " + "during PHI elimination")); + namespace { class PHIElimination : public MachineFunctionPass { MachineRegisterInfo *MRI; // Machine register information @@ -105,10 +110,12 @@ bool PHIElimination::runOnMachineFunction(MachineFunction &MF) { bool Changed = false; // Split critical edges to help the coalescer - if (LiveVariables *LV = getAnalysisIfAvailable()) { - MachineLoopInfo *MLI = getAnalysisIfAvailable(); - for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) - Changed |= SplitPHIEdges(MF, *I, *LV, MLI); + if (!DisableEdgeSplitting) { + if (LiveVariables *LV = getAnalysisIfAvailable()) { + MachineLoopInfo *MLI = getAnalysisIfAvailable(); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + Changed |= SplitPHIEdges(MF, *I, *LV, MLI); + } } // Populate VRegPHIUseCount diff --git a/contrib/llvm/lib/CodeGen/Passes.cpp b/contrib/llvm/lib/CodeGen/Passes.cpp index 3489db2e9f4f..315aedddb9ef 100644 --- a/contrib/llvm/lib/CodeGen/Passes.cpp +++ b/contrib/llvm/lib/CodeGen/Passes.cpp @@ -55,6 +55,11 @@ FunctionPass *llvm::createRegisterAllocator(CodeGenOpt::Level OptLevel) { RegisterRegAlloc::setDefault(RegAlloc); } + // This forces linking of the linear scan register allocator, + // so -regalloc=linearscan still works in clang. + if (Ctor == createLinearScanRegisterAllocator) + return createLinearScanRegisterAllocator(); + if (Ctor != createDefaultRegisterAllocator) return Ctor(); @@ -63,6 +68,6 @@ FunctionPass *llvm::createRegisterAllocator(CodeGenOpt::Level OptLevel) { case CodeGenOpt::None: return createFastRegisterAllocator(); default: - return createLinearScanRegisterAllocator(); + return createGreedyRegisterAllocator(); } } diff --git a/contrib/llvm/lib/CodeGen/PeepholeOptimizer.cpp b/contrib/llvm/lib/CodeGen/PeepholeOptimizer.cpp index 5d7123caa017..c105bb06ebe5 100644 --- a/contrib/llvm/lib/CodeGen/PeepholeOptimizer.cpp +++ b/contrib/llvm/lib/CodeGen/PeepholeOptimizer.cpp @@ -30,6 +30,15 @@ // If the "sub" instruction all ready sets (or could be modified to set) the // same flag that the "cmp" instruction sets and that "bz" uses, then we can // eliminate the "cmp" instruction. +// +// - Optimize Bitcast pairs: +// +// v1 = bitcast v0 +// v2 = bitcast v1 +// = v2 +// => +// v1 = bitcast v0 +// = v0 // //===----------------------------------------------------------------------===// @@ -57,7 +66,8 @@ DisablePeephole("disable-peephole", cl::Hidden, cl::init(false), cl::desc("Disable the peephole optimizer")); STATISTIC(NumReuse, "Number of extension results reused"); -STATISTIC(NumEliminated, "Number of compares eliminated"); +STATISTIC(NumBitcasts, "Number of bitcasts eliminated"); +STATISTIC(NumCmps, "Number of compares eliminated"); STATISTIC(NumImmFold, "Number of move immediate foled"); namespace { @@ -85,6 +95,7 @@ namespace { } private: + bool OptimizeBitcastInstr(MachineInstr *MI, MachineBasicBlock *MBB); bool OptimizeCmpInstr(MachineInstr *MI, MachineBasicBlock *MBB); bool OptimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, SmallPtrSet &LocalMIs); @@ -243,12 +254,85 @@ OptimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, return Changed; } +/// OptimizeBitcastInstr - If the instruction is a bitcast instruction A that +/// cannot be optimized away during isel (e.g. ARM::VMOVSR, which bitcast +/// a value cross register classes), and the source is defined by another +/// bitcast instruction B. And if the register class of source of B matches +/// the register class of instruction A, then it is legal to replace all uses +/// of the def of A with source of B. e.g. +/// %vreg0 = VMOVSR %vreg1 +/// %vreg3 = VMOVRS %vreg0 +/// Replace all uses of vreg3 with vreg1. + +bool PeepholeOptimizer::OptimizeBitcastInstr(MachineInstr *MI, + MachineBasicBlock *MBB) { + unsigned NumDefs = MI->getDesc().getNumDefs(); + unsigned NumSrcs = MI->getDesc().getNumOperands() - NumDefs; + if (NumDefs != 1) + return false; + + unsigned Def = 0; + unsigned Src = 0; + for (unsigned i = 0, e = NumDefs + NumSrcs; i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (MO.isDef()) + Def = Reg; + else if (Src) + // Multiple sources? + return false; + else + Src = Reg; + } + + assert(Def && Src && "Malformed bitcast instruction!"); + + MachineInstr *DefMI = MRI->getVRegDef(Src); + if (!DefMI || !DefMI->getDesc().isBitcast()) + return false; + + unsigned SrcDef = 0; + unsigned SrcSrc = 0; + NumDefs = DefMI->getDesc().getNumDefs(); + NumSrcs = DefMI->getDesc().getNumOperands() - NumDefs; + if (NumDefs != 1) + return false; + for (unsigned i = 0, e = NumDefs + NumSrcs; i != e; ++i) { + const MachineOperand &MO = DefMI->getOperand(i); + if (!MO.isReg() || MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (MO.isDef()) + SrcDef = Reg; + else if (SrcSrc) + // Multiple sources? + return false; + else + SrcSrc = Reg; + } + + if (MRI->getRegClass(SrcSrc) != MRI->getRegClass(Def)) + return false; + + MRI->replaceRegWith(Def, SrcSrc); + MRI->clearKillFlags(SrcSrc); + MI->eraseFromParent(); + ++NumBitcasts; + return true; +} + /// OptimizeCmpInstr - If the instruction is a compare and the previous /// instruction it's comparing against all ready sets (or could be modified to /// set) the same flag as the compare, then we can remove the comparison and use /// the flag from the previous instruction. bool PeepholeOptimizer::OptimizeCmpInstr(MachineInstr *MI, - MachineBasicBlock *MBB){ + MachineBasicBlock *MBB) { // If this instruction is a comparison against zero and isn't comparing a // physical register, we can try to optimize it. unsigned SrcReg; @@ -259,7 +343,7 @@ bool PeepholeOptimizer::OptimizeCmpInstr(MachineInstr *MI, // Attempt to optimize the comparison instruction. if (TII->OptimizeCompareInstr(MI, SrcReg, CmpMask, CmpValue, MRI)) { - ++NumEliminated; + ++NumCmps; return true; } @@ -345,7 +429,16 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { continue; } - if (MI->getDesc().isCompare()) { + const TargetInstrDesc &TID = MI->getDesc(); + + if (TID.isBitcast()) { + if (OptimizeBitcastInstr(MI, MBB)) { + // MI is deleted. + Changed = true; + MII = First ? I->begin() : llvm::next(PMII); + continue; + } + } else if (TID.isCompare()) { if (OptimizeCmpInstr(MI, MBB)) { // MI is deleted. Changed = true; diff --git a/contrib/llvm/lib/CodeGen/ProcessImplicitDefs.cpp b/contrib/llvm/lib/CodeGen/ProcessImplicitDefs.cpp index 9cd9941e56b3..c04d65637c94 100644 --- a/contrib/llvm/lib/CodeGen/ProcessImplicitDefs.cpp +++ b/contrib/llvm/lib/CodeGen/ProcessImplicitDefs.cpp @@ -47,7 +47,6 @@ void ProcessImplicitDefs::getAnalysisUsage(AnalysisUsage &AU) const { bool ProcessImplicitDefs::CanTurnIntoImplicitDef(MachineInstr *MI, unsigned Reg, unsigned OpIdx, - const TargetInstrInfo *tii_, SmallSet &ImpDefRegs) { switch(OpIdx) { case 1: @@ -61,7 +60,6 @@ ProcessImplicitDefs::CanTurnIntoImplicitDef(MachineInstr *MI, } static bool isUndefCopy(MachineInstr *MI, unsigned Reg, - const TargetInstrInfo *tii_, SmallSet &ImpDefRegs) { if (MI->isCopy()) { MachineOperand &MO0 = MI->getOperand(0); @@ -86,11 +84,10 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { bool Changed = false; - const TargetInstrInfo *tii_ = fn.getTarget().getInstrInfo(); - const TargetRegisterInfo *tri_ = fn.getTarget().getRegisterInfo(); - MachineRegisterInfo *mri_ = &fn.getRegInfo(); - - LiveVariables *lv_ = &getAnalysis(); + TII = fn.getTarget().getInstrInfo(); + TRI = fn.getTarget().getRegisterInfo(); + MRI = &fn.getRegInfo(); + LV = &getAnalysis(); SmallSet ImpDefRegs; SmallVector ImpDefMIs; @@ -113,7 +110,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { unsigned Reg = MI->getOperand(0).getReg(); ImpDefRegs.insert(Reg); if (TargetRegisterInfo::isPhysicalRegister(Reg)) { - for (const unsigned *SS = tri_->getSubRegisters(Reg); *SS; ++SS) + for (const unsigned *SS = TRI->getSubRegisters(Reg); *SS; ++SS) ImpDefRegs.insert(*SS); } ImpDefMIs.push_back(MI); @@ -125,7 +122,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { MachineOperand &MO = MI->getOperand(1); if (MO.isUndef() || ImpDefRegs.count(MO.getReg())) { if (MO.isKill()) { - LiveVariables::VarInfo& vi = lv_->getVarInfo(MO.getReg()); + LiveVariables::VarInfo& vi = LV->getVarInfo(MO.getReg()); vi.removeKill(MI); } MI->eraseFromParent(); @@ -145,14 +142,14 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { if (!ImpDefRegs.count(Reg)) continue; // Use is a copy, just turn it into an implicit_def. - if (CanTurnIntoImplicitDef(MI, Reg, i, tii_, ImpDefRegs)) { + if (CanTurnIntoImplicitDef(MI, Reg, i, ImpDefRegs)) { bool isKill = MO.isKill(); - MI->setDesc(tii_->get(TargetOpcode::IMPLICIT_DEF)); + MI->setDesc(TII->get(TargetOpcode::IMPLICIT_DEF)); for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j) MI->RemoveOperand(j); if (isKill) { ImpDefRegs.erase(Reg); - LiveVariables::VarInfo& vi = lv_->getVarInfo(Reg); + LiveVariables::VarInfo& vi = LV->getVarInfo(Reg); vi.removeKill(MI); } ChangedToImpDef = true; @@ -210,8 +207,8 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { // uses. bool Skip = false; SmallVector DeadImpDefs; - for (MachineRegisterInfo::def_iterator DI = mri_->def_begin(Reg), - DE = mri_->def_end(); DI != DE; ++DI) { + for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(Reg), + DE = MRI->def_end(); DI != DE; ++DI) { MachineInstr *DeadImpDef = &*DI; if (!DeadImpDef->isImplicitDef()) { Skip = true; @@ -229,8 +226,8 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { Changed = true; // Process each use instruction once. - for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg), - UE = mri_->use_end(); UI != UE; ++UI) { + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), + UE = MRI->use_end(); UI != UE; ++UI) { if (UI.getOperand().isUndef()) continue; MachineInstr *RMI = &*UI; @@ -242,8 +239,8 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { MachineInstr *RMI = RUses[i]; // Turn a copy use into an implicit_def. - if (isUndefCopy(RMI, Reg, tii_, ImpDefRegs)) { - RMI->setDesc(tii_->get(TargetOpcode::IMPLICIT_DEF)); + if (isUndefCopy(RMI, Reg, ImpDefRegs)) { + RMI->setDesc(TII->get(TargetOpcode::IMPLICIT_DEF)); bool isKill = false; SmallVector Ops; @@ -263,15 +260,15 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { // Update LiveVariables varinfo if the instruction is a kill. if (isKill) { - LiveVariables::VarInfo& vi = lv_->getVarInfo(Reg); + LiveVariables::VarInfo& vi = LV->getVarInfo(Reg); vi.removeKill(RMI); } continue; } // Replace Reg with a new vreg that's marked implicit. - const TargetRegisterClass* RC = mri_->getRegClass(Reg); - unsigned NewVReg = mri_->createVirtualRegister(RC); + const TargetRegisterClass* RC = MRI->getRegClass(Reg); + unsigned NewVReg = MRI->createVirtualRegister(RC); bool isKill = true; for (unsigned j = 0, ee = RMI->getNumOperands(); j != ee; ++j) { MachineOperand &RRMO = RMI->getOperand(j); diff --git a/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp index ad7b6e4aa97f..f1f3c9969cc8 100644 --- a/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -337,7 +337,7 @@ void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) { --BeforeI; // Restore all registers immediately before the return and any - // terminators that preceed it. + // terminators that precede it. if (!TFI->restoreCalleeSavedRegisters(*MBB, I, CSI, TRI)) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); @@ -437,7 +437,7 @@ void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) { --BeforeI; // Restore all registers immediately before the return and any - // terminators that preceed it. + // terminators that precede it. for (unsigned i = 0, e = blockCSI.size(); i != e; ++i) { unsigned Reg = blockCSI[i].getReg(); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); @@ -559,7 +559,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // Make sure the special register scavenging spill slot is closest to the // frame pointer if a frame pointer is required. const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); - if (RS && TFI.hasFP(Fn) && !RegInfo->needsStackRealignment(Fn)) { + if (RS && TFI.hasFP(Fn) && RegInfo->useFPForScavengingIndex(Fn) && + !RegInfo->needsStackRealignment(Fn)) { int SFI = RS->getScavengingFrameIndex(); if (SFI >= 0) AdjustStackOffset(MFI, SFI, StackGrowsDown, Offset, MaxAlign); @@ -641,7 +642,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // Make sure the special register scavenging spill slot is closest to the // stack pointer. - if (RS && (!TFI.hasFP(Fn) || RegInfo->needsStackRealignment(Fn))) { + if (RS && (!TFI.hasFP(Fn) || RegInfo->needsStackRealignment(Fn) || + !RegInfo->useFPForScavengingIndex(Fn))) { int SFI = RS->getScavengingFrameIndex(); if (SFI >= 0) AdjustStackOffset(MFI, SFI, StackGrowsDown, Offset, MaxAlign); @@ -811,7 +813,6 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) { // directly. for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) { MachineInstr *MI = I; - bool DoIncr = true; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { if (MI->getOperand(i).isReg()) { MachineOperand &MO = MI->getOperand(i); @@ -842,10 +843,8 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) { } } - if (DoIncr) { - RS->forward(I); - ++I; - } + RS->forward(I); + ++I; } } } diff --git a/contrib/llvm/lib/CodeGen/RegAllocBase.h b/contrib/llvm/lib/CodeGen/RegAllocBase.h index 5af0ce79acf7..f431d5a5a026 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocBase.h +++ b/contrib/llvm/lib/CodeGen/RegAllocBase.h @@ -61,6 +61,11 @@ class LiveVirtRegQueue; /// assignment order. class RegAllocBase { LiveIntervalUnion::Allocator UnionAllocator; + + // Cache tag for PhysReg2LiveUnion entries. Increment whenever virtual + // registers may have changed. + unsigned UserTag; + protected: // Array of LiveIntervalUnions indexed by physical register. class LiveUnionArray { @@ -92,7 +97,7 @@ class RegAllocBase { // query on a new live virtual register. OwningArrayPtr Queries; - RegAllocBase(): TRI(0), MRI(0), VRM(0), LIS(0) {} + RegAllocBase(): UserTag(0), TRI(0), MRI(0), VRM(0), LIS(0) {} virtual ~RegAllocBase() {} @@ -104,7 +109,7 @@ class RegAllocBase { // before querying a new live virtual register. This ties Queries and // PhysReg2LiveUnion together. LiveIntervalUnion::Query &query(LiveInterval &VirtReg, unsigned PhysReg) { - Queries[PhysReg].init(&VirtReg, &PhysReg2LiveUnion[PhysReg]); + Queries[PhysReg].init(UserTag, &VirtReg, &PhysReg2LiveUnion[PhysReg]); return Queries[PhysReg]; } diff --git a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp index 6923908a32d9..d92d80f181fc 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp @@ -13,7 +13,9 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "regalloc" +#include "LiveDebugVariables.h" #include "LiveIntervalUnion.h" +#include "LiveRangeEdit.h" #include "RegAllocBase.h" #include "RenderMachineFunction.h" #include "Spiller.h" @@ -136,6 +138,7 @@ char RABasic::ID = 0; } // end anonymous namespace RABasic::RABasic(): MachineFunctionPass(ID) { + initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry()); initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); @@ -154,6 +157,8 @@ void RABasic::getAnalysisUsage(AnalysisUsage &AU) const { AU.addPreserved(); AU.addRequired(); AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); if (StrongPHIElim) AU.addRequiredID(StrongPHIEliminationID); AU.addRequiredTransitive(); @@ -230,9 +235,12 @@ void RegAllocBase::init(VirtRegMap &vrm, LiveIntervals &lis) { MRI = &vrm.getRegInfo(); VRM = &vrm; LIS = &lis; - PhysReg2LiveUnion.init(UnionAllocator, TRI->getNumRegs()); - // Cache an interferece query for each physical reg - Queries.reset(new LiveIntervalUnion::Query[PhysReg2LiveUnion.numRegs()]); + const unsigned NumRegs = TRI->getNumRegs(); + if (NumRegs != PhysReg2LiveUnion.numRegs()) { + PhysReg2LiveUnion.init(UnionAllocator, NumRegs); + // Cache an interferece query for each physical reg + Queries.reset(new LiveIntervalUnion::Query[PhysReg2LiveUnion.numRegs()]); + } } void RegAllocBase::LiveUnionArray::clear() { @@ -246,13 +254,15 @@ void RegAllocBase::LiveUnionArray::clear() { } void RegAllocBase::releaseMemory() { - PhysReg2LiveUnion.clear(); + for (unsigned r = 0, e = PhysReg2LiveUnion.numRegs(); r != e; ++r) + PhysReg2LiveUnion[r].clear(); } // Visit all the live registers. If they are already assigned to a physical // register, unify them with the corresponding LiveIntervalUnion, otherwise push // them on the priority queue for later assignment. void RegAllocBase::seedLiveRegs() { + NamedRegionTimer T("Seed Live Regs", TimerGroupName, TimePassesIsEnabled); for (LiveIntervals::iterator I = LIS->begin(), E = LIS->end(); I != E; ++I) { unsigned RegNum = I->first; LiveInterval &VirtReg = *I->second; @@ -268,6 +278,7 @@ void RegAllocBase::assign(LiveInterval &VirtReg, unsigned PhysReg) { << " to " << PrintReg(PhysReg, TRI) << '\n'); assert(!VRM->hasPhys(VirtReg.reg) && "Duplicate VirtReg assignment"); VRM->assignVirt2Phys(VirtReg.reg, PhysReg); + MRI->setPhysRegUsed(PhysReg); PhysReg2LiveUnion[PhysReg].unify(VirtReg); ++NumAssigned; } @@ -288,6 +299,18 @@ void RegAllocBase::allocatePhysRegs() { // Continue assigning vregs one at a time to available physical registers. while (LiveInterval *VirtReg = dequeue()) { + assert(!VRM->hasPhys(VirtReg->reg) && "Register already assigned"); + + // Unused registers can appear when the spiller coalesces snippets. + if (MRI->reg_nodbg_empty(VirtReg->reg)) { + DEBUG(dbgs() << "Dropping unused " << *VirtReg << '\n'); + LIS->removeInterval(VirtReg->reg); + continue; + } + + // Invalidate all interference queries, live ranges could have changed. + ++UserTag; + // selectOrSplit requests the allocator to return an available physical // register if possible and populate a list of new live intervals that // result from splitting. @@ -304,7 +327,12 @@ void RegAllocBase::allocatePhysRegs() { for (VirtRegVec::iterator I = SplitVRegs.begin(), E = SplitVRegs.end(); I != E; ++I) { LiveInterval *SplitVirtReg = *I; - if (SplitVirtReg->empty()) continue; + assert(!VRM->hasPhys(SplitVirtReg->reg) && "Register already assigned"); + if (MRI->reg_nodbg_empty(SplitVirtReg->reg)) { + DEBUG(dbgs() << "not queueing unused " << *SplitVirtReg << '\n'); + LIS->removeInterval(SplitVirtReg->reg); + continue; + } DEBUG(dbgs() << "queuing new interval: " << *SplitVirtReg << "\n"); assert(TargetRegisterInfo::isVirtualRegister(SplitVirtReg->reg) && "expect split value in virtual register"); @@ -344,7 +372,8 @@ void RegAllocBase::spillReg(LiveInterval& VirtReg, unsigned PhysReg, unassign(SpilledVReg, PhysReg); // Spill the extracted interval. - spiller().spill(&SpilledVReg, SplitVRegs, PendingSpills); + LiveRangeEdit LRE(SpilledVReg, SplitVRegs, 0, &PendingSpills); + spiller().spill(LRE); } // After extracting segments, the query's results are invalid. But keep the // contents valid until we're done accessing pendingSpills. @@ -381,29 +410,31 @@ RegAllocBase::spillInterferences(LiveInterval &VirtReg, unsigned PhysReg, // Add newly allocated physical registers to the MBB live in sets. void RegAllocBase::addMBBLiveIns(MachineFunction *MF) { NamedRegionTimer T("MBB Live Ins", TimerGroupName, TimePassesIsEnabled); - typedef SmallVector MBBVec; - MBBVec liveInMBBs; - MachineBasicBlock &entryMBB = *MF->begin(); + SlotIndexes *Indexes = LIS->getSlotIndexes(); + if (MF->size() <= 1) + return; + LiveIntervalUnion::SegmentIter SI; for (unsigned PhysReg = 0; PhysReg < PhysReg2LiveUnion.numRegs(); ++PhysReg) { LiveIntervalUnion &LiveUnion = PhysReg2LiveUnion[PhysReg]; if (LiveUnion.empty()) continue; - for (LiveIntervalUnion::SegmentIter SI = LiveUnion.begin(); SI.valid(); - ++SI) { - - // Find the set of basic blocks which this range is live into... - liveInMBBs.clear(); - if (!LIS->findLiveInMBBs(SI.start(), SI.stop(), liveInMBBs)) continue; - - // And add the physreg for this interval to their live-in sets. - for (MBBVec::iterator I = liveInMBBs.begin(), E = liveInMBBs.end(); - I != E; ++I) { - MachineBasicBlock *MBB = *I; - if (MBB == &entryMBB) continue; - if (MBB->isLiveIn(PhysReg)) continue; - MBB->addLiveIn(PhysReg); - } + MachineFunction::iterator MBB = llvm::next(MF->begin()); + MachineFunction::iterator MFE = MF->end(); + SlotIndex Start, Stop; + tie(Start, Stop) = Indexes->getMBBRange(MBB); + SI.setMap(LiveUnion.getMap()); + SI.find(Start); + while (SI.valid()) { + if (SI.start() <= Start) { + if (!MBB->isLiveIn(PhysReg)) + MBB->addLiveIn(PhysReg); + } else if (SI.start() > Stop) + MBB = Indexes->getMBBFromIndex(SI.start().getPrevIndex()); + if (++MBB == MFE) + break; + tie(Start, Stop) = Indexes->getMBBRange(MBB); + SI.advanceTo(Start); } } } @@ -469,9 +500,8 @@ unsigned RABasic::selectOrSplit(LiveInterval &VirtReg, } // No other spill candidates were found, so spill the current VirtReg. DEBUG(dbgs() << "spilling: " << VirtReg << '\n'); - SmallVector pendingSpills; - - spiller().spill(&VirtReg, SplitVRegs, pendingSpills); + LiveRangeEdit LRE(VirtReg, SplitVRegs); + spiller().spill(LRE); // The live virtual register requesting allocation was spilled, so tell // the caller not to allocate anything during this round. @@ -490,7 +520,7 @@ bool RABasic::runOnMachineFunction(MachineFunction &mf) { ReservedRegs = TRI->getReservedRegs(*MF); - SpillerInstance.reset(createSpiller(*this, *MF, *VRM)); + SpillerInstance.reset(createInlineSpiller(*this, *MF, *VRM)); allocatePhysRegs(); @@ -525,6 +555,9 @@ bool RABasic::runOnMachineFunction(MachineFunction &mf) { // Run rewriter VRM->rewrite(LIS->getSlotIndexes()); + // Write out new DBG_VALUE instructions. + getAnalysis().emitDebugValues(VRM); + // The pass output is in VirtRegMap. Release all the transient data. releaseMemory(); diff --git a/contrib/llvm/lib/CodeGen/RegAllocFast.cpp b/contrib/llvm/lib/CodeGen/RegAllocFast.cpp index 15036e38b893..b2fd6e092ce6 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocFast.cpp @@ -97,7 +97,7 @@ namespace { // immediately without checking aliases. regFree, - // A reserved register has been assigned expolicitly (e.g., setting up a + // A reserved register has been assigned explicitly (e.g., setting up a // call parameter), and it remains reserved until it is used. regReserved @@ -396,7 +396,6 @@ void RAFast::definePhysReg(MachineInstr *MI, unsigned PhysReg, PhysRegState[PhysReg] = NewState; for (const unsigned *AS = TRI->getAliasSet(PhysReg); unsigned Alias = *AS; ++AS) { - UsedInInstr.set(Alias); switch (unsigned VirtReg = PhysRegState[Alias]) { case regDisabled: break; @@ -420,20 +419,25 @@ void RAFast::definePhysReg(MachineInstr *MI, unsigned PhysReg, // can be allocated directly. // Returns spillImpossible when PhysReg or an alias can't be spilled. unsigned RAFast::calcSpillCost(unsigned PhysReg) const { - if (UsedInInstr.test(PhysReg)) + if (UsedInInstr.test(PhysReg)) { + DEBUG(dbgs() << "PhysReg: " << PhysReg << " is already used in instr.\n"); return spillImpossible; + } switch (unsigned VirtReg = PhysRegState[PhysReg]) { case regDisabled: break; case regFree: return 0; case regReserved: + DEBUG(dbgs() << "VirtReg: " << VirtReg << " corresponding to PhysReg: " + << PhysReg << " is reserved already.\n"); return spillImpossible; default: return LiveVirtRegs.lookup(VirtReg).Dirty ? spillDirty : spillClean; } - // This is a disabled register, add up const of aliases. + // This is a disabled register, add up cost of aliases. + DEBUG(dbgs() << "\tRegister: " << PhysReg << " is disabled.\n"); unsigned Cost = 0; for (const unsigned *AS = TRI->getAliasSet(PhysReg); unsigned Alias = *AS; ++AS) { @@ -511,9 +515,14 @@ void RAFast::allocVirtReg(MachineInstr *MI, LiveRegEntry &LRE, unsigned Hint) { unsigned BestReg = 0, BestCost = spillImpossible; for (TargetRegisterClass::iterator I = AOB; I != AOE; ++I) { - if (!Allocatable.test(*I)) + if (!Allocatable.test(*I)) { + DEBUG(dbgs() << "\tRegister " << *I << " is not allocatable.\n"); continue; + } unsigned Cost = calcSpillCost(*I); + DEBUG(dbgs() << "\tRegister: " << *I << "\n"); + DEBUG(dbgs() << "\tCost: " << Cost << "\n"); + DEBUG(dbgs() << "\tBestCost: " << BestCost << "\n"); // Cost is 0 when all aliases are already disabled. if (Cost == 0) return assignVirtToPhysReg(LRE, *I); @@ -722,9 +731,8 @@ void RAFast::handleThroughOperands(MachineInstr *MI, if (!MO.isReg() || (MO.isDef() && !MO.isEarlyClobber())) continue; unsigned Reg = MO.getReg(); if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; + DEBUG(dbgs() << "\tSetting reg " << Reg << " as used in instr\n"); UsedInInstr.set(Reg); - for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) - UsedInInstr.set(*AS); } // Also mark PartialDefs as used to avoid reallocation. diff --git a/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp b/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp index 406485aaf496..7c461d8ea787 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp @@ -14,7 +14,8 @@ #define DEBUG_TYPE "regalloc" #include "AllocationOrder.h" -#include "LiveIntervalUnion.h" +#include "InterferenceCache.h" +#include "LiveDebugVariables.h" #include "LiveRangeEdit.h" #include "RegAllocBase.h" #include "Spiller.h" @@ -49,14 +50,16 @@ using namespace llvm; STATISTIC(NumGlobalSplits, "Number of split global live ranges"); STATISTIC(NumLocalSplits, "Number of split local live ranges"); -STATISTIC(NumReassigned, "Number of interferences reassigned"); STATISTIC(NumEvicted, "Number of interferences evicted"); static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator", createGreedyRegisterAllocator); namespace { -class RAGreedy : public MachineFunctionPass, public RegAllocBase { +class RAGreedy : public MachineFunctionPass, + public RegAllocBase, + private LiveRangeEdit::Delegate { + // context MachineFunction *MF; BitVector ReservedRegs; @@ -72,14 +75,73 @@ class RAGreedy : public MachineFunctionPass, public RegAllocBase { // state std::auto_ptr SpillerInstance; - std::auto_ptr SA; std::priority_queue > Queue; - IndexedMap Generation; + + // Live ranges pass through a number of stages as we try to allocate them. + // Some of the stages may also create new live ranges: + // + // - Region splitting. + // - Per-block splitting. + // - Local splitting. + // - Spilling. + // + // Ranges produced by one of the stages skip the previous stages when they are + // dequeued. This improves performance because we can skip interference checks + // that are unlikely to give any results. It also guarantees that the live + // range splitting algorithm terminates, something that is otherwise hard to + // ensure. + enum LiveRangeStage { + RS_New, ///< Never seen before. + RS_First, ///< First time in the queue. + RS_Second, ///< Second time in the queue. + RS_Global, ///< Produced by global splitting. + RS_Local, ///< Produced by local splitting. + RS_Spill ///< Produced by spilling. + }; + + IndexedMap LRStage; + + LiveRangeStage getStage(const LiveInterval &VirtReg) const { + return LiveRangeStage(LRStage[VirtReg.reg]); + } + + template + void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) { + LRStage.resize(MRI->getNumVirtRegs()); + for (;Begin != End; ++Begin) { + unsigned Reg = (*Begin)->reg; + if (LRStage[Reg] == RS_New) + LRStage[Reg] = NewStage; + } + } // splitting state. + std::auto_ptr SA; + std::auto_ptr SE; - /// All basic blocks where the current register is live. - SmallVector SpillConstraints; + /// Cached per-block interference maps + InterferenceCache IntfCache; + + /// All basic blocks where the current register has uses. + SmallVector SplitConstraints; + + /// Global live range splitting candidate info. + struct GlobalSplitCandidate { + unsigned PhysReg; + BitVector LiveBundles; + SmallVector ActiveBlocks; + + void reset(unsigned Reg) { + PhysReg = Reg; + LiveBundles.clear(); + ActiveBlocks.clear(); + } + }; + + /// Candidate info for for each PhysReg in AllocationOrder. + /// This vector never shrinks, but grows to the size of the largest register + /// class. + SmallVector GlobalCand; /// For every instruction in SA->UseSlots, store the previous non-copy /// instruction. @@ -108,42 +170,50 @@ class RAGreedy : public MachineFunctionPass, public RegAllocBase { static char ID; private: - bool checkUncachedInterference(LiveInterval&, unsigned); - LiveInterval *getSingleInterference(LiveInterval&, unsigned); - bool reassignVReg(LiveInterval &InterferingVReg, unsigned OldPhysReg); - float calcInterferenceWeight(LiveInterval&, unsigned); - float calcInterferenceInfo(LiveInterval&, unsigned); - float calcGlobalSplitCost(const BitVector&); - void splitAroundRegion(LiveInterval&, unsigned, const BitVector&, + void LRE_WillEraseInstruction(MachineInstr*); + bool LRE_CanEraseVirtReg(unsigned); + void LRE_WillShrinkVirtReg(unsigned); + void LRE_DidCloneVirtReg(unsigned, unsigned); + + float calcSpillCost(); + bool addSplitConstraints(InterferenceCache::Cursor, float&); + void addThroughConstraints(InterferenceCache::Cursor, ArrayRef); + void growRegion(GlobalSplitCandidate &Cand, InterferenceCache::Cursor); + float calcGlobalSplitCost(GlobalSplitCandidate&, InterferenceCache::Cursor); + void splitAroundRegion(LiveInterval&, GlobalSplitCandidate&, SmallVectorImpl&); void calcGapWeights(unsigned, SmallVectorImpl&); SlotIndex getPrevMappedIndex(const MachineInstr*); void calcPrevSlots(); unsigned nextSplitPoint(unsigned); - bool canEvictInterference(LiveInterval&, unsigned, unsigned, float&); + bool canEvictInterference(LiveInterval&, unsigned, float&); - unsigned tryReassign(LiveInterval&, AllocationOrder&, - SmallVectorImpl&); + unsigned tryAssign(LiveInterval&, AllocationOrder&, + SmallVectorImpl&); unsigned tryEvict(LiveInterval&, AllocationOrder&, - SmallVectorImpl&); + SmallVectorImpl&, unsigned = ~0u); unsigned tryRegionSplit(LiveInterval&, AllocationOrder&, SmallVectorImpl&); unsigned tryLocalSplit(LiveInterval&, AllocationOrder&, SmallVectorImpl&); unsigned trySplit(LiveInterval&, AllocationOrder&, SmallVectorImpl&); - unsigned trySpillInterferences(LiveInterval&, AllocationOrder&, - SmallVectorImpl&); }; } // end anonymous namespace char RAGreedy::ID = 0; +// Hysteresis to use when comparing floats. +// This helps stabilize decisions based on float comparisons. +const float Hysteresis = 0.98f; + + FunctionPass* llvm::createGreedyRegisterAllocator() { return new RAGreedy(); } -RAGreedy::RAGreedy(): MachineFunctionPass(ID) { +RAGreedy::RAGreedy(): MachineFunctionPass(ID), LRStage(RS_New) { + initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry()); initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); @@ -166,6 +236,8 @@ void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); AU.addRequired(); AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); if (StrongPHIElim) AU.addRequiredID(StrongPHIEliminationID); AU.addRequiredTransitive(); @@ -185,9 +257,49 @@ void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); } + +//===----------------------------------------------------------------------===// +// LiveRangeEdit delegate methods +//===----------------------------------------------------------------------===// + +void RAGreedy::LRE_WillEraseInstruction(MachineInstr *MI) { + // LRE itself will remove from SlotIndexes and parent basic block. + VRM->RemoveMachineInstrFromMaps(MI); +} + +bool RAGreedy::LRE_CanEraseVirtReg(unsigned VirtReg) { + if (unsigned PhysReg = VRM->getPhys(VirtReg)) { + unassign(LIS->getInterval(VirtReg), PhysReg); + return true; + } + // Unassigned virtreg is probably in the priority queue. + // RegAllocBase will erase it after dequeueing. + return false; +} + +void RAGreedy::LRE_WillShrinkVirtReg(unsigned VirtReg) { + unsigned PhysReg = VRM->getPhys(VirtReg); + if (!PhysReg) + return; + + // Register is assigned, put it back on the queue for reassignment. + LiveInterval &LI = LIS->getInterval(VirtReg); + unassign(LI, PhysReg); + enqueue(&LI); +} + +void RAGreedy::LRE_DidCloneVirtReg(unsigned New, unsigned Old) { + // LRE may clone a virtual register because dead code elimination causes it to + // be split into connected components. Ensure that the new register gets the + // same stage as the parent. + LRStage.grow(New); + LRStage[New] = LRStage[Old]; +} + void RAGreedy::releaseMemory() { SpillerInstance.reset(0); - Generation.clear(); + LRStage.clear(); + GlobalCand.clear(); RegAllocBase::releaseMemory(); } @@ -198,20 +310,26 @@ void RAGreedy::enqueue(LiveInterval *LI) { const unsigned Reg = LI->reg; assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Can only enqueue virtual registers"); - const unsigned Hint = VRM->getRegAllocPref(Reg); unsigned Prio; - Generation.grow(Reg); - if (++Generation[Reg] == 1) - // 1st generation ranges are handled first, long -> short. - Prio = (1u << 31) + Size; - else - // Repeat offenders are handled second, short -> long - Prio = (1u << 30) - Size; + LRStage.grow(Reg); + if (LRStage[Reg] == RS_New) + LRStage[Reg] = RS_First; - // Boost ranges that have a physical register hint. - if (TargetRegisterInfo::isPhysicalRegister(Hint)) - Prio |= (1u << 30); + if (LRStage[Reg] == RS_Second) + // Unsplit ranges that couldn't be allocated immediately are deferred until + // everything else has been allocated. Long ranges are allocated last so + // they are split against realistic interference. + Prio = (1u << 31) - Size; + else { + // Everything else is allocated in long->short order. Long ranges that don't + // fit should be spilled ASAP so they don't create interference. + Prio = (1u << 31) + Size; + + // Boost ranges that have a physical register hint. + if (TargetRegisterInfo::isPhysicalRegister(VRM->getRegAllocPref(Reg))) + Prio |= (1u << 30); + } Queue.push(std::make_pair(Prio, Reg)); } @@ -224,97 +342,34 @@ LiveInterval *RAGreedy::dequeue() { return LI; } + //===----------------------------------------------------------------------===// -// Register Reassignment +// Direct Assignment //===----------------------------------------------------------------------===// -// Check interference without using the cache. -bool RAGreedy::checkUncachedInterference(LiveInterval &VirtReg, - unsigned PhysReg) { - for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) { - LiveIntervalUnion::Query subQ(&VirtReg, &PhysReg2LiveUnion[*AliasI]); - if (subQ.checkInterference()) - return true; - } - return false; -} - -/// getSingleInterference - Return the single interfering virtual register -/// assigned to PhysReg. Return 0 if more than one virtual register is -/// interfering. -LiveInterval *RAGreedy::getSingleInterference(LiveInterval &VirtReg, - unsigned PhysReg) { - // Check physreg and aliases. - LiveInterval *Interference = 0; - for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) { - LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI); - if (Q.checkInterference()) { - if (Interference) - return 0; - if (Q.collectInterferingVRegs(2) > 1) - return 0; - Interference = Q.interferingVRegs().front(); - } - } - return Interference; -} - -// Attempt to reassign this virtual register to a different physical register. -// -// FIXME: we are not yet caching these "second-level" interferences discovered -// in the sub-queries. These interferences can change with each call to -// selectOrSplit. However, we could implement a "may-interfere" cache that -// could be conservatively dirtied when we reassign or split. -// -// FIXME: This may result in a lot of alias queries. We could summarize alias -// live intervals in their parent register's live union, but it's messy. -bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg, - unsigned WantedPhysReg) { - assert(TargetRegisterInfo::isVirtualRegister(InterferingVReg.reg) && - "Can only reassign virtual registers"); - assert(TRI->regsOverlap(WantedPhysReg, VRM->getPhys(InterferingVReg.reg)) && - "inconsistent phys reg assigment"); - - AllocationOrder Order(InterferingVReg.reg, *VRM, ReservedRegs); - while (unsigned PhysReg = Order.next()) { - // Don't reassign to a WantedPhysReg alias. - if (TRI->regsOverlap(PhysReg, WantedPhysReg)) - continue; - - if (checkUncachedInterference(InterferingVReg, PhysReg)) - continue; - - // Reassign the interfering virtual reg to this physical reg. - unsigned OldAssign = VRM->getPhys(InterferingVReg.reg); - DEBUG(dbgs() << "reassigning: " << InterferingVReg << " from " << - TRI->getName(OldAssign) << " to " << TRI->getName(PhysReg) << '\n'); - unassign(InterferingVReg, OldAssign); - assign(InterferingVReg, PhysReg); - ++NumReassigned; - return true; - } - return false; -} - -/// tryReassign - Try to reassign a single interference to a different physreg. -/// @param VirtReg Currently unassigned virtual register. -/// @param Order Physregs to try. -/// @return Physreg to assign VirtReg, or 0. -unsigned RAGreedy::tryReassign(LiveInterval &VirtReg, AllocationOrder &Order, - SmallVectorImpl &NewVRegs){ - NamedRegionTimer T("Reassign", TimerGroupName, TimePassesIsEnabled); - +/// tryAssign - Try to assign VirtReg to an available register. +unsigned RAGreedy::tryAssign(LiveInterval &VirtReg, + AllocationOrder &Order, + SmallVectorImpl &NewVRegs) { Order.rewind(); - while (unsigned PhysReg = Order.next()) { - LiveInterval *InterferingVReg = getSingleInterference(VirtReg, PhysReg); - if (!InterferingVReg) - continue; - if (TargetRegisterInfo::isPhysicalRegister(InterferingVReg->reg)) - continue; - if (reassignVReg(*InterferingVReg, PhysReg)) - return PhysReg; - } - return 0; + unsigned PhysReg; + while ((PhysReg = Order.next())) + if (!checkPhysRegInterference(VirtReg, PhysReg)) + break; + if (!PhysReg || Order.isHint(PhysReg)) + return PhysReg; + + // PhysReg is available. Try to evict interference from a cheaper alternative. + unsigned Cost = TRI->getCostPerUse(PhysReg); + + // Most registers have 0 additional cost. + if (!Cost) + return PhysReg; + + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " is available at cost " << Cost + << '\n'); + unsigned CheapReg = tryEvict(VirtReg, Order, NewVRegs, Cost); + return CheapReg ? CheapReg : PhysReg; } @@ -323,22 +378,24 @@ unsigned RAGreedy::tryReassign(LiveInterval &VirtReg, AllocationOrder &Order, //===----------------------------------------------------------------------===// /// canEvict - Return true if all interferences between VirtReg and PhysReg can -/// be evicted. Set maxWeight to the maximal spill weight of an interference. +/// be evicted. +/// Return false if any interference is heavier than MaxWeight. +/// On return, set MaxWeight to the maximal spill weight of an interference. bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg, - unsigned Size, float &MaxWeight) { + float &MaxWeight) { float Weight = 0; for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) { LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI); - // If there is 10 or more interferences, chances are one is smaller. - if (Q.collectInterferingVRegs(10) >= 10) + // If there is 10 or more interferences, chances are one is heavier. + if (Q.collectInterferingVRegs(10, MaxWeight) >= 10) return false; - // CHeck if any interfering live range is shorter than VirtReg. - for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) { - LiveInterval *Intf = Q.interferingVRegs()[i]; + // Check if any interfering live range is heavier than MaxWeight. + for (unsigned i = Q.interferingVRegs().size(); i; --i) { + LiveInterval *Intf = Q.interferingVRegs()[i - 1]; if (TargetRegisterInfo::isPhysicalRegister(Intf->reg)) return false; - if (Intf->getSize() <= Size) + if (Intf->weight >= MaxWeight) return false; Weight = std::max(Weight, Intf->weight); } @@ -353,25 +410,28 @@ bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg, /// @return Physreg to assign VirtReg, or 0. unsigned RAGreedy::tryEvict(LiveInterval &VirtReg, AllocationOrder &Order, - SmallVectorImpl &NewVRegs){ + SmallVectorImpl &NewVRegs, + unsigned CostPerUseLimit) { NamedRegionTimer T("Evict", TimerGroupName, TimePassesIsEnabled); - // We can only evict interference if all interfering registers are virtual and - // longer than VirtReg. - const unsigned Size = VirtReg.getSize(); - // Keep track of the lightest single interference seen so far. - float BestWeight = 0; + float BestWeight = VirtReg.weight; unsigned BestPhys = 0; Order.rewind(); while (unsigned PhysReg = Order.next()) { - float Weight = 0; - if (!canEvictInterference(VirtReg, PhysReg, Size, Weight)) + if (TRI->getCostPerUse(PhysReg) >= CostPerUseLimit) + continue; + // The first use of a register in a function has cost 1. + if (CostPerUseLimit == 1 && !MRI->isPhysRegUsed(PhysReg)) + continue; + + float Weight = BestWeight; + if (!canEvictInterference(VirtReg, PhysReg, Weight)) continue; // This is an eviction candidate. - DEBUG(dbgs() << "max " << PrintReg(PhysReg, TRI) << " interference = " + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " interference = " << Weight << '\n'); if (BestPhys && Weight >= BestWeight) continue; @@ -406,201 +466,228 @@ unsigned RAGreedy::tryEvict(LiveInterval &VirtReg, // Region Splitting //===----------------------------------------------------------------------===// -/// calcInterferenceInfo - Compute per-block outgoing and ingoing constraints -/// when considering interference from PhysReg. Also compute an optimistic local -/// cost of this interference pattern. -/// -/// The final cost of a split is the local cost + global cost of preferences -/// broken by SpillPlacement. -/// -float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) { +/// addSplitConstraints - Fill out the SplitConstraints vector based on the +/// interference pattern in Physreg and its aliases. Add the constraints to +/// SpillPlacement and return the static cost of this split in Cost, assuming +/// that all preferences in SplitConstraints are met. +/// Return false if there are no bundles with positive bias. +bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf, + float &Cost) { + ArrayRef UseBlocks = SA->getUseBlocks(); + // Reset interference dependent info. - SpillConstraints.resize(SA->LiveBlocks.size()); - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; - SpillPlacement::BlockConstraint &BC = SpillConstraints[i]; + SplitConstraints.resize(UseBlocks.size()); + float StaticCost = 0; + for (unsigned i = 0; i != UseBlocks.size(); ++i) { + const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; + SpillPlacement::BlockConstraint &BC = SplitConstraints[i]; + BC.Number = BI.MBB->getNumber(); - BC.Entry = (BI.Uses && BI.LiveIn) ? - SpillPlacement::PrefReg : SpillPlacement::DontCare; - BC.Exit = (BI.Uses && BI.LiveOut) ? - SpillPlacement::PrefReg : SpillPlacement::DontCare; - BI.OverlapEntry = BI.OverlapExit = false; - } + Intf.moveToBlock(BC.Number); + BC.Entry = BI.LiveIn ? SpillPlacement::PrefReg : SpillPlacement::DontCare; + BC.Exit = BI.LiveOut ? SpillPlacement::PrefReg : SpillPlacement::DontCare; - // Add interference info from each PhysReg alias. - for (const unsigned *AI = TRI->getOverlaps(PhysReg); *AI; ++AI) { - if (!query(VirtReg, *AI).checkInterference()) - continue; - LiveIntervalUnion::SegmentIter IntI = - PhysReg2LiveUnion[*AI].find(VirtReg.beginIndex()); - if (!IntI.valid()) + if (!Intf.hasInterference()) continue; - // Determine which blocks have interference live in or after the last split - // point. - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; - SpillPlacement::BlockConstraint &BC = SpillConstraints[i]; - SlotIndex Start, Stop; - tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); + // Number of spill code instructions to insert. + unsigned Ins = 0; - // Skip interference-free blocks. - if (IntI.start() >= Stop) - continue; - - // Is the interference live-in? - if (BI.LiveIn) { - IntI.advanceTo(Start); - if (!IntI.valid()) - break; - if (IntI.start() <= Start) - BC.Entry = SpillPlacement::MustSpill; - } - - // Is the interference overlapping the last split point? - if (BI.LiveOut) { - if (IntI.stop() < BI.LastSplitPoint) - IntI.advanceTo(BI.LastSplitPoint.getPrevSlot()); - if (!IntI.valid()) - break; - if (IntI.start() < Stop) - BC.Exit = SpillPlacement::MustSpill; - } + // Interference for the live-in value. + if (BI.LiveIn) { + if (Intf.first() <= Indexes->getMBBStartIdx(BC.Number)) + BC.Entry = SpillPlacement::MustSpill, ++Ins; + else if (Intf.first() < BI.FirstUse) + BC.Entry = SpillPlacement::PrefSpill, ++Ins; + else if (Intf.first() < (BI.LiveThrough ? BI.LastUse : BI.Kill)) + ++Ins; } - // Rewind iterator and check other interferences. - IntI.find(VirtReg.beginIndex()); - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; - SpillPlacement::BlockConstraint &BC = SpillConstraints[i]; - SlotIndex Start, Stop; - tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); + // Interference for the live-out value. + if (BI.LiveOut) { + if (Intf.last() >= SA->getLastSplitPoint(BC.Number)) + BC.Exit = SpillPlacement::MustSpill, ++Ins; + else if (Intf.last() > BI.LastUse) + BC.Exit = SpillPlacement::PrefSpill, ++Ins; + else if (Intf.last() > (BI.LiveThrough ? BI.FirstUse : BI.Def)) + ++Ins; + } - // Skip interference-free blocks. - if (IntI.start() >= Stop) - continue; + // Accumulate the total frequency of inserted spill code. + if (Ins) + StaticCost += Ins * SpillPlacer->getBlockFrequency(BC.Number); + } + Cost = StaticCost; - // Handle transparent blocks with interference separately. - // Transparent blocks never incur any fixed cost. - if (BI.LiveThrough && !BI.Uses) { - IntI.advanceTo(Start); - if (!IntI.valid()) - break; - if (IntI.start() >= Stop) + // Add constraints for use-blocks. Note that these are the only constraints + // that may add a positive bias, it is downhill from here. + SpillPlacer->addConstraints(SplitConstraints); + return SpillPlacer->scanActiveBundles(); +} + + +/// addThroughConstraints - Add constraints and links to SpillPlacer from the +/// live-through blocks in Blocks. +void RAGreedy::addThroughConstraints(InterferenceCache::Cursor Intf, + ArrayRef Blocks) { + const unsigned GroupSize = 8; + SpillPlacement::BlockConstraint BCS[GroupSize]; + unsigned TBS[GroupSize]; + unsigned B = 0, T = 0; + + for (unsigned i = 0; i != Blocks.size(); ++i) { + unsigned Number = Blocks[i]; + Intf.moveToBlock(Number); + + if (!Intf.hasInterference()) { + assert(T < GroupSize && "Array overflow"); + TBS[T] = Number; + if (++T == GroupSize) { + SpillPlacer->addLinks(ArrayRef(TBS, T)); + T = 0; + } + continue; + } + + assert(B < GroupSize && "Array overflow"); + BCS[B].Number = Number; + + // Interference for the live-in value. + if (Intf.first() <= Indexes->getMBBStartIdx(Number)) + BCS[B].Entry = SpillPlacement::MustSpill; + else + BCS[B].Entry = SpillPlacement::PrefSpill; + + // Interference for the live-out value. + if (Intf.last() >= SA->getLastSplitPoint(Number)) + BCS[B].Exit = SpillPlacement::MustSpill; + else + BCS[B].Exit = SpillPlacement::PrefSpill; + + if (++B == GroupSize) { + ArrayRef Array(BCS, B); + SpillPlacer->addConstraints(Array); + B = 0; + } + } + + ArrayRef Array(BCS, B); + SpillPlacer->addConstraints(Array); + SpillPlacer->addLinks(ArrayRef(TBS, T)); +} + +void RAGreedy::growRegion(GlobalSplitCandidate &Cand, + InterferenceCache::Cursor Intf) { + // Keep track of through blocks that have not been added to SpillPlacer. + BitVector Todo = SA->getThroughBlocks(); + SmallVectorImpl &ActiveBlocks = Cand.ActiveBlocks; + unsigned AddedTo = 0; +#ifndef NDEBUG + unsigned Visited = 0; +#endif + + for (;;) { + ArrayRef NewBundles = SpillPlacer->getRecentPositive(); + if (NewBundles.empty()) + break; + // Find new through blocks in the periphery of PrefRegBundles. + for (int i = 0, e = NewBundles.size(); i != e; ++i) { + unsigned Bundle = NewBundles[i]; + // Look at all blocks connected to Bundle in the full graph. + ArrayRef Blocks = Bundles->getBlocks(Bundle); + for (ArrayRef::iterator I = Blocks.begin(), E = Blocks.end(); + I != E; ++I) { + unsigned Block = *I; + if (!Todo.test(Block)) continue; - - if (BC.Entry != SpillPlacement::MustSpill) - BC.Entry = SpillPlacement::PrefSpill; - if (BC.Exit != SpillPlacement::MustSpill) - BC.Exit = SpillPlacement::PrefSpill; - continue; - } - - // Now we only have blocks with uses left. - // Check if the interference overlaps the uses. - assert(BI.Uses && "Non-transparent block without any uses"); - - // Check interference on entry. - if (BI.LiveIn && BC.Entry != SpillPlacement::MustSpill) { - IntI.advanceTo(Start); - if (!IntI.valid()) - break; - // Not live in, but before the first use. - if (IntI.start() < BI.FirstUse) { - BC.Entry = SpillPlacement::PrefSpill; - // If the block contains a kill from an earlier split, never split - // again in the same block. - if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Kill)) - BC.Entry = SpillPlacement::MustSpill; - } - } - - // Does interference overlap the uses in the entry segment - // [FirstUse;Kill)? - if (BI.LiveIn && !BI.OverlapEntry) { - IntI.advanceTo(BI.FirstUse); - if (!IntI.valid()) - break; - // A live-through interval has no kill. - // Check [FirstUse;LastUse) instead. - if (IntI.start() < (BI.LiveThrough ? BI.LastUse : BI.Kill)) - BI.OverlapEntry = true; - } - - // Does interference overlap the uses in the exit segment [Def;LastUse)? - if (BI.LiveOut && !BI.LiveThrough && !BI.OverlapExit) { - IntI.advanceTo(BI.Def); - if (!IntI.valid()) - break; - if (IntI.start() < BI.LastUse) - BI.OverlapExit = true; - } - - // Check interference on exit. - if (BI.LiveOut && BC.Exit != SpillPlacement::MustSpill) { - // Check interference between LastUse and Stop. - if (BC.Exit != SpillPlacement::PrefSpill) { - IntI.advanceTo(BI.LastUse); - if (!IntI.valid()) - break; - if (IntI.start() < Stop) { - BC.Exit = SpillPlacement::PrefSpill; - // Avoid splitting twice in the same block. - if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Def)) - BC.Exit = SpillPlacement::MustSpill; - } - } + Todo.reset(Block); + // This is a new through block. Add it to SpillPlacer later. + ActiveBlocks.push_back(Block); +#ifndef NDEBUG + ++Visited; +#endif } } + // Any new blocks to add? + if (ActiveBlocks.size() > AddedTo) { + ArrayRef Add(&ActiveBlocks[AddedTo], + ActiveBlocks.size() - AddedTo); + addThroughConstraints(Intf, Add); + AddedTo = ActiveBlocks.size(); + } + // Perhaps iterating can enable more bundles? + SpillPlacer->iterate(); } + DEBUG(dbgs() << ", v=" << Visited); +} - // Accumulate a local cost of this interference pattern. - float LocalCost = 0; - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; - if (!BI.Uses) - continue; - SpillPlacement::BlockConstraint &BC = SpillConstraints[i]; - unsigned Inserts = 0; +/// calcSpillCost - Compute how expensive it would be to split the live range in +/// SA around all use blocks instead of forming bundle regions. +float RAGreedy::calcSpillCost() { + float Cost = 0; + const LiveInterval &LI = SA->getParent(); + ArrayRef UseBlocks = SA->getUseBlocks(); + for (unsigned i = 0; i != UseBlocks.size(); ++i) { + const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; + unsigned Number = BI.MBB->getNumber(); + // We normally only need one spill instruction - a load or a store. + Cost += SpillPlacer->getBlockFrequency(Number); - // Do we need spill code for the entry segment? - if (BI.LiveIn) - Inserts += BI.OverlapEntry || BC.Entry != SpillPlacement::PrefReg; - - // For the exit segment? - if (BI.LiveOut) - Inserts += BI.OverlapExit || BC.Exit != SpillPlacement::PrefReg; - - // The local cost of spill code in this block is the block frequency times - // the number of spill instructions inserted. - if (Inserts) - LocalCost += Inserts * SpillPlacer->getBlockFrequency(BI.MBB); + // Unless the value is redefined in the block. + if (BI.LiveIn && BI.LiveOut) { + SlotIndex Start, Stop; + tie(Start, Stop) = Indexes->getMBBRange(Number); + LiveInterval::const_iterator I = LI.find(Start); + assert(I != LI.end() && "Expected live-in value"); + // Is there a different live-out value? If so, we need an extra spill + // instruction. + if (I->end < Stop) + Cost += SpillPlacer->getBlockFrequency(Number); + } } - DEBUG(dbgs() << "Local cost of " << PrintReg(PhysReg, TRI) << " = " - << LocalCost << '\n'); - return LocalCost; + return Cost; } /// calcGlobalSplitCost - Return the global split cost of following the split /// pattern in LiveBundles. This cost should be added to the local cost of the -/// interference pattern in SpillConstraints. +/// interference pattern in SplitConstraints. /// -float RAGreedy::calcGlobalSplitCost(const BitVector &LiveBundles) { +float RAGreedy::calcGlobalSplitCost(GlobalSplitCandidate &Cand, + InterferenceCache::Cursor Intf) { float GlobalCost = 0; - for (unsigned i = 0, e = SpillConstraints.size(); i != e; ++i) { - SpillPlacement::BlockConstraint &BC = SpillConstraints[i]; - unsigned Inserts = 0; - // Broken entry preference? - Inserts += LiveBundles[Bundles->getBundle(BC.Number, 0)] != - (BC.Entry == SpillPlacement::PrefReg); - // Broken exit preference? - Inserts += LiveBundles[Bundles->getBundle(BC.Number, 1)] != - (BC.Exit == SpillPlacement::PrefReg); - if (Inserts) - GlobalCost += - Inserts * SpillPlacer->getBlockFrequency(SA->LiveBlocks[i].MBB); + const BitVector &LiveBundles = Cand.LiveBundles; + ArrayRef UseBlocks = SA->getUseBlocks(); + for (unsigned i = 0; i != UseBlocks.size(); ++i) { + const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; + SpillPlacement::BlockConstraint &BC = SplitConstraints[i]; + bool RegIn = LiveBundles[Bundles->getBundle(BC.Number, 0)]; + bool RegOut = LiveBundles[Bundles->getBundle(BC.Number, 1)]; + unsigned Ins = 0; + + if (BI.LiveIn) + Ins += RegIn != (BC.Entry == SpillPlacement::PrefReg); + if (BI.LiveOut) + Ins += RegOut != (BC.Exit == SpillPlacement::PrefReg); + if (Ins) + GlobalCost += Ins * SpillPlacer->getBlockFrequency(BC.Number); + } + + for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) { + unsigned Number = Cand.ActiveBlocks[i]; + bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)]; + bool RegOut = LiveBundles[Bundles->getBundle(Number, 1)]; + if (!RegIn && !RegOut) + continue; + if (RegIn && RegOut) { + // We need double spill code if this block has interference. + Intf.moveToBlock(Number); + if (Intf.hasInterference()) + GlobalCost += 2*SpillPlacer->getBlockFrequency(Number); + continue; + } + // live-in / stack-out or stack-in live-out. + GlobalCost += SpillPlacer->getBlockFrequency(Number); } - DEBUG(dbgs() << "Global cost = " << GlobalCost << '\n'); return GlobalCost; } @@ -611,113 +698,74 @@ float RAGreedy::calcGlobalSplitCost(const BitVector &LiveBundles) { /// avoiding interference. The 'stack' interval is the complement constructed by /// SplitEditor. It will contain the rest. /// -void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, - const BitVector &LiveBundles, +void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, + GlobalSplitCandidate &Cand, SmallVectorImpl &NewVRegs) { + const BitVector &LiveBundles = Cand.LiveBundles; + DEBUG({ - dbgs() << "Splitting around region for " << PrintReg(PhysReg, TRI) + dbgs() << "Splitting around region for " << PrintReg(Cand.PhysReg, TRI) << " with bundles"; for (int i = LiveBundles.find_first(); i>=0; i = LiveBundles.find_next(i)) dbgs() << " EB#" << i; dbgs() << ".\n"; }); - // First compute interference ranges in the live blocks. - typedef std::pair IndexPair; - SmallVector InterferenceRanges; - InterferenceRanges.resize(SA->LiveBlocks.size()); - for (const unsigned *AI = TRI->getOverlaps(PhysReg); *AI; ++AI) { - if (!query(VirtReg, *AI).checkInterference()) - continue; - LiveIntervalUnion::SegmentIter IntI = - PhysReg2LiveUnion[*AI].find(VirtReg.beginIndex()); - if (!IntI.valid()) - continue; - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - const SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; - IndexPair &IP = InterferenceRanges[i]; - SlotIndex Start, Stop; - tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); - // Skip interference-free blocks. - if (IntI.start() >= Stop) - continue; - - // First interference in block. - if (BI.LiveIn) { - IntI.advanceTo(Start); - if (!IntI.valid()) - break; - if (IntI.start() >= Stop) - continue; - if (!IP.first.isValid() || IntI.start() < IP.first) - IP.first = IntI.start(); - } - - // Last interference in block. - if (BI.LiveOut) { - IntI.advanceTo(Stop); - if (!IntI.valid() || IntI.start() >= Stop) - --IntI; - if (IntI.stop() <= Start) - continue; - if (!IP.second.isValid() || IntI.stop() > IP.second) - IP.second = IntI.stop(); - } - } - } - - SmallVector SpillRegs; - LiveRangeEdit LREdit(VirtReg, NewVRegs, SpillRegs); - SplitEditor SE(*SA, *LIS, *VRM, *DomTree, LREdit); + InterferenceCache::Cursor Intf(IntfCache, Cand.PhysReg); + LiveRangeEdit LREdit(VirtReg, NewVRegs, this); + SE->reset(LREdit); // Create the main cross-block interval. - SE.openIntv(); + const unsigned MainIntv = SE->openIntv(); // First add all defs that are live out of a block. - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; + ArrayRef UseBlocks = SA->getUseBlocks(); + for (unsigned i = 0; i != UseBlocks.size(); ++i) { + const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + // Create separate intervals for isolated blocks with multiple uses. + if (!RegIn && !RegOut && BI.FirstUse != BI.LastUse) { + DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " isolated.\n"); + SE->splitSingleBlock(BI); + SE->selectIntv(MainIntv); + continue; + } + // Should the register be live out? if (!BI.LiveOut || !RegOut) continue; - IndexPair &IP = InterferenceRanges[i]; SlotIndex Start, Stop; tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); - + Intf.moveToBlock(BI.MBB->getNumber()); DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " -> EB#" << Bundles->getBundle(BI.MBB->getNumber(), 1) - << " intf [" << IP.first << ';' << IP.second << ')'); + << " [" << Start << ';' + << SA->getLastSplitPoint(BI.MBB->getNumber()) << '-' << Stop + << ") intf [" << Intf.first() << ';' << Intf.last() << ')'); // The interference interval should either be invalid or overlap MBB. - assert((!IP.first.isValid() || IP.first < Stop) && "Bad interference"); - assert((!IP.second.isValid() || IP.second > Start) && "Bad interference"); + assert((!Intf.hasInterference() || Intf.first() < Stop) + && "Bad interference"); + assert((!Intf.hasInterference() || Intf.last() > Start) + && "Bad interference"); // Check interference leaving the block. - if (!IP.second.isValid()) { + if (!Intf.hasInterference()) { // Block is interference-free. DEBUG(dbgs() << ", no interference"); - if (!BI.Uses) { - assert(BI.LiveThrough && "No uses, but not live through block?"); - // Block is live-through without interference. - DEBUG(dbgs() << ", no uses" - << (RegIn ? ", live-through.\n" : ", stack in.\n")); - if (!RegIn) - SE.enterIntvAtEnd(*BI.MBB); - continue; - } if (!BI.LiveThrough) { DEBUG(dbgs() << ", not live-through.\n"); - SE.useIntv(SE.enterIntvBefore(BI.Def), Stop); + SE->useIntv(SE->enterIntvBefore(BI.Def), Stop); continue; } if (!RegIn) { // Block is live-through, but entry bundle is on the stack. // Reload just before the first use. DEBUG(dbgs() << ", not live-in, enter before first use.\n"); - SE.useIntv(SE.enterIntvBefore(BI.FirstUse), Stop); + SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop); continue; } DEBUG(dbgs() << ", live-through.\n"); @@ -725,53 +773,45 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, } // Block has interference. - DEBUG(dbgs() << ", interference to " << IP.second); + DEBUG(dbgs() << ", interference to " << Intf.last()); - if (!BI.LiveThrough && IP.second <= BI.Def) { + if (!BI.LiveThrough && Intf.last() <= BI.Def) { // The interference doesn't reach the outgoing segment. DEBUG(dbgs() << " doesn't affect def from " << BI.Def << '\n'); - SE.useIntv(BI.Def, Stop); + SE->useIntv(BI.Def, Stop); continue; } - - if (!BI.Uses) { - // No uses in block, avoid interference by reloading as late as possible. - DEBUG(dbgs() << ", no uses.\n"); - SlotIndex SegStart = SE.enterIntvAtEnd(*BI.MBB); - assert(SegStart >= IP.second && "Couldn't avoid interference"); - continue; - } - - if (IP.second.getBoundaryIndex() < BI.LastUse) { + SlotIndex LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); + if (Intf.last().getBoundaryIndex() < BI.LastUse) { // There are interference-free uses at the end of the block. // Find the first use that can get the live-out register. SmallVectorImpl::const_iterator UI = std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), - IP.second.getBoundaryIndex()); + Intf.last().getBoundaryIndex()); assert(UI != SA->UseSlots.end() && "Couldn't find last use"); SlotIndex Use = *UI; assert(Use <= BI.LastUse && "Couldn't find last use"); // Only attempt a split befroe the last split point. - if (Use.getBaseIndex() <= BI.LastSplitPoint) { + if (Use.getBaseIndex() <= LastSplitPoint) { DEBUG(dbgs() << ", free use at " << Use << ".\n"); - SlotIndex SegStart = SE.enterIntvBefore(Use); - assert(SegStart >= IP.second && "Couldn't avoid interference"); - assert(SegStart < BI.LastSplitPoint && "Impossible split point"); - SE.useIntv(SegStart, Stop); + SlotIndex SegStart = SE->enterIntvBefore(Use); + assert(SegStart >= Intf.last() && "Couldn't avoid interference"); + assert(SegStart < LastSplitPoint && "Impossible split point"); + SE->useIntv(SegStart, Stop); continue; } } // Interference is after the last use. DEBUG(dbgs() << " after last use.\n"); - SlotIndex SegStart = SE.enterIntvAtEnd(*BI.MBB); - assert(SegStart >= IP.second && "Couldn't avoid interference"); + SlotIndex SegStart = SE->enterIntvAtEnd(*BI.MBB); + assert(SegStart >= Intf.last() && "Couldn't avoid interference"); } // Now all defs leading to live bundles are handled, do everything else. - for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { - SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; + for (unsigned i = 0; i != UseBlocks.size(); ++i) { + const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; @@ -780,152 +820,207 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, continue; // We have an incoming register. Check for interference. - IndexPair &IP = InterferenceRanges[i]; SlotIndex Start, Stop; tie(Start, Stop) = Indexes->getMBBRange(BI.MBB); - + Intf.moveToBlock(BI.MBB->getNumber()); DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0) - << " -> BB#" << BI.MBB->getNumber()); + << " -> BB#" << BI.MBB->getNumber() << " [" << Start << ';' + << SA->getLastSplitPoint(BI.MBB->getNumber()) << '-' << Stop + << ')'); // Check interference entering the block. - if (!IP.first.isValid()) { + if (!Intf.hasInterference()) { // Block is interference-free. DEBUG(dbgs() << ", no interference"); - if (!BI.Uses) { - assert(BI.LiveThrough && "No uses, but not live through block?"); - // Block is live-through without interference. - if (RegOut) { - DEBUG(dbgs() << ", no uses, live-through.\n"); - SE.useIntv(Start, Stop); - } else { - DEBUG(dbgs() << ", no uses, stack-out.\n"); - SE.leaveIntvAtTop(*BI.MBB); - } - continue; - } if (!BI.LiveThrough) { DEBUG(dbgs() << ", killed in block.\n"); - SE.useIntv(Start, SE.leaveIntvAfter(BI.Kill)); + SE->useIntv(Start, SE->leaveIntvAfter(BI.Kill)); continue; } if (!RegOut) { + SlotIndex LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber()); // Block is live-through, but exit bundle is on the stack. // Spill immediately after the last use. - if (BI.LastUse < BI.LastSplitPoint) { + if (BI.LastUse < LastSplitPoint) { DEBUG(dbgs() << ", uses, stack-out.\n"); - SE.useIntv(Start, SE.leaveIntvAfter(BI.LastUse)); + SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse)); continue; } // The last use is after the last split point, it is probably an // indirect jump. DEBUG(dbgs() << ", uses at " << BI.LastUse << " after split point " - << BI.LastSplitPoint << ", stack-out.\n"); - SlotIndex SegEnd = SE.leaveIntvBefore(BI.LastSplitPoint); - SE.useIntv(Start, SegEnd); + << LastSplitPoint << ", stack-out.\n"); + SlotIndex SegEnd = SE->leaveIntvBefore(LastSplitPoint); + SE->useIntv(Start, SegEnd); // Run a double interval from the split to the last use. // This makes it possible to spill the complement without affecting the // indirect branch. - SE.overlapIntv(SegEnd, BI.LastUse); + SE->overlapIntv(SegEnd, BI.LastUse); continue; } // Register is live-through. DEBUG(dbgs() << ", uses, live-through.\n"); - SE.useIntv(Start, Stop); + SE->useIntv(Start, Stop); continue; } // Block has interference. - DEBUG(dbgs() << ", interference from " << IP.first); + DEBUG(dbgs() << ", interference from " << Intf.first()); - if (!BI.LiveThrough && IP.first >= BI.Kill) { + if (!BI.LiveThrough && Intf.first() >= BI.Kill) { // The interference doesn't reach the outgoing segment. DEBUG(dbgs() << " doesn't affect kill at " << BI.Kill << '\n'); - SE.useIntv(Start, BI.Kill); + SE->useIntv(Start, BI.Kill); continue; } - if (!BI.Uses) { - // No uses in block, avoid interference by spilling as soon as possible. - DEBUG(dbgs() << ", no uses.\n"); - SlotIndex SegEnd = SE.leaveIntvAtTop(*BI.MBB); - assert(SegEnd <= IP.first && "Couldn't avoid interference"); - continue; - } - if (IP.first.getBaseIndex() > BI.FirstUse) { + if (Intf.first().getBaseIndex() > BI.FirstUse) { // There are interference-free uses at the beginning of the block. // Find the last use that can get the register. SmallVectorImpl::const_iterator UI = std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), - IP.first.getBaseIndex()); + Intf.first().getBaseIndex()); assert(UI != SA->UseSlots.begin() && "Couldn't find first use"); SlotIndex Use = (--UI)->getBoundaryIndex(); DEBUG(dbgs() << ", free use at " << *UI << ".\n"); - SlotIndex SegEnd = SE.leaveIntvAfter(Use); - assert(SegEnd <= IP.first && "Couldn't avoid interference"); - SE.useIntv(Start, SegEnd); + SlotIndex SegEnd = SE->leaveIntvAfter(Use); + assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); + SE->useIntv(Start, SegEnd); continue; } // Interference is before the first use. DEBUG(dbgs() << " before first use.\n"); - SlotIndex SegEnd = SE.leaveIntvAtTop(*BI.MBB); - assert(SegEnd <= IP.first && "Couldn't avoid interference"); + SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB); + assert(SegEnd <= Intf.first() && "Couldn't avoid interference"); } - SE.closeIntv(); + // Handle live-through blocks. + for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) { + unsigned Number = Cand.ActiveBlocks[i]; + bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)]; + bool RegOut = LiveBundles[Bundles->getBundle(Number, 1)]; + DEBUG(dbgs() << "Live through BB#" << Number << '\n'); + if (RegIn && RegOut) { + Intf.moveToBlock(Number); + if (!Intf.hasInterference()) { + SE->useIntv(Indexes->getMBBStartIdx(Number), + Indexes->getMBBEndIdx(Number)); + continue; + } + } + MachineBasicBlock *MBB = MF->getBlockNumbered(Number); + if (RegIn) + SE->leaveIntvAtTop(*MBB); + if (RegOut) + SE->enterIntvAtEnd(*MBB); + } - // FIXME: Should we be more aggressive about splitting the stack region into - // per-block segments? The current approach allows the stack region to - // separate into connected components. Some components may be allocatable. - SE.finish(); ++NumGlobalSplits; - if (VerifyEnabled) { - MF->verify(this, "After splitting live range around region"); + SmallVector IntvMap; + SE->finish(&IntvMap); + LRStage.resize(MRI->getNumVirtRegs()); + unsigned OrigBlocks = SA->getNumThroughBlocks() + SA->getUseBlocks().size(); -#ifndef NDEBUG - // Make sure that at least one of the new intervals can allocate to PhysReg. - // That was the whole point of splitting the live range. - bool found = false; - for (LiveRangeEdit::iterator I = LREdit.begin(), E = LREdit.end(); I != E; - ++I) - if (!checkUncachedInterference(**I, PhysReg)) { - found = true; - break; + // Sort out the new intervals created by splitting. We get four kinds: + // - Remainder intervals should not be split again. + // - Candidate intervals can be assigned to Cand.PhysReg. + // - Block-local splits are candidates for local splitting. + // - DCE leftovers should go back on the queue. + for (unsigned i = 0, e = LREdit.size(); i != e; ++i) { + unsigned Reg = LREdit.get(i)->reg; + + // Ignore old intervals from DCE. + if (LRStage[Reg] != RS_New) + continue; + + // Remainder interval. Don't try splitting again, spill if it doesn't + // allocate. + if (IntvMap[i] == 0) { + LRStage[Reg] = RS_Global; + continue; + } + + // Main interval. Allow repeated splitting as long as the number of live + // blocks is strictly decreasing. + if (IntvMap[i] == MainIntv) { + if (SA->countLiveBlocks(LREdit.get(i)) >= OrigBlocks) { + DEBUG(dbgs() << "Main interval covers the same " << OrigBlocks + << " blocks as original.\n"); + // Don't allow repeated splitting as a safe guard against looping. + LRStage[Reg] = RS_Global; } - assert(found && "No allocatable intervals after pointless splitting"); -#endif + continue; + } + + // Other intervals are treated as new. This includes local intervals created + // for blocks with multiple uses, and anything created by DCE. } + + if (VerifyEnabled) + MF->verify(this, "After splitting live range around region"); } unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order, SmallVectorImpl &NewVRegs) { - BitVector LiveBundles, BestBundles; - float BestCost = 0; - unsigned BestReg = 0; + float BestCost = Hysteresis * calcSpillCost(); + DEBUG(dbgs() << "Cost of isolating all blocks = " << BestCost << '\n'); + const unsigned NoCand = ~0u; + unsigned BestCand = NoCand; + Order.rewind(); - while (unsigned PhysReg = Order.next()) { - float Cost = calcInterferenceInfo(VirtReg, PhysReg); - if (BestReg && Cost >= BestCost) - continue; + for (unsigned Cand = 0; unsigned PhysReg = Order.next(); ++Cand) { + if (GlobalCand.size() <= Cand) + GlobalCand.resize(Cand+1); + GlobalCand[Cand].reset(PhysReg); + + SpillPlacer->prepare(GlobalCand[Cand].LiveBundles); + float Cost; + InterferenceCache::Cursor Intf(IntfCache, PhysReg); + if (!addSplitConstraints(Intf, Cost)) { + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tno positive bundles\n"); + continue; + } + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tstatic = " << Cost); + if (Cost >= BestCost) { + DEBUG({ + if (BestCand == NoCand) + dbgs() << " worse than no bundles\n"; + else + dbgs() << " worse than " + << PrintReg(GlobalCand[BestCand].PhysReg, TRI) << '\n'; + }); + continue; + } + growRegion(GlobalCand[Cand], Intf); + + SpillPlacer->finish(); - SpillPlacer->placeSpills(SpillConstraints, LiveBundles); // No live bundles, defer to splitSingleBlocks(). - if (!LiveBundles.any()) + if (!GlobalCand[Cand].LiveBundles.any()) { + DEBUG(dbgs() << " no bundles.\n"); continue; + } - Cost += calcGlobalSplitCost(LiveBundles); - if (!BestReg || Cost < BestCost) { - BestReg = PhysReg; - BestCost = Cost; - BestBundles.swap(LiveBundles); + Cost += calcGlobalSplitCost(GlobalCand[Cand], Intf); + DEBUG({ + dbgs() << ", total = " << Cost << " with bundles"; + for (int i = GlobalCand[Cand].LiveBundles.find_first(); i>=0; + i = GlobalCand[Cand].LiveBundles.find_next(i)) + dbgs() << " EB#" << i; + dbgs() << ".\n"; + }); + if (Cost < BestCost) { + BestCand = Cand; + BestCost = Hysteresis * Cost; // Prevent rounding effects. } } - if (!BestReg) + if (BestCand == NoCand) return 0; - splitAroundRegion(VirtReg, BestReg, BestBundles, NewVRegs); + splitAroundRegion(VirtReg, GlobalCand[BestCand], NewVRegs); return 0; } @@ -942,8 +1037,8 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order, /// void RAGreedy::calcGapWeights(unsigned PhysReg, SmallVectorImpl &GapWeight) { - assert(SA->LiveBlocks.size() == 1 && "Not a local interval"); - const SplitAnalysis::BlockInfo &BI = SA->LiveBlocks.front(); + assert(SA->getUseBlocks().size() == 1 && "Not a local interval"); + const SplitAnalysis::BlockInfo &BI = SA->getUseBlocks().front(); const SmallVectorImpl &Uses = SA->UseSlots; const unsigned NumGaps = Uses.size()-1; @@ -1034,8 +1129,8 @@ unsigned RAGreedy::nextSplitPoint(unsigned i) { /// unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, SmallVectorImpl &NewVRegs) { - assert(SA->LiveBlocks.size() == 1 && "Not a local interval"); - const SplitAnalysis::BlockInfo &BI = SA->LiveBlocks.front(); + assert(SA->getUseBlocks().size() == 1 && "Not a local interval"); + const SplitAnalysis::BlockInfo &BI = SA->getUseBlocks().front(); // Note that it is possible to have an interval that is live-in or live-out // while only covering a single block - A phi-def can use undef values from @@ -1065,7 +1160,7 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, unsigned BestAfter = 0; float BestDiff = 0; - const float blockFreq = SpillPlacer->getBlockFrequency(BI.MBB); + const float blockFreq = SpillPlacer->getBlockFrequency(BI.MBB->getNumber()); SmallVector GapWeight; Order.rewind(); @@ -1130,13 +1225,13 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, PrevSlot[SplitBefore].distance(Uses[SplitAfter])); // Would this split be possible to allocate? // Never allocate all gaps, we wouldn't be making progress. - float Diff = EstWeight - MaxGap; - DEBUG(dbgs() << " w=" << EstWeight << " d=" << Diff); - if (Diff > 0) { + DEBUG(dbgs() << " w=" << EstWeight); + if (EstWeight * Hysteresis >= MaxGap) { Shrink = false; + float Diff = EstWeight - MaxGap; if (Diff > BestDiff) { DEBUG(dbgs() << " (best)"); - BestDiff = Diff; + BestDiff = Hysteresis * Diff; BestBefore = SplitBefore; BestAfter = SplitAfter; } @@ -1181,16 +1276,15 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, << '-' << Uses[BestAfter] << ", " << BestDiff << ", " << (BestAfter - BestBefore + 1) << " instrs\n"); - SmallVector SpillRegs; - LiveRangeEdit LREdit(VirtReg, NewVRegs, SpillRegs); - SplitEditor SE(*SA, *LIS, *VRM, *DomTree, LREdit); + LiveRangeEdit LREdit(VirtReg, NewVRegs, this); + SE->reset(LREdit); - SE.openIntv(); - SlotIndex SegStart = SE.enterIntvBefore(Uses[BestBefore]); - SlotIndex SegStop = SE.leaveIntvAfter(Uses[BestAfter]); - SE.useIntv(SegStart, SegStop); - SE.closeIntv(); - SE.finish(); + SE->openIntv(); + SlotIndex SegStart = SE->enterIntvBefore(Uses[BestBefore]); + SlotIndex SegStop = SE->leaveIntvAfter(Uses[BestAfter]); + SE->useIntv(SegStart, SegStop); + SE->finish(); + setStage(NewVRegs.begin(), NewVRegs.end(), RS_Local); ++NumLocalSplits; return 0; @@ -1205,16 +1299,22 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, /// @return Physreg when VirtReg may be assigned and/or new NewVRegs. unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order, SmallVectorImpl&NewVRegs) { - SA->analyze(&VirtReg); - // Local intervals are handled separately. if (LIS->intervalIsInOneMBB(VirtReg)) { NamedRegionTimer T("Local Splitting", TimerGroupName, TimePassesIsEnabled); + SA->analyze(&VirtReg); return tryLocalSplit(VirtReg, Order, NewVRegs); } NamedRegionTimer T("Global Splitting", TimerGroupName, TimePassesIsEnabled); + // Don't iterate global splitting. + // Move straight to spilling if this range was produced by a global split. + if (getStage(VirtReg) >= RS_Global) + return 0; + + SA->analyze(&VirtReg); + // First try to split around a region spanning multiple blocks. unsigned PhysReg = tryRegionSplit(VirtReg, Order, NewVRegs); if (PhysReg || !NewVRegs.empty()) @@ -1223,9 +1323,10 @@ unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order, // Then isolate blocks with multiple uses. SplitAnalysis::BlockPtrSet Blocks; if (SA->getMultiUseBlocks(Blocks)) { - SmallVector SpillRegs; - LiveRangeEdit LREdit(VirtReg, NewVRegs, SpillRegs); - SplitEditor(*SA, *LIS, *VRM, *DomTree, LREdit).splitSingleBlocks(Blocks); + LiveRangeEdit LREdit(VirtReg, NewVRegs, this); + SE->reset(LREdit); + SE->splitSingleBlocks(Blocks); + setStage(NewVRegs.begin(), NewVRegs.end(), RS_Global); if (VerifyEnabled) MF->verify(this, "After splitting live range around basic blocks"); } @@ -1235,68 +1336,6 @@ unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order, } -//===----------------------------------------------------------------------===// -// Spilling -//===----------------------------------------------------------------------===// - -/// calcInterferenceWeight - Calculate the combined spill weight of -/// interferences when assigning VirtReg to PhysReg. -float RAGreedy::calcInterferenceWeight(LiveInterval &VirtReg, unsigned PhysReg){ - float Sum = 0; - for (const unsigned *AI = TRI->getOverlaps(PhysReg); *AI; ++AI) { - LiveIntervalUnion::Query &Q = query(VirtReg, *AI); - Q.collectInterferingVRegs(); - if (Q.seenUnspillableVReg()) - return HUGE_VALF; - for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) - Sum += Q.interferingVRegs()[i]->weight; - } - return Sum; -} - -/// trySpillInterferences - Try to spill interfering registers instead of the -/// current one. Only do it if the accumulated spill weight is smaller than the -/// current spill weight. -unsigned RAGreedy::trySpillInterferences(LiveInterval &VirtReg, - AllocationOrder &Order, - SmallVectorImpl &NewVRegs) { - NamedRegionTimer T("Spill Interference", TimerGroupName, TimePassesIsEnabled); - unsigned BestPhys = 0; - float BestWeight = 0; - - Order.rewind(); - while (unsigned PhysReg = Order.next()) { - float Weight = calcInterferenceWeight(VirtReg, PhysReg); - if (Weight == HUGE_VALF || Weight >= VirtReg.weight) - continue; - if (!BestPhys || Weight < BestWeight) - BestPhys = PhysReg, BestWeight = Weight; - } - - // No candidates found. - if (!BestPhys) - return 0; - - // Collect all interfering registers. - SmallVector Spills; - for (const unsigned *AI = TRI->getOverlaps(BestPhys); *AI; ++AI) { - LiveIntervalUnion::Query &Q = query(VirtReg, *AI); - Spills.append(Q.interferingVRegs().begin(), Q.interferingVRegs().end()); - for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) { - LiveInterval *VReg = Q.interferingVRegs()[i]; - unassign(*VReg, *AI); - } - } - - // Spill them all. - DEBUG(dbgs() << "spilling " << Spills.size() << " interferences with weight " - << BestWeight << '\n'); - for (unsigned i = 0, e = Spills.size(); i != e; ++i) - spiller().spill(Spills[i], NewVRegs, Spills); - return BestPhys; -} - - //===----------------------------------------------------------------------===// // Main Entry Point //===----------------------------------------------------------------------===// @@ -1305,12 +1344,7 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg, SmallVectorImpl &NewVRegs) { // First try assigning a free register. AllocationOrder Order(VirtReg.reg, *VRM, ReservedRegs); - while (unsigned PhysReg = Order.next()) { - if (!checkPhysRegInterference(VirtReg, PhysReg)) - return PhysReg; - } - - if (unsigned PhysReg = tryReassign(VirtReg, Order, NewVRegs)) + if (unsigned PhysReg = tryAssign(VirtReg, Order, NewVRegs)) return PhysReg; if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs)) @@ -1321,25 +1355,29 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg, // The first time we see a live range, don't try to split or spill. // Wait until the second time, when all smaller ranges have been allocated. // This gives a better picture of the interference to split around. - if (Generation[VirtReg.reg] == 1) { + LiveRangeStage Stage = getStage(VirtReg); + if (Stage == RS_First) { + LRStage[VirtReg.reg] = RS_Second; + DEBUG(dbgs() << "wait for second round\n"); NewVRegs.push_back(&VirtReg); return 0; } + assert(Stage < RS_Spill && "Cannot allocate after spilling"); + // Try splitting VirtReg or interferences. unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs); if (PhysReg || !NewVRegs.empty()) return PhysReg; - // Try to spill another interfering reg with less spill weight. - PhysReg = trySpillInterferences(VirtReg, Order, NewVRegs); - if (PhysReg) - return PhysReg; - // Finally spill VirtReg itself. NamedRegionTimer T("Spiller", TimerGroupName, TimePassesIsEnabled); - SmallVector pendingSpills; - spiller().spill(&VirtReg, NewVRegs, pendingSpills); + LiveRangeEdit LRE(VirtReg, NewVRegs, this); + spiller().spill(LRE); + setStage(NewVRegs.begin(), NewVRegs.end(), RS_Spill); + + if (VerifyEnabled) + MF->verify(this, "After spilling"); // The live virtual register requesting allocation was spilled, so tell // the caller not to allocate anything during this round. @@ -1366,6 +1404,10 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) { SpillPlacer = &getAnalysis(); SA.reset(new SplitAnalysis(*VRM, *LIS, *Loops)); + SE.reset(new SplitEditor(*SA, *LIS, *VRM, *DomTree)); + LRStage.clear(); + LRStage.resize(MRI->getNumVirtRegs()); + IntfCache.init(MF, &PhysReg2LiveUnion[0], Indexes, TRI); allocatePhysRegs(); addMBBLiveIns(MF); @@ -1377,6 +1419,9 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) { VRM->rewrite(Indexes); } + // Write out new DBG_VALUE instructions. + getAnalysis().emitDebugValues(VRM); + // The pass output is in VirtRegMap. Release all the transient data. releaseMemory(); diff --git a/contrib/llvm/lib/CodeGen/RegAllocLinearScan.cpp b/contrib/llvm/lib/CodeGen/RegAllocLinearScan.cpp index b959878bcdba..5ef88cb74ba5 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocLinearScan.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocLinearScan.cpp @@ -13,6 +13,7 @@ #define DEBUG_TYPE "regalloc" #include "LiveDebugVariables.h" +#include "LiveRangeEdit.h" #include "VirtRegMap.h" #include "VirtRegRewriter.h" #include "Spiller.h" @@ -39,7 +40,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include -#include #include #include #include @@ -66,6 +66,11 @@ TrivCoalesceEnds("trivial-coalesce-ends", cl::desc("Attempt trivial coalescing of interval ends"), cl::init(false), cl::Hidden); +static cl::opt +AvoidWAWHazard("avoid-waw-hazard", + cl::desc("Avoid write-write hazards for some register classes"), + cl::init(false), cl::Hidden); + static RegisterRegAlloc linearscanRegAlloc("linearscan", "linear scan register allocator", createLinearScanRegisterAllocator); @@ -109,6 +114,7 @@ namespace { if (NumRecentlyUsedRegs > 0) RecentRegs.resize(NumRecentlyUsedRegs, 0); RecentNext = RecentRegs.begin(); + avoidWAW_ = 0; } typedef std::pair IntervalPtr; @@ -179,6 +185,9 @@ namespace { SmallVector RecentRegs; SmallVector::iterator RecentNext; + // Last write-after-write register written. + unsigned avoidWAW_; + // Record that we just picked this register. void recordRecentlyUsed(unsigned reg) { assert(reg != 0 && "Recently used register is NOREG!"); @@ -226,8 +235,8 @@ namespace { // Determine if we skip this register due to its being recently used. bool isRecentlyUsed(unsigned reg) const { - return std::find(RecentRegs.begin(), RecentRegs.end(), reg) != - RecentRegs.end(); + return reg == avoidWAW_ || + std::find(RecentRegs.begin(), RecentRegs.end(), reg) != RecentRegs.end(); } private: @@ -374,7 +383,7 @@ namespace { dbgs() << str << " intervals:\n"; for (; i != e; ++i) { - dbgs() << "\t" << *i->first << " -> "; + dbgs() << '\t' << *i->first << " -> "; unsigned reg = i->first->reg; if (TargetRegisterInfo::isVirtualRegister(reg)) @@ -389,7 +398,7 @@ namespace { } INITIALIZE_PASS_BEGIN(RALinScan, "linearscan-regalloc", - "Linear Scan Register Allocator", false, false) + "Linear Scan Register Allocator", false, false) INITIALIZE_PASS_DEPENDENCY(LiveIntervals) INITIALIZE_PASS_DEPENDENCY(StrongPHIElimination) INITIALIZE_PASS_DEPENDENCY(CalculateSpillWeights) @@ -400,7 +409,7 @@ INITIALIZE_PASS_DEPENDENCY(VirtRegMap) INITIALIZE_AG_DEPENDENCY(RegisterCoalescer) INITIALIZE_AG_DEPENDENCY(AliasAnalysis) INITIALIZE_PASS_END(RALinScan, "linearscan-regalloc", - "Linear Scan Register Allocator", false, false) + "Linear Scan Register Allocator", false, false) void RALinScan::ComputeRelatedRegClasses() { // First pass, add all reg classes to the union, and determine at least one @@ -458,7 +467,7 @@ unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) { const LiveRange &range = cur.ranges.front(); VNInfo *vni = range.valno; - if (vni->isUnused()) + if (vni->isUnused() || !vni->def.isValid()) return Reg; unsigned CandReg; @@ -571,7 +580,7 @@ void RALinScan::initIntervalSets() for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) { if (TargetRegisterInfo::isPhysicalRegister(i->second->reg)) { - if (!i->second->empty()) { + if (!i->second->empty() && allocatableRegs_.test(i->second->reg)) { mri_->setPhysRegUsed(i->second->reg); fixed_.push_back(std::make_pair(i->second, i->second->begin())); } @@ -791,7 +800,7 @@ void RALinScan::updateSpillWeights(std::vector &Weights, // register class we are trying to allocate. Then add the weight to all // sub-registers of the super-register even if they are not aliases. // e.g. allocating for GR32, bh is not used, updating bl spill weight. - // bl should get the same spill weight otherwise it will be choosen + // bl should get the same spill weight otherwise it will be chosen // as a spill candidate since spilling bh doesn't make ebx available. for (unsigned i = 0, e = Supers.size(); i != e; ++i) { for (const unsigned *sr = tri_->getSubRegisters(Supers[i]); *sr; ++sr) @@ -993,7 +1002,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) { // one, e.g. X86::mov32to32_. These move instructions are not coalescable. if (!vrm_->getRegAllocPref(cur->reg) && cur->hasAtLeastOneValue()) { VNInfo *vni = cur->begin()->valno; - if (!vni->isUnused()) { + if (!vni->isUnused() && vni->def.isValid()) { MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def); if (CopyMI && CopyMI->isCopy()) { unsigned DstSubReg = CopyMI->getOperand(0).getSubReg(); @@ -1109,11 +1118,18 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) { // list. if (physReg) { DEBUG(dbgs() << tri_->getName(physReg) << '\n'); + assert(RC->contains(physReg) && "Invalid candidate"); vrm_->assignVirt2Phys(cur->reg, physReg); addRegUse(physReg); active_.push_back(std::make_pair(cur, cur->begin())); handled_.push_back(cur); + // Remember physReg for avoiding a write-after-write hazard in the next + // instruction. + if (AvoidWAWHazard && + tri_->avoidWriteAfterWrite(mri_->getRegClass(cur->reg))) + avoidWAW_ = physReg; + // "Upgrade" the physical register since it has been allocated. UpgradeRegister(physReg); if (LiveInterval *NextReloadLI = hasNextReloadInterval(cur)) { @@ -1229,8 +1245,9 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) { // linearscan. if (cur->weight != HUGE_VALF && cur->weight <= minWeight) { DEBUG(dbgs() << "\t\t\tspilling(c): " << *cur << '\n'); - SmallVector spillIs, added; - spiller_->spill(cur, added, spillIs); + SmallVector added; + LiveRangeEdit LRE(*cur, added); + spiller_->spill(LRE); std::sort(added.begin(), added.end(), LISorter()); if (added.empty()) @@ -1306,7 +1323,8 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) { DEBUG(dbgs() << "\t\t\tspilling(a): " << *sli << '\n'); if (sli->beginIndex() < earliestStart) earliestStart = sli->beginIndex(); - spiller_->spill(sli, added, spillIs); + LiveRangeEdit LRE(*sli, added, 0, &spillIs); + spiller_->spill(LRE); spilled.insert(sli->reg); } @@ -1442,7 +1460,7 @@ unsigned RALinScan::getFreePhysReg(LiveInterval* cur, if (reservedRegs_.test(Reg)) continue; // Skip recently allocated registers. - if (isRegAvail(Reg) && !isRecentlyUsed(Reg)) { + if (isRegAvail(Reg) && (!SkipDGRegs || !isRecentlyUsed(Reg))) { FreeReg = Reg; if (FreeReg < inactiveCounts.size()) FreeRegInactiveCount = inactiveCounts[FreeReg]; @@ -1473,7 +1491,8 @@ unsigned RALinScan::getFreePhysReg(LiveInterval* cur, if (reservedRegs_.test(Reg)) continue; if (isRegAvail(Reg) && Reg < inactiveCounts.size() && - FreeRegInactiveCount < inactiveCounts[Reg] && !isRecentlyUsed(Reg)) { + FreeRegInactiveCount < inactiveCounts[Reg] && + (!SkipDGRegs || !isRecentlyUsed(Reg))) { FreeReg = Reg; FreeRegInactiveCount = inactiveCounts[Reg]; if (FreeRegInactiveCount == MaxInactiveCount) @@ -1524,12 +1543,10 @@ unsigned RALinScan::getFreePhysReg(LiveInterval *cur) { return Preference; } - if (!DowngradedRegs.empty()) { - unsigned FreeReg = getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts, - true); - if (FreeReg) - return FreeReg; - } + unsigned FreeReg = getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts, + true); + if (FreeReg) + return FreeReg; return getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts, false); } diff --git a/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp b/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp index ea0d1fe0233f..1e1f1e0d3470 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp @@ -534,10 +534,9 @@ bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAProblem &problem, vregsToAlloc.erase(vreg); const LiveInterval* spillInterval = &lis->getInterval(vreg); double oldWeight = spillInterval->weight; - SmallVector spillIs; rmf->rememberUseDefs(spillInterval); std::vector newSpills = - lis->addIntervalsForSpills(*spillInterval, spillIs, loopInfo, *vrm); + lis->addIntervalsForSpills(*spillInterval, 0, loopInfo, *vrm); addStackInterval(spillInterval, mri); rmf->rememberSpills(spillInterval, newSpills); diff --git a/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp b/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp index a2580b85bcc3..ebfe533838d5 100644 --- a/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp +++ b/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp @@ -126,9 +126,10 @@ void RegScavenger::forward() { MBBI = MBB->begin(); Tracking = true; } else { - assert(MBBI != MBB->end() && "Already at the end of the basic block!"); + assert(MBBI != MBB->end() && "Already past the end of the basic block!"); MBBI = llvm::next(MBBI); } + assert(MBBI != MBB->end() && "Already at the end of the basic block!"); MachineInstr *MI = MBBI; @@ -241,12 +242,13 @@ unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RC) const { /// getRegsAvailable - Return all available registers in the register class /// in Mask. -void RegScavenger::getRegsAvailable(const TargetRegisterClass *RC, - BitVector &Mask) { +BitVector RegScavenger::getRegsAvailable(const TargetRegisterClass *RC) { + BitVector Mask(TRI->getNumRegs()); for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); I != E; ++I) if (!isAliasUsed(*I)) Mask.set(*I); + return Mask; } /// findSurvivorReg - Return the candidate register that is unused for the @@ -335,9 +337,13 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, } // Try to find a register that's unused if there is one, as then we won't - // have to spill. - if ((Candidates & RegsAvailable).any()) - Candidates &= RegsAvailable; + // have to spill. Search explicitly rather than masking out based on + // RegsAvailable, as RegsAvailable does not take aliases into account. + // That's what getRegsAvailable() is for. + BitVector Available = getRegsAvailable(RC); + + if ((Candidates & Available).any()) + Candidates &= Available; // Find the register whose use is furthest away. MachineBasicBlock::iterator UseMI; diff --git a/contrib/llvm/lib/CodeGen/RenderMachineFunction.cpp b/contrib/llvm/lib/CodeGen/RenderMachineFunction.cpp index cbfd5a23d63d..c8de3823553c 100644 --- a/contrib/llvm/lib/CodeGen/RenderMachineFunction.cpp +++ b/contrib/llvm/lib/CodeGen/RenderMachineFunction.cpp @@ -47,7 +47,7 @@ outputFileSuffix("rmf-file-suffix", static cl::opt machineFuncsToRender("rmf-funcs", - cl::desc("Coma seperated list of functions to render" + cl::desc("Comma separated list of functions to render" ", or \"*\"."), cl::init(""), cl::Hidden); diff --git a/contrib/llvm/lib/CodeGen/ScheduleDAG.cpp b/contrib/llvm/lib/CodeGen/ScheduleDAG.cpp index 3388889c9e91..1302395f423e 100644 --- a/contrib/llvm/lib/CodeGen/ScheduleDAG.cpp +++ b/contrib/llvm/lib/CodeGen/ScheduleDAG.cpp @@ -472,7 +472,7 @@ void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() { #endif } -/// AddPred - Updates the topological ordering to accomodate an edge +/// AddPred - Updates the topological ordering to accommodate an edge /// to be added from SUnit X to SUnit Y. void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) { int UpperBound, LowerBound; @@ -490,7 +490,7 @@ void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) { } } -/// RemovePred - Updates the topological ordering to accomodate an +/// RemovePred - Updates the topological ordering to accommodate an /// an edge to be removed from the specified node N from the predecessors /// of the current node M. void ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) { diff --git a/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp index f17023eabb72..67c209ea1977 100644 --- a/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -371,7 +371,7 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { // will be overlapped by work done outside the current // scheduling region. Latency -= std::min(Latency, Count); - // Add the artifical edge. + // Add the artificial edge. ExitSU.addPred(SDep(SU, SDep::Order, Latency, /*Reg=*/0, /*isNormalMemory=*/false, /*isMustAlias=*/false, diff --git a/contrib/llvm/lib/CodeGen/ScheduleDAGPrinter.cpp b/contrib/llvm/lib/CodeGen/ScheduleDAGPrinter.cpp index 027f6150e26b..4b55a2284f85 100644 --- a/contrib/llvm/lib/CodeGen/ScheduleDAGPrinter.cpp +++ b/contrib/llvm/lib/CodeGen/ScheduleDAGPrinter.cpp @@ -51,7 +51,8 @@ namespace llvm { /// If you want to override the dot attributes printed for a particular /// edge, override this method. static std::string getEdgeAttributes(const SUnit *Node, - SUnitIterator EI) { + SUnitIterator EI, + const ScheduleDAG *Graph) { if (EI.isArtificialDep()) return "color=cyan,style=dashed"; if (EI.isCtrlDep()) diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 9cc70a30927d..f42751167a45 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -319,6 +319,10 @@ void TargetLowering::DAGCombinerInfo::AddToWorklist(SDNode *N) { ((DAGCombiner*)DC)->AddToWorkList(N); } +void TargetLowering::DAGCombinerInfo::RemoveFromWorklist(SDNode *N) { + ((DAGCombiner*)DC)->removeFromWorkList(N); +} + SDValue TargetLowering::DAGCombinerInfo:: CombineTo(SDNode *N, const std::vector &To, bool AddTo) { return ((DAGCombiner*)DC)->CombineTo(N, &To[0], To.size(), AddTo); @@ -1290,6 +1294,16 @@ SDValue combineShlAddConstant(DebugLoc DL, SDValue N0, SDValue N1, return SDValue(); } +/// isCarryMaterialization - Returns true if V is an ADDE node that is known to +/// return 0 or 1 depending on the carry flag. +static bool isCarryMaterialization(SDValue V) { + if (V.getOpcode() != ISD::ADDE) + return false; + + ConstantSDNode *C = dyn_cast(V.getOperand(0)); + return C && C->isNullValue() && V.getOperand(0) == V.getOperand(1); +} + SDValue DAGCombiner::visitADD(SDNode *N) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -1453,6 +1467,18 @@ SDValue DAGCombiner::visitADD(SDNode *N) { return DAG.getNode(ISD::SUB, DL, VT, N1, ZExt); } + // add (adde 0, 0, glue), X -> adde X, 0, glue + if (N0->hasOneUse() && isCarryMaterialization(N0)) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), + DAG.getVTList(VT, MVT::Glue), N1, N0.getOperand(0), + N0.getOperand(2)); + + // add X, (adde 0, 0, glue) -> adde X, 0, glue + if (N1->hasOneUse() && isCarryMaterialization(N1)) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), + DAG.getVTList(VT, MVT::Glue), N0, N1.getOperand(0), + N1.getOperand(2)); + return SDValue(); } @@ -1496,6 +1522,16 @@ SDValue DAGCombiner::visitADDC(SDNode *N) { N->getDebugLoc(), MVT::Glue)); } + // addc (adde 0, 0, glue), X -> adde X, 0, glue + if (N0->hasOneUse() && isCarryMaterialization(N0)) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), N1, + DAG.getConstant(0, VT), N0.getOperand(2)); + + // addc X, (adde 0, 0, glue) -> adde X, 0, glue + if (N1->hasOneUse() && isCarryMaterialization(N1)) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), N0, + DAG.getConstant(0, VT), N1.getOperand(2)); + return SDValue(); } @@ -1506,6 +1542,12 @@ SDValue DAGCombiner::visitADDE(SDNode *N) { ConstantSDNode *N0C = dyn_cast(N0); ConstantSDNode *N1C = dyn_cast(N1); + // If both operands are null we know that carry out will always be false. + if (N0C && N0C->isNullValue() && N0 == N1) + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), DAG.getNode(ISD::CARRY_FALSE, + N->getDebugLoc(), + MVT::Glue)); + // canonicalize constant to RHS if (N0C && !N1C) return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), @@ -3281,8 +3323,10 @@ SDValue DAGCombiner::visitSRL(SDNode *N) { return DAG.getUNDEF(VT); if (!LegalTypes || TLI.isTypeDesirableForOp(ISD::SRL, SmallVT)) { + uint64_t ShiftAmt = N1C->getZExtValue(); SDValue SmallShift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), SmallVT, - N0.getOperand(0), N1); + N0.getOperand(0), + DAG.getConstant(ShiftAmt, getShiftAmountTy(SmallVT))); AddToWorkList(SmallShift.getNode()); return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, SmallShift); } @@ -3688,7 +3732,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { // fold (sext (load x)) -> (sext (truncate (sextload x))) // None of the supported targets knows how to perform load and sign extend - // in one instruction. We only perform this transformation on scalars. + // on vectors in one instruction. We only perform this transformation on + // scalars. if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() && ((!LegalOperations && !cast(N0)->isVolatile()) || TLI.isLoadExtLegal(ISD::SEXTLOAD, N0.getValueType()))) { @@ -3839,7 +3884,7 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { // CombineTo deleted the truncate, if needed, but not what's under it. AddToWorkList(oye); } - return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, NarrowLoad); + return SDValue(N, 0); // Return N so it doesn't get rechecked! } } @@ -3892,7 +3937,8 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { // fold (zext (load x)) -> (zext (truncate (zextload x))) // None of the supported targets knows how to perform load and vector_zext - // in one instruction. We only perform this transformation on scalar zext. + // on vectors in one instruction. We only perform this transformation on + // scalars. if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() && ((!LegalOperations && !cast(N0)->isVolatile()) || TLI.isLoadExtLegal(ISD::ZEXTLOAD, N0.getValueType()))) { @@ -4066,7 +4112,7 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { // CombineTo deleted the truncate, if needed, but not what's under it. AddToWorkList(oye); } - return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, NarrowLoad); + return SDValue(N, 0); // Return N so it doesn't get rechecked! } } @@ -4101,7 +4147,8 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { // fold (aext (load x)) -> (aext (truncate (extload x))) // None of the supported targets knows how to perform load and any_ext - // in one instruction. We only perform this transformation on scalars. + // on vectors in one instruction. We only perform this transformation on + // scalars. if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() && ((!LegalOperations && !cast(N0)->isVolatile()) || TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) { @@ -4514,7 +4561,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { // See if we can simplify the input to this truncate through knowledge that // only the low bits are being used. // For example "trunc (or (shl x, 8), y)" // -> trunc y - // Currenly we only perform this optimization on scalars because vectors + // Currently we only perform this optimization on scalars because vectors // may have different active low bits. if (!VT.isVector()) { SDValue Shorter = @@ -5101,7 +5148,9 @@ SDValue DAGCombiner::visitSINT_TO_FP(SDNode *N) { EVT OpVT = N0.getValueType(); // fold (sint_to_fp c1) -> c1fp - if (N0C && OpVT != MVT::ppcf128) + if (N0C && OpVT != MVT::ppcf128 && + // ...but only if the target supports immediate floating-point values + (Level == llvm::Unrestricted || TLI.isOperationLegalOrCustom(llvm::ISD::ConstantFP, VT))) return DAG.getNode(ISD::SINT_TO_FP, N->getDebugLoc(), VT, N0); // If the input is a legal type, and SINT_TO_FP is not legal on this target, @@ -5123,7 +5172,9 @@ SDValue DAGCombiner::visitUINT_TO_FP(SDNode *N) { EVT OpVT = N0.getValueType(); // fold (uint_to_fp c1) -> c1fp - if (N0C && OpVT != MVT::ppcf128) + if (N0C && OpVT != MVT::ppcf128 && + // ...but only if the target supports immediate floating-point values + (Level == llvm::Unrestricted || TLI.isOperationLegalOrCustom(llvm::ISD::ConstantFP, VT))) return DAG.getNode(ISD::UINT_TO_FP, N->getDebugLoc(), VT, N0); // If the input is a legal type, and UINT_TO_FP is not legal on this target, @@ -5817,8 +5868,7 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { // value. // TODO: Handle store large -> read small portion. // TODO: Handle TRUNCSTORE/LOADEXT - if (LD->getExtensionType() == ISD::NON_EXTLOAD && - !LD->isVolatile()) { + if (ISD::isNormalLoad(N) && !LD->isVolatile()) { if (ISD::isNON_TRUNCStore(Chain.getNode())) { StoreSDNode *PrevST = cast(Chain); if (PrevST->getBasePtr() == Ptr && @@ -6217,6 +6267,10 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { ST->isNonTemporal(), OrigAlign); } + // Turn 'store undef, Ptr' -> nothing. + if (Value.getOpcode() == ISD::UNDEF && ST->isUnindexed()) + return Chain; + // Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr' if (ConstantFPSDNode *CFP = dyn_cast(Value)) { // NOTE: If the original store is volatile, this transform must not increase @@ -6250,8 +6304,10 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getStore(Chain, N->getDebugLoc(), Tmp, Ptr, ST->getPointerInfo(), ST->isVolatile(), ST->isNonTemporal(), ST->getAlignment()); - } else if (!ST->isVolatile() && - TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) { + } + + if (!ST->isVolatile() && + TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) { // Many FP stores are not made apparent until after legalize, e.g. for // argument passing. Since this is so common, custom legalize the // 64-bit integer store into two 32-bit stores. diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index 490b857b0e9c..3af948288daf 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -43,6 +43,7 @@ #include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -121,10 +122,9 @@ unsigned FastISel::getRegForValue(const Value *V) { // only locally. This is because Instructions already have the SSA // def-dominates-use requirement enforced. DenseMap::iterator I = FuncInfo.ValueMap.find(V); - if (I != FuncInfo.ValueMap.end()) { - unsigned Reg = I->second; - return Reg; - } + if (I != FuncInfo.ValueMap.end()) + return I->second; + unsigned Reg = LocalValueMap[V]; if (Reg != 0) return Reg; @@ -164,8 +164,12 @@ unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) { Reg = getRegForValue(Constant::getNullValue(TD.getIntPtrType(V->getContext()))); } else if (const ConstantFP *CF = dyn_cast(V)) { - // Try to emit the constant directly. - Reg = FastEmit_f(VT, VT, ISD::ConstantFP, CF); + if (CF->isNullValue()) { + Reg = TargetMaterializeFloatZero(CF); + } else { + // Try to emit the constant directly. + Reg = FastEmit_f(VT, VT, ISD::ConstantFP, CF); + } if (!Reg) { // Try to emit the constant by using an integer constant with a cast. @@ -330,23 +334,51 @@ bool FastISel::SelectBinaryOp(const User *I, unsigned ISDOpcode) { return false; } + // Check if the first operand is a constant, and handle it as "ri". At -O0, + // we don't have anything that canonicalizes operand order. + if (ConstantInt *CI = dyn_cast(I->getOperand(0))) + if (isa(I) && cast(I)->isCommutative()) { + unsigned Op1 = getRegForValue(I->getOperand(1)); + if (Op1 == 0) return false; + + bool Op1IsKill = hasTrivialKill(I->getOperand(1)); + + unsigned ResultReg = FastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op1, + Op1IsKill, CI->getZExtValue(), + VT.getSimpleVT()); + if (ResultReg == 0) return false; + + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, ResultReg); + return true; + } + + unsigned Op0 = getRegForValue(I->getOperand(0)); - if (Op0 == 0) - // Unhandled operand. Halt "fast" selection and bail. + if (Op0 == 0) // Unhandled operand. Halt "fast" selection and bail. return false; bool Op0IsKill = hasTrivialKill(I->getOperand(0)); // Check if the second operand is a constant and handle it appropriately. if (ConstantInt *CI = dyn_cast(I->getOperand(1))) { - unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(), - ISDOpcode, Op0, Op0IsKill, - CI->getZExtValue()); - if (ResultReg != 0) { - // We successfully emitted code for the given LLVM Instruction. - UpdateValueMap(I, ResultReg); - return true; + uint64_t Imm = CI->getZExtValue(); + + // Transform "sdiv exact X, 8" -> "sra X, 3". + if (ISDOpcode == ISD::SDIV && isa(I) && + cast(I)->isExact() && + isPowerOf2_64(Imm)) { + Imm = Log2_64(Imm); + ISDOpcode = ISD::SRA; } + + unsigned ResultReg = FastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op0, + Op0IsKill, Imm, VT.getSimpleVT()); + if (ResultReg == 0) return false; + + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, ResultReg); + return true; } // Check if the second operand is a constant float. @@ -454,15 +486,35 @@ bool FastISel::SelectGetElementPtr(const User *I) { } bool FastISel::SelectCall(const User *I) { - const Function *F = cast(I)->getCalledFunction(); + const CallInst *Call = cast(I); + + // Handle simple inline asms. + if (const InlineAsm *IA = dyn_cast(Call->getArgOperand(0))) { + // Don't attempt to handle constraints. + if (!IA->getConstraintString().empty()) + return false; + + unsigned ExtraInfo = 0; + if (IA->hasSideEffects()) + ExtraInfo |= InlineAsm::Extra_HasSideEffects; + if (IA->isAlignStack()) + ExtraInfo |= InlineAsm::Extra_IsAlignStack; + + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::INLINEASM)) + .addExternalSymbol(IA->getAsmString().c_str()) + .addImm(ExtraInfo); + return true; + } + + const Function *F = Call->getCalledFunction(); if (!F) return false; // Handle selected intrinsic function calls. - unsigned IID = F->getIntrinsicID(); - switch (IID) { + switch (F->getIntrinsicID()) { default: break; case Intrinsic::dbg_declare: { - const DbgDeclareInst *DI = cast(I); + const DbgDeclareInst *DI = cast(Call); if (!DIVariable(DI->getVariable()).Verify() || !FuncInfo.MF->getMMI().hasDebugInfo()) return true; @@ -494,7 +546,7 @@ bool FastISel::SelectCall(const User *I) { } case Intrinsic::dbg_value: { // This form of DBG_VALUE is target-independent. - const DbgValueInst *DI = cast(I); + const DbgValueInst *DI = cast(Call); const TargetInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); const Value *V = DI->getValue(); if (!V) { @@ -523,65 +575,58 @@ bool FastISel::SelectCall(const User *I) { return true; } case Intrinsic::eh_exception: { - EVT VT = TLI.getValueType(I->getType()); - switch (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)) { - default: break; - case TargetLowering::Expand: { - assert(FuncInfo.MBB->isLandingPad() && - "Call to eh.exception not in landing pad!"); - unsigned Reg = TLI.getExceptionAddressRegister(); - const TargetRegisterClass *RC = TLI.getRegClassFor(VT); - unsigned ResultReg = createResultReg(RC); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), - ResultReg).addReg(Reg); - UpdateValueMap(I, ResultReg); - return true; - } - } - break; + EVT VT = TLI.getValueType(Call->getType()); + if (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)!=TargetLowering::Expand) + break; + + assert(FuncInfo.MBB->isLandingPad() && + "Call to eh.exception not in landing pad!"); + unsigned Reg = TLI.getExceptionAddressRegister(); + const TargetRegisterClass *RC = TLI.getRegClassFor(VT); + unsigned ResultReg = createResultReg(RC); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(Reg); + UpdateValueMap(Call, ResultReg); + return true; } case Intrinsic::eh_selector: { - EVT VT = TLI.getValueType(I->getType()); - switch (TLI.getOperationAction(ISD::EHSELECTION, VT)) { - default: break; - case TargetLowering::Expand: { - if (FuncInfo.MBB->isLandingPad()) - AddCatchInfo(*cast(I), &FuncInfo.MF->getMMI(), FuncInfo.MBB); - else { + EVT VT = TLI.getValueType(Call->getType()); + if (TLI.getOperationAction(ISD::EHSELECTION, VT) != TargetLowering::Expand) + break; + if (FuncInfo.MBB->isLandingPad()) + AddCatchInfo(*Call, &FuncInfo.MF->getMMI(), FuncInfo.MBB); + else { #ifndef NDEBUG - FuncInfo.CatchInfoLost.insert(cast(I)); + FuncInfo.CatchInfoLost.insert(Call); #endif - // FIXME: Mark exception selector register as live in. Hack for PR1508. - unsigned Reg = TLI.getExceptionSelectorRegister(); - if (Reg) FuncInfo.MBB->addLiveIn(Reg); - } - + // FIXME: Mark exception selector register as live in. Hack for PR1508. unsigned Reg = TLI.getExceptionSelectorRegister(); - EVT SrcVT = TLI.getPointerTy(); - const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); - unsigned ResultReg = createResultReg(RC); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), - ResultReg).addReg(Reg); - - bool ResultRegIsKill = hasTrivialKill(I); - - // Cast the register to the type of the selector. - if (SrcVT.bitsGT(MVT::i32)) - ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, - ResultReg, ResultRegIsKill); - else if (SrcVT.bitsLT(MVT::i32)) - ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, - ISD::SIGN_EXTEND, ResultReg, ResultRegIsKill); - if (ResultReg == 0) - // Unhandled operand. Halt "fast" selection and bail. - return false; - - UpdateValueMap(I, ResultReg); - - return true; + if (Reg) FuncInfo.MBB->addLiveIn(Reg); } - } - break; + + unsigned Reg = TLI.getExceptionSelectorRegister(); + EVT SrcVT = TLI.getPointerTy(); + const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); + unsigned ResultReg = createResultReg(RC); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(Reg); + + bool ResultRegIsKill = hasTrivialKill(Call); + + // Cast the register to the type of the selector. + if (SrcVT.bitsGT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, + ResultReg, ResultRegIsKill); + else if (SrcVT.bitsLT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, + ISD::SIGN_EXTEND, ResultReg, ResultRegIsKill); + if (ResultReg == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + UpdateValueMap(Call, ResultReg); + + return true; } } @@ -966,59 +1011,33 @@ unsigned FastISel::FastEmit_rri(MVT, MVT, unsigned FastISel::FastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm, MVT ImmType) { + // If this is a multiply by a power of two, emit this as a shift left. + if (Opcode == ISD::MUL && isPowerOf2_64(Imm)) { + Opcode = ISD::SHL; + Imm = Log2_64(Imm); + } else if (Opcode == ISD::UDIV && isPowerOf2_64(Imm)) { + // div x, 8 -> srl x, 3 + Opcode = ISD::SRL; + Imm = Log2_64(Imm); + } + + // Horrible hack (to be removed), check to make sure shift amounts are + // in-range. + if ((Opcode == ISD::SHL || Opcode == ISD::SRA || Opcode == ISD::SRL) && + Imm >= VT.getSizeInBits()) + return 0; + // First check if immediate type is legal. If not, we can't use the ri form. unsigned ResultReg = FastEmit_ri(VT, VT, Opcode, Op0, Op0IsKill, Imm); if (ResultReg != 0) return ResultReg; unsigned MaterialReg = FastEmit_i(ImmType, ImmType, ISD::Constant, Imm); - if (MaterialReg == 0) - return 0; - return FastEmit_rr(VT, VT, Opcode, - Op0, Op0IsKill, - MaterialReg, /*Kill=*/true); -} - -/// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries -/// to emit an instruction with a floating-point immediate operand using -/// FastEmit_rf. If that fails, it materializes the immediate into a register -/// and try FastEmit_rr instead. -unsigned FastISel::FastEmit_rf_(MVT VT, unsigned Opcode, - unsigned Op0, bool Op0IsKill, - const ConstantFP *FPImm, MVT ImmType) { - // First check if immediate type is legal. If not, we can't use the rf form. - unsigned ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, Op0IsKill, FPImm); - if (ResultReg != 0) - return ResultReg; - - // Materialize the constant in a register. - unsigned MaterialReg = FastEmit_f(ImmType, ImmType, ISD::ConstantFP, FPImm); if (MaterialReg == 0) { - // If the target doesn't have a way to directly enter a floating-point - // value into a register, use an alternate approach. - // TODO: The current approach only supports floating-point constants - // that can be constructed by conversion from integer values. This should - // be replaced by code that creates a load from a constant-pool entry, - // which will require some target-specific work. - const APFloat &Flt = FPImm->getValueAPF(); - EVT IntVT = TLI.getPointerTy(); - - uint64_t x[2]; - uint32_t IntBitWidth = IntVT.getSizeInBits(); - bool isExact; - (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, - APFloat::rmTowardZero, &isExact); - if (!isExact) - return 0; - APInt IntVal(IntBitWidth, 2, x); - - unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(), - ISD::Constant, IntVal.getZExtValue()); - if (IntegerReg == 0) - return 0; - MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT, - ISD::SINT_TO_FP, IntegerReg, /*Kill=*/true); - if (MaterialReg == 0) - return 0; + // This is a bit ugly/slow, but failing here means falling out of + // fast-isel, which would be very slow. + const IntegerType *ITy = IntegerType::get(FuncInfo.Fn->getContext(), + VT.getSizeInBits()); + MaterialReg = getRegForValue(ConstantInt::get(ITy, Imm)); } return FastEmit_rr(VT, VT, Opcode, Op0, Op0IsKill, @@ -1099,6 +1118,29 @@ unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode, return ResultReg; } +unsigned FastISel::FastEmitInst_rii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + uint64_t Imm1, uint64_t Imm2) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addImm(Imm1) + .addImm(Imm2); + else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addImm(Imm1) + .addImm(Imm2); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(II.ImplicitDefs[0]); + } + return ResultReg; +} + unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, @@ -1160,6 +1202,23 @@ unsigned FastISel::FastEmitInst_i(unsigned MachineInstOpcode, return ResultReg; } +unsigned FastISel::FastEmitInst_ii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + uint64_t Imm1, uint64_t Imm2) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addImm(Imm1).addImm(Imm2); + else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II).addImm(Imm1).addImm(Imm2); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(II.ImplicitDefs[0]); + } + return ResultReg; +} + unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill, uint32_t Idx) { @@ -1215,7 +1274,7 @@ bool FastISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) { // Only handle legal types. Two interesting things to note here. First, // by bailing out early, we may leave behind some dead instructions, // since SelectionDAG's HandlePHINodesInSuccessorBlocks will insert its - // own moves. Second, this check is necessary becuase FastISel doesn't + // own moves. Second, this check is necessary because FastISel doesn't // use CreateRegs to create registers, so it always creates // exactly one register for each non-void instruction. EVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 2ae3286829dd..d8a5770d36c0 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -448,16 +448,30 @@ void llvm::AddCatchInfo(const CallInst &I, MachineModuleInfo *MMI, } } -void llvm::CopyCatchInfo(const BasicBlock *SrcBB, const BasicBlock *DestBB, +void llvm::CopyCatchInfo(const BasicBlock *SuccBB, const BasicBlock *LPad, MachineModuleInfo *MMI, FunctionLoweringInfo &FLI) { - for (BasicBlock::const_iterator I = SrcBB->begin(), E = --SrcBB->end(); - I != E; ++I) - if (const EHSelectorInst *EHSel = dyn_cast(I)) { - // Apply the catch info to DestBB. - AddCatchInfo(*EHSel, MMI, FLI.MBBMap[DestBB]); + SmallPtrSet Visited; + + // The 'eh.selector' call may not be in the direct successor of a basic block, + // but could be several successors deeper. If we don't find it, try going one + // level further. + while (Visited.insert(SuccBB)) { + for (BasicBlock::const_iterator I = SuccBB->begin(), E = --SuccBB->end(); + I != E; ++I) + if (const EHSelectorInst *EHSel = dyn_cast(I)) { + // Apply the catch info to LPad. + AddCatchInfo(*EHSel, MMI, FLI.MBBMap[LPad]); #ifndef NDEBUG - if (!FLI.MBBMap[SrcBB]->isLandingPad()) - FLI.CatchInfoFound.insert(EHSel); + if (!FLI.MBBMap[SuccBB]->isLandingPad()) + FLI.CatchInfoFound.insert(EHSel); #endif - } + return; + } + + const BranchInst *Br = dyn_cast(SuccBB->getTerminator()); + if (Br && Br->isUnconditional()) + SuccBB = Br->getSuccessor(0); + else + break; + } } diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index f08528fe2dc3..2b6c56eafd73 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -61,10 +61,10 @@ class SelectionDAGLegalize { // Libcall insertion helpers. - /// LastCALLSEQ_END - This keeps track of the CALLSEQ_END node that has been + /// LastCALLSEQ - This keeps track of the CALLSEQ_END node that has been /// legalized. We use this to ensure that calls are properly serialized /// against each other, including inserted libcalls. - SDValue LastCALLSEQ_END; + SmallVector LastCALLSEQ; enum LegalizeAction { Legal, // The target natively supports this operation. @@ -142,6 +142,9 @@ class SelectionDAGLegalize { DebugLoc dl); SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned); + SDValue ExpandLibCall(RTLIB::Libcall LC, EVT RetVT, const SDValue *Ops, + unsigned NumOps, bool isSigned, DebugLoc dl); + std::pair ExpandChainLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned); SDValue ExpandFPLibCall(SDNode *Node, RTLIB::Libcall Call_F32, @@ -153,6 +156,7 @@ class SelectionDAGLegalize { RTLIB::Libcall Call_I32, RTLIB::Libcall Call_I64, RTLIB::Libcall Call_I128); + void ExpandDivRemLibCall(SDNode *Node, SmallVectorImpl &Results); SDValue EmitStackConvert(SDValue SrcOp, EVT SlotVT, EVT DestVT, DebugLoc dl); SDValue ExpandBUILD_VECTOR(SDNode *Node); @@ -178,6 +182,15 @@ class SelectionDAGLegalize { void ExpandNode(SDNode *Node, SmallVectorImpl &Results); void PromoteNode(SDNode *Node, SmallVectorImpl &Results); + + SDValue getLastCALLSEQ() { return LastCALLSEQ.back(); } + void setLastCALLSEQ(const SDValue s) { LastCALLSEQ.back() = s; } + void pushLastCALLSEQ(SDValue s) { + LastCALLSEQ.push_back(s); + } + void popLastCALLSEQ() { + LastCALLSEQ.pop_back(); + } }; } @@ -223,7 +236,7 @@ SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag, } void SelectionDAGLegalize::LegalizeDAG() { - LastCALLSEQ_END = DAG.getEntryNode(); + pushLastCALLSEQ(DAG.getEntryNode()); // The legalize process is inherently a bottom-up recursive process (users // legalize their uses before themselves). Given infinite stack space, we @@ -251,14 +264,15 @@ void SelectionDAGLegalize::LegalizeDAG() { /// FindCallEndFromCallStart - Given a chained node that is part of a call /// sequence, find the CALLSEQ_END node that terminates the call sequence. static SDNode *FindCallEndFromCallStart(SDNode *Node, int depth = 0) { - // Nested CALLSEQ_START/END constructs aren't yet legal, - // but we can DTRT and handle them correctly here. + int next_depth = depth; if (Node->getOpcode() == ISD::CALLSEQ_START) - depth++; - else if (Node->getOpcode() == ISD::CALLSEQ_END) { - depth--; - if (depth == 0) + next_depth = depth + 1; + if (Node->getOpcode() == ISD::CALLSEQ_END) { + assert(depth > 0 && "negative depth!"); + if (depth == 1) return Node; + else + next_depth = depth - 1; } if (Node->use_empty()) return 0; // No CallSeqEnd @@ -289,7 +303,7 @@ static SDNode *FindCallEndFromCallStart(SDNode *Node, int depth = 0) { SDNode *User = *UI; for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) if (User->getOperand(i) == TheChain) - if (SDNode *Result = FindCallEndFromCallStart(User, depth)) + if (SDNode *Result = FindCallEndFromCallStart(User, next_depth)) return Result; } return 0; @@ -786,7 +800,7 @@ SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { } } } - return SDValue(); + return SDValue(0, 0); } /// LegalizeOp - We know that the specified value has a legal type, and @@ -934,11 +948,12 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case ISD::BR_JT: case ISD::BR_CC: case ISD::BRCOND: - // Branches tweak the chain to include LastCALLSEQ_END + assert(LastCALLSEQ.size() == 1 && "branch inside CALLSEQ_BEGIN/END?"); + // Branches tweak the chain to include LastCALLSEQ Ops[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Ops[0], - LastCALLSEQ_END); + getLastCALLSEQ()); Ops[0] = LegalizeOp(Ops[0]); - LastCALLSEQ_END = DAG.getEntryNode(); + setLastCALLSEQ(DAG.getEntryNode()); break; case ISD::SHL: case ISD::SRL: @@ -948,7 +963,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Legalizing shifts/rotates requires adjusting the shift amount // to the appropriate width. if (!Ops[1].getValueType().isVector()) - Ops[1] = LegalizeOp(DAG.getShiftAmountOperand(Ops[1])); + Ops[1] = LegalizeOp(DAG.getShiftAmountOperand(Ops[0].getValueType(), + Ops[1])); break; case ISD::SRL_PARTS: case ISD::SRA_PARTS: @@ -956,7 +972,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Legalizing shifts/rotates requires adjusting the shift amount // to the appropriate width. if (!Ops[2].getValueType().isVector()) - Ops[2] = LegalizeOp(DAG.getShiftAmountOperand(Ops[2])); + Ops[2] = LegalizeOp(DAG.getShiftAmountOperand(Ops[0].getValueType(), + Ops[2])); break; } @@ -1024,8 +1041,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } break; case ISD::CALLSEQ_START: { - static int depth = 0; SDNode *CallEnd = FindCallEndFromCallStart(Node); + assert(CallEnd && "didn't find CALLSEQ_END!"); // Recursively Legalize all of the inputs of the call end that do not lead // to this call start. This ensures that any libcalls that need be inserted @@ -1042,9 +1059,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Merge in the last call to ensure that this call starts after the last // call ended. - if (LastCALLSEQ_END.getOpcode() != ISD::EntryToken && depth == 0) { + if (getLastCALLSEQ().getOpcode() != ISD::EntryToken) { Tmp1 = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - Tmp1, LastCALLSEQ_END); + Tmp1, getLastCALLSEQ()); Tmp1 = LegalizeOp(Tmp1); } @@ -1065,29 +1082,28 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // sequence have been legalized, legalize the call itself. During this // process, no libcalls can/will be inserted, guaranteeing that no calls // can overlap. - - SDValue Saved_LastCALLSEQ_END = LastCALLSEQ_END ; // Note that we are selecting this call! - LastCALLSEQ_END = SDValue(CallEnd, 0); + setLastCALLSEQ(SDValue(CallEnd, 0)); - depth++; // Legalize the call, starting from the CALLSEQ_END. - LegalizeOp(LastCALLSEQ_END); - depth--; - assert(depth >= 0 && "Un-matched CALLSEQ_START?"); - if (depth > 0) - LastCALLSEQ_END = Saved_LastCALLSEQ_END; + LegalizeOp(getLastCALLSEQ()); return Result; } case ISD::CALLSEQ_END: - // If the CALLSEQ_START node hasn't been legalized first, legalize it. This - // will cause this node to be legalized as well as handling libcalls right. - if (LastCALLSEQ_END.getNode() != Node) { - LegalizeOp(SDValue(FindCallStartFromCallEnd(Node), 0)); - DenseMap::iterator I = LegalizedNodes.find(Op); - assert(I != LegalizedNodes.end() && - "Legalizing the call start should have legalized this node!"); - return I->second; + { + SDNode *myCALLSEQ_BEGIN = FindCallStartFromCallEnd(Node); + + // If the CALLSEQ_START node hasn't been legalized first, legalize it. This + // will cause this node to be legalized as well as handling libcalls right. + if (getLastCALLSEQ().getNode() != Node) { + LegalizeOp(SDValue(myCALLSEQ_BEGIN, 0)); + DenseMap::iterator I = LegalizedNodes.find(Op); + assert(I != LegalizedNodes.end() && + "Legalizing the call start should have legalized this node!"); + return I->second; + } + + pushLastCALLSEQ(SDValue(myCALLSEQ_BEGIN, 0)); } // Otherwise, the call start has been legalized and everything is going @@ -1116,6 +1132,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } } // This finishes up call legalization. + popLastCALLSEQ(); + // If the CALLSEQ_END node has a flag, remember that we legalized it. AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0)); if (Node->getNumValues() == 2) @@ -2034,10 +2052,44 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, // It's a tailcall, return the chain (which is the DAG root). return DAG.getRoot(); + // Legalize the call sequence, starting with the chain. This will advance + // the LastCALLSEQ to the legalized version of the CALLSEQ_END node that + // was added by LowerCallTo (guaranteeing proper serialization of calls). + LegalizeOp(CallInfo.second); + return CallInfo.first; +} + +/// ExpandLibCall - Generate a libcall taking the given operands as arguments +/// and returning a result of type RetVT. +SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, EVT RetVT, + const SDValue *Ops, unsigned NumOps, + bool isSigned, DebugLoc dl) { + TargetLowering::ArgListTy Args; + Args.reserve(NumOps); + + TargetLowering::ArgListEntry Entry; + for (unsigned i = 0; i != NumOps; ++i) { + Entry.Node = Ops[i]; + Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext()); + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), + TLI.getPointerTy()); + + const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); + std::pair CallInfo = + TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, + false, 0, TLI.getLibcallCallingConv(LC), false, + /*isReturnValueUsed=*/true, + Callee, Args, DAG, dl); + // Legalize the call sequence, starting with the chain. This will advance // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that // was added by LowerCallTo (guaranteeing proper serialization of calls). LegalizeOp(CallInfo.second); + return CallInfo.first; } @@ -2072,7 +2124,7 @@ SelectionDAGLegalize::ExpandChainLibCall(RTLIB::Libcall LC, Callee, Args, DAG, Node->getDebugLoc()); // Legalize the call sequence, starting with the chain. This will advance - // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that + // the LastCALLSEQ to the legalized version of the CALLSEQ_END node that // was added by LowerCallTo (guaranteeing proper serialization of calls). LegalizeOp(CallInfo.second); return CallInfo; @@ -2112,6 +2164,113 @@ SDValue SelectionDAGLegalize::ExpandIntLibCall(SDNode* Node, bool isSigned, return ExpandLibCall(LC, Node, isSigned); } +/// isDivRemLibcallAvailable - Return true if divmod libcall is available. +static bool isDivRemLibcallAvailable(SDNode *Node, bool isSigned, + const TargetLowering &TLI) { + RTLIB::Libcall LC; + switch (Node->getValueType(0).getSimpleVT().SimpleTy) { + default: assert(0 && "Unexpected request for libcall!"); + case MVT::i8: LC= isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8; break; + case MVT::i16: LC= isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16; break; + case MVT::i32: LC= isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32; break; + case MVT::i64: LC= isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64; break; + case MVT::i128: LC= isSigned ? RTLIB::SDIVREM_I128:RTLIB::UDIVREM_I128; break; + } + + return TLI.getLibcallName(LC) != 0; +} + +/// UseDivRem - Only issue divrem libcall if both quotient and remainder are +/// needed. +static bool UseDivRem(SDNode *Node, bool isSigned, bool isDIV) { + unsigned OtherOpcode = 0; + if (isSigned) + OtherOpcode = isDIV ? ISD::SREM : ISD::SDIV; + else + OtherOpcode = isDIV ? ISD::UREM : ISD::UDIV; + + SDValue Op0 = Node->getOperand(0); + SDValue Op1 = Node->getOperand(1); + for (SDNode::use_iterator UI = Op0.getNode()->use_begin(), + UE = Op0.getNode()->use_end(); UI != UE; ++UI) { + SDNode *User = *UI; + if (User == Node) + continue; + if (User->getOpcode() == OtherOpcode && + User->getOperand(0) == Op0 && + User->getOperand(1) == Op1) + return true; + } + return false; +} + +/// ExpandDivRemLibCall - Issue libcalls to __{u}divmod to compute div / rem +/// pairs. +void +SelectionDAGLegalize::ExpandDivRemLibCall(SDNode *Node, + SmallVectorImpl &Results) { + unsigned Opcode = Node->getOpcode(); + bool isSigned = Opcode == ISD::SDIVREM; + + RTLIB::Libcall LC; + switch (Node->getValueType(0).getSimpleVT().SimpleTy) { + default: assert(0 && "Unexpected request for libcall!"); + case MVT::i8: LC= isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8; break; + case MVT::i16: LC= isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16; break; + case MVT::i32: LC= isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32; break; + case MVT::i64: LC= isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64; break; + case MVT::i128: LC= isSigned ? RTLIB::SDIVREM_I128:RTLIB::UDIVREM_I128; break; + } + + // The input chain to this libcall is the entry node of the function. + // Legalizing the call will automatically add the previous call to the + // dependence. + SDValue InChain = DAG.getEntryNode(); + + EVT RetVT = Node->getValueType(0); + const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); + + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) { + EVT ArgVT = Node->getOperand(i).getValueType(); + const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy; + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } + + // Also pass the return address of the remainder. + SDValue FIPtr = DAG.CreateStackTemporary(RetVT); + Entry.Node = FIPtr; + Entry.Ty = RetTy->getPointerTo(); + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), + TLI.getPointerTy()); + + // Splice the libcall in wherever FindInputOutputChains tells us to. + DebugLoc dl = Node->getDebugLoc(); + std::pair CallInfo = + TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, + 0, TLI.getLibcallCallingConv(LC), /*isTailCall=*/false, + /*isReturnValueUsed=*/true, Callee, Args, DAG, dl); + + // Legalize the call sequence, starting with the chain. This will advance + // the LastCALLSEQ to the legalized version of the CALLSEQ_END node that + // was added by LowerCallTo (guaranteeing proper serialization of calls). + LegalizeOp(CallInfo.second); + + // Remainder is loaded back from the stack frame. + SDValue Rem = DAG.getLoad(RetVT, dl, getLastCALLSEQ(), FIPtr, + MachinePointerInfo(), false, false, 0); + Results.push_back(CallInfo.first); + Results.push_back(Rem); +} + /// ExpandLegalINT_TO_FP - This function is responsible for legalizing a /// INT_TO_FP operation of the specified operand when the target requests that /// we expand it. At this point, we know that the result and operand types are @@ -2759,7 +2918,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, } case ISD::FP_ROUND_INREG: { // The only way we can lower this is to turn it into a TRUNCSTORE, - // EXTLOAD pair, targetting a temporary location (a stack slot). + // EXTLOAD pair, targeting a temporary location (a stack slot). // NOTE: there is a choice here between constantly creating new stack // slots and always reusing the same one. We currently always create @@ -3085,24 +3244,25 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM; Tmp2 = Node->getOperand(0); Tmp3 = Node->getOperand(1); - if (TLI.isOperationLegalOrCustom(DivRemOpc, VT)) { + if (TLI.isOperationLegalOrCustom(DivRemOpc, VT) || + (isDivRemLibcallAvailable(Node, isSigned, TLI) && + UseDivRem(Node, isSigned, false))) { Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Tmp2, Tmp3).getValue(1); } else if (TLI.isOperationLegalOrCustom(DivOpc, VT)) { // X % Y -> X-X/Y*Y Tmp1 = DAG.getNode(DivOpc, dl, VT, Tmp2, Tmp3); Tmp1 = DAG.getNode(ISD::MUL, dl, VT, Tmp1, Tmp3); Tmp1 = DAG.getNode(ISD::SUB, dl, VT, Tmp2, Tmp1); - } else if (isSigned) { + } else if (isSigned) Tmp1 = ExpandIntLibCall(Node, true, RTLIB::SREM_I8, RTLIB::SREM_I16, RTLIB::SREM_I32, RTLIB::SREM_I64, RTLIB::SREM_I128); - } else { + else Tmp1 = ExpandIntLibCall(Node, false, RTLIB::UREM_I8, RTLIB::UREM_I16, RTLIB::UREM_I32, RTLIB::UREM_I64, RTLIB::UREM_I128); - } Results.push_back(Tmp1); break; } @@ -3112,7 +3272,9 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM; EVT VT = Node->getValueType(0); SDVTList VTs = DAG.getVTList(VT, VT); - if (TLI.isOperationLegalOrCustom(DivRemOpc, VT)) + if (TLI.isOperationLegalOrCustom(DivRemOpc, VT) || + (isDivRemLibcallAvailable(Node, isSigned, TLI) && + UseDivRem(Node, isSigned, true))) Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Node->getOperand(0), Node->getOperand(1)); else if (isSigned) @@ -3141,6 +3303,11 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, Results.push_back(Tmp1.getValue(1)); break; } + case ISD::SDIVREM: + case ISD::UDIVREM: + // Expand into divrem libcall + ExpandDivRemLibCall(Node, Results); + break; case ISD::MUL: { EVT VT = Node->getValueType(0); SDVTList VTs = DAG.getVTList(VT, VT); @@ -3225,6 +3392,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, case ISD::UMULO: case ISD::SMULO: { EVT VT = Node->getValueType(0); + EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2); SDValue LHS = Node->getOperand(0); SDValue RHS = Node->getOperand(1); SDValue BottomHalf; @@ -3242,7 +3410,6 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, TopHalf = BottomHalf.getValue(1); } else if (TLI.isTypeLegal(EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2))) { - EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2); LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS); RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS); Tmp1 = DAG.getNode(ISD::MUL, dl, WideVT, LHS, RHS); @@ -3255,7 +3422,6 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, // have a libcall big enough. // Also, we can fall back to a division in some cases, but that's a big // performance hit in the general case. - EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2); RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; if (WideVT == MVT::i16) LC = RTLIB::MUL_I16; @@ -3266,15 +3432,27 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, else if (WideVT == MVT::i128) LC = RTLIB::MUL_I128; assert(LC != RTLIB::UNKNOWN_LIBCALL && "Cannot expand this operation!"); - LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS); - RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS); + + // The high part is obtained by SRA'ing all but one of the bits of low + // part. + unsigned LoSize = VT.getSizeInBits(); + SDValue HiLHS = DAG.getNode(ISD::SRA, dl, VT, RHS, + DAG.getConstant(LoSize-1, TLI.getPointerTy())); + SDValue HiRHS = DAG.getNode(ISD::SRA, dl, VT, LHS, + DAG.getConstant(LoSize-1, TLI.getPointerTy())); - SDValue Ret = ExpandLibCall(LC, Node, isSigned); - BottomHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, Ret); - TopHalf = DAG.getNode(ISD::SRL, dl, Ret.getValueType(), Ret, - DAG.getConstant(VT.getSizeInBits(), TLI.getPointerTy())); - TopHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, TopHalf); + // Here we're passing the 2 arguments explicitly as 4 arguments that are + // pre-lowered to the correct types. This all depends upon WideVT not + // being a legal type for the architecture and thus has to be split to + // two arguments. + SDValue Args[] = { LHS, HiLHS, RHS, HiRHS }; + SDValue Ret = ExpandLibCall(LC, WideVT, Args, 4, isSigned, dl); + BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Ret, + DAG.getIntPtrConstant(0)); + TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Ret, + DAG.getIntPtrConstant(1)); } + if (isSigned) { Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1, TLI.getShiftAmountTy(BottomHalf.getValueType())); @@ -3409,7 +3587,8 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, LegalizeSetCCCondCode(TLI.getSetCCResultType(Tmp2.getValueType()), Tmp2, Tmp3, Tmp4, dl); - LastCALLSEQ_END = DAG.getEntryNode(); + assert(LastCALLSEQ.size() == 1 && "branch inside CALLSEQ_BEGIN/END?"); + setLastCALLSEQ(DAG.getEntryNode()); assert(!Tmp3.getNode() && "Can't legalize BR_CC with legal condition!"); Tmp3 = DAG.getConstant(0, Tmp2.getValueType()); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index f0752df80f12..935aab0e59af 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1051,8 +1051,6 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { case ISD::SSUBO: ExpandIntRes_SADDSUBO(N, Lo, Hi); break; case ISD::UADDO: case ISD::USUBO: ExpandIntRes_UADDSUBO(N, Lo, Hi); break; - case ISD::UMULO: - case ISD::SMULO: ExpandIntRes_UMULSMULO(N, Lo, Hi); break; } // If Lo/Hi is null, the sub-method took care of registering results etc. @@ -1428,9 +1426,9 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, HiOps[2] = Lo.getValue(1); Hi = DAG.getNode(ISD::SUBE, dl, VTList, HiOps, 3); } - return; + return; } - + if (N->getOpcode() == ISD::ADD) { Lo = DAG.getNode(ISD::ADD, dl, NVT, LoOps, 2); Hi = DAG.getNode(ISD::ADD, dl, NVT, HiOps, 2); @@ -2128,31 +2126,6 @@ void DAGTypeLegalizer::ExpandIntRes_UADDSUBO(SDNode *N, ReplaceValueWith(SDValue(N, 1), Ofl); } -void DAGTypeLegalizer::ExpandIntRes_UMULSMULO(SDNode *N, - SDValue &Lo, SDValue &Hi) { - SDValue LHS = N->getOperand(0); - SDValue RHS = N->getOperand(1); - DebugLoc dl = N->getDebugLoc(); - EVT VT = N->getValueType(0); - EVT HalfVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() / 2); - // Expand the result by simply replacing it with the equivalent - // non-overflow-checking operation. - SDValue Ret = DAG.getNode(ISD::MUL, dl, LHS.getValueType(), LHS, RHS); - SplitInteger(Ret, Lo, Hi); - - // Now calculate overflow. - SDValue Ofl; - if (N->getOpcode() == ISD::UMULO) - Ofl = DAG.getSetCC(dl, N->getValueType(1), Hi, - DAG.getConstant(0, VT), ISD::SETNE); - else { - SDValue Tmp = DAG.getConstant(VT.getSizeInBits() - 1, HalfVT); - Tmp = DAG.getNode(ISD::SRA, dl, HalfVT, Lo, Tmp); - Ofl = DAG.getSetCC(dl, N->getValueType(1), Hi, Tmp, ISD::SETNE); - } - ReplaceValueWith(SDValue(N, 1), Ofl); -} - void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N, SDValue &Lo, SDValue &Hi) { EVT VT = N->getValueType(0); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 3f81bbbe4061..5409b88efaba 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -348,7 +348,6 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer { void ExpandIntRes_SADDSUBO (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandIntRes_UADDSUBO (SDNode *N, SDValue &Lo, SDValue &Hi); - void ExpandIntRes_UMULSMULO (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandShiftByConstant(SDNode *N, unsigned Amt, SDValue &Lo, SDValue &Hi); @@ -523,6 +522,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer { SDValue ScalarizeVecRes_BITCAST(SDNode *N); SDValue ScalarizeVecRes_CONVERT_RNDSAT(SDNode *N); SDValue ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N); + SDValue ScalarizeVecRes_FP_ROUND(SDNode *N); SDValue ScalarizeVecRes_FPOWI(SDNode *N); SDValue ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N); SDValue ScalarizeVecRes_LOAD(LoadSDNode *N); @@ -566,7 +566,6 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer { void SplitVecRes_BUILD_PAIR(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo, SDValue &Hi); - void SplitVecRes_CONVERT_RNDSAT(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_FPOWI(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue &Hi); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp index 167dbe0377b3..5d0f923afb0f 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -58,6 +58,9 @@ class VectorLegalizer { SDValue UnrollVSETCC(SDValue Op); // Implements expansion for FNEG; falls back to UnrollVectorOp if FSUB // isn't legal. + // Implements expansion for UINT_TO_FLOAT; falls back to UnrollVectorOp if + // SINT_TO_FLOAT and SHR on vectors isn't legal. + SDValue ExpandUINT_TO_FLOAT(SDValue Op); SDValue ExpandFNEG(SDValue Op); // Implements vector promotion; this is essentially just bitcasting the // operands to a different type and bitcasting the result back to the @@ -207,7 +210,9 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) { // FALL THROUGH } case TargetLowering::Expand: - if (Node->getOpcode() == ISD::FNEG) + if (Node->getOpcode() == ISD::UINT_TO_FP) + Result = ExpandUINT_TO_FLOAT(Op); + else if (Node->getOpcode() == ISD::FNEG) Result = ExpandFNEG(Op); else if (Node->getOpcode() == ISD::VSETCC) Result = UnrollVSETCC(Op); @@ -251,6 +256,48 @@ SDValue VectorLegalizer::PromoteVectorOp(SDValue Op) { return DAG.getNode(ISD::BITCAST, dl, VT, Op); } +SDValue VectorLegalizer::ExpandUINT_TO_FLOAT(SDValue Op) { + + + EVT VT = Op.getOperand(0).getValueType(); + DebugLoc DL = Op.getDebugLoc(); + + // Make sure that the SINT_TO_FP and SRL instructions are available. + if (!TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, VT) || + !TLI.isOperationLegalOrCustom(ISD::SRL, VT)) + return DAG.UnrollVectorOp(Op.getNode()); + + EVT SVT = VT.getScalarType(); + assert((SVT.getSizeInBits() == 64 || SVT.getSizeInBits() == 32) && + "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide"); + + unsigned BW = SVT.getSizeInBits(); + SDValue HalfWord = DAG.getConstant(BW/2, VT); + + // Constants to clear the upper part of the word. + // Notice that we can also use SHL+SHR, but using a constant is slightly + // faster on x86. + uint64_t HWMask = (SVT.getSizeInBits()==64)?0x00000000FFFFFFFF:0x0000FFFF; + SDValue HalfWordMask = DAG.getConstant(HWMask, VT); + + // Two to the power of half-word-size. + SDValue TWOHW = DAG.getConstantFP((1<<(BW/2)), Op.getValueType()); + + // Clear upper part of LO, lower HI + SDValue HI = DAG.getNode(ISD::SRL, DL, VT, Op.getOperand(0), HalfWord); + SDValue LO = DAG.getNode(ISD::AND, DL, VT, Op.getOperand(0), HalfWordMask); + + // Convert hi and lo to floats + // Convert the hi part back to the upper values + SDValue fHI = DAG.getNode(ISD::SINT_TO_FP, DL, Op.getValueType(), HI); + fHI = DAG.getNode(ISD::FMUL, DL, Op.getValueType(), fHI, TWOHW); + SDValue fLO = DAG.getNode(ISD::SINT_TO_FP, DL, Op.getValueType(), LO); + + // Add the two halves + return DAG.getNode(ISD::FADD, DL, Op.getValueType(), fHI, fLO); +} + + SDValue VectorLegalizer::ExpandFNEG(SDValue Op) { if (TLI.isOperationLegalOrCustom(ISD::FSUB, Op.getValueType())) { SDValue Zero = DAG.getConstantFP(-0.0, Op.getValueType()); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index 182f8fcbfbf3..0b4dd357c39d 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -50,6 +50,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) { case ISD::BUILD_VECTOR: R = N->getOperand(0); break; case ISD::CONVERT_RNDSAT: R = ScalarizeVecRes_CONVERT_RNDSAT(N); break; case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break; + case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break; case ISD::FP_ROUND_INREG: R = ScalarizeVecRes_InregOp(N); break; case ISD::FPOWI: R = ScalarizeVecRes_FPOWI(N); break; case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break; @@ -63,27 +64,33 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) { case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break; case ISD::VSETCC: R = ScalarizeVecRes_VSETCC(N); break; + case ISD::ANY_EXTEND: case ISD::CTLZ: case ISD::CTPOP: case ISD::CTTZ: case ISD::FABS: + case ISD::FCEIL: case ISD::FCOS: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FFLOOR: + case ISD::FLOG: + case ISD::FLOG10: + case ISD::FLOG2: + case ISD::FNEARBYINT: case ISD::FNEG: + case ISD::FP_EXTEND: case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: + case ISD::FRINT: case ISD::FSIN: case ISD::FSQRT: case ISD::FTRUNC: - case ISD::FFLOOR: - case ISD::FCEIL: - case ISD::FRINT: - case ISD::FNEARBYINT: - case ISD::UINT_TO_FP: + case ISD::SIGN_EXTEND: case ISD::SINT_TO_FP: case ISD::TRUNCATE: - case ISD::SIGN_EXTEND: + case ISD::UINT_TO_FP: case ISD::ZERO_EXTEND: - case ISD::ANY_EXTEND: R = ScalarizeVecRes_UnaryOp(N); break; @@ -145,6 +152,13 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) { N->getOperand(0), N->getOperand(1)); } +SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_ROUND(SDNode *N) { + EVT NewVT = N->getValueType(0).getVectorElementType(); + SDValue Op = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), + NewVT, Op, N->getOperand(1)); +} + SDValue DAGTypeLegalizer::ScalarizeVecRes_FPOWI(SDNode *N) { SDValue Op = GetScalarizedVector(N->getOperand(0)); return DAG.getNode(ISD::FPOWI, N->getDebugLoc(), @@ -405,11 +419,9 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) { case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; - case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break; case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break; case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break; - case ISD::CONVERT_RNDSAT: SplitVecRes_CONVERT_RNDSAT(N, Lo, Hi); break; case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break; case ISD::FP_ROUND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break; case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break; @@ -427,32 +439,35 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) { SplitVecRes_VECTOR_SHUFFLE(cast(N), Lo, Hi); break; - case ISD::CTTZ: + case ISD::ANY_EXTEND: + case ISD::CONVERT_RNDSAT: case ISD::CTLZ: case ISD::CTPOP: - case ISD::FNEG: + case ISD::CTTZ: case ISD::FABS: - case ISD::FSQRT: - case ISD::FSIN: - case ISD::FCOS: - case ISD::FTRUNC: - case ISD::FFLOOR: case ISD::FCEIL: - case ISD::FRINT: - case ISD::FNEARBYINT: - case ISD::FP_TO_SINT: - case ISD::FP_TO_UINT: - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: - case ISD::TRUNCATE: - case ISD::SIGN_EXTEND: - case ISD::ZERO_EXTEND: - case ISD::ANY_EXTEND: + case ISD::FCOS: case ISD::FEXP: case ISD::FEXP2: + case ISD::FFLOOR: case ISD::FLOG: - case ISD::FLOG2: case ISD::FLOG10: + case ISD::FLOG2: + case ISD::FNEARBYINT: + case ISD::FNEG: + case ISD::FP_EXTEND: + case ISD::FP_ROUND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::FRINT: + case ISD::FSIN: + case ISD::FSQRT: + case ISD::FTRUNC: + case ISD::SIGN_EXTEND: + case ISD::SINT_TO_FP: + case ISD::TRUNCATE: + case ISD::UINT_TO_FP: + case ISD::ZERO_EXTEND: SplitVecRes_UnaryOp(N, Lo, Hi); break; @@ -587,60 +602,6 @@ void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo, Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, &HiOps[0], HiOps.size()); } -void DAGTypeLegalizer::SplitVecRes_CONVERT_RNDSAT(SDNode *N, SDValue &Lo, - SDValue &Hi) { - EVT LoVT, HiVT; - DebugLoc dl = N->getDebugLoc(); - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - SDValue DTyOpLo = DAG.getValueType(LoVT); - SDValue DTyOpHi = DAG.getValueType(HiVT); - - SDValue RndOp = N->getOperand(3); - SDValue SatOp = N->getOperand(4); - ISD::CvtCode CvtCode = cast(N)->getCvtCode(); - - // Split the input. - SDValue VLo, VHi; - EVT InVT = N->getOperand(0).getValueType(); - switch (getTypeAction(InVT)) { - default: llvm_unreachable("Unexpected type action!"); - case Legal: { - EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), - LoVT.getVectorNumElements()); - VLo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), - DAG.getIntPtrConstant(0)); - VHi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), - DAG.getIntPtrConstant(InNVT.getVectorNumElements())); - break; - } - case SplitVector: - GetSplitVector(N->getOperand(0), VLo, VHi); - break; - case WidenVector: { - // If the result needs to be split and the input needs to be widened, - // the two types must have different lengths. Use the widened result - // and extract from it to do the split. - SDValue InOp = GetWidenedVector(N->getOperand(0)); - EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), - LoVT.getVectorNumElements()); - VLo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, - DAG.getIntPtrConstant(0)); - VHi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, - DAG.getIntPtrConstant(InNVT.getVectorNumElements())); - break; - } - } - - SDValue STyOpLo = DAG.getValueType(VLo.getValueType()); - SDValue STyOpHi = DAG.getValueType(VHi.getValueType()); - - Lo = DAG.getConvertRndSat(LoVT, dl, VLo, DTyOpLo, STyOpLo, RndOp, SatOp, - CvtCode); - Hi = DAG.getConvertRndSat(HiVT, dl, VHi, DTyOpHi, STyOpHi, RndOp, SatOp, - CvtCode); -} - void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo, SDValue &Hi) { SDValue Vec = N->getOperand(0); @@ -840,8 +801,25 @@ void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo, } } - Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo); - Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi); + if (N->getOpcode() == ISD::FP_ROUND) { + Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo, N->getOperand(1)); + Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi, N->getOperand(1)); + } else if (N->getOpcode() == ISD::CONVERT_RNDSAT) { + SDValue DTyOpLo = DAG.getValueType(LoVT); + SDValue DTyOpHi = DAG.getValueType(HiVT); + SDValue STyOpLo = DAG.getValueType(Lo.getValueType()); + SDValue STyOpHi = DAG.getValueType(Hi.getValueType()); + SDValue RndOp = N->getOperand(3); + SDValue SatOp = N->getOperand(4); + ISD::CvtCode CvtCode = cast(N)->getCvtCode(); + Lo = DAG.getConvertRndSat(LoVT, dl, Lo, DTyOpLo, STyOpLo, RndOp, SatOp, + CvtCode); + Hi = DAG.getConvertRndSat(HiVT, dl, Hi, DTyOpHi, STyOpHi, RndOp, SatOp, + CvtCode); + } else { + Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo); + Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi); + } } void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, @@ -989,11 +967,11 @@ bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) { case ISD::CTTZ: case ISD::CTLZ: case ISD::CTPOP: + case ISD::FP_EXTEND: case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: case ISD::SINT_TO_FP: case ISD::UINT_TO_FP: - case ISD::FP_EXTEND: case ISD::FTRUNC: case ISD::TRUNCATE: case ISD::SIGN_EXTEND: @@ -1270,15 +1248,16 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { Res = WidenVecRes_Shift(N); break; + case ISD::ANY_EXTEND: + case ISD::FP_EXTEND: case ISD::FP_ROUND: case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: - case ISD::TRUNCATE: case ISD::SIGN_EXTEND: + case ISD::SINT_TO_FP: + case ISD::TRUNCATE: + case ISD::UINT_TO_FP: case ISD::ZERO_EXTEND: - case ISD::ANY_EXTEND: Res = WidenVecRes_Convert(N); break; @@ -1286,15 +1265,20 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { case ISD::CTPOP: case ISD::CTTZ: case ISD::FABS: + case ISD::FCEIL: case ISD::FCOS: - case ISD::FNEG: - case ISD::FSIN: - case ISD::FSQRT: case ISD::FEXP: case ISD::FEXP2: + case ISD::FFLOOR: case ISD::FLOG: - case ISD::FLOG2: case ISD::FLOG10: + case ISD::FLOG2: + case ISD::FNEARBYINT: + case ISD::FNEG: + case ISD::FRINT: + case ISD::FSIN: + case ISD::FSQRT: + case ISD::FTRUNC: Res = WidenVecRes_Unary(N); break; } @@ -2004,7 +1988,7 @@ bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned ResNo) { case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break; case ISD::STORE: Res = WidenVecOp_STORE(N); break; - case ISD::FP_ROUND: + case ISD::FP_EXTEND: case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: case ISD::SINT_TO_FP: diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp index e3da2084529a..7b560d173ed3 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp @@ -570,13 +570,20 @@ void ScheduleDAGFast::ListScheduleBottomUp() { TRI->getMinimalPhysRegClass(Reg, VT); const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC); - // If cross copy register class is null, then it must be possible copy - // the value directly. Do not try duplicate the def. + // If cross copy register class is the same as RC, then it must be + // possible copy the value directly. Do not try duplicate the def. + // If cross copy register class is not the same as RC, then it's + // possible to copy the value but it require cross register class copies + // and it is expensive. + // If cross copy register class is null, then it's not possible to copy + // the value at all. SUnit *NewDef = 0; - if (DestRC) + if (DestRC != RC) { NewDef = CopyAndMoveSuccessors(LRDef); - else - DestRC = RC; + if (!DestRC && !NewDef) + report_fatal_error("Can't handle live physical " + "register dependency!"); + } if (!NewDef) { // Issue copies, these can be expensive cross register class copies. SmallVector Copies; diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index 0b548b277f4c..88bd4509b468 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -70,6 +70,50 @@ static cl::opt DisableSchedCycles( "disable-sched-cycles", cl::Hidden, cl::init(false), cl::desc("Disable cycle-level precision during preRA scheduling")); +// Temporary sched=list-ilp flags until the heuristics are robust. +// Some options are also available under sched=list-hybrid. +static cl::opt DisableSchedRegPressure( + "disable-sched-reg-pressure", cl::Hidden, cl::init(false), + cl::desc("Disable regpressure priority in sched=list-ilp")); +static cl::opt DisableSchedLiveUses( + "disable-sched-live-uses", cl::Hidden, cl::init(true), + cl::desc("Disable live use priority in sched=list-ilp")); +static cl::opt DisableSchedVRegCycle( + "disable-sched-vrcycle", cl::Hidden, cl::init(false), + cl::desc("Disable virtual register cycle interference checks")); +static cl::opt DisableSchedPhysRegJoin( + "disable-sched-physreg-join", cl::Hidden, cl::init(false), + cl::desc("Disable physreg def-use affinity")); +static cl::opt DisableSchedStalls( + "disable-sched-stalls", cl::Hidden, cl::init(true), + cl::desc("Disable no-stall priority in sched=list-ilp")); +static cl::opt DisableSchedCriticalPath( + "disable-sched-critical-path", cl::Hidden, cl::init(false), + cl::desc("Disable critical path priority in sched=list-ilp")); +static cl::opt DisableSchedHeight( + "disable-sched-height", cl::Hidden, cl::init(false), + cl::desc("Disable scheduled-height priority in sched=list-ilp")); + +static cl::opt MaxReorderWindow( + "max-sched-reorder", cl::Hidden, cl::init(6), + cl::desc("Number of instructions to allow ahead of the critical path " + "in sched=list-ilp")); + +static cl::opt AvgIPC( + "sched-avg-ipc", cl::Hidden, cl::init(1), + cl::desc("Average inst/cycle whan no target itinerary exists.")); + +#ifndef NDEBUG +namespace { + // For sched=list-ilp, Count the number of times each factor comes into play. + enum { FactPressureDiff, FactRegUses, FactStall, FactHeight, FactDepth, + FactStatic, FactOther, NumFactors }; +} +static const char *FactorName[NumFactors] = +{"PressureDiff", "RegUses", "Stall", "Height", "Depth","Static", "Other"}; +static int FactorCount[NumFactors]; +#endif //!NDEBUG + namespace { //===----------------------------------------------------------------------===// /// ScheduleDAGRRList - The actual register reduction list scheduler @@ -103,6 +147,10 @@ class ScheduleDAGRRList : public ScheduleDAGSDNodes { /// MinAvailableCycle - Cycle of the soonest available instruction. unsigned MinAvailableCycle; + /// IssueCount - Count instructions issued in this cycle + /// Currently valid only for bottom-up scheduling. + unsigned IssueCount; + /// LiveRegDefs - A set of physical registers and their definition /// that are "live". These nodes must be scheduled before any other nodes that /// modifies the registers can be scheduled. @@ -234,8 +282,14 @@ void ScheduleDAGRRList::Schedule() { DEBUG(dbgs() << "********** List Scheduling BB#" << BB->getNumber() << " '" << BB->getName() << "' **********\n"); +#ifndef NDEBUG + for (int i = 0; i < NumFactors; ++i) { + FactorCount[i] = 0; + } +#endif //!NDEBUG CurCycle = 0; + IssueCount = 0; MinAvailableCycle = DisableSchedCycles ? 0 : UINT_MAX; NumLiveRegs = 0; LiveRegDefs.resize(TRI->getNumRegs(), NULL); @@ -258,6 +312,11 @@ void ScheduleDAGRRList::Schedule() { else ListScheduleTopDown(); +#ifndef NDEBUG + for (int i = 0; i < NumFactors; ++i) { + DEBUG(dbgs() << FactorName[i] << "\t" << FactorCount[i] << "\n"); + } +#endif // !NDEBUG AvailableQueue->releaseState(); } @@ -295,7 +354,7 @@ void ScheduleDAGRRList::ReleasePred(SUnit *SU, const SDep *PredEdge) { if (Height < MinAvailableCycle) MinAvailableCycle = Height; - if (isReady(SU)) { + if (isReady(PredSU)) { AvailableQueue->push(PredSU); } // CapturePred and others may have left the node in the pending queue, avoid @@ -383,6 +442,7 @@ void ScheduleDAGRRList::AdvanceToCycle(unsigned NextCycle) { if (NextCycle <= CurCycle) return; + IssueCount = 0; AvailableQueue->setCurCycle(NextCycle); if (!HazardRec->isEnabled()) { // Bypass lots of virtual calls in case of long latency. @@ -407,6 +467,13 @@ void ScheduleDAGRRList::AdvancePastStalls(SUnit *SU) { if (DisableSchedCycles) return; + // FIXME: Nodes such as CopyFromReg probably should not advance the current + // cycle. Otherwise, we can wrongly mask real stalls. If the non-machine node + // has predecessors the cycle will be advanced when they are scheduled. + // But given the crude nature of modeling latency though such nodes, we + // currently need to treat these nodes like real instructions. + // if (!SU->getNode() || !SU->getNode()->isMachineOpcode()) return; + unsigned ReadyCycle = isBottomUp ? SU->getHeight() : SU->getDepth(); // Bump CurCycle to account for latency. We assume the latency of other @@ -477,6 +544,8 @@ void ScheduleDAGRRList::EmitNode(SUnit *SU) { } } +static void resetVRegCycle(SUnit *SU); + /// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending /// count of its predecessors. If a predecessor pending count is zero, add it to /// the Available queue. @@ -486,12 +555,13 @@ void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) { #ifndef NDEBUG if (CurCycle < SU->getHeight()) - DEBUG(dbgs() << " Height [" << SU->getHeight() << "] pipeline stall!\n"); + DEBUG(dbgs() << " Height [" << SU->getHeight() + << "] pipeline stall!\n"); #endif // FIXME: Do not modify node height. It may interfere with // backtracking. Instead add a "ready cycle" to SUnit. Before scheduling the - // node it's ready cycle can aid heuristics, and after scheduling it can + // node its ready cycle can aid heuristics, and after scheduling it can // indicate the scheduled cycle. SU->setHeightToAtLeast(CurCycle); @@ -502,6 +572,12 @@ void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) { AvailableQueue->ScheduledNode(SU); + // If HazardRec is disabled, and each inst counts as one cycle, then + // advance CurCycle before ReleasePredecessors to avoid useless pushes to + // PendingQueue for schedulers that implement HasReadyFilter. + if (!HazardRec->isEnabled() && AvgIPC < 2) + AdvanceToCycle(CurCycle + 1); + // Update liveness of predecessors before successors to avoid treating a // two-address node as a live range def. ReleasePredecessors(SU); @@ -518,16 +594,25 @@ void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) { } } + resetVRegCycle(SU); + SU->isScheduled = true; // Conditions under which the scheduler should eagerly advance the cycle: // (1) No available instructions // (2) All pipelines full, so available instructions must have hazards. // - // If HazardRec is disabled, count each inst as one cycle. - if (!HazardRec->isEnabled() || HazardRec->atIssueLimit() - || AvailableQueue->empty()) - AdvanceToCycle(CurCycle + 1); + // If HazardRec is disabled, the cycle was pre-advanced before calling + // ReleasePredecessors. In that case, IssueCount should remain 0. + // + // Check AvailableQueue after ReleasePredecessors in case of zero latency. + if (HazardRec->isEnabled() || AvgIPC > 1) { + if (SU->getNode() && SU->getNode()->isMachineOpcode()) + ++IssueCount; + if ((HazardRec->isEnabled() && HazardRec->atIssueLimit()) + || (!HazardRec->isEnabled() && IssueCount == AvgIPC)) + AdvanceToCycle(CurCycle + 1); + } } /// CapturePred - This does the opposite of ReleasePred. Since SU is being @@ -872,6 +957,15 @@ void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg, AddPred(SuccSU, D); DelDeps.push_back(std::make_pair(SuccSU, *I)); } + else { + // Avoid scheduling the def-side copy before other successors. Otherwise + // we could introduce another physreg interference on the copy and + // continue inserting copies indefinitely. + SDep D(CopyFromSU, SDep::Order, /*Latency=*/0, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, /*isArtificial=*/true); + AddPred(SuccSU, D); + } } for (unsigned i = 0, e = DelDeps.size(); i != e; ++i) RemovePred(DelDeps[i].first, DelDeps[i].second); @@ -1077,13 +1171,19 @@ SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() { TRI->getMinimalPhysRegClass(Reg, VT); const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC); - // If cross copy register class is null, then it must be possible copy - // the value directly. Do not try duplicate the def. + // If cross copy register class is the same as RC, then it must be possible + // copy the value directly. Do not try duplicate the def. + // If cross copy register class is not the same as RC, then it's possible to + // copy the value but it require cross register class copies and it is + // expensive. + // If cross copy register class is null, then it's not possible to copy + // the value at all. SUnit *NewDef = 0; - if (DestRC) + if (DestRC != RC) { NewDef = CopyAndMoveSuccessors(LRDef); - else - DestRC = RC; + if (!DestRC && !NewDef) + report_fatal_error("Can't handle live physical register dependency!"); + } if (!NewDef) { // Issue copies, these can be expensive cross register class copies. SmallVector Copies; @@ -1139,7 +1239,7 @@ void ScheduleDAGRRList::ListScheduleBottomUp() { // priority. If it is not ready put it back. Schedule the node. Sequence.reserve(SUnits.size()); while (!AvailableQueue->empty()) { - DEBUG(dbgs() << "\n*** Examining Available\n"; + DEBUG(dbgs() << "\nExamining Available:\n"; AvailableQueue->dump(this)); // Pick the best node to schedule taking all constraints into @@ -1318,7 +1418,7 @@ struct src_ls_rr_sort : public queue_sort { struct hybrid_ls_rr_sort : public queue_sort { enum { IsBottomUp = true, - HasReadyFilter = true + HasReadyFilter = false }; RegReductionPQBase *SPQ; @@ -1337,7 +1437,7 @@ struct hybrid_ls_rr_sort : public queue_sort { struct ilp_ls_rr_sort : public queue_sort { enum { IsBottomUp = true, - HasReadyFilter = true + HasReadyFilter = false }; RegReductionPQBase *SPQ; @@ -1395,7 +1495,7 @@ class RegReductionPQBase : public SchedulingPriorityQueue { std::fill(RegPressure.begin(), RegPressure.end(), 0); for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(), E = TRI->regclass_end(); I != E; ++I) - RegLimit[(*I)->getID()] = tli->getRegPressureLimit(*I, MF); + RegLimit[(*I)->getID()] = tri->getRegPressureLimit(*I, MF); } } @@ -1422,6 +1522,8 @@ class RegReductionPQBase : public SchedulingPriorityQueue { unsigned getNodePriority(const SUnit *SU) const; unsigned getNodeOrdering(const SUnit *SU) const { + if (!SU->getNode()) return 0; + return scheduleDAG->DAG->GetOrdering(SU->getNode()); } @@ -1450,7 +1552,9 @@ class RegReductionPQBase : public SchedulingPriorityQueue { bool HighRegPressure(const SUnit *SU) const; - bool MayReduceRegPressure(SUnit *SU); + bool MayReduceRegPressure(SUnit *SU) const; + + int RegPressureDiff(SUnit *SU, unsigned &LiveUses) const; void ScheduledNode(SUnit *SU); @@ -1538,6 +1642,20 @@ ILPBURRPriorityQueue; // Static Node Priority for Register Pressure Reduction //===----------------------------------------------------------------------===// +// Check for special nodes that bypass scheduling heuristics. +// Currently this pushes TokenFactor nodes down, but may be used for other +// pseudo-ops as well. +// +// Return -1 to schedule right above left, 1 for left above right. +// Return 0 if no bias exists. +static int checkSpecialNodes(const SUnit *left, const SUnit *right) { + bool LSchedLow = left->isScheduleLow; + bool RSchedLow = right->isScheduleLow; + if (LSchedLow != RSchedLow) + return LSchedLow < RSchedLow ? 1 : -1; + return 0; +} + /// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number. /// Smaller number is the higher priority. static unsigned @@ -1576,17 +1694,6 @@ void RegReductionPQBase::CalculateSethiUllmanNumbers() { CalcNodeSethiUllmanNumber(&(*SUnits)[i], SethiUllmanNumbers); } -void RegReductionPQBase::initNodes(std::vector &sunits) { - SUnits = &sunits; - // Add pseudo dependency edges for two-address nodes. - AddPseudoTwoAddrDeps(); - // Reroute edges to nodes with multiple uses. - if (!TracksRegPressure) - PrescheduleNodesWithMultipleUses(); - // Calculate node priorities. - CalculateSethiUllmanNumbers(); -} - void RegReductionPQBase::addNode(const SUnit *SU) { unsigned SUSize = SethiUllmanNumbers.size(); if (SUnits->size() > SUSize) @@ -1625,7 +1732,17 @@ unsigned RegReductionPQBase::getNodePriority(const SUnit *SU) const { // If SU does not have a register def, schedule it close to its uses // because it does not lengthen any live ranges. return 0; +#if 1 return SethiUllmanNumbers[SU->NodeNum]; +#else + unsigned Priority = SethiUllmanNumbers[SU->NodeNum]; + if (SU->isCallOp) { + // FIXME: This assumes all of the defs are used as call operands. + int NP = (int)Priority - SU->getNode()->getNumValues(); + return (NP > 0) ? NP : 0; + } + return Priority; +#endif } //===----------------------------------------------------------------------===// @@ -1670,7 +1787,7 @@ bool RegReductionPQBase::HighRegPressure(const SUnit *SU) const { return false; } -bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU) { +bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU) const { const SDNode *N = SU->getNode(); if (!N->isMachineOpcode() || !SU->NumSuccs) @@ -1688,10 +1805,60 @@ bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU) { return false; } +// Compute the register pressure contribution by this instruction by count up +// for uses that are not live and down for defs. Only count register classes +// that are already under high pressure. As a side effect, compute the number of +// uses of registers that are already live. +// +// FIXME: This encompasses the logic in HighRegPressure and MayReduceRegPressure +// so could probably be factored. +int RegReductionPQBase::RegPressureDiff(SUnit *SU, unsigned &LiveUses) const { + LiveUses = 0; + int PDiff = 0; + for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) + continue; + SUnit *PredSU = I->getSUnit(); + // NumRegDefsLeft is zero when enough uses of this node have been scheduled + // to cover the number of registers defined (they are all live). + if (PredSU->NumRegDefsLeft == 0) { + if (PredSU->getNode()->isMachineOpcode()) + ++LiveUses; + continue; + } + for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG); + RegDefPos.IsValid(); RegDefPos.Advance()) { + EVT VT = RegDefPos.GetValue(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + if (RegPressure[RCId] >= RegLimit[RCId]) + ++PDiff; + } + } + const SDNode *N = SU->getNode(); + + if (!N || !N->isMachineOpcode() || !SU->NumSuccs) + return PDiff; + + unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); + for (unsigned i = 0; i != NumDefs; ++i) { + EVT VT = N->getValueType(i); + if (!N->hasAnyUseOfValue(i)) + continue; + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + if (RegPressure[RCId] >= RegLimit[RCId]) + --PDiff; + } + return PDiff; +} + void RegReductionPQBase::ScheduledNode(SUnit *SU) { if (!TracksRegPressure) return; + if (!SU->getNode()) + return; + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); I != E; ++I) { if (I->isCtrl()) @@ -1758,6 +1925,8 @@ void RegReductionPQBase::UnscheduledNode(SUnit *SU) { return; const SDNode *N = SU->getNode(); + if (!N) return; + if (!N->isMachineOpcode()) { if (N->getOpcode() != ISD::CopyToReg) return; @@ -1871,7 +2040,29 @@ static unsigned calcMaxScratches(const SUnit *SU) { return Scratches; } -/// hasOnlyLiveOutUse - Return true if SU has a single value successor that is a +/// hasOnlyLiveInOpers - Return true if SU has only value predecessors that are +/// CopyFromReg from a virtual register. +static bool hasOnlyLiveInOpers(const SUnit *SU) { + bool RetVal = false; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; + const SUnit *PredSU = I->getSUnit(); + if (PredSU->getNode() && + PredSU->getNode()->getOpcode() == ISD::CopyFromReg) { + unsigned Reg = + cast(PredSU->getNode()->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + RetVal = true; + continue; + } + } + return false; + } + return RetVal; +} + +/// hasOnlyLiveOutUses - Return true if SU has only value successors that are /// CopyToReg to a virtual register. This SU def is probably a liveout and /// it has no other use. It should be scheduled closer to the terminator. static bool hasOnlyLiveOutUses(const SUnit *SU) { @@ -1893,20 +2084,67 @@ static bool hasOnlyLiveOutUses(const SUnit *SU) { return RetVal; } -/// UnitsSharePred - Return true if the two scheduling units share a common -/// data predecessor. -static bool UnitsSharePred(const SUnit *left, const SUnit *right) { - SmallSet Preds; - for (SUnit::const_pred_iterator I = left->Preds.begin(),E = left->Preds.end(); +// Set isVRegCycle for a node with only live in opers and live out uses. Also +// set isVRegCycle for its CopyFromReg operands. +// +// This is only relevant for single-block loops, in which case the VRegCycle +// node is likely an induction variable in which the operand and target virtual +// registers should be coalesced (e.g. pre/post increment values). Setting the +// isVRegCycle flag helps the scheduler prioritize other uses of the same +// CopyFromReg so that this node becomes the virtual register "kill". This +// avoids interference between the values live in and out of the block and +// eliminates a copy inside the loop. +static void initVRegCycle(SUnit *SU) { + if (DisableSchedVRegCycle) + return; + + if (!hasOnlyLiveInOpers(SU) || !hasOnlyLiveOutUses(SU)) + return; + + DEBUG(dbgs() << "VRegCycle: SU(" << SU->NodeNum << ")\n"); + + SU->isVRegCycle = true; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); I != E; ++I) { - if (I->isCtrl()) continue; // ignore chain preds - Preds.insert(I->getSUnit()); + if (I->isCtrl()) continue; + I->getSUnit()->isVRegCycle = true; } - for (SUnit::const_pred_iterator I = right->Preds.begin(),E = right->Preds.end(); +} + +// After scheduling the definition of a VRegCycle, clear the isVRegCycle flag of +// CopyFromReg operands. We should no longer penalize other uses of this VReg. +static void resetVRegCycle(SUnit *SU) { + if (!SU->isVRegCycle) + return; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); I != E; ++I) { if (I->isCtrl()) continue; // ignore chain preds - if (Preds.count(I->getSUnit())) + SUnit *PredSU = I->getSUnit(); + if (PredSU->isVRegCycle) { + assert(PredSU->getNode()->getOpcode() == ISD::CopyFromReg && + "VRegCycle def must be CopyFromReg"); + I->getSUnit()->isVRegCycle = 0; + } + } +} + +// Return true if this SUnit uses a CopyFromReg node marked as a VRegCycle. This +// means a node that defines the VRegCycle has not been scheduled yet. +static bool hasVRegCycleUse(const SUnit *SU) { + // If this SU also defines the VReg, don't hoist it as a "use". + if (SU->isVRegCycle) + return false; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain preds + if (I->getSUnit()->isVRegCycle && + I->getSUnit()->getNode()->getOpcode() == ISD::CopyFromReg) { + DEBUG(dbgs() << " VReg cycle use: SU (" << SU->NodeNum << ")\n"); return true; + } } return false; } @@ -1926,23 +2164,12 @@ static bool BUHasStall(SUnit *SU, int Height, RegReductionPQBase *SPQ) { // Return 0 if latency-based priority is equivalent. static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, RegReductionPQBase *SPQ) { - // If the two nodes share an operand and one of them has a single - // use that is a live out copy, favor the one that is live out. Otherwise - // it will be difficult to eliminate the copy if the instruction is a - // loop induction variable update. e.g. - // BB: - // sub r1, r3, #1 - // str r0, [r2, r3] - // mov r3, r1 - // cmp - // bne BB - bool SharePred = UnitsSharePred(left, right); - // FIXME: Only adjust if BB is a loop back edge. - // FIXME: What's the cost of a copy? - int LBonus = (SharePred && hasOnlyLiveOutUses(left)) ? 1 : 0; - int RBonus = (SharePred && hasOnlyLiveOutUses(right)) ? 1 : 0; - int LHeight = (int)left->getHeight() - LBonus; - int RHeight = (int)right->getHeight() - RBonus; + // Scheduling an instruction that uses a VReg whose postincrement has not yet + // been scheduled will induce a copy. Model this as an extra cycle of latency. + int LPenalty = hasVRegCycleUse(left) ? 1 : 0; + int RPenalty = hasVRegCycleUse(right) ? 1 : 0; + int LHeight = (int)left->getHeight() + LPenalty; + int RHeight = (int)right->getHeight() + RPenalty; bool LStall = (!checkPref || left->SchedulingPref == Sched::Latency) && BUHasStall(left, LHeight, SPQ); @@ -1953,45 +2180,102 @@ static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, // If scheduling either one of the node will cause a pipeline stall, sort // them according to their height. if (LStall) { - if (!RStall) + if (!RStall) { + DEBUG(++FactorCount[FactStall]); return 1; - if (LHeight != RHeight) + } + if (LHeight != RHeight) { + DEBUG(++FactorCount[FactStall]); return LHeight > RHeight ? 1 : -1; - } else if (RStall) + } + } else if (RStall) { + DEBUG(++FactorCount[FactStall]); return -1; + } // If either node is scheduling for latency, sort them by height/depth // and latency. if (!checkPref || (left->SchedulingPref == Sched::Latency || right->SchedulingPref == Sched::Latency)) { if (DisableSchedCycles) { - if (LHeight != RHeight) + if (LHeight != RHeight) { + DEBUG(++FactorCount[FactHeight]); return LHeight > RHeight ? 1 : -1; + } } else { // If neither instruction stalls (!LStall && !RStall) then - // it's height is already covered so only its depth matters. We also reach + // its height is already covered so only its depth matters. We also reach // this if both stall but have the same height. - unsigned LDepth = left->getDepth(); - unsigned RDepth = right->getDepth(); + int LDepth = left->getDepth() - LPenalty; + int RDepth = right->getDepth() - RPenalty; if (LDepth != RDepth) { + DEBUG(++FactorCount[FactDepth]); DEBUG(dbgs() << " Comparing latency of SU (" << left->NodeNum << ") depth " << LDepth << " vs SU (" << right->NodeNum << ") depth " << RDepth << "\n"); return LDepth < RDepth ? 1 : -1; } } - if (left->Latency != right->Latency) + if (left->Latency != right->Latency) { + DEBUG(++FactorCount[FactOther]); return left->Latency > right->Latency ? 1 : -1; + } } return 0; } static bool BURRSort(SUnit *left, SUnit *right, RegReductionPQBase *SPQ) { + // Schedule physical register definitions close to their use. This is + // motivated by microarchitectures that can fuse cmp+jump macro-ops. But as + // long as shortening physreg live ranges is generally good, we can defer + // creating a subtarget hook. + if (!DisableSchedPhysRegJoin) { + bool LHasPhysReg = left->hasPhysRegDefs; + bool RHasPhysReg = right->hasPhysRegDefs; + if (LHasPhysReg != RHasPhysReg) { + DEBUG(++FactorCount[FactRegUses]); + #ifndef NDEBUG + const char *PhysRegMsg[] = {" has no physreg", " defines a physreg"}; + #endif + DEBUG(dbgs() << " SU (" << left->NodeNum << ") " + << PhysRegMsg[LHasPhysReg] << " SU(" << right->NodeNum << ") " + << PhysRegMsg[RHasPhysReg] << "\n"); + return LHasPhysReg < RHasPhysReg; + } + } + + // Prioritize by Sethi-Ulmann number and push CopyToReg nodes down. unsigned LPriority = SPQ->getNodePriority(left); unsigned RPriority = SPQ->getNodePriority(right); - if (LPriority != RPriority) + + // Be really careful about hoisting call operands above previous calls. + // Only allows it if it would reduce register pressure. + if (left->isCall && right->isCallOp) { + unsigned RNumVals = right->getNode()->getNumValues(); + RPriority = (RPriority > RNumVals) ? (RPriority - RNumVals) : 0; + } + if (right->isCall && left->isCallOp) { + unsigned LNumVals = left->getNode()->getNumValues(); + LPriority = (LPriority > LNumVals) ? (LPriority - LNumVals) : 0; + } + + if (LPriority != RPriority) { + DEBUG(++FactorCount[FactStatic]); return LPriority > RPriority; + } + + // One or both of the nodes are calls and their sethi-ullman numbers are the + // same, then keep source order. + if (left->isCall || right->isCall) { + unsigned LOrder = SPQ->getNodeOrdering(left); + unsigned ROrder = SPQ->getNodeOrdering(right); + + // Prefer an ordering where the lower the non-zero order number, the higher + // the preference. + if ((LOrder || ROrder) && LOrder != ROrder) + return LOrder != 0 && (LOrder < ROrder || ROrder == 0); + } // Try schedule def + use closer when Sethi-Ullman numbers are the same. // e.g. @@ -2012,40 +2296,62 @@ static bool BURRSort(SUnit *left, SUnit *right, RegReductionPQBase *SPQ) { // This creates more short live intervals. unsigned LDist = closestSucc(left); unsigned RDist = closestSucc(right); - if (LDist != RDist) + if (LDist != RDist) { + DEBUG(++FactorCount[FactOther]); return LDist < RDist; + } // How many registers becomes live when the node is scheduled. unsigned LScratch = calcMaxScratches(left); unsigned RScratch = calcMaxScratches(right); - if (LScratch != RScratch) + if (LScratch != RScratch) { + DEBUG(++FactorCount[FactOther]); return LScratch > RScratch; + } - if (!DisableSchedCycles) { + // Comparing latency against a call makes little sense unless the node + // is register pressure-neutral. + if ((left->isCall && RPriority > 0) || (right->isCall && LPriority > 0)) + return (left->NodeQueueId > right->NodeQueueId); + + // Do not compare latencies when one or both of the nodes are calls. + if (!DisableSchedCycles && + !(left->isCall || right->isCall)) { int result = BUCompareLatency(left, right, false /*checkPref*/, SPQ); if (result != 0) return result > 0; } else { - if (left->getHeight() != right->getHeight()) + if (left->getHeight() != right->getHeight()) { + DEBUG(++FactorCount[FactHeight]); return left->getHeight() > right->getHeight(); + } - if (left->getDepth() != right->getDepth()) + if (left->getDepth() != right->getDepth()) { + DEBUG(++FactorCount[FactDepth]); return left->getDepth() < right->getDepth(); + } } assert(left->NodeQueueId && right->NodeQueueId && "NodeQueueId cannot be zero"); + DEBUG(++FactorCount[FactOther]); return (left->NodeQueueId > right->NodeQueueId); } // Bottom up bool bu_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res > 0; + return BURRSort(left, right, SPQ); } // Source order, otherwise bottom up. bool src_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res > 0; + unsigned LOrder = SPQ->getNodeOrdering(left); unsigned ROrder = SPQ->getNodeOrdering(right); @@ -2077,6 +2383,9 @@ bool hybrid_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const { // Return true if right should be scheduled with higher priority than left. bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res > 0; + if (left->isCall || right->isCall) // No way to compute latency of calls. return BURRSort(left, right, SPQ); @@ -2086,16 +2395,18 @@ bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { // Avoid causing spills. If register pressure is high, schedule for // register pressure reduction. if (LHigh && !RHigh) { + DEBUG(++FactorCount[FactPressureDiff]); DEBUG(dbgs() << " pressure SU(" << left->NodeNum << ") > SU(" << right->NodeNum << ")\n"); return true; } else if (!LHigh && RHigh) { + DEBUG(++FactorCount[FactPressureDiff]); DEBUG(dbgs() << " pressure SU(" << right->NodeNum << ") > SU(" << left->NodeNum << ")\n"); return false; } - else if (!LHigh && !RHigh) { + if (!LHigh && !RHigh) { int result = BUCompareLatency(left, right, true /*checkPref*/, SPQ); if (result != 0) return result > 0; @@ -2112,34 +2423,118 @@ bool ilp_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const { != ScheduleHazardRecognizer::NoHazard) return false; - return SU->getHeight() <= CurCycle; + return true; } +static bool canEnableCoalescing(SUnit *SU) { + unsigned Opc = SU->getNode() ? SU->getNode()->getOpcode() : 0; + if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg) + // CopyToReg should be close to its uses to facilitate coalescing and + // avoid spilling. + return true; + + if (Opc == TargetOpcode::EXTRACT_SUBREG || + Opc == TargetOpcode::SUBREG_TO_REG || + Opc == TargetOpcode::INSERT_SUBREG) + // EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG nodes should be + // close to their uses to facilitate coalescing. + return true; + + if (SU->NumPreds == 0 && SU->NumSuccs != 0) + // If SU does not have a register def, schedule it close to its uses + // because it does not lengthen any live ranges. + return true; + + return false; +} + +// list-ilp is currently an experimental scheduler that allows various +// heuristics to be enabled prior to the normal register reduction logic. bool ilp_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res > 0; + if (left->isCall || right->isCall) // No way to compute latency of calls. return BURRSort(left, right, SPQ); - bool LHigh = SPQ->HighRegPressure(left); - bool RHigh = SPQ->HighRegPressure(right); - // Avoid causing spills. If register pressure is high, schedule for - // register pressure reduction. - if (LHigh && !RHigh) - return true; - else if (!LHigh && RHigh) - return false; - else if (!LHigh && !RHigh) { - // Low register pressure situation, schedule to maximize instruction level - // parallelism. - if (left->NumPreds > right->NumPreds) - return false; - else if (left->NumPreds < right->NumPreds) - return false; + unsigned LLiveUses = 0, RLiveUses = 0; + int LPDiff = 0, RPDiff = 0; + if (!DisableSchedRegPressure || !DisableSchedLiveUses) { + LPDiff = SPQ->RegPressureDiff(left, LLiveUses); + RPDiff = SPQ->RegPressureDiff(right, RLiveUses); + } + if (!DisableSchedRegPressure && LPDiff != RPDiff) { + DEBUG(++FactorCount[FactPressureDiff]); + DEBUG(dbgs() << "RegPressureDiff SU(" << left->NodeNum << "): " << LPDiff + << " != SU(" << right->NodeNum << "): " << RPDiff << "\n"); + return LPDiff > RPDiff; + } + + if (!DisableSchedRegPressure && (LPDiff > 0 || RPDiff > 0)) { + bool LReduce = canEnableCoalescing(left); + bool RReduce = canEnableCoalescing(right); + DEBUG(if (LReduce != RReduce) ++FactorCount[FactPressureDiff]); + if (LReduce && !RReduce) return false; + if (RReduce && !LReduce) return true; + } + + if (!DisableSchedLiveUses && (LLiveUses != RLiveUses)) { + DEBUG(dbgs() << "Live uses SU(" << left->NodeNum << "): " << LLiveUses + << " != SU(" << right->NodeNum << "): " << RLiveUses << "\n"); + DEBUG(++FactorCount[FactRegUses]); + return LLiveUses < RLiveUses; + } + + if (!DisableSchedStalls) { + bool LStall = BUHasStall(left, left->getHeight(), SPQ); + bool RStall = BUHasStall(right, right->getHeight(), SPQ); + if (LStall != RStall) { + DEBUG(++FactorCount[FactHeight]); + return left->getHeight() > right->getHeight(); + } + } + + if (!DisableSchedCriticalPath) { + int spread = (int)left->getDepth() - (int)right->getDepth(); + if (std::abs(spread) > MaxReorderWindow) { + DEBUG(dbgs() << "Depth of SU(" << left->NodeNum << "): " + << left->getDepth() << " != SU(" << right->NodeNum << "): " + << right->getDepth() << "\n"); + DEBUG(++FactorCount[FactDepth]); + return left->getDepth() < right->getDepth(); + } + } + + if (!DisableSchedHeight && left->getHeight() != right->getHeight()) { + int spread = (int)left->getHeight() - (int)right->getHeight(); + if (std::abs(spread) > MaxReorderWindow) { + DEBUG(++FactorCount[FactHeight]); + return left->getHeight() > right->getHeight(); + } } return BURRSort(left, right, SPQ); } +void RegReductionPQBase::initNodes(std::vector &sunits) { + SUnits = &sunits; + // Add pseudo dependency edges for two-address nodes. + AddPseudoTwoAddrDeps(); + // Reroute edges to nodes with multiple uses. + if (!TracksRegPressure) + PrescheduleNodesWithMultipleUses(); + // Calculate node priorities. + CalculateSethiUllmanNumbers(); + + // For single block loops, mark nodes that look like canonical IV increments. + if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB)) { + for (unsigned i = 0, e = sunits.size(); i != e; ++i) { + initVRegCycle(&sunits[i]); + } + } +} + //===----------------------------------------------------------------------===// // Preschedule for Register Pressure //===----------------------------------------------------------------------===// @@ -2417,6 +2812,9 @@ static unsigned LimitedSumOfUnscheduledPredsOfSuccs(const SUnit *SU, // Top down bool td_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res < 0; + unsigned LPriority = SPQ->getNodePriority(left); unsigned RPriority = SPQ->getNodePriority(right); bool LIsTarget = left->getNode() && left->getNode()->isMachineOpcode(); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index 477c1ffe65d3..9f2f0121a86d 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -27,12 +27,21 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; STATISTIC(LoadsClustered, "Number of loads clustered together"); +// This allows latency based scheduler to notice high latency instructions +// without a target itinerary. The choise if number here has more to do with +// balancing scheduler heursitics than with the actual machine latency. +static cl::opt HighLatencyCycles( + "sched-high-latency-cycles", cl::Hidden, cl::init(10), + cl::desc("Roughly estimate the number of cycles that 'long latency'" + "instructions take for targets with no itinerary")); + ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf) : ScheduleDAG(mf), InstrItins(mf.getTarget().getInstrItineraryData()) {} @@ -72,11 +81,15 @@ SUnit *ScheduleDAGSDNodes::Clone(SUnit *Old) { SUnit *SU = NewSUnit(Old->getNode()); SU->OrigNode = Old->OrigNode; SU->Latency = Old->Latency; + SU->isVRegCycle = Old->isVRegCycle; SU->isCall = Old->isCall; + SU->isCallOp = Old->isCallOp; SU->isTwoAddress = Old->isTwoAddress; SU->isCommutable = Old->isCommutable; SU->hasPhysRegDefs = Old->hasPhysRegDefs; SU->hasPhysRegClobbers = Old->hasPhysRegClobbers; + SU->isScheduleHigh = Old->isScheduleHigh; + SU->isScheduleLow = Old->isScheduleLow; SU->SchedulingPref = Old->SchedulingPref; Old->isCloned = true; return SU; @@ -273,6 +286,7 @@ void ScheduleDAGSDNodes::BuildSchedUnits() { Worklist.push_back(DAG->getRoot().getNode()); Visited.insert(DAG->getRoot().getNode()); + SmallVector CallSUnits; while (!Worklist.empty()) { SDNode *NI = Worklist.pop_back_val(); @@ -325,6 +339,15 @@ void ScheduleDAGSDNodes::BuildSchedUnits() { if (!HasGlueUse) break; } + if (NodeSUnit->isCall) + CallSUnits.push_back(NodeSUnit); + + // Schedule zero-latency TokenFactor below any nodes that may increase the + // schedule height. Otherwise, ancestors of the TokenFactor may appear to + // have false stalls. + if (NI->getOpcode() == ISD::TokenFactor) + NodeSUnit->isScheduleLow = true; + // If there are glue operands involved, N is now the bottom-most node // of the sequence of nodes that are glued together. // Update the SUnit. @@ -338,6 +361,20 @@ void ScheduleDAGSDNodes::BuildSchedUnits() { // Assign the Latency field of NodeSUnit using target-provided information. ComputeLatency(NodeSUnit); } + + // Find all call operands. + while (!CallSUnits.empty()) { + SUnit *SU = CallSUnits.pop_back_val(); + for (const SDNode *SUNode = SU->getNode(); SUNode; + SUNode = SUNode->getGluedNode()) { + if (SUNode->getOpcode() != ISD::CopyToReg) + continue; + SDNode *SrcN = SUNode->getOperand(2).getNode(); + if (isPassiveNode(SrcN)) continue; // Not scheduled. + SUnit *SrcSU = &SUnits[SrcN->getNodeId()]; + SrcSU->isCallOp = true; + } + } } void ScheduleDAGSDNodes::AddSchedEdges() { @@ -403,6 +440,10 @@ void ScheduleDAGSDNodes::AddSchedEdges() { // If this is a ctrl dep, latency is 1. unsigned OpLatency = isChain ? 1 : OpSU->Latency; + // Special-case TokenFactor chains as zero-latency. + if(isChain && OpN->getOpcode() == ISD::TokenFactor) + OpLatency = 0; + const SDep &dep = SDep(OpSU, isChain ? SDep::Order : SDep::Data, OpLatency, PhysReg); if (!isChain && !UnitLatencies) { @@ -410,11 +451,15 @@ void ScheduleDAGSDNodes::AddSchedEdges() { ST.adjustSchedDependency(OpSU, SU, const_cast(dep)); } - if (!SU->addPred(dep) && !dep.isCtrl() && OpSU->NumRegDefsLeft > 0) { + if (!SU->addPred(dep) && !dep.isCtrl() && OpSU->NumRegDefsLeft > 1) { // Multiple register uses are combined in the same SUnit. For example, // we could have a set of glued nodes with all their defs consumed by // another set of glued nodes. Register pressure tracking sees this as // a single use, so to keep pressure balanced we reduce the defs. + // + // We can't tell (without more book-keeping) if this results from + // glued nodes or duplicate operands. As long as we don't reduce + // NumRegDefsLeft to zero, we handle the common cases well. --OpSU->NumRegDefsLeft; } } @@ -437,6 +482,10 @@ void ScheduleDAGSDNodes::BuildSchedGraph(AliasAnalysis *AA) { // Initialize NumNodeDefs for the current Node's opcode. void ScheduleDAGSDNodes::RegDefIter::InitNodeNumDefs() { + // Check for phys reg copy. + if (!Node) + return; + if (!Node->isMachineOpcode()) { if (Node->getOpcode() == ISD::CopyFromReg) NodeNumDefs = 1; @@ -499,6 +548,16 @@ void ScheduleDAGSDNodes::InitNumRegDefsLeft(SUnit *SU) { } void ScheduleDAGSDNodes::ComputeLatency(SUnit *SU) { + SDNode *N = SU->getNode(); + + // TokenFactor operands are considered zero latency, and some schedulers + // (e.g. Top-Down list) may rely on the fact that operand latency is nonzero + // whenever node latency is nonzero. + if (N && N->getOpcode() == ISD::TokenFactor) { + SU->Latency = 0; + return; + } + // Check to see if the scheduler cares about latencies. if (ForceUnitLatencies()) { SU->Latency = 1; @@ -506,7 +565,11 @@ void ScheduleDAGSDNodes::ComputeLatency(SUnit *SU) { } if (!InstrItins || InstrItins->isEmpty()) { - SU->Latency = 1; + if (N && N->isMachineOpcode() && + TII->isHighLatencyDef(N->getMachineOpcode())) + SU->Latency = HighLatencyCycles; + else + SU->Latency = 1; return; } @@ -573,7 +636,7 @@ namespace { }; } -/// ProcessSDDbgValues - Process SDDbgValues assoicated with this node. +/// ProcessSDDbgValues - Process SDDbgValues associated with this node. static void ProcessSDDbgValues(SDNode *N, SelectionDAG *DAG, InstrEmitter &Emitter, SmallVector, 32> &Orders, diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h index cc7310e4ca42..b5f68f3055cf 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h @@ -80,6 +80,12 @@ namespace llvm { /// flagged together nodes with a single SUnit. virtual void BuildSchedGraph(AliasAnalysis *AA); + /// InitVRegCycleFlag - Set isVRegCycle if this node's single use is + /// CopyToReg and its only active data operands are CopyFromReg within a + /// single block loop. + /// + void InitVRegCycleFlag(SUnit *SU); + /// InitNumRegDefsLeft - Determine the # of regs defined by this node. /// void InitNumRegDefsLeft(SUnit *SU); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 9120288921e2..c2711c8097d0 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1418,9 +1418,9 @@ SDValue SelectionDAG::getMDNode(const MDNode *MD) { /// getShiftAmountOperand - Return the specified value casted to /// the target's desired shift amount type. -SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) { +SDValue SelectionDAG::getShiftAmountOperand(EVT LHSTy, SDValue Op) { EVT OpTy = Op.getValueType(); - MVT ShTy = TLI.getShiftAmountTy(OpTy); + MVT ShTy = TLI.getShiftAmountTy(LHSTy); if (OpTy == ShTy || OpTy.isVector()) return Op; ISD::NodeType Opcode = OpTy.bitsGT(ShTy) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; @@ -2482,6 +2482,9 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, "Vector element count mismatch!"); if (OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ZERO_EXTEND) return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); + else if (OpOpcode == ISD::UNDEF) + // sext(undef) = 0, because the top bits will all be the same. + return getConstant(0, VT); break; case ISD::ZERO_EXTEND: assert(VT.isInteger() && Operand.getValueType().isInteger() && @@ -2496,6 +2499,9 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, if (OpOpcode == ISD::ZERO_EXTEND) // (zext (zext x)) -> (zext x) return getNode(ISD::ZERO_EXTEND, DL, VT, Operand.getNode()->getOperand(0)); + else if (OpOpcode == ISD::UNDEF) + // zext(undef) = 0, because the top bits will be zero. + return getConstant(0, VT); break; case ISD::ANY_EXTEND: assert(VT.isInteger() && Operand.getValueType().isInteger() && @@ -2512,6 +2518,8 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, OpOpcode == ISD::ANY_EXTEND) // (ext (zext x)) -> (zext x) and (ext (sext x)) -> (sext x) return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); + else if (OpOpcode == ISD::UNDEF) + return getUNDEF(VT); // (ext (trunx x)) -> x if (OpOpcode == ISD::TRUNCATE) { @@ -5904,7 +5912,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::UINT_TO_FP: return "uint_to_fp"; case ISD::FP_TO_SINT: return "fp_to_sint"; case ISD::FP_TO_UINT: return "fp_to_uint"; - case ISD::BITCAST: return "bit_convert"; + case ISD::BITCAST: return "bitcast"; case ISD::FP16_TO_FP32: return "fp16_to_fp32"; case ISD::FP32_TO_FP16: return "fp32_to_fp16"; @@ -6226,6 +6234,9 @@ static void printrWithDepthHelper(raw_ostream &OS, const SDNode *N, return; for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + // Don't follow chain operands. + if (N->getOperand(i).getValueType() == MVT::Other) + continue; OS << '\n'; printrWithDepthHelper(OS, N->getOperand(i).getNode(), G, depth-1, indent+2); } @@ -6238,7 +6249,7 @@ void SDNode::printrWithDepth(raw_ostream &OS, const SelectionDAG *G, void SDNode::printrFull(raw_ostream &OS, const SelectionDAG *G) const { // Don't print impossibly deep things. - printrWithDepth(OS, G, 100); + printrWithDepth(OS, G, 10); } void SDNode::dumprWithDepth(const SelectionDAG *G, unsigned depth) const { @@ -6247,7 +6258,7 @@ void SDNode::dumprWithDepth(const SelectionDAG *G, unsigned depth) const { void SDNode::dumprFull(const SelectionDAG *G) const { // Don't print impossibly deep things. - dumprWithDepth(G, 100); + dumprWithDepth(G, 10); } static void DumpNodes(const SDNode *N, unsigned indent, const SelectionDAG *G) { @@ -6311,7 +6322,8 @@ SDValue SelectionDAG::UnrollVectorOp(SDNode *N, unsigned ResNE) { case ISD::ROTL: case ISD::ROTR: Scalars.push_back(getNode(N->getOpcode(), dl, EltVT, Operands[0], - getShiftAmountOperand(Operands[1]))); + getShiftAmountOperand(Operands[0].getValueType(), + Operands[1]))); break; case ISD::SIGN_EXTEND_INREG: case ISD::FP_ROUND_INREG: { diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 48d9bbb5132e..b02a7b66c496 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -50,7 +50,6 @@ #include "llvm/Target/TargetIntrinsicInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -84,9 +83,7 @@ LimitFPPrecision("limit-float-precision", // %buffer = alloca [4096 x i8] // %data = load [4096 x i8]* %argPtr // store [4096 x i8] %data, [4096 x i8]* %buffer -static cl::opt -MaxParallelChains("dag-chain-limit", cl::desc("Max parallel isel dag chains"), - cl::init(64), cl::Hidden); +static const unsigned MaxParallelChains = 64; static SDValue getCopyFromPartsVector(SelectionDAG &DAG, DebugLoc DL, const SDValue *Parts, unsigned NumParts, @@ -1130,15 +1127,8 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) { else if (F->paramHasAttr(0, Attribute::ZExt)) ExtendKind = ISD::ZERO_EXTEND; - // FIXME: C calling convention requires the return type to be promoted - // to at least 32-bit. But this is not necessary for non-C calling - // conventions. The frontend should mark functions whose return values - // require promoting with signext or zeroext attributes. - if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) { - EVT MinVT = TLI.getRegisterType(*DAG.getContext(), MVT::i32); - if (VT.bitsLT(MinVT)) - VT = MinVT; - } + if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) + VT = TLI.getTypeForExtArgOrReturn(*DAG.getContext(), VT, ExtendKind); unsigned NumParts = TLI.getNumRegisters(*DAG.getContext(), VT); EVT PartVT = TLI.getRegisterType(*DAG.getContext(), VT); @@ -1153,9 +1143,9 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) { Flags.setInReg(); // Propagate extension type if any - if (F->paramHasAttr(0, Attribute::SExt)) + if (ExtendKind == ISD::SIGN_EXTEND) Flags.setSExt(); - else if (F->paramHasAttr(0, Attribute::ZExt)) + else if (ExtendKind == ISD::ZERO_EXTEND) Flags.setZExt(); for (unsigned i = 0; i < NumParts; ++i) { @@ -2029,9 +2019,13 @@ bool SelectionDAGBuilder::handleBTSplitSwitchCase(CaseRec& CR, APInt Range = ComputeRange(LEnd, RBegin); assert((Range - 2ULL).isNonNegative() && "Invalid case distance"); - double LDensity = (double)LSize.roundToDouble() / + // Use volatile double here to avoid excess precision issues on some hosts, + // e.g. that use 80-bit X87 registers. + volatile double LDensity = + (double)LSize.roundToDouble() / (LEnd - First + 1ULL).roundToDouble(); - double RDensity = (double)RSize.roundToDouble() / + volatile double RDensity = + (double)RSize.roundToDouble() / (Last - RBegin + 1ULL).roundToDouble(); double Metric = Range.logBase2()*(LDensity+RDensity); // Should always split in some non-trivial place @@ -4039,10 +4033,6 @@ SelectionDAGBuilder::EmitFuncArgumentDbgValue(const Value *V, MDNode *Variable, if (DV.isInlinedFnArgument(MF.getFunction())) return false; - MachineBasicBlock *MBB = FuncInfo.MBB; - if (MBB != &MF.front()) - return false; - unsigned Reg = 0; if (Arg->hasByValAttr()) { // Byval arguments' frame index is recorded during argument lowering. @@ -4413,7 +4403,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { } case Intrinsic::eh_sjlj_dispatch_setup: { DAG.setRoot(DAG.getNode(ISD::EH_SJLJ_DISPATCHSETUP, dl, MVT::Other, - getRoot(), getValue(I.getArgOperand(0)))); + getRoot())); return 0; } @@ -4682,9 +4672,22 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { case Intrinsic::flt_rounds: setValue(&I, DAG.getNode(ISD::FLT_ROUNDS_, dl, MVT::i32)); return 0; - case Intrinsic::trap: - DAG.setRoot(DAG.getNode(ISD::TRAP, dl,MVT::Other, getRoot())); + case Intrinsic::trap: { + StringRef TrapFuncName = getTrapFunctionName(); + if (TrapFuncName.empty()) { + DAG.setRoot(DAG.getNode(ISD::TRAP, dl,MVT::Other, getRoot())); + return 0; + } + TargetLowering::ArgListTy Args; + std::pair Result = + TLI.LowerCallTo(getRoot(), I.getType(), + false, false, false, false, 0, CallingConv::C, + /*isTailCall=*/false, /*isReturnValueUsed=*/true, + DAG.getExternalSymbol(TrapFuncName.data(), TLI.getPointerTy()), + Args, DAG, getCurDebugLoc()); + DAG.setRoot(Result.second); return 0; + } case Intrinsic::uadd_with_overflow: return implVisitAluOverflow(I, ISD::UADDO); case Intrinsic::sadd_with_overflow: @@ -4937,15 +4940,21 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), DAG.getVTList(&RetTys[0], RetTys.size()), &ReturnValues[0], ReturnValues.size())); - } - // As a special case, a null chain means that a tail call has been emitted and - // the DAG root is already updated. - if (Result.second.getNode()) - DAG.setRoot(Result.second); - else + // Assign order to nodes here. If the call does not produce a result, it won't + // be mapped to a SDNode and visit() will not assign it an order number. + if (!Result.second.getNode()) { + // As a special case, a null chain means that a tail call has been emitted and + // the DAG root is already updated. HasTailCall = true; + ++SDNodeOrder; + AssignOrderingToNode(DAG.getRoot().getNode()); + } else { + DAG.setRoot(Result.second); + ++SDNodeOrder; + AssignOrderingToNode(Result.second.getNode()); + } if (LandingPad) { // Insert a label at the end of the invoke call to mark the try range. This @@ -5211,12 +5220,11 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) { LowerCallTo(&I, Callee, I.isTailCall()); } -namespace llvm { +namespace { /// AsmOperandInfo - This contains information for each constraint that we are /// lowering. -class LLVM_LIBRARY_VISIBILITY SDISelAsmOperandInfo : - public TargetLowering::AsmOperandInfo { +class SDISelAsmOperandInfo : public TargetLowering::AsmOperandInfo { public: /// CallOperand - If this is the result output operand or a clobber /// this is null, otherwise it is the incoming operand to the CallInst. @@ -5304,7 +5312,7 @@ class LLVM_LIBRARY_VISIBILITY SDISelAsmOperandInfo : typedef SmallVector SDISelAsmOperandInfoVector; -} // end llvm namespace. +} // end anonymous namespace /// isAllocatableRegister - If the specified register is safe to allocate, /// i.e. it isn't a stack pointer or some other special register, return the @@ -5363,11 +5371,13 @@ isAllocatableRegister(unsigned Reg, MachineFunction &MF, /// OpInfo describes the operand. /// Input and OutputRegs are the set of already allocated physical registers. /// -void SelectionDAGBuilder:: -GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, - std::set &OutputRegs, - std::set &InputRegs) { - LLVMContext &Context = FuncInfo.Fn->getContext(); +static void GetRegistersForValue(SelectionDAG &DAG, + const TargetLowering &TLI, + DebugLoc DL, + SDISelAsmOperandInfo &OpInfo, + std::set &OutputRegs, + std::set &InputRegs) { + LLVMContext &Context = *DAG.getContext(); // Compute whether this value requires an input register, an output register, // or both. @@ -5413,7 +5423,7 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, // vector types). EVT RegVT = *PhysReg.second->vt_begin(); if (RegVT.getSizeInBits() == OpInfo.ConstraintVT.getSizeInBits()) { - OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, getCurDebugLoc(), + OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, DL, RegVT, OpInfo.CallOperand); OpInfo.ConstraintVT = RegVT; } else if (RegVT.isInteger() && OpInfo.ConstraintVT.isFloatingPoint()) { @@ -5423,7 +5433,7 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, // machine. RegVT = EVT::getIntegerVT(Context, OpInfo.ConstraintVT.getSizeInBits()); - OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, getCurDebugLoc(), + OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, DL, RegVT, OpInfo.CallOperand); OpInfo.ConstraintVT = RegVT; } @@ -5694,7 +5704,8 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { // If this constraint is for a specific register, allocate it before // anything else. if (OpInfo.ConstraintType == TargetLowering::C_Register) - GetRegistersForValue(OpInfo, OutputRegs, InputRegs); + GetRegistersForValue(DAG, TLI, getCurDebugLoc(), OpInfo, OutputRegs, + InputRegs); } // Second pass - Loop over all of the operands, assigning virtual or physregs @@ -5705,7 +5716,8 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { // C_Register operands have already been allocated, Other/Memory don't need // to be. if (OpInfo.ConstraintType == TargetLowering::C_RegisterClass) - GetRegistersForValue(OpInfo, OutputRegs, InputRegs); + GetRegistersForValue(DAG, TLI, getCurDebugLoc(), OpInfo, OutputRegs, + InputRegs); } // AsmNodeOperands - The operands for the ISD::INLINEASM node. @@ -6181,7 +6193,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, // For a function returning void, there is no return value. We can't create // such a node, so we just return a null return value in that case. In - // that case, nothing will actualy look at the value. + // that case, nothing will actually look at the value. if (ReturnValues.empty()) return std::make_pair(SDValue(), Chain); @@ -6397,7 +6409,7 @@ void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) { SDB->setValue(I, Res); // If this argument is live outside of the entry block, insert a copy from - // whereever we got it to the vreg that other BB's will reference it as. + // wherever we got it to the vreg that other BB's will reference it as. SDB->CopyToExportRegsIfNeeded(I); } } diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 8f466d913bbb..a689b76cdc88 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -23,7 +23,6 @@ #include "llvm/Support/CallSite.h" #include "llvm/Support/ErrorHandling.h" #include -#include namespace llvm { @@ -60,7 +59,6 @@ class MDNode; class PHINode; class PtrToIntInst; class ReturnInst; -class SDISelAsmOperandInfo; class SDDbgValue; class SExtInst; class SelectInst; @@ -380,10 +378,6 @@ class SelectionDAGBuilder { assert(N.getNode() == 0 && "Already set a value for this node!"); N = NewN; } - - void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, - std::set &OutputRegs, - std::set &InputRegs); void FindMergedConditions(const Value *Cond, MachineBasicBlock *TBB, MachineBasicBlock *FBB, MachineBasicBlock *CurBB, diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 68ba966d268a..fdf3767d8c65 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -421,10 +421,9 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { return true; } -void -SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin, - BasicBlock::const_iterator End, - bool &HadTailCall) { +void SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin, + BasicBlock::const_iterator End, + bool &HadTailCall) { // Lower all of the non-terminator instructions. If a call is emitted // as a tail call, cease emitting nodes for this block. Terminators // are handled below. @@ -438,7 +437,6 @@ SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin, // Final step, emit the lowered DAG as machine code. CodeGenAndEmitDAG(); - return; } void SelectionDAGISel::ComputeLiveOutVRegInfo() { @@ -489,13 +487,19 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { if (TimePassesIsEnabled) GroupName = "Instruction Selection and Scheduling"; std::string BlockName; + int BlockNumber = -1; +#ifdef NDEBUG if (ViewDAGCombine1 || ViewLegalizeTypesDAGs || ViewLegalizeDAGs || ViewDAGCombine2 || ViewDAGCombineLT || ViewISelDAGs || ViewSchedDAGs || ViewSUnitDAGs) +#endif + { + BlockNumber = FuncInfo->MBB->getNumber(); BlockName = MF->getFunction()->getNameStr() + ":" + FuncInfo->MBB->getBasicBlock()->getNameStr(); - - DEBUG(dbgs() << "Initial selection DAG:\n"; CurDAG->dump()); + } + DEBUG(dbgs() << "Initial selection DAG: BB#" << BlockNumber + << " '" << BlockName << "'\n"; CurDAG->dump()); if (ViewDAGCombine1) CurDAG->viewGraph("dag-combine1 input for " + BlockName); @@ -505,7 +509,8 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Combine(Unrestricted, *AA, OptLevel); } - DEBUG(dbgs() << "Optimized lowered selection DAG:\n"; CurDAG->dump()); + DEBUG(dbgs() << "Optimized lowered selection DAG: BB#" << BlockNumber + << " '" << BlockName << "'\n"; CurDAG->dump()); // Second step, hack on the DAG until it only uses operations and types that // the target supports. @@ -518,7 +523,8 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { Changed = CurDAG->LegalizeTypes(); } - DEBUG(dbgs() << "Type-legalized selection DAG:\n"; CurDAG->dump()); + DEBUG(dbgs() << "Type-legalized selection DAG: BB#" << BlockNumber + << " '" << BlockName << "'\n"; CurDAG->dump()); if (Changed) { if (ViewDAGCombineLT) @@ -531,8 +537,8 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Combine(NoIllegalTypes, *AA, OptLevel); } - DEBUG(dbgs() << "Optimized type-legalized selection DAG:\n"; - CurDAG->dump()); + DEBUG(dbgs() << "Optimized type-legalized selection DAG: BB#" << BlockNumber + << " '" << BlockName << "'\n"; CurDAG->dump()); } { @@ -556,8 +562,8 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Combine(NoIllegalOperations, *AA, OptLevel); } - DEBUG(dbgs() << "Optimized vector-legalized selection DAG:\n"; - CurDAG->dump()); + DEBUG(dbgs() << "Optimized vector-legalized selection DAG: BB#" + << BlockNumber << " '" << BlockName << "'\n"; CurDAG->dump()); } if (ViewLegalizeDAGs) CurDAG->viewGraph("legalize input for " + BlockName); @@ -567,7 +573,8 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Legalize(OptLevel); } - DEBUG(dbgs() << "Legalized selection DAG:\n"; CurDAG->dump()); + DEBUG(dbgs() << "Legalized selection DAG: BB#" << BlockNumber + << " '" << BlockName << "'\n"; CurDAG->dump()); if (ViewDAGCombine2) CurDAG->viewGraph("dag-combine2 input for " + BlockName); @@ -577,7 +584,8 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Combine(NoIllegalOperations, *AA, OptLevel); } - DEBUG(dbgs() << "Optimized legalized selection DAG:\n"; CurDAG->dump()); + DEBUG(dbgs() << "Optimized legalized selection DAG: BB#" << BlockNumber + << " '" << BlockName << "'\n"; CurDAG->dump()); if (OptLevel != CodeGenOpt::None) ComputeLiveOutVRegInfo(); @@ -591,7 +599,8 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { DoInstructionSelection(); } - DEBUG(dbgs() << "Selected selection DAG:\n"; CurDAG->dump()); + DEBUG(dbgs() << "Selected selection DAG: BB#" << BlockNumber + << " '" << BlockName << "'\n"; CurDAG->dump()); if (ViewSchedDAGs) CurDAG->viewGraph("scheduler input for " + BlockName); @@ -632,7 +641,9 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { } void SelectionDAGISel::DoInstructionSelection() { - DEBUG(errs() << "===== Instruction selection begins:\n"); + DEBUG(errs() << "===== Instruction selection begins: BB#" + << FuncInfo->MBB->getNumber() + << " '" << FuncInfo->MBB->getName() << "'\n"); PreprocessISelDAG(); @@ -735,16 +746,49 @@ void SelectionDAGISel::PrepareEHLandingPad() { - +/// TryToFoldFastISelLoad - We're checking to see if we can fold the specified +/// load into the specified FoldInst. Note that we could have a sequence where +/// multiple LLVM IR instructions are folded into the same machineinstr. For +/// example we could have: +/// A: x = load i32 *P +/// B: y = icmp A, 42 +/// C: br y, ... +/// +/// In this scenario, LI is "A", and FoldInst is "C". We know about "B" (and +/// any other folded instructions) because it is between A and C. +/// +/// If we succeed in folding the load into the operation, return true. +/// bool SelectionDAGISel::TryToFoldFastISelLoad(const LoadInst *LI, + const Instruction *FoldInst, FastISel *FastIS) { + // We know that the load has a single use, but don't know what it is. If it + // isn't one of the folded instructions, then we can't succeed here. Handle + // this by scanning the single-use users of the load until we get to FoldInst. + unsigned MaxUsers = 6; // Don't scan down huge single-use chains of instrs. + + const Instruction *TheUser = LI->use_back(); + while (TheUser != FoldInst && // Scan up until we find FoldInst. + // Stay in the right block. + TheUser->getParent() == FoldInst->getParent() && + --MaxUsers) { // Don't scan too far. + // If there are multiple or no uses of this instruction, then bail out. + if (!TheUser->hasOneUse()) + return false; + + TheUser = TheUser->use_back(); + } + // Don't try to fold volatile loads. Target has to deal with alignment // constraints. if (LI->isVolatile()) return false; - // Figure out which vreg this is going into. + // Figure out which vreg this is going into. If there is no assigned vreg yet + // then there actually was no reference to it. Perhaps the load is referenced + // by a dead instruction. unsigned LoadReg = FastIS->getRegForValue(LI); - assert(LoadReg && "Load isn't already assigned a vreg? "); + if (LoadReg == 0) + return false; // Check to see what the uses of this vreg are. If it has no uses, or more // than one use (at the machine instr level) then we can't fold it. @@ -764,7 +808,7 @@ bool SelectionDAGISel::TryToFoldFastISelLoad(const LoadInst *LI, "The only use of the vreg must be a use, we haven't emitted the def!"); MachineInstr *User = &*RI; - + // Set the insertion point properly. Folding the load can cause generation of // other random instructions (like sign extends) for addressing modes, make // sure they get inserted in a logical place before the new instruction. @@ -817,6 +861,17 @@ static void CheckLineNumbers(const MachineBasicBlock *MBB) { } #endif +/// isFoldedOrDeadInstruction - Return true if the specified instruction is +/// side-effect free and is either dead or folded into a generated instruction. +/// Return false if it needs to be emitted. +static bool isFoldedOrDeadInstruction(const Instruction *I, + FunctionLoweringInfo *FuncInfo) { + return !I->mayWriteToMemory() && // Side-effecting instructions aren't folded. + !isa(I) && // Terminators aren't folded. + !isa(I) && // Debug instructions aren't folded. + !FuncInfo->isExportedInst(I); // Exported instrs must be computed. +} + void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { // Initialize the Fast-ISel state, if needed. FastISel *FastIS = 0; @@ -843,15 +898,13 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { } if (AllPredsVisited) { - for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end(); - I != E && isa(I); ++I) { + for (BasicBlock::const_iterator I = LLVMBB->begin(); + isa(I); ++I) FuncInfo->ComputePHILiveOutRegInfo(cast(I)); - } } else { - for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end(); - I != E && isa(I); ++I) { + for (BasicBlock::const_iterator I = LLVMBB->begin(); + isa(I); ++I) FuncInfo->InvalidatePHILiveOutRegInfo(cast(I)); - } } FuncInfo->VisitedBBs.insert(LLVMBB); @@ -899,10 +952,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { const Instruction *Inst = llvm::prior(BI); // If we no longer require this instruction, skip it. - if (!Inst->mayWriteToMemory() && - !isa(Inst) && - !isa(Inst) && - !FuncInfo->isExportedInst(Inst)) + if (isFoldedOrDeadInstruction(Inst, FuncInfo)) continue; // Bottom-up: reset the insert pos at the top, after any local-value @@ -911,16 +961,20 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { // Try to select the instruction with FastISel. if (FastIS->SelectInstruction(Inst)) { - // If fast isel succeeded, check to see if there is a single-use - // non-volatile load right before the selected instruction, and see if - // the load is used by the instruction. If so, try to fold it. - const Instruction *BeforeInst = 0; - if (Inst != Begin) - BeforeInst = llvm::prior(llvm::prior(BI)); - if (BeforeInst && isa(BeforeInst) && - BeforeInst->hasOneUse() && *BeforeInst->use_begin() == Inst && - TryToFoldFastISelLoad(cast(BeforeInst), FastIS)) - --BI; // If we succeeded, don't re-select the load. + // If fast isel succeeded, skip over all the folded instructions, and + // then see if there is a load right before the selected instructions. + // Try to fold the load if so. + const Instruction *BeforeInst = Inst; + while (BeforeInst != Begin) { + BeforeInst = llvm::prior(BasicBlock::const_iterator(BeforeInst)); + if (!isFoldedOrDeadInstruction(BeforeInst, FuncInfo)) + break; + } + if (BeforeInst != Inst && isa(BeforeInst) && + BeforeInst->hasOneUse() && + TryToFoldFastISelLoad(cast(BeforeInst), Inst, FastIS)) + // If we succeeded, don't re-select the load. + BI = llvm::next(BasicBlock::const_iterator(BeforeInst)); continue; } @@ -974,11 +1028,13 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { else ++NumFastIselBlocks; - // Run SelectionDAG instruction selection on the remainder of the block - // not handled by FastISel. If FastISel is not run, this is the entire - // block. - bool HadTailCall; - SelectBasicBlock(Begin, BI, HadTailCall); + if (Begin != BI) { + // Run SelectionDAG instruction selection on the remainder of the block + // not handled by FastISel. If FastISel is not run, this is the entire + // block. + bool HadTailCall; + SelectBasicBlock(Begin, BI, HadTailCall); + } FinishBasicBlock(); FuncInfo->PHINodesToUpdate.clear(); @@ -2392,6 +2448,18 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, CurDAG->getRegister(RegNo, VT), (SDNode*)0)); continue; } + case OPC_EmitRegister2: { + // For targets w/ more than 256 register names, the register enum + // values are stored in two bytes in the matcher table (just like + // opcodes). + MVT::SimpleValueType VT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + unsigned RegNo = MatcherTable[MatcherIndex++]; + RegNo |= MatcherTable[MatcherIndex++] << 8; + RecordedNodes.push_back(std::pair( + CurDAG->getRegister(RegNo, VT), (SDNode*)0)); + continue; + } case OPC_EmitConvertToTarget: { // Convert from IMM/FPIMM to target version. diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp index 76eb9453561e..cd1647b17b9b 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp @@ -90,7 +90,8 @@ namespace llvm { /// If you want to override the dot attributes printed for a particular /// edge, override this method. template - static std::string getEdgeAttributes(const void *Node, EdgeIter EI) { + static std::string getEdgeAttributes(const void *Node, EdgeIter EI, + const SelectionDAG *Graph) { SDValue Op = EI.getNode()->getOperand(EI.getOperand()); EVT VT = Op.getValueType(); if (VT == MVT::Glue) diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 35b847ccabfb..15606af787f8 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -93,6 +93,19 @@ static void InitLibcallNames(const char **Names) { Names[RTLIB::UREM_I32] = "__umodsi3"; Names[RTLIB::UREM_I64] = "__umoddi3"; Names[RTLIB::UREM_I128] = "__umodti3"; + + // These are generally not available. + Names[RTLIB::SDIVREM_I8] = 0; + Names[RTLIB::SDIVREM_I16] = 0; + Names[RTLIB::SDIVREM_I32] = 0; + Names[RTLIB::SDIVREM_I64] = 0; + Names[RTLIB::SDIVREM_I128] = 0; + Names[RTLIB::UDIVREM_I8] = 0; + Names[RTLIB::UDIVREM_I16] = 0; + Names[RTLIB::UDIVREM_I32] = 0; + Names[RTLIB::UDIVREM_I64] = 0; + Names[RTLIB::UDIVREM_I128] = 0; + Names[RTLIB::NEG_I32] = "__negsi2"; Names[RTLIB::NEG_I64] = "__negdi2"; Names[RTLIB::ADD_F32] = "__addsf3"; @@ -1665,6 +1678,13 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op, ConstantSDNode *ShAmt = dyn_cast(In.getOperand(1)); if (!ShAmt) break; + SDValue Shift = In.getOperand(1); + if (TLO.LegalTypes()) { + uint64_t ShVal = ShAmt->getZExtValue(); + Shift = + TLO.DAG.getConstant(ShVal, getShiftAmountTy(Op.getValueType())); + } + APInt HighBits = APInt::getHighBitsSet(OperandBitWidth, OperandBitWidth - BitWidth); HighBits = HighBits.lshr(ShAmt->getZExtValue()).trunc(BitWidth); @@ -1678,7 +1698,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op, return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl, Op.getValueType(), NewTrunc, - In.getOperand(1))); + Shift)); } break; } @@ -1829,7 +1849,6 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, bool foldBooleans, DAGCombinerInfo &DCI, DebugLoc dl) const { SelectionDAG &DAG = DCI.DAG; - LLVMContext &Context = *DAG.getContext(); // These setcc operations always fold. switch (Cond) { @@ -1840,12 +1859,11 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, case ISD::SETTRUE2: return DAG.getConstant(1, VT); } - if (isa(N0.getNode())) { - // Ensure that the constant occurs on the RHS, and fold constant - // comparisons. + // Ensure that the constant occurs on the RHS, and fold constant + // comparisons. + if (isa(N0.getNode())) return DAG.getSetCC(dl, VT, N1, N0, ISD::getSetCCSwappedOperands(Cond)); - } - + if (ConstantSDNode *N1C = dyn_cast(N1.getNode())) { const APInt &C1 = N1C->getAPIntValue(); @@ -1898,6 +1916,42 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, // TODO: (ctpop x) == 1 -> x && (x & x-1) == 0 iff ctpop is illegal. } + // (zext x) == C --> x == (trunc C) + if (DCI.isBeforeLegalize() && N0->hasOneUse() && + (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { + unsigned MinBits = N0.getValueSizeInBits(); + SDValue PreZExt; + if (N0->getOpcode() == ISD::ZERO_EXTEND) { + // ZExt + MinBits = N0->getOperand(0).getValueSizeInBits(); + PreZExt = N0->getOperand(0); + } else if (N0->getOpcode() == ISD::AND) { + // DAGCombine turns costly ZExts into ANDs + if (ConstantSDNode *C = dyn_cast(N0->getOperand(1))) + if ((C->getAPIntValue()+1).isPowerOf2()) { + MinBits = C->getAPIntValue().countTrailingOnes(); + PreZExt = N0->getOperand(0); + } + } else if (LoadSDNode *LN0 = dyn_cast(N0)) { + // ZEXTLOAD + if (LN0->getExtensionType() == ISD::ZEXTLOAD) { + MinBits = LN0->getMemoryVT().getSizeInBits(); + PreZExt = N0; + } + } + + // Make sure we're not loosing bits from the constant. + if (MinBits < C1.getBitWidth() && MinBits > C1.getActiveBits()) { + EVT MinVT = EVT::getIntegerVT(*DAG.getContext(), MinBits); + if (isTypeDesirableForOp(ISD::SETCC, MinVT)) { + // Will get folded away. + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, dl, MinVT, PreZExt); + SDValue C = DAG.getConstant(C1.trunc(MinBits), MinVT); + return DAG.getSetCC(dl, VT, Trunc, C, Cond); + } + } + } + // If the LHS is '(and load, const)', the RHS is 0, // the test is for equality or unsigned, and all 1 bits of the const are // in the same partial word, see if we can shorten the load. @@ -1936,7 +1990,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, } } if (bestWidth) { - EVT newVT = EVT::getIntegerVT(Context, bestWidth); + EVT newVT = EVT::getIntegerVT(*DAG.getContext(), bestWidth); if (newVT.isRound()) { EVT PtrType = Lod->getOperand(1).getValueType(); SDValue Ptr = Lod->getBasePtr(); @@ -3174,26 +3228,39 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG, // FIXME: We should use a narrower constant when the upper // bits are known to be zero. - ConstantSDNode *N1C = cast(N->getOperand(1)); - APInt::mu magics = N1C->getAPIntValue().magicu(); + const APInt &N1C = cast(N->getOperand(1))->getAPIntValue(); + APInt::mu magics = N1C.magicu(); + + SDValue Q = N->getOperand(0); + + // If the divisor is even, we can avoid using the expensive fixup by shifting + // the divided value upfront. + if (magics.a != 0 && !N1C[0]) { + unsigned Shift = N1C.countTrailingZeros(); + Q = DAG.getNode(ISD::SRL, dl, VT, Q, + DAG.getConstant(Shift, getShiftAmountTy(Q.getValueType()))); + if (Created) + Created->push_back(Q.getNode()); + + // Get magic number for the shifted divisor. + magics = N1C.lshr(Shift).magicu(Shift); + assert(magics.a == 0 && "Should use cheap fixup now"); + } // Multiply the numerator (operand 0) by the magic value // FIXME: We should support doing a MUL in a wider type - SDValue Q; if (isOperationLegalOrCustom(ISD::MULHU, VT)) - Q = DAG.getNode(ISD::MULHU, dl, VT, N->getOperand(0), - DAG.getConstant(magics.m, VT)); + Q = DAG.getNode(ISD::MULHU, dl, VT, Q, DAG.getConstant(magics.m, VT)); else if (isOperationLegalOrCustom(ISD::UMUL_LOHI, VT)) - Q = SDValue(DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(VT, VT), - N->getOperand(0), - DAG.getConstant(magics.m, VT)).getNode(), 1); + Q = SDValue(DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(VT, VT), Q, + DAG.getConstant(magics.m, VT)).getNode(), 1); else return SDValue(); // No mulhu or equvialent if (Created) Created->push_back(Q.getNode()); if (magics.a == 0) { - assert(magics.s < N1C->getAPIntValue().getBitWidth() && + assert(magics.s < N1C.getBitWidth() && "We shouldn't generate an undefined shift!"); return DAG.getNode(ISD::SRL, dl, VT, Q, DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType()))); diff --git a/contrib/llvm/lib/CodeGen/ShrinkWrapping.cpp b/contrib/llvm/lib/CodeGen/ShrinkWrapping.cpp index 7b5bca495206..160f38f69236 100644 --- a/contrib/llvm/lib/CodeGen/ShrinkWrapping.cpp +++ b/contrib/llvm/lib/CodeGen/ShrinkWrapping.cpp @@ -277,7 +277,7 @@ void PEI::calculateAnticAvail(MachineFunction &Fn) { // Initialize data flow sets. clearAnticAvailSets(); - // Calulate Antic{In,Out} and Avail{In,Out} iteratively on the MCFG. + // Calculate Antic{In,Out} and Avail{In,Out} iteratively on the MCFG. bool changed = true; unsigned iterations = 0; while (changed) { diff --git a/contrib/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp b/contrib/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp index 2843c1a5b6d8..35b8e14ddc61 100644 --- a/contrib/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/contrib/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -104,6 +104,18 @@ void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); } +void SimpleRegisterCoalescing::markAsJoined(MachineInstr *CopyMI) { + /// Joined copies are not deleted immediately, but kept in JoinedCopies. + JoinedCopies.insert(CopyMI); + + /// Mark all register operands of CopyMI as so they won't affect dead + /// code elimination. + for (MachineInstr::mop_iterator I = CopyMI->operands_begin(), + E = CopyMI->operands_end(); I != E; ++I) + if (I->isReg()) + I->setIsUndef(true); +} + /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy with IntA /// being the source and IntB being the dest, thus this defines a value number /// in IntB. If the source value number (in IntA) is defined by a copy from B, @@ -196,15 +208,14 @@ bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(const CoalescerPair &CP, if (ValLR+1 != BLR) return false; // If a live interval is a physical register, conservatively check if any - // of its sub-registers is overlapping the live interval of the virtual - // register. If so, do not coalesce. - if (TargetRegisterInfo::isPhysicalRegister(IntB.reg) && - *tri_->getSubRegisters(IntB.reg)) { - for (const unsigned* SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) - if (li_->hasInterval(*SR) && IntA.overlaps(li_->getInterval(*SR))) { + // of its aliases is overlapping the live interval of the virtual register. + // If so, do not coalesce. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { + for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) + if (li_->hasInterval(*AS) && IntA.overlaps(li_->getInterval(*AS))) { DEBUG({ - dbgs() << "\t\tInterfere with sub-register "; - li_->getInterval(*SR).print(dbgs(), tri_); + dbgs() << "\t\tInterfere with alias "; + li_->getInterval(*AS).print(dbgs(), tri_); }); return false; } @@ -471,7 +482,7 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(const CoalescerPair &CP, DEBUG(dbgs() << "\t\tnoop: " << DefIdx << '\t' << *UseMI); assert(DVNI->def == DefIdx); BValNo = IntB.MergeValueNumberInto(BValNo, DVNI); - JoinedCopies.insert(UseMI); + markAsJoined(UseMI); } // Extend BValNo by merging in IntA live ranges of AValNo. Val# definition @@ -901,6 +912,58 @@ SimpleRegisterCoalescing::ShortenDeadCopySrcLiveRange(LiveInterval &li, return removeIntervalIfEmpty(li, li_, tri_); } +/// shouldJoinPhys - Return true if a copy involving a physreg should be joined. +/// We need to be careful about coalescing a source physical register with a +/// virtual register. Once the coalescing is done, it cannot be broken and these +/// are not spillable! If the destination interval uses are far away, think +/// twice about coalescing them! +bool SimpleRegisterCoalescing::shouldJoinPhys(CoalescerPair &CP) { + bool Allocatable = li_->isAllocatable(CP.getDstReg()); + LiveInterval &JoinVInt = li_->getInterval(CP.getSrcReg()); + + /// Always join simple intervals that are defined by a single copy from a + /// reserved register. This doesn't increase register pressure, so it is + /// always beneficial. + if (!Allocatable && CP.isFlipped() && JoinVInt.containsOneValue()) + return true; + + if (DisablePhysicalJoin) { + DEBUG(dbgs() << "\tPhysreg joins disabled.\n"); + return false; + } + + // Only coalesce to allocatable physreg, we don't want to risk modifying + // reserved registers. + if (!Allocatable) { + DEBUG(dbgs() << "\tRegister is an unallocatable physreg.\n"); + return false; // Not coalescable. + } + + // Don't join with physregs that have a ridiculous number of live + // ranges. The data structure performance is really bad when that + // happens. + if (li_->hasInterval(CP.getDstReg()) && + li_->getInterval(CP.getDstReg()).ranges.size() > 1000) { + ++numAborts; + DEBUG(dbgs() + << "\tPhysical register live interval too complicated, abort!\n"); + return false; + } + + // FIXME: Why are we skipping this test for partial copies? + // CodeGen/X86/phys_subreg_coalesce-3.ll needs it. + if (!CP.isPartial()) { + const TargetRegisterClass *RC = mri_->getRegClass(CP.getSrcReg()); + unsigned Threshold = allocatableRCRegs_[RC].count() * 2; + unsigned Length = li_->getApproximateInstructionCount(JoinVInt); + if (Length > Threshold) { + ++numAborts; + DEBUG(dbgs() << "\tMay tie down a physical register, abort!\n"); + return false; + } + } + return true; +} /// isWinToJoinCrossClass - Return true if it's profitable to coalesce /// two virtual registers from different register classes. @@ -973,27 +1036,25 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { return false; // Not coalescable. } - if (DisablePhysicalJoin && CP.isPhys()) { - DEBUG(dbgs() << "\tPhysical joins disabled.\n"); - return false; - } - - DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), tri_)); + DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), tri_) + << " with " << PrintReg(CP.getDstReg(), tri_, CP.getSubIdx()) + << "\n"); // Enforce policies. if (CP.isPhys()) { - DEBUG(dbgs() <<" with physreg " << PrintReg(CP.getDstReg(), tri_) << "\n"); - // Only coalesce to allocatable physreg. - if (!li_->isAllocatable(CP.getDstReg())) { - DEBUG(dbgs() << "\tRegister is an unallocatable physreg.\n"); - return false; // Not coalescable. + if (!shouldJoinPhys(CP)) { + // Before giving up coalescing, if definition of source is defined by + // trivial computation, try rematerializing it. + if (!CP.isFlipped() && + ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, + CP.getDstReg(), 0, CopyMI)) + return true; + return false; } } else { - DEBUG(dbgs() << " with " << PrintReg(CP.getDstReg(), tri_, CP.getSubIdx()) - << " to " << CP.getNewRC()->getName() << "\n"); - // Avoid constraining virtual register regclass too much. if (CP.isCrossClass()) { + DEBUG(dbgs() << "\tCross-class to " << CP.getNewRC()->getName() << ".\n"); if (DisableCrossClassJoin) { DEBUG(dbgs() << "\tCross-class joins disabled.\n"); return false; @@ -1002,8 +1063,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { mri_->getRegClass(CP.getSrcReg()), mri_->getRegClass(CP.getDstReg()), CP.getNewRC())) { - DEBUG(dbgs() << "\tAvoid coalescing to constrained register class: " - << CP.getNewRC()->getName() << ".\n"); + DEBUG(dbgs() << "\tAvoid coalescing to constrained register class.\n"); Again = true; // May be possible to coalesce later. return false; } @@ -1015,45 +1075,6 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { CP.flip(); } - // We need to be careful about coalescing a source physical register with a - // virtual register. Once the coalescing is done, it cannot be broken and - // these are not spillable! If the destination interval uses are far away, - // think twice about coalescing them! - // FIXME: Why are we skipping this test for partial copies? - // CodeGen/X86/phys_subreg_coalesce-3.ll needs it. - if (!CP.isPartial() && CP.isPhys()) { - LiveInterval &JoinVInt = li_->getInterval(CP.getSrcReg()); - - // Don't join with physregs that have a ridiculous number of live - // ranges. The data structure performance is really bad when that - // happens. - if (li_->hasInterval(CP.getDstReg()) && - li_->getInterval(CP.getDstReg()).ranges.size() > 1000) { - ++numAborts; - DEBUG(dbgs() - << "\tPhysical register live interval too complicated, abort!\n"); - return false; - } - - const TargetRegisterClass *RC = mri_->getRegClass(CP.getSrcReg()); - unsigned Threshold = allocatableRCRegs_[RC].count() * 2; - unsigned Length = li_->getApproximateInstructionCount(JoinVInt); - if (Length > Threshold && - std::distance(mri_->use_nodbg_begin(CP.getSrcReg()), - mri_->use_nodbg_end()) * Threshold < Length) { - // Before giving up coalescing, if definition of source is defined by - // trivial computation, try rematerializing it. - if (!CP.isFlipped() && - ReMaterializeTrivialDef(JoinVInt, true, CP.getDstReg(), 0, CopyMI)) - return true; - - ++numAborts; - DEBUG(dbgs() << "\tMay tie down a physical register, abort!\n"); - Again = true; // May be possible to coalesce later. - return false; - } - } - // Okay, attempt to join these two intervals. On failure, this returns false. // Otherwise, if one of the intervals being joined is a physreg, this method // always canonicalizes DstInt to be it. The output "SrcInt" will not have @@ -1072,7 +1093,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { if (!CP.isPartial()) { if (AdjustCopiesBackFrom(CP, CopyMI) || RemoveCopyByCommutingDef(CP, CopyMI)) { - JoinedCopies.insert(CopyMI); + markAsJoined(CopyMI); DEBUG(dbgs() << "\tTrivial!\n"); return true; } @@ -1092,7 +1113,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { } // Remember to delete the copy instruction. - JoinedCopies.insert(CopyMI); + markAsJoined(CopyMI); UpdateRegDefsUses(CP); @@ -1568,9 +1589,7 @@ SimpleRegisterCoalescing::lastRegisterUse(SlotIndex Start, if (UseMI->isIdentityCopy()) continue; SlotIndex Idx = li_->getInstructionIndex(UseMI); - // FIXME: Should this be Idx != UseIdx? SlotIndex() will return something - // that compares higher than any other interval. - if (Idx >= Start && Idx < End && Idx >= UseIdx) { + if (Idx >= Start && Idx < End && (!UseIdx.isValid() || Idx >= UseIdx)) { LastUse = &Use; UseIdx = Idx.getUseIndex(); } diff --git a/contrib/llvm/lib/CodeGen/SimpleRegisterCoalescing.h b/contrib/llvm/lib/CodeGen/SimpleRegisterCoalescing.h index 56703dfa2ddd..65cf542836dd 100644 --- a/contrib/llvm/lib/CodeGen/SimpleRegisterCoalescing.h +++ b/contrib/llvm/lib/CodeGen/SimpleRegisterCoalescing.h @@ -68,16 +68,6 @@ namespace llvm { initializeSimpleRegisterCoalescingPass(*PassRegistry::getPassRegistry()); } - struct InstrSlots { - enum { - LOAD = 0, - USE = 1, - DEF = 2, - STORE = 3, - NUM = 4 - }; - }; - virtual void getAnalysisUsage(AnalysisUsage &AU) const; virtual void releaseMemory(); @@ -148,6 +138,9 @@ namespace llvm { unsigned DstReg, unsigned DstSubIdx, MachineInstr *CopyMI); + /// shouldJoinPhys - Return true if a physreg copy should be joined. + bool shouldJoinPhys(CoalescerPair &CP); + /// isWinToJoinCrossClass - Return true if it's profitable to coalesce /// two virtual registers from different register classes. bool isWinToJoinCrossClass(unsigned SrcReg, @@ -186,6 +179,9 @@ namespace llvm { /// cycles Start and End or NULL if there are no uses. MachineOperand *lastRegisterUse(SlotIndex Start, SlotIndex End, unsigned Reg, SlotIndex &LastUseIdx) const; + + /// markAsJoined - Remember that CopyMI has already been joined. + void markAsJoined(MachineInstr *CopyMI); }; } // End llvm namespace diff --git a/contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp b/contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp index 13e1454fa5f3..43904a76cf13 100644 --- a/contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp +++ b/contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp @@ -442,25 +442,18 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { BasicBlock *DispatchBlock = BasicBlock::Create(F.getContext(), "eh.sjlj.setjmp.catch", &F); - // Add a call to dispatch_setup at the start of the dispatch block. This is - // expanded to any target-specific setup that needs to be done. - Value *SetupArg = - CastInst::Create(Instruction::BitCast, FunctionContext, - Type::getInt8PtrTy(F.getContext()), "", - DispatchBlock); - CallInst::Create(DispatchSetupFn, SetupArg, "", DispatchBlock); - // Insert a load of the callsite in the dispatch block, and a switch on its - // value. By default, we go to a block that just does an unwind (which is the - // correct action for a standard call). - BasicBlock *UnwindBlock = - BasicBlock::Create(F.getContext(), "unwindbb", &F); - Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBlock)); + // value. By default, we issue a trap statement. + BasicBlock *TrapBlock = + BasicBlock::Create(F.getContext(), "trapbb", &F); + CallInst::Create(Intrinsic::getDeclaration(F.getParent(), Intrinsic::trap), + "", TrapBlock); + new UnreachableInst(F.getContext(), TrapBlock); Value *DispatchLoad = new LoadInst(CallSite, "invoke.num", true, DispatchBlock); SwitchInst *DispatchSwitch = - SwitchInst::Create(DispatchLoad, UnwindBlock, Invokes.size(), + SwitchInst::Create(DispatchLoad, TrapBlock, Invokes.size(), DispatchBlock); // Split the entry block to insert the conditional branch for the setjmp. BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(), @@ -524,6 +517,11 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { Value *DispatchVal = CallInst::Create(BuiltinSetjmpFn, SetjmpArg, "dispatch", EntryBB->getTerminator()); + + // Add a call to dispatch_setup after the setjmp call. This is expanded to any + // target-specific setup that needs to be done. + CallInst::Create(DispatchSetupFn, "", EntryBB->getTerminator()); + // check the return value of the setjmp. non-zero goes to dispatcher. Value *IsNormal = new ICmpInst(EntryBB->getTerminator(), ICmpInst::ICMP_EQ, DispatchVal, Zero, @@ -564,7 +562,7 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { // Replace all unwinds with a branch to the unwind handler. // ??? Should this ever happen with sjlj exceptions? for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) { - BranchInst::Create(UnwindBlock, Unwinds[i]); + BranchInst::Create(TrapBlock, Unwinds[i]); Unwinds[i]->eraseFromParent(); } diff --git a/contrib/llvm/lib/CodeGen/SlotIndexes.cpp b/contrib/llvm/lib/CodeGen/SlotIndexes.cpp index 6e3fa90e4341..ca79cafcf4be 100644 --- a/contrib/llvm/lib/CodeGen/SlotIndexes.cpp +++ b/contrib/llvm/lib/CodeGen/SlotIndexes.cpp @@ -10,47 +10,20 @@ #define DEBUG_TYPE "slotindexes" #include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Target/TargetInstrInfo.h" using namespace llvm; - -// Yep - these are thread safe. See the header for details. -namespace { - - - class EmptyIndexListEntry : public IndexListEntry { - public: - EmptyIndexListEntry() : IndexListEntry(EMPTY_KEY) {} - }; - - class TombstoneIndexListEntry : public IndexListEntry { - public: - TombstoneIndexListEntry() : IndexListEntry(TOMBSTONE_KEY) {} - }; - - // The following statics are thread safe. They're read only, and you - // can't step from them to any other list entries. - ManagedStatic IndexListEntryEmptyKey; - ManagedStatic IndexListEntryTombstoneKey; -} - char SlotIndexes::ID = 0; INITIALIZE_PASS(SlotIndexes, "slotindexes", "Slot index numbering", false, false) -IndexListEntry* IndexListEntry::getEmptyKeyEntry() { - return &*IndexListEntryEmptyKey; -} - -IndexListEntry* IndexListEntry::getTombstoneKeyEntry() { - return &*IndexListEntryTombstoneKey; -} - +STATISTIC(NumLocalRenum, "Number of local renumberings"); +STATISTIC(NumGlobalRenum, "Number of global renumberings"); void SlotIndexes::getAnalysisUsage(AnalysisUsage &au) const { au.setPreservesAll(); @@ -59,7 +32,7 @@ void SlotIndexes::getAnalysisUsage(AnalysisUsage &au) const { void SlotIndexes::releaseMemory() { mi2iMap.clear(); - mbb2IdxMap.clear(); + MBBRanges.clear(); idx2MBBMap.clear(); clearList(); } @@ -85,13 +58,15 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { "Index list non-empty at initial numbering?"); assert(idx2MBBMap.empty() && "Index -> MBB mapping non-empty at initial numbering?"); - assert(mbb2IdxMap.empty() && + assert(MBBRanges.empty() && "MBB -> Index mapping non-empty at initial numbering?"); assert(mi2iMap.empty() && "MachineInstr -> Index mapping non-empty at initial numbering?"); functionSize = 0; unsigned index = 0; + MBBRanges.resize(mf->getNumBlockIDs()); + idx2MBBMap.reserve(mf->size()); push_back(createEntry(0, index)); @@ -103,8 +78,6 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { // Insert an index for the MBB start. SlotIndex blockStartIndex(back(), SlotIndex::LOAD); - index += SlotIndex::NUM; - for (MachineBasicBlock::iterator miItr = mbb->begin(), miEnd = mbb->end(); miItr != miEnd; ++miItr) { MachineInstr *mi = miItr; @@ -112,32 +85,19 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { continue; // Insert a store index for the instr. - push_back(createEntry(mi, index)); + push_back(createEntry(mi, index += SlotIndex::InstrDist)); // Save this base index in the maps. - mi2iMap.insert( - std::make_pair(mi, SlotIndex(back(), SlotIndex::LOAD))); + mi2iMap.insert(std::make_pair(mi, SlotIndex(back(), SlotIndex::LOAD))); ++functionSize; - - unsigned Slots = mi->getDesc().getNumDefs(); - if (Slots == 0) - Slots = 1; - - index += (Slots + 1) * SlotIndex::NUM; } - // We insert two blank instructions between basic blocks. - // One to represent live-out registers and one to represent live-ins. - push_back(createEntry(0, index)); - index += SlotIndex::NUM; - - push_back(createEntry(0, index)); - - SlotIndex blockEndIndex(back(), SlotIndex::LOAD); - mbb2IdxMap.insert( - std::make_pair(mbb, std::make_pair(blockStartIndex, blockEndIndex))); + // We insert one blank instructions between basic blocks. + push_back(createEntry(0, index += SlotIndex::InstrDist)); + MBBRanges[mbb->getNumber()].first = blockStartIndex; + MBBRanges[mbb->getNumber()].second = SlotIndex(back(), SlotIndex::LOAD); idx2MBBMap.push_back(IdxMBBPair(blockStartIndex, mbb)); } @@ -151,38 +111,41 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { } void SlotIndexes::renumberIndexes() { - // Renumber updates the index of every element of the index list. - // If all instrs in the function have been allocated an index (which has been - // placed in the index list in the order of instruction iteration) then the - // resulting numbering will match what would have been generated by the - // pass during the initial numbering of the function if the new instructions - // had been present. DEBUG(dbgs() << "\n*** Renumbering SlotIndexes ***\n"); + ++NumGlobalRenum; - functionSize = 0; unsigned index = 0; for (IndexListEntry *curEntry = front(); curEntry != getTail(); curEntry = curEntry->getNext()) { - curEntry->setIndex(index); - - if (curEntry->getInstr() == 0) { - // MBB start entry. Just step index by 1. - index += SlotIndex::NUM; - } - else { - ++functionSize; - unsigned Slots = curEntry->getInstr()->getDesc().getNumDefs(); - if (Slots == 0) - Slots = 1; - - index += (Slots + 1) * SlotIndex::NUM; - } + index += SlotIndex::InstrDist; } } +// Renumber indexes locally after curEntry was inserted, but failed to get a new +// index. +void SlotIndexes::renumberIndexes(IndexListEntry *curEntry) { + // Number indexes with half the default spacing so we can catch up quickly. + const unsigned Space = SlotIndex::InstrDist/2; + assert((Space & 3) == 0 && "InstrDist must be a multiple of 2*NUM"); + + IndexListEntry *start = curEntry->getPrev(); + unsigned index = start->getIndex(); + IndexListEntry *tail = getTail(); + do { + curEntry->setIndex(index += Space); + curEntry = curEntry->getNext(); + // If the next index is bigger, we have caught up. + } while (curEntry != tail && curEntry->getIndex() <= index); + + DEBUG(dbgs() << "\n*** Renumbered SlotIndexes " << start->getIndex() << '-' + << index << " ***\n"); + ++NumLocalRenum; +} + + void SlotIndexes::dump() const { for (const IndexListEntry *itr = front(); itr != getTail(); itr = itr->getNext()) { @@ -195,11 +158,9 @@ void SlotIndexes::dump() const { } } - for (MBB2IdxMap::const_iterator itr = mbb2IdxMap.begin(); - itr != mbb2IdxMap.end(); ++itr) { - dbgs() << "MBB " << itr->first->getNumber() << " (" << itr->first << ") - [" - << itr->second.first << ", " << itr->second.second << "]\n"; - } + for (unsigned i = 0, e = MBBRanges.size(); i != e; ++i) + dbgs() << "BB#" << i << "\t[" << MBBRanges[i].first << ';' + << MBBRanges[i].second << ")\n"; } // Print a SlotIndex to a raw_ostream. diff --git a/contrib/llvm/lib/CodeGen/SpillPlacement.cpp b/contrib/llvm/lib/CodeGen/SpillPlacement.cpp index 9c0bf1629a14..694961863261 100644 --- a/contrib/llvm/lib/CodeGen/SpillPlacement.cpp +++ b/contrib/llvm/lib/CodeGen/SpillPlacement.cpp @@ -67,11 +67,11 @@ void SpillPlacement::getAnalysisUsage(AnalysisUsage &AU) const { /// because all weights are positive. /// struct SpillPlacement::Node { - /// Frequency - Total block frequency feeding into[0] or out of[1] the bundle. + /// Scale - Inverse block frequency feeding into[0] or out of[1] the bundle. /// Ideally, these two numbers should be identical, but inaccuracies in the /// block frequency estimates means that we need to normalize ingoing and /// outgoing frequencies separately so they are commensurate. - float Frequency[2]; + float Scale[2]; /// Bias - Normalized contributions from non-transparent blocks. /// A bundle connected to a MustSpill block has a huge negative bias, @@ -107,7 +107,7 @@ struct SpillPlacement::Node { /// Node - Create a blank Node. Node() { - Frequency[0] = Frequency[1] = 0; + Scale[0] = Scale[1] = 0; } /// clear - Reset per-query data, but preserve frequencies that only depend on @@ -121,7 +121,7 @@ struct SpillPlacement::Node { /// out=0 for an ingoing link, and 1 for an outgoing link. void addLink(unsigned b, float w, bool out) { // Normalize w relative to all connected blocks from that direction. - w /= Frequency[out]; + w *= Scale[out]; // There can be multiple links to the same bundle, add them up. for (LinkVector::iterator I = Links.begin(), E = Links.end(); I != E; ++I) @@ -134,9 +134,10 @@ struct SpillPlacement::Node { } /// addBias - Bias this node from an ingoing[0] or outgoing[1] link. + /// Return the change to the total number of positive biases. void addBias(float w, bool out) { // Normalize w relative to all connected blocks from that direction. - w /= Frequency[out]; + w *= Scale[out]; Bias += w; } @@ -175,13 +176,22 @@ bool SpillPlacement::runOnMachineFunction(MachineFunction &mf) { nodes = new Node[bundles->getNumBundles()]; // Compute total ingoing and outgoing block frequencies for all bundles. + BlockFrequency.resize(mf.getNumBlockIDs()); for (MachineFunction::iterator I = mf.begin(), E = mf.end(); I != E; ++I) { - float Freq = getBlockFrequency(I); + float Freq = LiveIntervals::getSpillWeight(true, false, + loops->getLoopDepth(I)); unsigned Num = I->getNumber(); - nodes[bundles->getBundle(Num, 1)].Frequency[0] += Freq; - nodes[bundles->getBundle(Num, 0)].Frequency[1] += Freq; + BlockFrequency[Num] = Freq; + nodes[bundles->getBundle(Num, 1)].Scale[0] += Freq; + nodes[bundles->getBundle(Num, 0)].Scale[1] += Freq; } + // Scales are reciprocal frequencies. + for (unsigned i = 0, e = bundles->getNumBundles(); i != e; ++i) + for (unsigned d = 0; d != 2; ++d) + if (nodes[i].Scale[d] > 0) + nodes[i].Scale[d] = 1 / nodes[i].Scale[d]; + // We never change the function. return false; } @@ -200,31 +210,12 @@ void SpillPlacement::activate(unsigned n) { } -/// prepareNodes - Compute node biases and weights from a set of constraints. +/// addConstraints - Compute node biases and weights from a set of constraints. /// Set a bit in NodeMask for each active node. -void SpillPlacement:: -prepareNodes(const SmallVectorImpl &LiveBlocks) { - for (SmallVectorImpl::const_iterator I = LiveBlocks.begin(), +void SpillPlacement::addConstraints(ArrayRef LiveBlocks) { + for (ArrayRef::iterator I = LiveBlocks.begin(), E = LiveBlocks.end(); I != E; ++I) { - MachineBasicBlock *MBB = MF->getBlockNumbered(I->Number); - float Freq = getBlockFrequency(MBB); - - // Is this a transparent block? Link ingoing and outgoing bundles. - if (I->Entry == DontCare && I->Exit == DontCare) { - unsigned ib = bundles->getBundle(I->Number, 0); - unsigned ob = bundles->getBundle(I->Number, 1); - - // Ignore self-loops. - if (ib == ob) - continue; - activate(ib); - activate(ob); - nodes[ib].addLink(ob, Freq, 1); - nodes[ob].addLink(ib, Freq, 0); - continue; - } - - // This block is not transparent, but it can still add bias. + float Freq = getBlockFrequency(I->Number); const float Bias[] = { 0, // DontCare, 1, // PrefReg, @@ -248,10 +239,54 @@ prepareNodes(const SmallVectorImpl &LiveBlocks) { } } +void SpillPlacement::addLinks(ArrayRef Links) { + for (ArrayRef::iterator I = Links.begin(), E = Links.end(); I != E; + ++I) { + unsigned Number = *I; + unsigned ib = bundles->getBundle(Number, 0); + unsigned ob = bundles->getBundle(Number, 1); + + // Ignore self-loops. + if (ib == ob) + continue; + activate(ib); + activate(ob); + if (nodes[ib].Links.empty() && !nodes[ib].mustSpill()) + Linked.push_back(ib); + if (nodes[ob].Links.empty() && !nodes[ob].mustSpill()) + Linked.push_back(ob); + float Freq = getBlockFrequency(Number); + nodes[ib].addLink(ob, Freq, 1); + nodes[ob].addLink(ib, Freq, 0); + } +} + +bool SpillPlacement::scanActiveBundles() { + Linked.clear(); + RecentPositive.clear(); + for (int n = ActiveNodes->find_first(); n>=0; n = ActiveNodes->find_next(n)) { + nodes[n].update(nodes); + // A node that must spill, or a node without any links is not going to + // change its value ever again, so exclude it from iterations. + if (nodes[n].mustSpill()) + continue; + if (!nodes[n].Links.empty()) + Linked.push_back(n); + if (nodes[n].preferReg()) + RecentPositive.push_back(n); + } + return !RecentPositive.empty(); +} + /// iterate - Repeatedly update the Hopfield nodes until stability or the /// maximum number of iterations is reached. /// @param Linked - Numbers of linked nodes that need updating. -void SpillPlacement::iterate(const SmallVectorImpl &Linked) { +void SpillPlacement::iterate() { + // First update the recently positive nodes. They have likely received new + // negative bias that will turn them off. + while (!RecentPositive.empty()) + nodes[RecentPositive.pop_back_val()].update(nodes); + if (Linked.empty()) return; @@ -267,10 +302,13 @@ void SpillPlacement::iterate(const SmallVectorImpl &Linked) { for (SmallVectorImpl::const_reverse_iterator I = llvm::next(Linked.rbegin()), E = Linked.rend(); I != E; ++I) { unsigned n = *I; - bool C = nodes[n].update(nodes); - Changed |= C; + if (nodes[n].update(nodes)) { + Changed = true; + if (nodes[n].preferReg()) + RecentPositive.push_back(n); + } } - if (!Changed) + if (!Changed || !RecentPositive.empty()) return; // Scan forwards, skipping the first node which was just updated. @@ -278,53 +316,37 @@ void SpillPlacement::iterate(const SmallVectorImpl &Linked) { for (SmallVectorImpl::const_iterator I = llvm::next(Linked.begin()), E = Linked.end(); I != E; ++I) { unsigned n = *I; - bool C = nodes[n].update(nodes); - Changed |= C; + if (nodes[n].update(nodes)) { + Changed = true; + if (nodes[n].preferReg()) + RecentPositive.push_back(n); + } } - if (!Changed) + if (!Changed || !RecentPositive.empty()) return; } } -bool -SpillPlacement::placeSpills(const SmallVectorImpl &LiveBlocks, - BitVector &RegBundles) { +void SpillPlacement::prepare(BitVector &RegBundles) { + Linked.clear(); + RecentPositive.clear(); // Reuse RegBundles as our ActiveNodes vector. ActiveNodes = &RegBundles; ActiveNodes->clear(); ActiveNodes->resize(bundles->getNumBundles()); +} - // Compute active nodes, links and biases. - prepareNodes(LiveBlocks); +bool +SpillPlacement::finish() { + assert(ActiveNodes && "Call prepare() first"); - // Update all active nodes, and find the ones that are actually linked to - // something so their value may change when iterating. - SmallVector Linked; - for (int n = RegBundles.find_first(); n>=0; n = RegBundles.find_next(n)) { - nodes[n].update(nodes); - // A node that must spill, or a node without any links is not going to - // change its value ever again, so exclude it from iterations. - if (!nodes[n].Links.empty() && !nodes[n].mustSpill()) - Linked.push_back(n); - } - - // Iterate the network to convergence. - iterate(Linked); - - // Write preferences back to RegBundles. + // Write preferences back to ActiveNodes. bool Perfect = true; - for (int n = RegBundles.find_first(); n>=0; n = RegBundles.find_next(n)) + for (int n = ActiveNodes->find_first(); n>=0; n = ActiveNodes->find_next(n)) if (!nodes[n].preferReg()) { - RegBundles.reset(n); + ActiveNodes->reset(n); Perfect = false; } + ActiveNodes = 0; return Perfect; } - -/// getBlockFrequency - Return our best estimate of the block frequency which is -/// the expected number of block executions per function invocation. -float SpillPlacement::getBlockFrequency(const MachineBasicBlock *MBB) { - // Use the unnormalized spill weight for real block frequencies. - return LiveIntervals::getSpillWeight(true, false, loops->getLoopDepth(MBB)); -} - diff --git a/contrib/llvm/lib/CodeGen/SpillPlacement.h b/contrib/llvm/lib/CodeGen/SpillPlacement.h index ef2d516cdce7..6952ad800965 100644 --- a/contrib/llvm/lib/CodeGen/SpillPlacement.h +++ b/contrib/llvm/lib/CodeGen/SpillPlacement.h @@ -10,8 +10,8 @@ // This analysis computes the optimal spill code placement between basic blocks. // // The runOnMachineFunction() method only precomputes some profiling information -// about the CFG. The real work is done by placeSpills() which is called by the -// register allocator. +// about the CFG. The real work is done by prepare(), addConstraints(), and +// finish() which are called by the register allocator. // // Given a variable that is live across multiple basic blocks, and given // constraints on the basic blocks where the variable is live, determine which @@ -27,6 +27,8 @@ #ifndef LLVM_CODEGEN_SPILLPLACEMENT_H #define LLVM_CODEGEN_SPILLPLACEMENT_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" namespace llvm { @@ -35,7 +37,6 @@ class BitVector; class EdgeBundles; class MachineBasicBlock; class MachineLoopInfo; -template class SmallVectorImpl; class SpillPlacement : public MachineFunctionPass { struct Node; @@ -44,10 +45,20 @@ class SpillPlacement : public MachineFunctionPass { const MachineLoopInfo *loops; Node *nodes; - // Nodes that are active in the current computation. Owned by the placeSpills + // Nodes that are active in the current computation. Owned by the prepare() // caller. BitVector *ActiveNodes; + // Nodes with active links. Populated by scanActiveBundles. + SmallVector Linked; + + // Nodes that went positive during the last call to scanActiveBundles or + // iterate. + SmallVector RecentPositive; + + // Block frequencies are computed once. Indexed by block number. + SmallVector BlockFrequency; + public: static char ID; // Pass identification, replacement for typeid. @@ -70,28 +81,53 @@ class SpillPlacement : public MachineFunctionPass { BorderConstraint Exit : 8; ///< Constraint on block exit. }; - /// placeSpills - Compute the optimal spill code placement given the - /// constraints. No MustSpill constraints will be violated, and the smallest - /// possible number of PrefX constraints will be violated, weighted by - /// expected execution frequencies. - /// @param LiveBlocks Constraints for blocks that have the variable live in or - /// live out. DontCare/DontCare means the variable is live - /// through the block. DontCare/X means the variable is live - /// out, but not live in. + /// prepare - Reset state and prepare for a new spill placement computation. /// @param RegBundles Bit vector to receive the edge bundles where the /// variable should be kept in a register. Each bit /// corresponds to an edge bundle, a set bit means the /// variable should be kept in a register through the /// bundle. A clear bit means the variable should be - /// spilled. + /// spilled. This vector is retained. + void prepare(BitVector &RegBundles); + + /// addConstraints - Add constraints and biases. This method may be called + /// more than once to accumulate constraints. + /// @param LiveBlocks Constraints for blocks that have the variable live in or + /// live out. + void addConstraints(ArrayRef LiveBlocks); + + /// addLinks - Add transparent blocks with the given numbers. + void addLinks(ArrayRef Links); + + /// scanActiveBundles - Perform an initial scan of all bundles activated by + /// addConstraints and addLinks, updating their state. Add all the bundles + /// that now prefer a register to RecentPositive. + /// Prepare internal data structures for iterate. + /// Return true is there are any positive nodes. + bool scanActiveBundles(); + + /// iterate - Update the network iteratively until convergence, or new bundles + /// are found. + void iterate(); + + /// getRecentPositive - Return an array of bundles that became positive during + /// the previous call to scanActiveBundles or iterate. + ArrayRef getRecentPositive() { return RecentPositive; } + + /// finish - Compute the optimal spill code placement given the + /// constraints. No MustSpill constraints will be violated, and the smallest + /// possible number of PrefX constraints will be violated, weighted by + /// expected execution frequencies. + /// The selected bundles are returned in the bitvector passed to prepare(). /// @return True if a perfect solution was found, allowing the variable to be /// in a register through all relevant bundles. - bool placeSpills(const SmallVectorImpl &LiveBlocks, - BitVector &RegBundles); + bool finish(); /// getBlockFrequency - Return the estimated block execution frequency per /// function invocation. - float getBlockFrequency(const MachineBasicBlock*); + float getBlockFrequency(unsigned Number) const { + return BlockFrequency[Number]; + } private: virtual bool runOnMachineFunction(MachineFunction&); @@ -99,8 +135,6 @@ class SpillPlacement : public MachineFunctionPass { virtual void releaseMemory(); void activate(unsigned); - void prepareNodes(const SmallVectorImpl&); - void iterate(const SmallVectorImpl&); }; } // end namespace llvm diff --git a/contrib/llvm/lib/CodeGen/Spiller.cpp b/contrib/llvm/lib/CodeGen/Spiller.cpp index fd385824aff9..b6bbcd7176dd 100644 --- a/contrib/llvm/lib/CodeGen/Spiller.cpp +++ b/contrib/llvm/lib/CodeGen/Spiller.cpp @@ -11,6 +11,7 @@ #include "Spiller.h" #include "VirtRegMap.h" +#include "LiveRangeEdit.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveStackAnalysis.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -24,7 +25,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include using namespace llvm; @@ -180,11 +180,9 @@ class TrivialSpiller : public SpillerBase { VirtRegMap &vrm) : SpillerBase(pass, mf, vrm) {} - void spill(LiveInterval *li, - SmallVectorImpl &newIntervals, - const SmallVectorImpl &) { + void spill(LiveRangeEdit &LRE) { // Ignore spillIs - we don't use it. - trivialSpillEverywhere(li, newIntervals); + trivialSpillEverywhere(&LRE.getParent(), *LRE.getNewVRegs()); } }; @@ -210,22 +208,22 @@ class StandardSpiller : public Spiller { vrm(&vrm) {} /// Falls back on LiveIntervals::addIntervalsForSpills. - void spill(LiveInterval *li, - SmallVectorImpl &newIntervals, - const SmallVectorImpl &spillIs) { + void spill(LiveRangeEdit &LRE) { std::vector added = - lis->addIntervalsForSpills(*li, spillIs, loopInfo, *vrm); - newIntervals.insert(newIntervals.end(), added.begin(), added.end()); + lis->addIntervalsForSpills(LRE.getParent(), LRE.getUselessVRegs(), + loopInfo, *vrm); + LRE.getNewVRegs()->insert(LRE.getNewVRegs()->end(), + added.begin(), added.end()); // Update LiveStacks. - int SS = vrm->getStackSlot(li->reg); + int SS = vrm->getStackSlot(LRE.getReg()); if (SS == VirtRegMap::NO_STACK_SLOT) return; - const TargetRegisterClass *RC = mf->getRegInfo().getRegClass(li->reg); + const TargetRegisterClass *RC = mf->getRegInfo().getRegClass(LRE.getReg()); LiveInterval &SI = lss->getOrCreateInterval(SS, RC); if (!SI.hasAtLeastOneValue()) SI.getNextValue(SlotIndex(), 0, lss->getVNInfoAllocator()); - SI.MergeRangesInAsValue(*li, SI.getValNumInfo(0)); + SI.MergeRangesInAsValue(LRE.getParent(), SI.getValNumInfo(0)); } }; diff --git a/contrib/llvm/lib/CodeGen/Spiller.h b/contrib/llvm/lib/CodeGen/Spiller.h index f017583494ed..41f1727da439 100644 --- a/contrib/llvm/lib/CodeGen/Spiller.h +++ b/contrib/llvm/lib/CodeGen/Spiller.h @@ -12,11 +12,9 @@ namespace llvm { - class LiveInterval; + class LiveRangeEdit; class MachineFunction; class MachineFunctionPass; - class SlotIndex; - template class SmallVectorImpl; class VirtRegMap; /// Spiller interface. @@ -27,16 +25,8 @@ namespace llvm { public: virtual ~Spiller() = 0; - /// spill - Spill the given live interval. The method used will depend on - /// the Spiller implementation selected. - /// - /// @param li The live interval to be spilled. - /// @param spillIs A list of intervals that are about to be spilled, - /// and so cannot be used for remat etc. - /// @param newIntervals The newly created intervals will be appended here. - virtual void spill(LiveInterval *li, - SmallVectorImpl &newIntervals, - const SmallVectorImpl &spillIs) = 0; + /// spill - Spill the LRE.getParent() live interval. + virtual void spill(LiveRangeEdit &LRE) = 0; }; diff --git a/contrib/llvm/lib/CodeGen/SplitKit.cpp b/contrib/llvm/lib/CodeGen/SplitKit.cpp index fd5d50b7ecb8..ac9d72bf62c9 100644 --- a/contrib/llvm/lib/CodeGen/SplitKit.cpp +++ b/contrib/llvm/lib/CodeGen/SplitKit.cpp @@ -16,12 +16,11 @@ #include "SplitKit.h" #include "LiveRangeEdit.h" #include "VirtRegMap.h" -#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" @@ -29,9 +28,8 @@ using namespace llvm; -static cl::opt -AllowSplit("spiller-splits-edges", - cl::desc("Allow critical edge splitting during spilling")); +STATISTIC(NumFinished, "Number of splits finished"); +STATISTIC(NumSimple, "Number of splits that were simple"); //===----------------------------------------------------------------------===// // Split Analysis @@ -45,49 +43,105 @@ SplitAnalysis::SplitAnalysis(const VirtRegMap &vrm, LIS(lis), Loops(mli), TII(*MF.getTarget().getInstrInfo()), - CurLI(0) {} + CurLI(0), + LastSplitPoint(MF.getNumBlockIDs()) {} void SplitAnalysis::clear() { UseSlots.clear(); - UsingInstrs.clear(); - UsingBlocks.clear(); - LiveBlocks.clear(); + UseBlocks.clear(); + ThroughBlocks.clear(); CurLI = 0; } -bool SplitAnalysis::canAnalyzeBranch(const MachineBasicBlock *MBB) { - MachineBasicBlock *T, *F; - SmallVector Cond; - return !TII.AnalyzeBranch(const_cast(*MBB), T, F, Cond); +SlotIndex SplitAnalysis::computeLastSplitPoint(unsigned Num) { + const MachineBasicBlock *MBB = MF.getBlockNumbered(Num); + const MachineBasicBlock *LPad = MBB->getLandingPadSuccessor(); + std::pair &LSP = LastSplitPoint[Num]; + + // Compute split points on the first call. The pair is independent of the + // current live interval. + if (!LSP.first.isValid()) { + MachineBasicBlock::const_iterator FirstTerm = MBB->getFirstTerminator(); + if (FirstTerm == MBB->end()) + LSP.first = LIS.getMBBEndIdx(MBB); + else + LSP.first = LIS.getInstructionIndex(FirstTerm); + + // If there is a landing pad successor, also find the call instruction. + if (!LPad) + return LSP.first; + // There may not be a call instruction (?) in which case we ignore LPad. + LSP.second = LSP.first; + for (MachineBasicBlock::const_iterator I = FirstTerm, E = MBB->begin(); + I != E; --I) + if (I->getDesc().isCall()) { + LSP.second = LIS.getInstructionIndex(I); + break; + } + } + + // If CurLI is live into a landing pad successor, move the last split point + // back to the call that may throw. + if (LPad && LSP.second.isValid() && LIS.isLiveInToMBB(*CurLI, LPad)) + return LSP.second; + else + return LSP.first; } /// analyzeUses - Count instructions, basic blocks, and loops using CurLI. void SplitAnalysis::analyzeUses() { + assert(UseSlots.empty() && "Call clear first"); + + // First get all the defs from the interval values. This provides the correct + // slots for early clobbers. + for (LiveInterval::const_vni_iterator I = CurLI->vni_begin(), + E = CurLI->vni_end(); I != E; ++I) + if (!(*I)->isPHIDef() && !(*I)->isUnused()) + UseSlots.push_back((*I)->def); + + // Get use slots form the use-def chain. const MachineRegisterInfo &MRI = MF.getRegInfo(); - for (MachineRegisterInfo::reg_iterator I = MRI.reg_begin(CurLI->reg), - E = MRI.reg_end(); I != E; ++I) { - MachineOperand &MO = I.getOperand(); - if (MO.isUse() && MO.isUndef()) - continue; - MachineInstr *MI = MO.getParent(); - if (MI->isDebugValue() || !UsingInstrs.insert(MI)) - continue; - UseSlots.push_back(LIS.getInstructionIndex(MI).getDefIndex()); - MachineBasicBlock *MBB = MI->getParent(); - UsingBlocks[MBB]++; - } + for (MachineRegisterInfo::use_nodbg_iterator + I = MRI.use_nodbg_begin(CurLI->reg), E = MRI.use_nodbg_end(); I != E; + ++I) + if (!I.getOperand().isUndef()) + UseSlots.push_back(LIS.getInstructionIndex(&*I).getDefIndex()); + array_pod_sort(UseSlots.begin(), UseSlots.end()); - calcLiveBlockInfo(); - DEBUG(dbgs() << " counted " - << UsingInstrs.size() << " instrs, " - << UsingBlocks.size() << " blocks.\n"); + + // Remove duplicates, keeping the smaller slot for each instruction. + // That is what we want for early clobbers. + UseSlots.erase(std::unique(UseSlots.begin(), UseSlots.end(), + SlotIndex::isSameInstr), + UseSlots.end()); + + // Compute per-live block info. + if (!calcLiveBlockInfo()) { + // FIXME: calcLiveBlockInfo found inconsistencies in the live range. + // I am looking at you, SimpleRegisterCoalescing! + DEBUG(dbgs() << "*** Fixing inconsistent live interval! ***\n"); + const_cast(LIS) + .shrinkToUses(const_cast(CurLI)); + UseBlocks.clear(); + ThroughBlocks.clear(); + bool fixed = calcLiveBlockInfo(); + (void)fixed; + assert(fixed && "Couldn't fix broken live interval"); + } + + DEBUG(dbgs() << "Analyze counted " + << UseSlots.size() << " instrs in " + << UseBlocks.size() << " blocks, through " + << NumThroughBlocks << " blocks.\n"); } /// calcLiveBlockInfo - Fill the LiveBlocks array with information about blocks /// where CurLI is live. -void SplitAnalysis::calcLiveBlockInfo() { +bool SplitAnalysis::calcLiveBlockInfo() { + ThroughBlocks.resize(MF.getNumBlockIDs()); + NumThroughBlocks = 0; if (CurLI->empty()) - return; + return true; LiveInterval::const_iterator LVI = CurLI->begin(); LiveInterval::const_iterator LVE = CurLI->end(); @@ -104,24 +158,14 @@ void SplitAnalysis::calcLiveBlockInfo() { SlotIndex Start, Stop; tie(Start, Stop) = LIS.getSlotIndexes()->getMBBRange(BI.MBB); - // The last split point is the latest possible insertion point that dominates - // all successor blocks. If interference reaches LastSplitPoint, it is not - // possible to insert a split or reload that makes CurLI live in the - // outgoing bundle. - MachineBasicBlock::iterator LSP = LIS.getLastSplitPoint(*CurLI, BI.MBB); - if (LSP == BI.MBB->end()) - BI.LastSplitPoint = Stop; - else - BI.LastSplitPoint = LIS.getInstructionIndex(LSP); - // LVI is the first live segment overlapping MBB. BI.LiveIn = LVI->start <= Start; if (!BI.LiveIn) BI.Def = LVI->start; // Find the first and last uses in the block. - BI.Uses = hasUses(MFI); - if (BI.Uses && UseI != UseE) { + bool Uses = UseI != UseE && *UseI < Stop; + if (Uses) { BI.FirstUse = *UseI; assert(BI.FirstUse >= Start); do ++UseI; @@ -149,7 +193,16 @@ void SplitAnalysis::calcLiveBlockInfo() { // Don't set LiveThrough when the block has a gap. BI.LiveThrough = !hasGap && BI.LiveIn && BI.LiveOut; - LiveBlocks.push_back(BI); + if (Uses) + UseBlocks.push_back(BI); + else { + ++NumThroughBlocks; + ThroughBlocks.set(BI.MBB->getNumber()); + } + // FIXME: This should never happen. The live range stops or starts without a + // corresponding use. An earlier pass did something wrong. + if (!BI.LiveThrough && !Uses) + return false; // LVI is now at LVE or LVI->end >= Stop. if (LVI == LVE) @@ -165,6 +218,30 @@ void SplitAnalysis::calcLiveBlockInfo() { else MFI = LIS.getMBBFromIndex(LVI->start); } + return true; +} + +unsigned SplitAnalysis::countLiveBlocks(const LiveInterval *cli) const { + if (cli->empty()) + return 0; + LiveInterval *li = const_cast(cli); + LiveInterval::iterator LVI = li->begin(); + LiveInterval::iterator LVE = li->end(); + unsigned Count = 0; + + // Loop over basic blocks where li is live. + MachineFunction::const_iterator MFI = LIS.getMBBFromIndex(LVI->start); + SlotIndex Stop = LIS.getMBBEndIdx(MFI); + for (;;) { + ++Count; + LVI = li->advanceTo(LVI, Stop); + if (LVI == LVE) + return Count; + do { + ++MFI; + Stop = LIS.getMBBEndIdx(MFI); + } while (Stop <= LVI->start); + } } bool SplitAnalysis::isOriginalEndpoint(SlotIndex Idx) const { @@ -181,15 +258,6 @@ bool SplitAnalysis::isOriginalEndpoint(SlotIndex Idx) const { return I != Orig.begin() && (--I)->end == Idx; } -void SplitAnalysis::print(const BlockPtrSet &B, raw_ostream &OS) const { - for (BlockPtrSet::const_iterator I = B.begin(), E = B.end(); I != E; ++I) { - unsigned count = UsingBlocks.lookup(*I); - OS << " BB#" << (*I)->getNumber(); - if (count) - OS << '(' << count << ')'; - } -} - void SplitAnalysis::analyze(const LiveInterval *li) { clear(); CurLI = li; @@ -198,171 +266,242 @@ void SplitAnalysis::analyze(const LiveInterval *li) { //===----------------------------------------------------------------------===// -// LiveIntervalMap +// Split Editor //===----------------------------------------------------------------------===// -// Work around the fact that the std::pair constructors are broken for pointer -// pairs in some implementations. makeVV(x, 0) works. -static inline std::pair -makeVV(const VNInfo *a, VNInfo *b) { - return std::make_pair(a, b); -} +/// Create a new SplitEditor for editing the LiveInterval analyzed by SA. +SplitEditor::SplitEditor(SplitAnalysis &sa, + LiveIntervals &lis, + VirtRegMap &vrm, + MachineDominatorTree &mdt) + : SA(sa), LIS(lis), VRM(vrm), + MRI(vrm.getMachineFunction().getRegInfo()), + MDT(mdt), + TII(*vrm.getMachineFunction().getTarget().getInstrInfo()), + TRI(*vrm.getMachineFunction().getTarget().getRegisterInfo()), + Edit(0), + OpenIdx(0), + RegAssign(Allocator) +{} -void LiveIntervalMap::reset(LiveInterval *li) { - LI = li; +void SplitEditor::reset(LiveRangeEdit &lre) { + Edit = &lre; + OpenIdx = 0; + RegAssign.clear(); Values.clear(); - LiveOutCache.clear(); + + // We don't need to clear LiveOutCache, only LiveOutSeen entries are read. + LiveOutSeen.clear(); + + // We don't need an AliasAnalysis since we will only be performing + // cheap-as-a-copy remats anyway. + Edit->anyRematerializable(LIS, TII, 0); } -bool LiveIntervalMap::isComplexMapped(const VNInfo *ParentVNI) const { - ValueMap::const_iterator i = Values.find(ParentVNI); - return i != Values.end() && i->second == 0; +void SplitEditor::dump() const { + if (RegAssign.empty()) { + dbgs() << " empty\n"; + return; + } + + for (RegAssignMap::const_iterator I = RegAssign.begin(); I.valid(); ++I) + dbgs() << " [" << I.start() << ';' << I.stop() << "):" << I.value(); + dbgs() << '\n'; } -// defValue - Introduce a LI def for ParentVNI that could be later than -// ParentVNI->def. -VNInfo *LiveIntervalMap::defValue(const VNInfo *ParentVNI, SlotIndex Idx) { - assert(LI && "call reset first"); +VNInfo *SplitEditor::defValue(unsigned RegIdx, + const VNInfo *ParentVNI, + SlotIndex Idx) { assert(ParentVNI && "Mapping NULL value"); assert(Idx.isValid() && "Invalid SlotIndex"); - assert(ParentLI.getVNInfoAt(Idx) == ParentVNI && "Bad ParentVNI"); + assert(Edit->getParent().getVNInfoAt(Idx) == ParentVNI && "Bad Parent VNI"); + LiveInterval *LI = Edit->get(RegIdx); // Create a new value. VNInfo *VNI = LI->getNextValue(Idx, 0, LIS.getVNInfoAllocator()); - // Preserve the PHIDef bit. - if (ParentVNI->isPHIDef() && Idx == ParentVNI->def) - VNI->setIsPHIDef(true); - // Use insert for lookup, so we can add missing values with a second lookup. - std::pair InsP = - Values.insert(makeVV(ParentVNI, Idx == ParentVNI->def ? VNI : 0)); + std::pair InsP = + Values.insert(std::make_pair(std::make_pair(RegIdx, ParentVNI->id), VNI)); - // This is now a complex def. Mark with a NULL in valueMap. - if (!InsP.second) + // This was the first time (RegIdx, ParentVNI) was mapped. + // Keep it as a simple def without any liveness. + if (InsP.second) + return VNI; + + // If the previous value was a simple mapping, add liveness for it now. + if (VNInfo *OldVNI = InsP.first->second) { + SlotIndex Def = OldVNI->def; + LI->addRange(LiveRange(Def, Def.getNextSlot(), OldVNI)); + // No longer a simple mapping. InsP.first->second = 0; + } + + // This is a complex mapping, add liveness for VNI + SlotIndex Def = VNI->def; + LI->addRange(LiveRange(Def, Def.getNextSlot(), VNI)); return VNI; } - -// mapValue - Find the mapped value for ParentVNI at Idx. -// Potentially create phi-def values. -VNInfo *LiveIntervalMap::mapValue(const VNInfo *ParentVNI, SlotIndex Idx, - bool *simple) { - assert(LI && "call reset first"); +void SplitEditor::markComplexMapped(unsigned RegIdx, const VNInfo *ParentVNI) { assert(ParentVNI && "Mapping NULL value"); + VNInfo *&VNI = Values[std::make_pair(RegIdx, ParentVNI->id)]; + + // ParentVNI was either unmapped or already complex mapped. Either way. + if (!VNI) + return; + + // This was previously a single mapping. Make sure the old def is represented + // by a trivial live range. + SlotIndex Def = VNI->def; + Edit->get(RegIdx)->addRange(LiveRange(Def, Def.getNextSlot(), VNI)); + VNI = 0; +} + +// extendRange - Extend the live range to reach Idx. +// Potentially create phi-def values. +void SplitEditor::extendRange(unsigned RegIdx, SlotIndex Idx) { assert(Idx.isValid() && "Invalid SlotIndex"); - assert(ParentLI.getVNInfoAt(Idx) == ParentVNI && "Bad ParentVNI"); - - // Use insert for lookup, so we can add missing values with a second lookup. - std::pair InsP = - Values.insert(makeVV(ParentVNI, 0)); - - // This was an unknown value. Create a simple mapping. - if (InsP.second) { - if (simple) *simple = true; - return InsP.first->second = LI->createValueCopy(ParentVNI, - LIS.getVNInfoAllocator()); - } - - // This was a simple mapped value. - if (InsP.first->second) { - if (simple) *simple = true; - return InsP.first->second; - } - - // This is a complex mapped value. There may be multiple defs, and we may need - // to create phi-defs. - if (simple) *simple = false; MachineBasicBlock *IdxMBB = LIS.getMBBFromIndex(Idx); assert(IdxMBB && "No MBB at Idx"); + LiveInterval *LI = Edit->get(RegIdx); // Is there a def in the same MBB we can extend? - if (VNInfo *VNI = extendTo(IdxMBB, Idx)) - return VNI; + if (LI->extendInBlock(LIS.getMBBStartIdx(IdxMBB), Idx)) + return; // Now for the fun part. We know that ParentVNI potentially has multiple defs, // and we may need to create even more phi-defs to preserve VNInfo SSA form. // Perform a search for all predecessor blocks where we know the dominating - // VNInfo. Insert phi-def VNInfos along the path back to IdxMBB. - DEBUG(dbgs() << "\n Reaching defs for BB#" << IdxMBB->getNumber() - << " at " << Idx << " in " << *LI << '\n'); + // VNInfo. + VNInfo *VNI = findReachingDefs(LI, IdxMBB, Idx.getNextSlot()); + + // When there were multiple different values, we may need new PHIs. + if (!VNI) + return updateSSA(); + + // Poor man's SSA update for the single-value case. + LiveOutPair LOP(VNI, MDT[LIS.getMBBFromIndex(VNI->def)]); + for (SmallVectorImpl::iterator I = LiveInBlocks.begin(), + E = LiveInBlocks.end(); I != E; ++I) { + MachineBasicBlock *MBB = I->DomNode->getBlock(); + SlotIndex Start = LIS.getMBBStartIdx(MBB); + if (I->Kill.isValid()) + LI->addRange(LiveRange(Start, I->Kill, VNI)); + else { + LiveOutCache[MBB] = LOP; + LI->addRange(LiveRange(Start, LIS.getMBBEndIdx(MBB), VNI)); + } + } +} + +/// findReachingDefs - Search the CFG for known live-out values. +/// Add required live-in blocks to LiveInBlocks. +VNInfo *SplitEditor::findReachingDefs(LiveInterval *LI, + MachineBasicBlock *KillMBB, + SlotIndex Kill) { + // Initialize the live-out cache the first time it is needed. + if (LiveOutSeen.empty()) { + unsigned N = VRM.getMachineFunction().getNumBlockIDs(); + LiveOutSeen.resize(N); + LiveOutCache.resize(N); + } // Blocks where LI should be live-in. - SmallVector LiveIn; - LiveIn.push_back(MDT[IdxMBB]); + SmallVector WorkList(1, KillMBB); + + // Remember if we have seen more than one value. + bool UniqueVNI = true; + VNInfo *TheVNI = 0; // Using LiveOutCache as a visited set, perform a BFS for all reaching defs. - for (unsigned i = 0; i != LiveIn.size(); ++i) { - MachineBasicBlock *MBB = LiveIn[i]->getBlock(); + for (unsigned i = 0; i != WorkList.size(); ++i) { + MachineBasicBlock *MBB = WorkList[i]; + assert(!MBB->pred_empty() && "Value live-in to entry block?"); for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), PE = MBB->pred_end(); PI != PE; ++PI) { MachineBasicBlock *Pred = *PI; + LiveOutPair &LOP = LiveOutCache[Pred]; + // Is this a known live-out block? - std::pair LOIP = - LiveOutCache.insert(std::make_pair(Pred, LiveOutPair())); - // Yes, we have been here before. - if (!LOIP.second) { - DEBUG(if (VNInfo *VNI = LOIP.first->second.first) - dbgs() << " known valno #" << VNI->id - << " at BB#" << Pred->getNumber() << '\n'); + if (LiveOutSeen.test(Pred->getNumber())) { + if (VNInfo *VNI = LOP.first) { + if (TheVNI && TheVNI != VNI) + UniqueVNI = false; + TheVNI = VNI; + } continue; } + // First time. LOP is garbage and must be cleared below. + LiveOutSeen.set(Pred->getNumber()); + // Does Pred provide a live-out value? - SlotIndex Last = LIS.getMBBEndIdx(Pred).getPrevSlot(); - if (VNInfo *VNI = extendTo(Pred, Last)) { - MachineBasicBlock *DefMBB = LIS.getMBBFromIndex(VNI->def); - DEBUG(dbgs() << " found valno #" << VNI->id - << " from BB#" << DefMBB->getNumber() - << " at BB#" << Pred->getNumber() << '\n'); - LiveOutPair &LOP = LOIP.first->second; - LOP.first = VNI; - LOP.second = MDT[DefMBB]; + SlotIndex Start, Last; + tie(Start, Last) = LIS.getSlotIndexes()->getMBBRange(Pred); + Last = Last.getPrevSlot(); + VNInfo *VNI = LI->extendInBlock(Start, Last); + LOP.first = VNI; + if (VNI) { + LOP.second = MDT[LIS.getMBBFromIndex(VNI->def)]; + if (TheVNI && TheVNI != VNI) + UniqueVNI = false; + TheVNI = VNI; continue; } + LOP.second = 0; + // No, we need a live-in value for Pred as well - if (Pred != IdxMBB) - LiveIn.push_back(MDT[Pred]); + if (Pred != KillMBB) + WorkList.push_back(Pred); + else + // Loopback to KillMBB, so value is really live through. + Kill = SlotIndex(); } } - // We may need to add phi-def values to preserve the SSA form. + // Transfer WorkList to LiveInBlocks in reverse order. + // This ordering works best with updateSSA(). + LiveInBlocks.clear(); + LiveInBlocks.reserve(WorkList.size()); + while(!WorkList.empty()) + LiveInBlocks.push_back(MDT[WorkList.pop_back_val()]); + + // The kill block may not be live-through. + assert(LiveInBlocks.back().DomNode->getBlock() == KillMBB); + LiveInBlocks.back().Kill = Kill; + + return UniqueVNI ? TheVNI : 0; +} + +void SplitEditor::updateSSA() { // This is essentially the same iterative algorithm that SSAUpdater uses, // except we already have a dominator tree, so we don't have to recompute it. - VNInfo *IdxVNI = 0; unsigned Changes; do { Changes = 0; - DEBUG(dbgs() << " Iterating over " << LiveIn.size() << " blocks.\n"); - // Propagate live-out values down the dominator tree, inserting phi-defs when - // necessary. Since LiveIn was created by a BFS, going backwards makes it more - // likely for us to visit immediate dominators before their children. - for (unsigned i = LiveIn.size(); i; --i) { - MachineDomTreeNode *Node = LiveIn[i-1]; + // Propagate live-out values down the dominator tree, inserting phi-defs + // when necessary. + for (SmallVectorImpl::iterator I = LiveInBlocks.begin(), + E = LiveInBlocks.end(); I != E; ++I) { + MachineDomTreeNode *Node = I->DomNode; + // Skip block if the live-in value has already been determined. + if (!Node) + continue; MachineBasicBlock *MBB = Node->getBlock(); MachineDomTreeNode *IDom = Node->getIDom(); LiveOutPair IDomValue; + // We need a live-in value to a block with no immediate dominator? // This is probably an unreachable block that has survived somehow. - bool needPHI = !IDom; + bool needPHI = !IDom || !LiveOutSeen.test(IDom->getBlock()->getNumber()); - // Get the IDom live-out value. - if (!needPHI) { - LiveOutMap::iterator I = LiveOutCache.find(IDom->getBlock()); - if (I != LiveOutCache.end()) - IDomValue = I->second; - else - // If IDom is outside our set of live-out blocks, there must be new - // defs, and we need a phi-def here. - needPHI = true; - } - - // IDom dominates all of our predecessors, but it may not be the immediate - // dominator. Check if any of them have live-out values that are properly - // dominated by IDom. If so, we need a phi-def here. + // IDom dominates all of our predecessors, but it may not be their + // immediate dominator. Check if any of them have live-out values that are + // properly dominated by IDom. If so, we need a phi-def here. if (!needPHI) { + IDomValue = LiveOutCache[IDom->getBlock()]; for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), PE = MBB->pred_end(); PI != PE; ++PI) { LiveOutPair Value = LiveOutCache[*PI]; @@ -378,215 +517,57 @@ VNInfo *LiveIntervalMap::mapValue(const VNInfo *ParentVNI, SlotIndex Idx, } } + // The value may be live-through even if Kill is set, as can happen when + // we are called from extendRange. In that case LiveOutSeen is true, and + // LiveOutCache indicates a foreign or missing value. + LiveOutPair &LOP = LiveOutCache[MBB]; + // Create a phi-def if required. if (needPHI) { ++Changes; SlotIndex Start = LIS.getMBBStartIdx(MBB); + unsigned RegIdx = RegAssign.lookup(Start); + LiveInterval *LI = Edit->get(RegIdx); VNInfo *VNI = LI->getNextValue(Start, 0, LIS.getVNInfoAllocator()); VNI->setIsPHIDef(true); - DEBUG(dbgs() << " - BB#" << MBB->getNumber() - << " phi-def #" << VNI->id << " at " << Start << '\n'); - // We no longer need LI to be live-in. - LiveIn.erase(LiveIn.begin()+(i-1)); - // Blocks in LiveIn are either IdxMBB, or have a value live-through. - if (MBB == IdxMBB) - IdxVNI = VNI; - // Check if we need to update live-out info. - LiveOutMap::iterator I = LiveOutCache.find(MBB); - if (I == LiveOutCache.end() || I->second.second == Node) { - // We already have a live-out defined in MBB, so this must be IdxMBB. - assert(MBB == IdxMBB && "Adding phi-def to known live-out"); - LI->addRange(LiveRange(Start, Idx.getNextSlot(), VNI)); - } else { - // This phi-def is also live-out, so color the whole block. + I->Value = VNI; + // This block is done, we know the final value. + I->DomNode = 0; + if (I->Kill.isValid()) + LI->addRange(LiveRange(Start, I->Kill, VNI)); + else { LI->addRange(LiveRange(Start, LIS.getMBBEndIdx(MBB), VNI)); - I->second = LiveOutPair(VNI, Node); + LOP = LiveOutPair(VNI, Node); } } else if (IDomValue.first) { - // No phi-def here. Remember incoming value for IdxMBB. - if (MBB == IdxMBB) - IdxVNI = IDomValue.first; + // No phi-def here. Remember incoming value. + I->Value = IDomValue.first; + if (I->Kill.isValid()) + continue; // Propagate IDomValue if needed: // MBB is live-out and doesn't define its own value. - LiveOutMap::iterator I = LiveOutCache.find(MBB); - if (I != LiveOutCache.end() && I->second.second != Node && - I->second.first != IDomValue.first) { + if (LOP.second != Node && LOP.first != IDomValue.first) { ++Changes; - I->second = IDomValue; - DEBUG(dbgs() << " - BB#" << MBB->getNumber() - << " idom valno #" << IDomValue.first->id - << " from BB#" << IDom->getBlock()->getNumber() << '\n'); + LOP = IDomValue; } } } - DEBUG(dbgs() << " - made " << Changes << " changes.\n"); } while (Changes); - assert(IdxVNI && "Didn't find value for Idx"); - -#ifndef NDEBUG - // Check the LiveOutCache invariants. - for (LiveOutMap::iterator I = LiveOutCache.begin(), E = LiveOutCache.end(); - I != E; ++I) { - assert(I->first && "Null MBB entry in cache"); - assert(I->second.first && "Null VNInfo in cache"); - assert(I->second.second && "Null DomTreeNode in cache"); - if (I->second.second->getBlock() == I->first) - continue; - for (MachineBasicBlock::pred_iterator PI = I->first->pred_begin(), - PE = I->first->pred_end(); PI != PE; ++PI) - assert(LiveOutCache.lookup(*PI) == I->second && "Bad invariant"); - } -#endif - - // Since we went through the trouble of a full BFS visiting all reaching defs, - // the values in LiveIn are now accurate. No more phi-defs are needed + // The values in LiveInBlocks are now accurate. No more phi-defs are needed // for these blocks, so we can color the live ranges. - // This makes the next mapValue call much faster. - for (unsigned i = 0, e = LiveIn.size(); i != e; ++i) { - MachineBasicBlock *MBB = LiveIn[i]->getBlock(); + for (SmallVectorImpl::iterator I = LiveInBlocks.begin(), + E = LiveInBlocks.end(); I != E; ++I) { + if (!I->DomNode) + continue; + assert(I->Value && "No live-in value found"); + MachineBasicBlock *MBB = I->DomNode->getBlock(); SlotIndex Start = LIS.getMBBStartIdx(MBB); - VNInfo *VNI = LiveOutCache.lookup(MBB).first; - - // Anything in LiveIn other than IdxMBB is live-through. - // In IdxMBB, we should stop at Idx unless the same value is live-out. - if (MBB == IdxMBB && IdxVNI != VNI) - LI->addRange(LiveRange(Start, Idx.getNextSlot(), IdxVNI)); - else - LI->addRange(LiveRange(Start, LIS.getMBBEndIdx(MBB), VNI)); + unsigned RegIdx = RegAssign.lookup(Start); + LiveInterval *LI = Edit->get(RegIdx); + LI->addRange(LiveRange(Start, I->Kill.isValid() ? + I->Kill : LIS.getMBBEndIdx(MBB), I->Value)); } - - return IdxVNI; -} - -#ifndef NDEBUG -void LiveIntervalMap::dumpCache() { - for (LiveOutMap::iterator I = LiveOutCache.begin(), E = LiveOutCache.end(); - I != E; ++I) { - assert(I->first && "Null MBB entry in cache"); - assert(I->second.first && "Null VNInfo in cache"); - assert(I->second.second && "Null DomTreeNode in cache"); - dbgs() << " cache: BB#" << I->first->getNumber() - << " has valno #" << I->second.first->id << " from BB#" - << I->second.second->getBlock()->getNumber() << ", preds"; - for (MachineBasicBlock::pred_iterator PI = I->first->pred_begin(), - PE = I->first->pred_end(); PI != PE; ++PI) - dbgs() << " BB#" << (*PI)->getNumber(); - dbgs() << '\n'; - } - dbgs() << " cache: " << LiveOutCache.size() << " entries.\n"; -} -#endif - -// extendTo - Find the last LI value defined in MBB at or before Idx. The -// ParentLI is assumed to be live at Idx. Extend the live range to Idx. -// Return the found VNInfo, or NULL. -VNInfo *LiveIntervalMap::extendTo(const MachineBasicBlock *MBB, SlotIndex Idx) { - assert(LI && "call reset first"); - LiveInterval::iterator I = std::upper_bound(LI->begin(), LI->end(), Idx); - if (I == LI->begin()) - return 0; - --I; - if (I->end <= LIS.getMBBStartIdx(MBB)) - return 0; - if (I->end <= Idx) - I->end = Idx.getNextSlot(); - return I->valno; -} - -// addSimpleRange - Add a simple range from ParentLI to LI. -// ParentVNI must be live in the [Start;End) interval. -void LiveIntervalMap::addSimpleRange(SlotIndex Start, SlotIndex End, - const VNInfo *ParentVNI) { - assert(LI && "call reset first"); - bool simple; - VNInfo *VNI = mapValue(ParentVNI, Start, &simple); - // A simple mapping is easy. - if (simple) { - LI->addRange(LiveRange(Start, End, VNI)); - return; - } - - // ParentVNI is a complex value. We must map per MBB. - MachineFunction::iterator MBB = LIS.getMBBFromIndex(Start); - MachineFunction::iterator MBBE = LIS.getMBBFromIndex(End.getPrevSlot()); - - if (MBB == MBBE) { - LI->addRange(LiveRange(Start, End, VNI)); - return; - } - - // First block. - LI->addRange(LiveRange(Start, LIS.getMBBEndIdx(MBB), VNI)); - - // Run sequence of full blocks. - for (++MBB; MBB != MBBE; ++MBB) { - Start = LIS.getMBBStartIdx(MBB); - LI->addRange(LiveRange(Start, LIS.getMBBEndIdx(MBB), - mapValue(ParentVNI, Start))); - } - - // Final block. - Start = LIS.getMBBStartIdx(MBB); - if (Start != End) - LI->addRange(LiveRange(Start, End, mapValue(ParentVNI, Start))); -} - -/// addRange - Add live ranges to LI where [Start;End) intersects ParentLI. -/// All needed values whose def is not inside [Start;End) must be defined -/// beforehand so mapValue will work. -void LiveIntervalMap::addRange(SlotIndex Start, SlotIndex End) { - assert(LI && "call reset first"); - LiveInterval::const_iterator B = ParentLI.begin(), E = ParentLI.end(); - LiveInterval::const_iterator I = std::lower_bound(B, E, Start); - - // Check if --I begins before Start and overlaps. - if (I != B) { - --I; - if (I->end > Start) - addSimpleRange(Start, std::min(End, I->end), I->valno); - ++I; - } - - // The remaining ranges begin after Start. - for (;I != E && I->start < End; ++I) - addSimpleRange(I->start, std::min(End, I->end), I->valno); -} - - -//===----------------------------------------------------------------------===// -// Split Editor -//===----------------------------------------------------------------------===// - -/// Create a new SplitEditor for editing the LiveInterval analyzed by SA. -SplitEditor::SplitEditor(SplitAnalysis &sa, - LiveIntervals &lis, - VirtRegMap &vrm, - MachineDominatorTree &mdt, - LiveRangeEdit &edit) - : SA(sa), LIS(lis), VRM(vrm), - MRI(vrm.getMachineFunction().getRegInfo()), - MDT(mdt), - TII(*vrm.getMachineFunction().getTarget().getInstrInfo()), - TRI(*vrm.getMachineFunction().getTarget().getRegisterInfo()), - Edit(edit), - OpenIdx(0), - RegAssign(Allocator) -{ - // We don't need an AliasAnalysis since we will only be performing - // cheap-as-a-copy remats anyway. - Edit.anyRematerializable(LIS, TII, 0); -} - -void SplitEditor::dump() const { - if (RegAssign.empty()) { - dbgs() << " empty\n"; - return; - } - - for (RegAssignMap::const_iterator I = RegAssign.begin(); I.valid(); ++I) - dbgs() << " [" << I.start() << ';' << I.stop() << "):" << I.value(); - dbgs() << '\n'; } VNInfo *SplitEditor::defFromParent(unsigned RegIdx, @@ -596,51 +577,53 @@ VNInfo *SplitEditor::defFromParent(unsigned RegIdx, MachineBasicBlock::iterator I) { MachineInstr *CopyMI = 0; SlotIndex Def; - LiveInterval *LI = Edit.get(RegIdx); + LiveInterval *LI = Edit->get(RegIdx); + + // We may be trying to avoid interference that ends at a deleted instruction, + // so always begin RegIdx 0 early and all others late. + bool Late = RegIdx != 0; // Attempt cheap-as-a-copy rematerialization. LiveRangeEdit::Remat RM(ParentVNI); - if (Edit.canRematerializeAt(RM, UseIdx, true, LIS)) { - Def = Edit.rematerializeAt(MBB, I, LI->reg, RM, LIS, TII, TRI); + if (Edit->canRematerializeAt(RM, UseIdx, true, LIS)) { + Def = Edit->rematerializeAt(MBB, I, LI->reg, RM, LIS, TII, TRI, Late); } else { // Can't remat, just insert a copy from parent. CopyMI = BuildMI(MBB, I, DebugLoc(), TII.get(TargetOpcode::COPY), LI->reg) - .addReg(Edit.getReg()); - Def = LIS.InsertMachineInstrInMaps(CopyMI).getDefIndex(); + .addReg(Edit->getReg()); + Def = LIS.getSlotIndexes()->insertMachineInstrInMaps(CopyMI, Late) + .getDefIndex(); } // Define the value in Reg. - VNInfo *VNI = LIMappers[RegIdx].defValue(ParentVNI, Def); + VNInfo *VNI = defValue(RegIdx, ParentVNI, Def); VNI->setCopy(CopyMI); - - // Add minimal liveness for the new value. - Edit.get(RegIdx)->addRange(LiveRange(Def, Def.getNextSlot(), VNI)); return VNI; } /// Create a new virtual register and live interval. -void SplitEditor::openIntv() { - assert(!OpenIdx && "Previous LI not closed before openIntv"); - +unsigned SplitEditor::openIntv() { // Create the complement as index 0. - if (Edit.empty()) { - Edit.create(MRI, LIS, VRM); - LIMappers.push_back(LiveIntervalMap(LIS, MDT, Edit.getParent())); - LIMappers.back().reset(Edit.get(0)); - } + if (Edit->empty()) + Edit->create(LIS, VRM); // Create the open interval. - OpenIdx = Edit.size(); - Edit.create(MRI, LIS, VRM); - LIMappers.push_back(LiveIntervalMap(LIS, MDT, Edit.getParent())); - LIMappers[OpenIdx].reset(Edit.get(OpenIdx)); + OpenIdx = Edit->size(); + Edit->create(LIS, VRM); + return OpenIdx; +} + +void SplitEditor::selectIntv(unsigned Idx) { + assert(Idx != 0 && "Cannot select the complement interval"); + assert(Idx < Edit->size() && "Can only select previously opened interval"); + OpenIdx = Idx; } SlotIndex SplitEditor::enterIntvBefore(SlotIndex Idx) { assert(OpenIdx && "openIntv not called before enterIntvBefore"); DEBUG(dbgs() << " enterIntvBefore " << Idx); Idx = Idx.getBaseIndex(); - VNInfo *ParentVNI = Edit.getParent().getVNInfoAt(Idx); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); if (!ParentVNI) { DEBUG(dbgs() << ": not live\n"); return Idx; @@ -658,14 +641,14 @@ SlotIndex SplitEditor::enterIntvAtEnd(MachineBasicBlock &MBB) { SlotIndex End = LIS.getMBBEndIdx(&MBB); SlotIndex Last = End.getPrevSlot(); DEBUG(dbgs() << " enterIntvAtEnd BB#" << MBB.getNumber() << ", " << Last); - VNInfo *ParentVNI = Edit.getParent().getVNInfoAt(Last); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Last); if (!ParentVNI) { DEBUG(dbgs() << ": not live\n"); return End; } DEBUG(dbgs() << ": valno " << ParentVNI->id); VNInfo *VNI = defFromParent(OpenIdx, ParentVNI, Last, MBB, - LIS.getLastSplitPoint(Edit.getParent(), &MBB)); + LIS.getLastSplitPoint(Edit->getParent(), &MBB)); RegAssign.insert(VNI->def, End, OpenIdx); DEBUG(dump()); return VNI->def; @@ -689,7 +672,7 @@ SlotIndex SplitEditor::leaveIntvAfter(SlotIndex Idx) { // The interval must be live beyond the instruction at Idx. Idx = Idx.getBoundaryIndex(); - VNInfo *ParentVNI = Edit.getParent().getVNInfoAt(Idx); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); if (!ParentVNI) { DEBUG(dbgs() << ": not live\n"); return Idx.getNextSlot(); @@ -709,7 +692,7 @@ SlotIndex SplitEditor::leaveIntvBefore(SlotIndex Idx) { // The interval must be live into the instruction at Idx. Idx = Idx.getBoundaryIndex(); - VNInfo *ParentVNI = Edit.getParent().getVNInfoAt(Idx); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); if (!ParentVNI) { DEBUG(dbgs() << ": not live\n"); return Idx.getNextSlot(); @@ -727,7 +710,7 @@ SlotIndex SplitEditor::leaveIntvAtTop(MachineBasicBlock &MBB) { SlotIndex Start = LIS.getMBBStartIdx(&MBB); DEBUG(dbgs() << " leaveIntvAtTop BB#" << MBB.getNumber() << ", " << Start); - VNInfo *ParentVNI = Edit.getParent().getVNInfoAt(Start); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Start); if (!ParentVNI) { DEBUG(dbgs() << ": not live\n"); return Start; @@ -742,30 +725,169 @@ SlotIndex SplitEditor::leaveIntvAtTop(MachineBasicBlock &MBB) { void SplitEditor::overlapIntv(SlotIndex Start, SlotIndex End) { assert(OpenIdx && "openIntv not called before overlapIntv"); - assert(Edit.getParent().getVNInfoAt(Start) == - Edit.getParent().getVNInfoAt(End.getPrevSlot()) && + const VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Start); + assert(ParentVNI == Edit->getParent().getVNInfoAt(End.getPrevSlot()) && "Parent changes value in extended range"); - assert(Edit.get(0)->getVNInfoAt(Start) && "Start must come from leaveIntv*"); assert(LIS.getMBBFromIndex(Start) == LIS.getMBBFromIndex(End) && "Range cannot span basic blocks"); - // Treat this as useIntv() for now. The complement interval will be extended - // as needed by mapValue(). + // The complement interval will be extended as needed by extendRange(). + if (ParentVNI) + markComplexMapped(0, ParentVNI); DEBUG(dbgs() << " overlapIntv [" << Start << ';' << End << "):"); RegAssign.insert(Start, End, OpenIdx); DEBUG(dump()); } -/// closeIntv - Indicate that we are done editing the currently open -/// LiveInterval, and ranges can be trimmed. -void SplitEditor::closeIntv() { - assert(OpenIdx && "openIntv not called before closeIntv"); - OpenIdx = 0; +/// transferValues - Transfer all possible values to the new live ranges. +/// Values that were rematerialized are left alone, they need extendRange(). +bool SplitEditor::transferValues() { + bool Skipped = false; + LiveInBlocks.clear(); + RegAssignMap::const_iterator AssignI = RegAssign.begin(); + for (LiveInterval::const_iterator ParentI = Edit->getParent().begin(), + ParentE = Edit->getParent().end(); ParentI != ParentE; ++ParentI) { + DEBUG(dbgs() << " blit " << *ParentI << ':'); + VNInfo *ParentVNI = ParentI->valno; + // RegAssign has holes where RegIdx 0 should be used. + SlotIndex Start = ParentI->start; + AssignI.advanceTo(Start); + do { + unsigned RegIdx; + SlotIndex End = ParentI->end; + if (!AssignI.valid()) { + RegIdx = 0; + } else if (AssignI.start() <= Start) { + RegIdx = AssignI.value(); + if (AssignI.stop() < End) { + End = AssignI.stop(); + ++AssignI; + } + } else { + RegIdx = 0; + End = std::min(End, AssignI.start()); + } + + // The interval [Start;End) is continuously mapped to RegIdx, ParentVNI. + DEBUG(dbgs() << " [" << Start << ';' << End << ")=" << RegIdx); + LiveInterval *LI = Edit->get(RegIdx); + + // Check for a simply defined value that can be blitted directly. + if (VNInfo *VNI = Values.lookup(std::make_pair(RegIdx, ParentVNI->id))) { + DEBUG(dbgs() << ':' << VNI->id); + LI->addRange(LiveRange(Start, End, VNI)); + Start = End; + continue; + } + + // Skip rematerialized values, we need to use extendRange() and + // extendPHIKillRanges() to completely recompute the live ranges. + if (Edit->didRematerialize(ParentVNI)) { + DEBUG(dbgs() << "(remat)"); + Skipped = true; + Start = End; + continue; + } + + // Initialize the live-out cache the first time it is needed. + if (LiveOutSeen.empty()) { + unsigned N = VRM.getMachineFunction().getNumBlockIDs(); + LiveOutSeen.resize(N); + LiveOutCache.resize(N); + } + + // This value has multiple defs in RegIdx, but it wasn't rematerialized, + // so the live range is accurate. Add live-in blocks in [Start;End) to the + // LiveInBlocks. + MachineFunction::iterator MBB = LIS.getMBBFromIndex(Start); + SlotIndex BlockStart, BlockEnd; + tie(BlockStart, BlockEnd) = LIS.getSlotIndexes()->getMBBRange(MBB); + + // The first block may be live-in, or it may have its own def. + if (Start != BlockStart) { + VNInfo *VNI = LI->extendInBlock(BlockStart, + std::min(BlockEnd, End).getPrevSlot()); + assert(VNI && "Missing def for complex mapped value"); + DEBUG(dbgs() << ':' << VNI->id << "*BB#" << MBB->getNumber()); + // MBB has its own def. Is it also live-out? + if (BlockEnd <= End) { + LiveOutSeen.set(MBB->getNumber()); + LiveOutCache[MBB] = LiveOutPair(VNI, MDT[MBB]); + } + // Skip to the next block for live-in. + ++MBB; + BlockStart = BlockEnd; + } + + // Handle the live-in blocks covered by [Start;End). + assert(Start <= BlockStart && "Expected live-in block"); + while (BlockStart < End) { + DEBUG(dbgs() << ">BB#" << MBB->getNumber()); + BlockEnd = LIS.getMBBEndIdx(MBB); + if (BlockStart == ParentVNI->def) { + // This block has the def of a parent PHI, so it isn't live-in. + assert(ParentVNI->isPHIDef() && "Non-phi defined at block start?"); + VNInfo *VNI = LI->extendInBlock(BlockStart, + std::min(BlockEnd, End).getPrevSlot()); + assert(VNI && "Missing def for complex mapped parent PHI"); + if (End >= BlockEnd) { + // Live-out as well. + LiveOutSeen.set(MBB->getNumber()); + LiveOutCache[MBB] = LiveOutPair(VNI, MDT[MBB]); + } + } else { + // This block needs a live-in value. + LiveInBlocks.push_back(MDT[MBB]); + // The last block covered may not be live-out. + if (End < BlockEnd) + LiveInBlocks.back().Kill = End; + else { + // Live-out, but we need updateSSA to tell us the value. + LiveOutSeen.set(MBB->getNumber()); + LiveOutCache[MBB] = LiveOutPair((VNInfo*)0, + (MachineDomTreeNode*)0); + } + } + BlockStart = BlockEnd; + ++MBB; + } + Start = End; + } while (Start != ParentI->end); + DEBUG(dbgs() << '\n'); + } + + if (!LiveInBlocks.empty()) + updateSSA(); + + return Skipped; } -/// rewriteAssigned - Rewrite all uses of Edit.getReg(). -void SplitEditor::rewriteAssigned() { - for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Edit.getReg()), +void SplitEditor::extendPHIKillRanges() { + // Extend live ranges to be live-out for successor PHI values. + for (LiveInterval::const_vni_iterator I = Edit->getParent().vni_begin(), + E = Edit->getParent().vni_end(); I != E; ++I) { + const VNInfo *PHIVNI = *I; + if (PHIVNI->isUnused() || !PHIVNI->isPHIDef()) + continue; + unsigned RegIdx = RegAssign.lookup(PHIVNI->def); + MachineBasicBlock *MBB = LIS.getMBBFromIndex(PHIVNI->def); + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + SlotIndex End = LIS.getMBBEndIdx(*PI).getPrevSlot(); + // The predecessor may not have a live-out value. That is OK, like an + // undef PHI operand. + if (Edit->getParent().liveAt(End)) { + assert(RegAssign.lookup(End) == RegIdx && + "Different register assignment in phi predecessor"); + extendRange(RegIdx, End); + } + } + } +} + +/// rewriteAssigned - Rewrite all uses of Edit->getReg(). +void SplitEditor::rewriteAssigned(bool ExtendRanges) { + for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Edit->getReg()), RE = MRI.reg_end(); RI != RE;) { MachineOperand &MO = RI.getOperand(); MachineInstr *MI = MO.getParent(); @@ -780,147 +902,145 @@ void SplitEditor::rewriteAssigned() { // operands don't really read the register, so just assign them to // the complement. if (MO.isUse() && MO.isUndef()) { - MO.setReg(Edit.get(0)->reg); + MO.setReg(Edit->get(0)->reg); continue; } SlotIndex Idx = LIS.getInstructionIndex(MI); - Idx = MO.isUse() ? Idx.getUseIndex() : Idx.getDefIndex(); + if (MO.isDef()) + Idx = MO.isEarlyClobber() ? Idx.getUseIndex() : Idx.getDefIndex(); // Rewrite to the mapped register at Idx. unsigned RegIdx = RegAssign.lookup(Idx); - MO.setReg(Edit.get(RegIdx)->reg); + MO.setReg(Edit->get(RegIdx)->reg); DEBUG(dbgs() << " rewr BB#" << MI->getParent()->getNumber() << '\t' << Idx << ':' << RegIdx << '\t' << *MI); - // Extend liveness to Idx. - const VNInfo *ParentVNI = Edit.getParent().getVNInfoAt(Idx); - LIMappers[RegIdx].mapValue(ParentVNI, Idx); - } -} - -/// rewriteSplit - Rewrite uses of Intvs[0] according to the ConEQ mapping. -void SplitEditor::rewriteComponents(const SmallVectorImpl &Intvs, - const ConnectedVNInfoEqClasses &ConEq) { - for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Intvs[0]->reg), - RE = MRI.reg_end(); RI != RE;) { - MachineOperand &MO = RI.getOperand(); - MachineInstr *MI = MO.getParent(); - ++RI; - if (MO.isUse() && MO.isUndef()) + // Extend liveness to Idx if the instruction reads reg. + if (!ExtendRanges) continue; - // DBG_VALUE instructions should have been eliminated earlier. - SlotIndex Idx = LIS.getInstructionIndex(MI); - Idx = MO.isUse() ? Idx.getUseIndex() : Idx.getDefIndex(); - DEBUG(dbgs() << " rewr BB#" << MI->getParent()->getNumber() << '\t' - << Idx << ':'); - const VNInfo *VNI = Intvs[0]->getVNInfoAt(Idx); - assert(VNI && "Interval not live at use."); - MO.setReg(Intvs[ConEq.getEqClass(VNI)]->reg); - DEBUG(dbgs() << VNI->id << '\t' << *MI); + + // Skip instructions that don't read Reg. + if (MO.isDef()) { + if (!MO.getSubReg() && !MO.isEarlyClobber()) + continue; + // We may wan't to extend a live range for a partial redef, or for a use + // tied to an early clobber. + Idx = Idx.getPrevSlot(); + if (!Edit->getParent().liveAt(Idx)) + continue; + } else + Idx = Idx.getUseIndex(); + + extendRange(RegIdx, Idx); } } -void SplitEditor::finish() { - assert(OpenIdx == 0 && "Previous LI not closed before rewrite"); +void SplitEditor::deleteRematVictims() { + SmallVector Dead; + for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I){ + LiveInterval *LI = *I; + for (LiveInterval::const_iterator LII = LI->begin(), LIE = LI->end(); + LII != LIE; ++LII) { + // Dead defs end at the store slot. + if (LII->end != LII->valno->def.getNextSlot()) + continue; + MachineInstr *MI = LIS.getInstructionFromIndex(LII->valno->def); + assert(MI && "Missing instruction for dead def"); + MI->addRegisterDead(LI->reg, &TRI); + + if (!MI->allDefsAreDead()) + continue; + + DEBUG(dbgs() << "All defs dead: " << *MI); + Dead.push_back(MI); + } + } + + if (Dead.empty()) + return; + + Edit->eliminateDeadDefs(Dead, LIS, VRM, TII); +} + +void SplitEditor::finish(SmallVectorImpl *LRMap) { + ++NumFinished; // At this point, the live intervals in Edit contain VNInfos corresponding to // the inserted copies. // Add the original defs from the parent interval. - for (LiveInterval::const_vni_iterator I = Edit.getParent().vni_begin(), - E = Edit.getParent().vni_end(); I != E; ++I) { + for (LiveInterval::const_vni_iterator I = Edit->getParent().vni_begin(), + E = Edit->getParent().vni_end(); I != E; ++I) { const VNInfo *ParentVNI = *I; if (ParentVNI->isUnused()) continue; - LiveIntervalMap &LIM = LIMappers[RegAssign.lookup(ParentVNI->def)]; - VNInfo *VNI = LIM.defValue(ParentVNI, ParentVNI->def); - LIM.getLI()->addRange(LiveRange(ParentVNI->def, - ParentVNI->def.getNextSlot(), VNI)); - // Mark all values as complex to force liveness computation. - // This should really only be necessary for remat victims, but we are lazy. - LIM.markComplexMapped(ParentVNI); + unsigned RegIdx = RegAssign.lookup(ParentVNI->def); + VNInfo *VNI = defValue(RegIdx, ParentVNI, ParentVNI->def); + VNI->setIsPHIDef(ParentVNI->isPHIDef()); + VNI->setCopy(ParentVNI->getCopy()); + + // Mark rematted values as complex everywhere to force liveness computation. + // The new live ranges may be truncated. + if (Edit->didRematerialize(ParentVNI)) + for (unsigned i = 0, e = Edit->size(); i != e; ++i) + markComplexMapped(i, ParentVNI); } #ifndef NDEBUG // Every new interval must have a def by now, otherwise the split is bogus. - for (LiveRangeEdit::iterator I = Edit.begin(), E = Edit.end(); I != E; ++I) + for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I) assert((*I)->hasAtLeastOneValue() && "Split interval has no value"); #endif - // FIXME: Don't recompute the liveness of all values, infer it from the - // overlaps between the parent live interval and RegAssign. - // The mapValue algorithm is only necessary when: - // - The parent value maps to multiple defs, and new phis are needed, or - // - The value has been rematerialized before some uses, and we want to - // minimize the live range so it only reaches the remaining uses. - // All other values have simple liveness that can be computed from RegAssign - // and the parent live interval. + // Transfer the simply mapped values, check if any are skipped. + bool Skipped = transferValues(); + if (Skipped) + extendPHIKillRanges(); + else + ++NumSimple; - // Extend live ranges to be live-out for successor PHI values. - for (LiveInterval::const_vni_iterator I = Edit.getParent().vni_begin(), - E = Edit.getParent().vni_end(); I != E; ++I) { - const VNInfo *PHIVNI = *I; - if (PHIVNI->isUnused() || !PHIVNI->isPHIDef()) - continue; - unsigned RegIdx = RegAssign.lookup(PHIVNI->def); - LiveIntervalMap &LIM = LIMappers[RegIdx]; - MachineBasicBlock *MBB = LIS.getMBBFromIndex(PHIVNI->def); - DEBUG(dbgs() << " map phi in BB#" << MBB->getNumber() << '@' << PHIVNI->def - << " -> " << RegIdx << '\n'); - for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), - PE = MBB->pred_end(); PI != PE; ++PI) { - SlotIndex End = LIS.getMBBEndIdx(*PI).getPrevSlot(); - DEBUG(dbgs() << " pred BB#" << (*PI)->getNumber() << '@' << End); - // The predecessor may not have a live-out value. That is OK, like an - // undef PHI operand. - if (VNInfo *VNI = Edit.getParent().getVNInfoAt(End)) { - DEBUG(dbgs() << " has parent valno #" << VNI->id << " live out\n"); - assert(RegAssign.lookup(End) == RegIdx && - "Different register assignment in phi predecessor"); - LIM.mapValue(VNI, End); - } - else - DEBUG(dbgs() << " is not live-out\n"); - } - DEBUG(dbgs() << " " << *LIM.getLI() << '\n'); - } + // Rewrite virtual registers, possibly extending ranges. + rewriteAssigned(Skipped); - // Rewrite instructions. - rewriteAssigned(); - - // FIXME: Delete defs that were rematted everywhere. + // Delete defs that were rematted everywhere. + if (Skipped) + deleteRematVictims(); // Get rid of unused values and set phi-kill flags. - for (LiveRangeEdit::iterator I = Edit.begin(), E = Edit.end(); I != E; ++I) + for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I) (*I)->RenumberValues(LIS); + // Provide a reverse mapping from original indices to Edit ranges. + if (LRMap) { + LRMap->clear(); + for (unsigned i = 0, e = Edit->size(); i != e; ++i) + LRMap->push_back(i); + } + // Now check if any registers were separated into multiple components. ConnectedVNInfoEqClasses ConEQ(LIS); - for (unsigned i = 0, e = Edit.size(); i != e; ++i) { + for (unsigned i = 0, e = Edit->size(); i != e; ++i) { // Don't use iterators, they are invalidated by create() below. - LiveInterval *li = Edit.get(i); + LiveInterval *li = Edit->get(i); unsigned NumComp = ConEQ.Classify(li); if (NumComp <= 1) continue; DEBUG(dbgs() << " " << NumComp << " components: " << *li << '\n'); SmallVector dups; dups.push_back(li); - for (unsigned i = 1; i != NumComp; ++i) - dups.push_back(&Edit.create(MRI, LIS, VRM)); - rewriteComponents(dups, ConEQ); - ConEQ.Distribute(&dups[0]); + for (unsigned j = 1; j != NumComp; ++j) + dups.push_back(&Edit->create(LIS, VRM)); + ConEQ.Distribute(&dups[0], MRI); + // The new intervals all map back to i. + if (LRMap) + LRMap->resize(Edit->size(), i); } // Calculate spill weight and allocation hints for new intervals. - VirtRegAuxInfo vrai(VRM.getMachineFunction(), LIS, SA.Loops); - for (LiveRangeEdit::iterator I = Edit.begin(), E = Edit.end(); I != E; ++I){ - LiveInterval &li = **I; - vrai.CalculateRegClass(li.reg); - vrai.CalculateWeightAndHint(li); - DEBUG(dbgs() << " new interval " << MRI.getRegClass(li.reg)->getName() - << ":" << li << '\n'); - } + Edit->calculateRegClassAndHint(VRM.getMachineFunction(), LIS, SA.Loops); + + assert(!LRMap || LRMap->size() == Edit->size()); } @@ -932,113 +1052,42 @@ void SplitEditor::finish() { /// may be an advantage to split CurLI for the duration of the block. bool SplitAnalysis::getMultiUseBlocks(BlockPtrSet &Blocks) { // If CurLI is local to one block, there is no point to splitting it. - if (LiveBlocks.size() <= 1) + if (UseBlocks.size() <= 1) return false; // Add blocks with multiple uses. - for (unsigned i = 0, e = LiveBlocks.size(); i != e; ++i) { - const BlockInfo &BI = LiveBlocks[i]; - if (!BI.Uses) - continue; - unsigned Instrs = UsingBlocks.lookup(BI.MBB); - if (Instrs <= 1) - continue; - if (Instrs == 2 && BI.LiveIn && BI.LiveOut && !BI.LiveThrough) + for (unsigned i = 0, e = UseBlocks.size(); i != e; ++i) { + const BlockInfo &BI = UseBlocks[i]; + if (BI.FirstUse == BI.LastUse) continue; Blocks.insert(BI.MBB); } return !Blocks.empty(); } +void SplitEditor::splitSingleBlock(const SplitAnalysis::BlockInfo &BI) { + openIntv(); + SlotIndex LastSplitPoint = SA.getLastSplitPoint(BI.MBB->getNumber()); + SlotIndex SegStart = enterIntvBefore(std::min(BI.FirstUse, + LastSplitPoint)); + if (!BI.LiveOut || BI.LastUse < LastSplitPoint) { + useIntv(SegStart, leaveIntvAfter(BI.LastUse)); + } else { + // The last use is after the last valid split point. + SlotIndex SegStop = leaveIntvBefore(LastSplitPoint); + useIntv(SegStart, SegStop); + overlapIntv(SegStop, BI.LastUse); + } +} + /// splitSingleBlocks - Split CurLI into a separate live interval inside each /// basic block in Blocks. void SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) { DEBUG(dbgs() << " splitSingleBlocks for " << Blocks.size() << " blocks.\n"); - - for (unsigned i = 0, e = SA.LiveBlocks.size(); i != e; ++i) { - const SplitAnalysis::BlockInfo &BI = SA.LiveBlocks[i]; - if (!BI.Uses || !Blocks.count(BI.MBB)) - continue; - - openIntv(); - SlotIndex SegStart = enterIntvBefore(BI.FirstUse); - if (!BI.LiveOut || BI.LastUse < BI.LastSplitPoint) { - useIntv(SegStart, leaveIntvAfter(BI.LastUse)); - } else { - // The last use is after the last valid split point. - SlotIndex SegStop = leaveIntvBefore(BI.LastSplitPoint); - useIntv(SegStart, SegStop); - overlapIntv(SegStop, BI.LastUse); - } - closeIntv(); + ArrayRef UseBlocks = SA.getUseBlocks(); + for (unsigned i = 0; i != UseBlocks.size(); ++i) { + const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; + if (Blocks.count(BI.MBB)) + splitSingleBlock(BI); } finish(); } - - -//===----------------------------------------------------------------------===// -// Sub Block Splitting -//===----------------------------------------------------------------------===// - -/// getBlockForInsideSplit - If CurLI is contained inside a single basic block, -/// and it wou pay to subdivide the interval inside that block, return it. -/// Otherwise return NULL. The returned block can be passed to -/// SplitEditor::splitInsideBlock. -const MachineBasicBlock *SplitAnalysis::getBlockForInsideSplit() { - // The interval must be exclusive to one block. - if (UsingBlocks.size() != 1) - return 0; - // Don't to this for less than 4 instructions. We want to be sure that - // splitting actually reduces the instruction count per interval. - if (UsingInstrs.size() < 4) - return 0; - return UsingBlocks.begin()->first; -} - -/// splitInsideBlock - Split CurLI into multiple intervals inside MBB. -void SplitEditor::splitInsideBlock(const MachineBasicBlock *MBB) { - SmallVector Uses; - Uses.reserve(SA.UsingInstrs.size()); - for (SplitAnalysis::InstrPtrSet::const_iterator I = SA.UsingInstrs.begin(), - E = SA.UsingInstrs.end(); I != E; ++I) - if ((*I)->getParent() == MBB) - Uses.push_back(LIS.getInstructionIndex(*I)); - DEBUG(dbgs() << " splitInsideBlock BB#" << MBB->getNumber() << " for " - << Uses.size() << " instructions.\n"); - assert(Uses.size() >= 3 && "Need at least 3 instructions"); - array_pod_sort(Uses.begin(), Uses.end()); - - // Simple algorithm: Find the largest gap between uses as determined by slot - // indices. Create new intervals for instructions before the gap and after the - // gap. - unsigned bestPos = 0; - int bestGap = 0; - DEBUG(dbgs() << " dist (" << Uses[0]); - for (unsigned i = 1, e = Uses.size(); i != e; ++i) { - int g = Uses[i-1].distance(Uses[i]); - DEBUG(dbgs() << ") -" << g << "- (" << Uses[i]); - if (g > bestGap) - bestPos = i, bestGap = g; - } - DEBUG(dbgs() << "), best: -" << bestGap << "-\n"); - - // bestPos points to the first use after the best gap. - assert(bestPos > 0 && "Invalid gap"); - - // FIXME: Don't create intervals for low densities. - - // First interval before the gap. Don't create single-instr intervals. - if (bestPos > 1) { - openIntv(); - useIntv(enterIntvBefore(Uses.front()), leaveIntvAfter(Uses[bestPos-1])); - closeIntv(); - } - - // Second interval after the gap. - if (bestPos < Uses.size()-1) { - openIntv(); - useIntv(enterIntvBefore(Uses[bestPos]), leaveIntvAfter(Uses.back())); - closeIntv(); - } - - finish(); -} diff --git a/contrib/llvm/lib/CodeGen/SplitKit.h b/contrib/llvm/lib/CodeGen/SplitKit.h index e02e6297035d..2ae760a58da5 100644 --- a/contrib/llvm/lib/CodeGen/SplitKit.h +++ b/contrib/llvm/lib/CodeGen/SplitKit.h @@ -12,7 +12,13 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_CODEGEN_SPLITKIT_H +#define LLVM_CODEGEN_SPLITKIT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/CodeGen/SlotIndexes.h" @@ -48,17 +54,9 @@ class SplitAnalysis { const MachineLoopInfo &Loops; const TargetInstrInfo &TII; - // Instructions using the the current register. - typedef SmallPtrSet InstrPtrSet; - InstrPtrSet UsingInstrs; - // Sorted slot indexes of using instructions. SmallVector UseSlots; - // The number of instructions using CurLI in each basic block. - typedef DenseMap BlockCountMap; - BlockCountMap UsingBlocks; - /// Additional information about basic blocks where the current variable is /// live. Such a block will look like one of these templates: /// @@ -75,35 +73,37 @@ class SplitAnalysis { SlotIndex LastUse; ///< Last instr using current reg. SlotIndex Kill; ///< Interval end point inside block. SlotIndex Def; ///< Interval start point inside block. - /// Last possible point for splitting live ranges. - SlotIndex LastSplitPoint; - bool Uses; ///< Current reg has uses or defs in block. bool LiveThrough; ///< Live in whole block (Templ 5. or 6. above). bool LiveIn; ///< Current reg is live in. bool LiveOut; ///< Current reg is live out. - - // Per-interference pattern scratch data. - bool OverlapEntry; ///< Interference overlaps entering interval. - bool OverlapExit; ///< Interference overlaps exiting interval. }; - /// Basic blocks where var is live. This array is parallel to - /// SpillConstraints. - SmallVector LiveBlocks; - private: // Current live interval. const LiveInterval *CurLI; + /// LastSplitPoint - Last legal split point in each basic block in the current + /// function. The first entry is the first terminator, the second entry is the + /// last valid split point for a variable that is live in to a landing pad + /// successor. + SmallVector, 8> LastSplitPoint; + + /// UseBlocks - Blocks where CurLI has uses. + SmallVector UseBlocks; + + /// ThroughBlocks - Block numbers where CurLI is live through without uses. + BitVector ThroughBlocks; + + /// NumThroughBlocks - Number of live-through blocks. + unsigned NumThroughBlocks; + + SlotIndex computeLastSplitPoint(unsigned Num); + // Sumarize statistics by counting instructions using CurLI. void analyzeUses(); /// calcLiveBlockInfo - Compute per-block information about CurLI. - void calcLiveBlockInfo(); - - /// canAnalyzeBranch - Return true if MBB ends in a branch that can be - /// analyzed. - bool canAnalyzeBranch(const MachineBasicBlock *MBB); + bool calcLiveBlockInfo(); public: SplitAnalysis(const VirtRegMap &vrm, const LiveIntervals &lis, @@ -120,9 +120,14 @@ class SplitAnalysis { /// getParent - Return the last analyzed interval. const LiveInterval &getParent() const { return *CurLI; } - /// hasUses - Return true if MBB has any uses of CurLI. - bool hasUses(const MachineBasicBlock *MBB) const { - return UsingBlocks.lookup(MBB); + /// getLastSplitPoint - Return that base index of the last valid split point + /// in the basic block numbered Num. + SlotIndex getLastSplitPoint(unsigned Num) { + // Inline the common simple case. + if (LastSplitPoint[Num].first.isValid() && + !LastSplitPoint[Num].second.isValid()) + return LastSplitPoint[Num].first; + return computeLastSplitPoint(Num); } /// isOriginalEndpoint - Return true if the original live range was killed or @@ -132,127 +137,30 @@ class SplitAnalysis { /// splitting. bool isOriginalEndpoint(SlotIndex Idx) const; - typedef SmallPtrSet BlockPtrSet; + /// getUseBlocks - Return an array of BlockInfo objects for the basic blocks + /// where CurLI has uses. + ArrayRef getUseBlocks() { return UseBlocks; } - // Print a set of blocks with use counts. - void print(const BlockPtrSet&, raw_ostream&) const; + /// getNumThroughBlocks - Return the number of through blocks. + unsigned getNumThroughBlocks() const { return NumThroughBlocks; } + + /// isThroughBlock - Return true if CurLI is live through MBB without uses. + bool isThroughBlock(unsigned MBB) const { return ThroughBlocks.test(MBB); } + + /// getThroughBlocks - Return the set of through blocks. + const BitVector &getThroughBlocks() const { return ThroughBlocks; } + + /// countLiveBlocks - Return the number of blocks where li is live. + /// This is guaranteed to return the same number as getNumThroughBlocks() + + /// getUseBlocks().size() after calling analyze(li). + unsigned countLiveBlocks(const LiveInterval *li) const; + + typedef SmallPtrSet BlockPtrSet; /// getMultiUseBlocks - Add basic blocks to Blocks that may benefit from /// having CurLI split to a new live interval. Return true if Blocks can be /// passed to SplitEditor::splitSingleBlocks. bool getMultiUseBlocks(BlockPtrSet &Blocks); - - /// getBlockForInsideSplit - If CurLI is contained inside a single basic - /// block, and it would pay to subdivide the interval inside that block, - /// return it. Otherwise return NULL. The returned block can be passed to - /// SplitEditor::splitInsideBlock. - const MachineBasicBlock *getBlockForInsideSplit(); -}; - - -/// LiveIntervalMap - Map values from a large LiveInterval into a small -/// interval that is a subset. Insert phi-def values as needed. This class is -/// used by SplitEditor to create new smaller LiveIntervals. -/// -/// ParentLI is the larger interval, LI is the subset interval. Every value -/// in LI corresponds to exactly one value in ParentLI, and the live range -/// of the value is contained within the live range of the ParentLI value. -/// Values in ParentLI may map to any number of OpenLI values, including 0. -class LiveIntervalMap { - LiveIntervals &LIS; - MachineDominatorTree &MDT; - - // The parent interval is never changed. - const LiveInterval &ParentLI; - - // The child interval's values are fully contained inside ParentLI values. - LiveInterval *LI; - - typedef DenseMap ValueMap; - - // Map ParentLI values to simple values in LI that are defined at the same - // SlotIndex, or NULL for ParentLI values that have complex LI defs. - // Note there is a difference between values mapping to NULL (complex), and - // values not present (unknown/unmapped). - ValueMap Values; - - typedef std::pair LiveOutPair; - typedef DenseMap LiveOutMap; - - // LiveOutCache - Map each basic block where LI is live out to the live-out - // value and its defining block. One of these conditions shall be true: - // - // 1. !LiveOutCache.count(MBB) - // 2. LiveOutCache[MBB].second.getNode() == MBB - // 3. forall P in preds(MBB): LiveOutCache[P] == LiveOutCache[MBB] - // - // This is only a cache, the values can be computed as: - // - // VNI = LI->getVNInfoAt(LIS.getMBBEndIdx(MBB)) - // Node = mbt_[LIS.getMBBFromIndex(VNI->def)] - // - // The cache is also used as a visiteed set by mapValue(). - LiveOutMap LiveOutCache; - - // Dump the live-out cache to dbgs(). - void dumpCache(); - -public: - LiveIntervalMap(LiveIntervals &lis, - MachineDominatorTree &mdt, - const LiveInterval &parentli) - : LIS(lis), MDT(mdt), ParentLI(parentli), LI(0) {} - - /// reset - clear all data structures and start a new live interval. - void reset(LiveInterval *); - - /// getLI - return the current live interval. - LiveInterval *getLI() const { return LI; } - - /// defValue - define a value in LI from the ParentLI value VNI and Idx. - /// Idx does not have to be ParentVNI->def, but it must be contained within - /// ParentVNI's live range in ParentLI. - /// Return the new LI value. - VNInfo *defValue(const VNInfo *ParentVNI, SlotIndex Idx); - - /// mapValue - map ParentVNI to the corresponding LI value at Idx. It is - /// assumed that ParentVNI is live at Idx. - /// If ParentVNI has not been defined by defValue, it is assumed that - /// ParentVNI->def dominates Idx. - /// If ParentVNI has been defined by defValue one or more times, a value that - /// dominates Idx will be returned. This may require creating extra phi-def - /// values and adding live ranges to LI. - /// If simple is not NULL, *simple will indicate if ParentVNI is a simply - /// mapped value. - VNInfo *mapValue(const VNInfo *ParentVNI, SlotIndex Idx, bool *simple = 0); - - // extendTo - Find the last LI value defined in MBB at or before Idx. The - // parentli is assumed to be live at Idx. Extend the live range to include - // Idx. Return the found VNInfo, or NULL. - VNInfo *extendTo(const MachineBasicBlock *MBB, SlotIndex Idx); - - /// isMapped - Return true is ParentVNI is a known mapped value. It may be a - /// simple 1-1 mapping or a complex mapping to later defs. - bool isMapped(const VNInfo *ParentVNI) const { - return Values.count(ParentVNI); - } - - /// isComplexMapped - Return true if ParentVNI has received new definitions - /// with defValue. - bool isComplexMapped(const VNInfo *ParentVNI) const; - - /// markComplexMapped - Mark ParentVNI as complex mapped regardless of the - /// number of definitions. - void markComplexMapped(const VNInfo *ParentVNI) { Values[ParentVNI] = 0; } - - // addSimpleRange - Add a simple range from ParentLI to LI. - // ParentVNI must be live in the [Start;End) interval. - void addSimpleRange(SlotIndex Start, SlotIndex End, const VNInfo *ParentVNI); - - /// addRange - Add live ranges to LI where [Start;End) intersects ParentLI. - /// All needed values whose def is not inside [Start;End) must be defined - /// beforehand so mapValue will work. - void addRange(SlotIndex Start, SlotIndex End); }; @@ -277,7 +185,7 @@ class SplitEditor { const TargetRegisterInfo &TRI; /// Edit - The current parent register and new intervals created. - LiveRangeEdit &Edit; + LiveRangeEdit *Edit; /// Index into Edit of the currently open interval. /// The index 0 is used for the complement, so the first interval started by @@ -295,8 +203,76 @@ class SplitEditor { /// Idx. RegAssignMap RegAssign; - /// LIMappers - One LiveIntervalMap or each interval in Edit. - SmallVector LIMappers; + typedef DenseMap, VNInfo*> ValueMap; + + /// Values - keep track of the mapping from parent values to values in the new + /// intervals. Given a pair (RegIdx, ParentVNI->id), Values contains: + /// + /// 1. No entry - the value is not mapped to Edit.get(RegIdx). + /// 2. Null - the value is mapped to multiple values in Edit.get(RegIdx). + /// Each value is represented by a minimal live range at its def. + /// 3. A non-null VNInfo - the value is mapped to a single new value. + /// The new value has no live ranges anywhere. + ValueMap Values; + + typedef std::pair LiveOutPair; + typedef IndexedMap LiveOutMap; + + // LiveOutCache - Map each basic block where a new register is live out to the + // live-out value and its defining block. + // One of these conditions shall be true: + // + // 1. !LiveOutCache.count(MBB) + // 2. LiveOutCache[MBB].second.getNode() == MBB + // 3. forall P in preds(MBB): LiveOutCache[P] == LiveOutCache[MBB] + // + // This is only a cache, the values can be computed as: + // + // VNI = Edit.get(RegIdx)->getVNInfoAt(LIS.getMBBEndIdx(MBB)) + // Node = mbt_[LIS.getMBBFromIndex(VNI->def)] + // + // The cache is also used as a visited set by extendRange(). It can be shared + // by all the new registers because at most one is live out of each block. + LiveOutMap LiveOutCache; + + // LiveOutSeen - Indexed by MBB->getNumber(), a bit is set for each valid + // entry in LiveOutCache. + BitVector LiveOutSeen; + + /// LiveInBlock - Info for updateSSA() about a block where a register is + /// live-in. + /// The updateSSA caller provides DomNode and Kill inside MBB, updateSSA() + /// adds the computed live-in value. + struct LiveInBlock { + // Dominator tree node for the block. + // Cleared by updateSSA when the final value has been determined. + MachineDomTreeNode *DomNode; + + // Live-in value filled in by updateSSA once it is known. + VNInfo *Value; + + // Position in block where the live-in range ends, or SlotIndex() if the + // range passes through the block. + SlotIndex Kill; + + LiveInBlock(MachineDomTreeNode *node) : DomNode(node), Value(0) {} + }; + + /// LiveInBlocks - List of live-in blocks used by findReachingDefs() and + /// updateSSA(). This list is usually empty, it exists here to avoid frequent + /// reallocations. + SmallVector LiveInBlocks; + + /// defValue - define a value in RegIdx from ParentVNI at Idx. + /// Idx does not have to be ParentVNI->def, but it must be contained within + /// ParentVNI's live range in ParentLI. The new value is added to the value + /// map. + /// Return the new LI value. + VNInfo *defValue(unsigned RegIdx, const VNInfo *ParentVNI, SlotIndex Idx); + + /// markComplexMapped - Mark ParentVNI as complex mapped in RegIdx regardless + /// of the number of defs. + void markComplexMapped(unsigned RegIdx, const VNInfo *ParentVNI); /// defFromParent - Define Reg from ParentVNI at UseIdx using either /// rematerialization or a COPY from parent. Return the new value. @@ -306,27 +282,56 @@ class SplitEditor { MachineBasicBlock &MBB, MachineBasicBlock::iterator I); - /// rewriteAssigned - Rewrite all uses of Edit.getReg() to assigned registers. - void rewriteAssigned(); + /// extendRange - Extend the live range of Edit.get(RegIdx) so it reaches Idx. + /// Insert PHIDefs as needed to preserve SSA form. + void extendRange(unsigned RegIdx, SlotIndex Idx); - /// rewriteComponents - Rewrite all uses of Intv[0] according to the eq - /// classes in ConEQ. - /// This must be done when Intvs[0] is styill live at all uses, before calling - /// ConEq.Distribute(). - void rewriteComponents(const SmallVectorImpl &Intvs, - const ConnectedVNInfoEqClasses &ConEq); + /// findReachingDefs - Starting from MBB, add blocks to LiveInBlocks until all + /// reaching defs for LI are found. + /// @param LI Live interval whose value is needed. + /// @param MBB Block where LI should be live-in. + /// @param Kill Kill point in MBB. + /// @return Unique value seen, or NULL. + VNInfo *findReachingDefs(LiveInterval *LI, MachineBasicBlock *MBB, + SlotIndex Kill); + + /// updateSSA - Compute and insert PHIDefs such that all blocks in + // LiveInBlocks get a known live-in value. Add live ranges to the blocks. + void updateSSA(); + + /// transferValues - Transfer values to the new ranges. + /// Return true if any ranges were skipped. + bool transferValues(); + + /// extendPHIKillRanges - Extend the ranges of all values killed by original + /// parent PHIDefs. + void extendPHIKillRanges(); + + /// rewriteAssigned - Rewrite all uses of Edit.getReg() to assigned registers. + void rewriteAssigned(bool ExtendRanges); + + /// deleteRematVictims - Delete defs that are dead after rematerializing. + void deleteRematVictims(); public: /// Create a new SplitEditor for editing the LiveInterval analyzed by SA. /// Newly created intervals will be appended to newIntervals. SplitEditor(SplitAnalysis &SA, LiveIntervals&, VirtRegMap&, - MachineDominatorTree&, LiveRangeEdit&); + MachineDominatorTree&); - /// getAnalysis - Get the corresponding analysis. - SplitAnalysis &getAnalysis() { return SA; } + /// reset - Prepare for a new split. + void reset(LiveRangeEdit&); /// Create a new virtual register and live interval. - void openIntv(); + /// Return the interval index, starting from 1. Interval index 0 is the + /// implicit complement interval. + unsigned openIntv(); + + /// currentIntv - Return the current interval index. + unsigned currentIntv() const { return OpenIdx; } + + /// selectIntv - Select a previously opened interval index. + void selectIntv(unsigned Idx); /// enterIntvBefore - Enter the open interval before the instruction at Idx. /// If the parent interval is not live before Idx, a COPY is not inserted. @@ -369,25 +374,28 @@ class SplitEditor { /// void overlapIntv(SlotIndex Start, SlotIndex End); - /// closeIntv - Indicate that we are done editing the currently open - /// LiveInterval, and ranges can be trimmed. - void closeIntv(); - /// finish - after all the new live ranges have been created, compute the /// remaining live range, and rewrite instructions to use the new registers. - void finish(); + /// @param LRMap When not null, this vector will map each live range in Edit + /// back to the indices returned by openIntv. + /// There may be extra indices created by dead code elimination. + void finish(SmallVectorImpl *LRMap = 0); /// dump - print the current interval maping to dbgs(). void dump() const; // ===--- High level methods ---=== + /// splitSingleBlock - Split CurLI into a separate live interval around the + /// uses in a single block. This is intended to be used as part of a larger + /// split, and doesn't call finish(). + void splitSingleBlock(const SplitAnalysis::BlockInfo &BI); + /// splitSingleBlocks - Split CurLI into a separate live interval inside each /// basic block in Blocks. void splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks); - - /// splitInsideBlock - Split CurLI into multiple intervals inside MBB. - void splitInsideBlock(const MachineBasicBlock *); }; } + +#endif diff --git a/contrib/llvm/lib/CodeGen/StackProtector.cpp b/contrib/llvm/lib/CodeGen/StackProtector.cpp index fcaee4208ba3..f0a44abaf5cd 100644 --- a/contrib/llvm/lib/CodeGen/StackProtector.cpp +++ b/contrib/llvm/lib/CodeGen/StackProtector.cpp @@ -153,7 +153,6 @@ bool StackProtector::InsertStackProtectors() { for (Function::iterator I = F->begin(), E = F->end(); I != E; ) { BasicBlock *BB = I++; - ReturnInst *RI = dyn_cast(BB->getTerminator()); if (!RI) continue; @@ -191,8 +190,6 @@ bool StackProtector::InsertStackProtectors() { // Create the basic block to jump to when the guard check fails. FailBB = CreateFailBB(); - if (DT) - FailBBDom = DT->isReachableFromEntry(BB) ? BB : 0; } // For each block with a return instruction, convert this: @@ -219,9 +216,10 @@ bool StackProtector::InsertStackProtectors() { // Split the basic block before the return instruction. BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return"); - if (DT) { - DT->addNewBlock(NewBB, DT->isReachableFromEntry(BB) ? BB : 0); - FailBBDom = DT->findNearestCommonDominator(FailBBDom, BB); + + if (DT && DT->isReachableFromEntry(BB)) { + DT->addNewBlock(NewBB, BB); + FailBBDom = FailBBDom ? DT->findNearestCommonDominator(FailBBDom, BB) :BB; } // Remove default branch instruction to the new BB. @@ -242,7 +240,7 @@ bool StackProtector::InsertStackProtectors() { // statements in the function. if (!FailBB) return false; - if (DT) + if (DT && FailBBDom) DT->addNewBlock(FailBB, FailBBDom); return true; diff --git a/contrib/llvm/lib/CodeGen/StrongPHIElimination.cpp b/contrib/llvm/lib/CodeGen/StrongPHIElimination.cpp index ec7829ec39fe..227eb47e6827 100644 --- a/contrib/llvm/lib/CodeGen/StrongPHIElimination.cpp +++ b/contrib/llvm/lib/CodeGen/StrongPHIElimination.cpp @@ -587,7 +587,7 @@ StrongPHIElimination::SplitInterferencesForBasicBlock( } // We now walk the PHIs in successor blocks and check for interferences. This - // is necesary because the use of a PHI's operands are logically contained in + // is necessary because the use of a PHI's operands are logically contained in // the predecessor block. The def of a PHI's destination register is processed // along with the other defs in a basic block. diff --git a/contrib/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp b/contrib/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp index 15340a3f1084..b9fcd3804d7f 100644 --- a/contrib/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp +++ b/contrib/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp @@ -388,11 +388,6 @@ isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, if (MO.isDef() != (i == 0)) return false; - // For the def, it should be the only def of that register. - if (MO.isDef() && (llvm::next(MRI.def_begin(Reg)) != MRI.def_end() || - MRI.isLiveIn(Reg))) - return false; - // Don't allow any virtual-register uses. Rematting an instruction with // virtual register uses would length the live ranges of the uses, which // is not necessarily a good idea, certainly not "trivial". diff --git a/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index fa311dc5d66c..6ed91b09966e 100644 --- a/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -23,6 +23,7 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" @@ -176,6 +177,52 @@ const MCSection *TargetLoweringObjectFileELF::getEHFrameSection() const { SectionKind::getDataRel()); } +MCSymbol * +TargetLoweringObjectFileELF::getCFIPersonalitySymbol(const GlobalValue *GV, + Mangler *Mang, + MachineModuleInfo *MMI) const { + unsigned Encoding = getPersonalityEncoding(); + switch (Encoding & 0x70) { + default: + report_fatal_error("We do not support this DWARF encoding yet!"); + case dwarf::DW_EH_PE_absptr: + return Mang->getSymbol(GV); + break; + case dwarf::DW_EH_PE_pcrel: { + Twine FullName = StringRef("DW.ref.") + Mang->getSymbol(GV)->getName(); + return getContext().GetOrCreateSymbol(FullName); + break; + } + } +} + +void TargetLoweringObjectFileELF::emitPersonalityValue(MCStreamer &Streamer, + const TargetMachine &TM, + const MCSymbol *Sym) const { + Twine FullName = StringRef("DW.ref.") + Sym->getName(); + MCSymbol *Label = getContext().GetOrCreateSymbol(FullName); + Streamer.EmitSymbolAttribute(Label, MCSA_Hidden); + Streamer.EmitSymbolAttribute(Label, MCSA_Weak); + Twine SectionName = StringRef(".data.") + Label->getName(); + SmallString<64> NameData; + SectionName.toVector(NameData); + unsigned Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_GROUP; + const MCSection *Sec = getContext().getELFSection(NameData, + ELF::SHT_PROGBITS, + Flags, + SectionKind::getDataRel(), + 0, Label->getName()); + Streamer.SwitchSection(Sec); + Streamer.EmitValueToAlignment(8); + Streamer.EmitSymbolAttribute(Label, MCSA_ELF_TypeObject); + const MCExpr *E = MCConstantExpr::Create(8, getContext()); + Streamer.EmitELFSize(Label, E); + Streamer.EmitLabel(Label); + + unsigned Size = TM.getTargetData()->getPointerSize(); + Streamer.EmitSymbolValue(Sym, Size); +} + static SectionKind getELFKindForNamedSection(StringRef Name, SectionKind K) { // FIXME: Why is this here? Codegen is should not be in the business @@ -424,8 +471,7 @@ getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, } return TargetLoweringObjectFile:: - getExprForDwarfReference(SSym, Mang, MMI, - Encoding & ~dwarf::DW_EH_PE_indirect, Streamer); + getExprForDwarfReference(SSym, Encoding & ~dwarf::DW_EH_PE_indirect, Streamer); } return TargetLoweringObjectFile:: @@ -446,18 +492,10 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, IsFunctionEHFrameSymbolPrivate = false; SupportsWeakOmittedEHFrame = false; + // .comm doesn't support alignment before Leopard. Triple T(((LLVMTargetMachine&)TM).getTargetTriple()); - if (T.getOS() == Triple::Darwin) { - switch (T.getDarwinMajorNumber()) { - case 7: // 10.3 Panther. - case 8: // 10.4 Tiger. - CommDirectiveSupportsAlignment = false; - break; - case 9: // 10.5 Leopard. - case 10: // 10.6 SnowLeopard. - break; - } - } + if (T.isMacOSX() && T.isMacOSXVersionLT(10, 5)) + CommDirectiveSupportsAlignment = false; TargetLoweringObjectFile::Initialize(Ctx, TM); @@ -641,10 +679,11 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { // Parse the section specifier and create it if valid. StringRef Segment, Section; - unsigned TAA = (unsigned)MCSectionMachO::SECTION_ATTRIBUTES, StubSize = 0; + unsigned TAA = 0, StubSize = 0; + bool TAAParsed; std::string ErrorCode = MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section, - TAA, StubSize); + TAA, TAAParsed, StubSize); if (!ErrorCode.empty()) { // If invalid, report the error with report_fatal_error. report_fatal_error("Global variable '" + GV->getNameStr() + @@ -654,17 +693,13 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, return DataSection; } - bool TAAWasSet = (TAA != MCSectionMachO::SECTION_ATTRIBUTES); - if (!TAAWasSet) - TAA = 0; // Sensible default if this is a new section. - // Get the section. const MCSectionMachO *S = getContext().getMachOSection(Segment, Section, TAA, StubSize, Kind); // If TAA wasn't set by ParseSectionSpecifier() above, // use the value returned by getMachOSection() as a default. - if (!TAAWasSet) + if (!TAAParsed) TAA = S->getTypeAndAttributes(); // Okay, now that we got the section, verify that the TAA & StubSize agree. @@ -806,14 +841,36 @@ getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, } return TargetLoweringObjectFile:: - getExprForDwarfReference(SSym, Mang, MMI, - Encoding & ~dwarf::DW_EH_PE_indirect, Streamer); + getExprForDwarfReference(SSym, Encoding & ~dwarf::DW_EH_PE_indirect, Streamer); } return TargetLoweringObjectFile:: getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, Streamer); } +MCSymbol *TargetLoweringObjectFileMachO:: +getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI) const { + // The mach-o version of this method defaults to returning a stub reference. + MachineModuleInfoMachO &MachOMMI = + MMI->getObjFileInfo(); + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, true); + Name += "$non_lazy_ptr"; + + // Add information about the stub reference to MachOMMI so that the stub + // gets emitted by the asmprinter. + MCSymbol *SSym = getContext().GetOrCreateSymbol(Name.str()); + MachineModuleInfoImpl::StubValueTy &StubSym = MachOMMI.getGVStubEntry(SSym); + if (StubSym.getPointer() == 0) { + MCSymbol *Sym = Mang->getSymbol(GV); + StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage()); + } + + return SSym; +} + unsigned TargetLoweringObjectFileMachO::getPersonalityEncoding() const { return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; } @@ -822,7 +879,7 @@ unsigned TargetLoweringObjectFileMachO::getLSDAEncoding() const { return DW_EH_PE_pcrel; } -unsigned TargetLoweringObjectFileMachO::getFDEEncoding() const { +unsigned TargetLoweringObjectFileMachO::getFDEEncoding(bool CFI) const { return DW_EH_PE_pcrel; } diff --git a/contrib/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/contrib/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp index b3120b8be1ab..52ea87231ccd 100644 --- a/contrib/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/contrib/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -105,7 +105,7 @@ namespace { MachineFunction::iterator &mbbi, unsigned RegB, unsigned RegC, unsigned Dist); - bool isProfitableToConv3Addr(unsigned RegA); + bool isProfitableToConv3Addr(unsigned RegA, unsigned RegB); bool ConvertInstTo3Addr(MachineBasicBlock::iterator &mi, MachineBasicBlock::iterator &nmi, @@ -124,7 +124,11 @@ namespace { MachineBasicBlock::iterator &nmi, MachineFunction::iterator &mbbi, unsigned SrcIdx, unsigned DstIdx, - unsigned Dist); + unsigned Dist, + SmallPtrSet &Processed); + + void ScanUses(unsigned DstReg, MachineBasicBlock *MBB, + SmallPtrSet &Processed); void ProcessCopy(MachineInstr *MI, MachineBasicBlock *MBB, SmallPtrSet &Processed); @@ -615,16 +619,18 @@ TwoAddressInstructionPass::CommuteInstruction(MachineBasicBlock::iterator &mi, /// isProfitableToConv3Addr - Return true if it is profitable to convert the /// given 2-address instruction to a 3-address one. bool -TwoAddressInstructionPass::isProfitableToConv3Addr(unsigned RegA) { +TwoAddressInstructionPass::isProfitableToConv3Addr(unsigned RegA,unsigned RegB){ // Look for situations like this: // %reg1024 = MOV r1 // %reg1025 = MOV r0 // %reg1026 = ADD %reg1024, %reg1025 // r2 = MOV %reg1026 // Turn ADD into a 3-address instruction to avoid a copy. - unsigned FromRegA = getMappedReg(RegA, SrcRegMap); + unsigned FromRegB = getMappedReg(RegB, SrcRegMap); + if (!FromRegB) + return false; unsigned ToRegA = getMappedReg(RegA, DstRegMap); - return (FromRegA && ToRegA && !regsAreCompatible(FromRegA, ToRegA, TRI)); + return (ToRegA && !regsAreCompatible(FromRegB, ToRegA, TRI)); } /// ConvertInstTo3Addr - Convert the specified two-address instruction into a @@ -664,6 +670,54 @@ TwoAddressInstructionPass::ConvertInstTo3Addr(MachineBasicBlock::iterator &mi, return false; } +/// ScanUses - Scan forward recursively for only uses, update maps if the use +/// is a copy or a two-address instruction. +void +TwoAddressInstructionPass::ScanUses(unsigned DstReg, MachineBasicBlock *MBB, + SmallPtrSet &Processed) { + SmallVector VirtRegPairs; + bool IsDstPhys; + bool IsCopy = false; + unsigned NewReg = 0; + unsigned Reg = DstReg; + while (MachineInstr *UseMI = findOnlyInterestingUse(Reg, MBB, MRI, TII,IsCopy, + NewReg, IsDstPhys)) { + if (IsCopy && !Processed.insert(UseMI)) + break; + + DenseMap::iterator DI = DistanceMap.find(UseMI); + if (DI != DistanceMap.end()) + // Earlier in the same MBB.Reached via a back edge. + break; + + if (IsDstPhys) { + VirtRegPairs.push_back(NewReg); + break; + } + bool isNew = SrcRegMap.insert(std::make_pair(NewReg, Reg)).second; + if (!isNew) + assert(SrcRegMap[NewReg] == Reg && "Can't map to two src registers!"); + VirtRegPairs.push_back(NewReg); + Reg = NewReg; + } + + if (!VirtRegPairs.empty()) { + unsigned ToReg = VirtRegPairs.back(); + VirtRegPairs.pop_back(); + while (!VirtRegPairs.empty()) { + unsigned FromReg = VirtRegPairs.back(); + VirtRegPairs.pop_back(); + bool isNew = DstRegMap.insert(std::make_pair(FromReg, ToReg)).second; + if (!isNew) + assert(DstRegMap[FromReg] == ToReg &&"Can't map to two dst registers!"); + ToReg = FromReg; + } + bool isNew = DstRegMap.insert(std::make_pair(DstReg, ToReg)).second; + if (!isNew) + assert(DstRegMap[DstReg] == ToReg && "Can't map to two dst registers!"); + } +} + /// ProcessCopy - If the specified instruction is not yet processed, process it /// if it's a copy. For a copy instruction, we find the physical registers the /// source and destination registers might be mapped to. These are kept in @@ -695,49 +749,11 @@ void TwoAddressInstructionPass::ProcessCopy(MachineInstr *MI, assert(SrcRegMap[DstReg] == SrcReg && "Can't map to two src physical registers!"); - SmallVector VirtRegPairs; - bool IsCopy = false; - unsigned NewReg = 0; - while (MachineInstr *UseMI = findOnlyInterestingUse(DstReg, MBB, MRI,TII, - IsCopy, NewReg, IsDstPhys)) { - if (IsCopy) { - if (!Processed.insert(UseMI)) - break; - } - - DenseMap::iterator DI = DistanceMap.find(UseMI); - if (DI != DistanceMap.end()) - // Earlier in the same MBB.Reached via a back edge. - break; - - if (IsDstPhys) { - VirtRegPairs.push_back(NewReg); - break; - } - bool isNew = SrcRegMap.insert(std::make_pair(NewReg, DstReg)).second; - if (!isNew) - assert(SrcRegMap[NewReg] == DstReg && - "Can't map to two src physical registers!"); - VirtRegPairs.push_back(NewReg); - DstReg = NewReg; - } - - if (!VirtRegPairs.empty()) { - unsigned ToReg = VirtRegPairs.back(); - VirtRegPairs.pop_back(); - while (!VirtRegPairs.empty()) { - unsigned FromReg = VirtRegPairs.back(); - VirtRegPairs.pop_back(); - bool isNew = DstRegMap.insert(std::make_pair(FromReg, ToReg)).second; - if (!isNew) - assert(DstRegMap[FromReg] == ToReg && - "Can't map to two dst physical registers!"); - ToReg = FromReg; - } - } + ScanUses(DstReg, MBB, Processed); } Processed.insert(MI); + return; } /// isSafeToDelete - If the specified instruction does not produce any side @@ -836,7 +852,8 @@ bool TwoAddressInstructionPass:: TryInstructionTransform(MachineBasicBlock::iterator &mi, MachineBasicBlock::iterator &nmi, MachineFunction::iterator &mbbi, - unsigned SrcIdx, unsigned DstIdx, unsigned Dist) { + unsigned SrcIdx, unsigned DstIdx, unsigned Dist, + SmallPtrSet &Processed) { const TargetInstrDesc &TID = mi->getDesc(); unsigned regA = mi->getOperand(DstIdx).getReg(); unsigned regB = mi->getOperand(SrcIdx).getReg(); @@ -887,10 +904,13 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi, return false; } + if (TargetRegisterInfo::isVirtualRegister(regA)) + ScanUses(regA, &*mbbi, Processed); + if (TID.isConvertibleTo3Addr()) { // This instruction is potentially convertible to a true // three-address instruction. Check if it is profitable. - if (!regBKilled || isProfitableToConv3Addr(regA)) { + if (!regBKilled || isProfitableToConv3Addr(regA, regB)) { // Try to convert it. if (ConvertInstTo3Addr(mi, nmi, mbbi, regA, regB, Dist)) { ++NumConvertedTo3Addr; @@ -951,7 +971,7 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi, MachineBasicBlock::iterator NewMI = NewMIs[1]; bool TransformSuccess = TryInstructionTransform(NewMI, mi, mbbi, - NewSrcIdx, NewDstIdx, Dist); + NewSrcIdx, NewDstIdx, Dist, Processed); if (TransformSuccess || NewMIs[1]->getOperand(NewSrcIdx).isKill()) { // Success, or at least we made an improvement. Keep the unfolded @@ -1100,7 +1120,8 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { mi->getOperand(DstIdx).getReg()) break; // Done with this instruction. - if (TryInstructionTransform(mi, nmi, mbbi, SrcIdx, DstIdx, Dist)) + if (TryInstructionTransform(mi, nmi, mbbi, SrcIdx, DstIdx, Dist, + Processed)) break; // The tied operands have been eliminated. } diff --git a/contrib/llvm/lib/CodeGen/VirtRegMap.cpp b/contrib/llvm/lib/CodeGen/VirtRegMap.cpp index 734b87e62f62..226b78f7bcbd 100644 --- a/contrib/llvm/lib/CodeGen/VirtRegMap.cpp +++ b/contrib/llvm/lib/CodeGen/VirtRegMap.cpp @@ -259,7 +259,9 @@ void VirtRegMap::rewrite(SlotIndexes *Indexes) { DEBUG(dbgs() << "********** REWRITE VIRTUAL REGISTERS **********\n" << "********** Function: " << MF->getFunction()->getName() << '\n'); - + DEBUG(dump()); + SmallVector SuperDeads; + SmallVector SuperDefs; SmallVector SuperKills; for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end(); @@ -283,12 +285,13 @@ void VirtRegMap::rewrite(SlotIndexes *Indexes) { if (MO.getSubReg()) { // A virtual register kill refers to the whole register, so we may // have to add operands for the super-register. - if (MO.isUse() && MO.isKill() && !MO.isUndef()) - SuperKills.push_back(PhysReg); - - // We don't have to deal with sub-register defs because - // LiveIntervalAnalysis already added the necessary - // operands. + if (MO.isUse()) { + if (MO.isKill() && !MO.isUndef()) + SuperKills.push_back(PhysReg); + } else if (MO.isDead()) + SuperDeads.push_back(PhysReg); + else + SuperDefs.push_back(PhysReg); // PhysReg operands cannot have subregister indexes. PhysReg = TRI->getSubReg(PhysReg, MO.getSubReg()); @@ -305,16 +308,28 @@ void VirtRegMap::rewrite(SlotIndexes *Indexes) { while (!SuperKills.empty()) MI->addRegisterKilled(SuperKills.pop_back_val(), TRI, true); + while (!SuperDeads.empty()) + MI->addRegisterDead(SuperDeads.pop_back_val(), TRI, true); + + while (!SuperDefs.empty()) + MI->addRegisterDefined(SuperDefs.pop_back_val(), TRI); + DEBUG(dbgs() << "> " << *MI); // Finally, remove any identity copies. if (MI->isIdentityCopy()) { - DEBUG(dbgs() << "Deleting identity copy.\n"); - RemoveMachineInstrFromMaps(MI); - if (Indexes) - Indexes->removeMachineInstrFromMaps(MI); - // It's safe to erase MI because MII has already been incremented. - MI->eraseFromParent(); + if (MI->getNumOperands() == 2) { + DEBUG(dbgs() << "Deleting identity copy.\n"); + RemoveMachineInstrFromMaps(MI); + if (Indexes) + Indexes->removeMachineInstrFromMaps(MI); + // It's safe to erase MI because MII has already been incremented. + MI->eraseFromParent(); + } else { + // Transform identity copy to a KILL to deal with subregisters. + MI->setDesc(TII->get(TargetOpcode::KILL)); + DEBUG(dbgs() << "Identity copy: " << *MI); + } } } } diff --git a/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp b/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp index ec149dddc1d9..185065880581 100644 --- a/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp +++ b/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp @@ -32,7 +32,7 @@ STATISTIC(NumCommutes, "Number of instructions commuted"); STATISTIC(NumDRM , "Number of re-materializable defs elided"); STATISTIC(NumStores , "Number of stores added"); STATISTIC(NumPSpills , "Number of physical register spills"); -STATISTIC(NumOmitted , "Number of reloads omited"); +STATISTIC(NumOmitted , "Number of reloads omitted"); STATISTIC(NumAvoided , "Number of reloads deemed unnecessary"); STATISTIC(NumCopified, "Number of available reloads turned into copies"); STATISTIC(NumReMats , "Number of re-materialization"); @@ -261,6 +261,10 @@ class AvailableSpills { /// now). void ModifyStackSlotOrReMat(int SlotOrReMat); + /// ClobberSharingStackSlots - When a register mapped to a stack slot changes, + /// other stack slots sharing the same register are no longer valid. + void ClobberSharingStackSlots(int StackSlot); + /// AddAvailableRegsToLiveIn - Availability information is being kept coming /// into the specified MBB. Add available physical registers as potential /// live-in's. If they are reused in the MBB, they will be added to the @@ -665,7 +669,7 @@ static void UpdateKills(MachineInstr &MI, const TargetRegisterInfo* TRI, } } -/// ReMaterialize - Re-materialize definition for Reg targetting DestReg. +/// ReMaterialize - Re-materialize definition for Reg targeting DestReg. /// static void ReMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MII, @@ -831,6 +835,26 @@ void AvailableSpills::ModifyStackSlotOrReMat(int SlotOrReMat) { PhysRegsAvailable.erase(I); } +void AvailableSpills::ClobberSharingStackSlots(int StackSlot) { + std::map::iterator It = + SpillSlotsOrReMatsAvailable.find(StackSlot); + if (It == SpillSlotsOrReMatsAvailable.end()) return; + unsigned Reg = It->second >> 1; + + // Erase entries in PhysRegsAvailable for other stack slots. + std::multimap::iterator I = PhysRegsAvailable.lower_bound(Reg); + while (I != PhysRegsAvailable.end() && I->first == Reg) { + std::multimap::iterator NextI = llvm::next(I); + if (I->second != StackSlot) { + DEBUG(dbgs() << "Clobbered sharing SS#" << I->second << " in " + << PrintReg(Reg, TRI) << '\n'); + SpillSlotsOrReMatsAvailable.erase(I->second); + PhysRegsAvailable.erase(I); + } + I = NextI; + } +} + // ************************** // // Reuse Info Implementation // // ************************** // @@ -1791,8 +1815,8 @@ bool LocalRewriter::InsertRestores(MachineInstr *MI, else DEBUG(dbgs() << "Reusing SS#" << SSorRMId); DEBUG(dbgs() << " from physreg " - << TRI->getName(InReg) << " for vreg" - << VirtReg <<" instead of reloading into physreg " + << TRI->getName(InReg) << " for " << PrintReg(VirtReg) + <<" instead of reloading into physreg " << TRI->getName(Phys) << '\n'); // Reusing a physreg may resurrect it. But we expect ProcessUses to update @@ -1807,8 +1831,8 @@ bool LocalRewriter::InsertRestores(MachineInstr *MI, else DEBUG(dbgs() << "Reusing SS#" << SSorRMId); DEBUG(dbgs() << " from physreg " - << TRI->getName(InReg) << " for vreg" - << VirtReg <<" by copying it into physreg " + << TRI->getName(InReg) << " for " << PrintReg(VirtReg) + <<" by copying it into physreg " << TRI->getName(Phys) << '\n'); // If the reloaded / remat value is available in another register, @@ -2025,7 +2049,8 @@ void LocalRewriter::ProcessUses(MachineInstr &MI, AvailableSpills &Spills, TRI->regsOverlap(MOk.getReg(), PhysReg)) { CanReuse = false; DEBUG(dbgs() << "Not reusing physreg " << TRI->getName(PhysReg) - << " for vreg" << VirtReg << ": " << MOk << '\n'); + << " for " << PrintReg(VirtReg) << ": " << MOk + << '\n'); break; } } @@ -2039,9 +2064,9 @@ void LocalRewriter::ProcessUses(MachineInstr &MI, AvailableSpills &Spills, else DEBUG(dbgs() << "Reusing SS#" << ReuseSlot); DEBUG(dbgs() << " from physreg " - << TRI->getName(PhysReg) << " for vreg" - << VirtReg <<" instead of reloading into physreg " - << TRI->getName(VRM->getPhys(VirtReg)) << '\n'); + << TRI->getName(PhysReg) << " for " << PrintReg(VirtReg) + << " instead of reloading into " + << PrintReg(VRM->getPhys(VirtReg), TRI) << '\n'); unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; MI.getOperand(i).setReg(RReg); MI.getOperand(i).setSubReg(0); @@ -2126,7 +2151,7 @@ void LocalRewriter::ProcessUses(MachineInstr &MI, AvailableSpills &Spills, else DEBUG(dbgs() << "Reusing SS#" << ReuseSlot); DEBUG(dbgs() << " from physreg " << TRI->getName(PhysReg) - << " for vreg" << VirtReg + << " for " << PrintReg(VirtReg) << " instead of reloading into same physreg.\n"); unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; MI.getOperand(i).setReg(RReg); @@ -2315,7 +2340,7 @@ LocalRewriter::RewriteMBB(LiveIntervals *LIs, for (unsigned FVI = 0, FVE = FoldedVirts.size(); FVI != FVE; ++FVI) { unsigned VirtReg = FoldedVirts[FVI].first; VirtRegMap::ModRef MR = FoldedVirts[FVI].second; - DEBUG(dbgs() << "Folded vreg: " << VirtReg << " MR: " << MR); + DEBUG(dbgs() << "Folded " << PrintReg(VirtReg) << " MR: " << MR); int SS = VRM->getStackSlot(VirtReg); if (SS == VirtRegMap::NO_STACK_SLOT) @@ -2549,6 +2574,10 @@ LocalRewriter::RewriteMBB(LiveIntervals *LIs, } } + // If StackSlot is available in a register that also holds other stack + // slots, clobber those stack slots now. + Spills.ClobberSharingStackSlots(StackSlot); + assert(PhysReg && "VR not assigned a physical register?"); MRI->setPhysRegUsed(PhysReg); unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp index f28697530b3d..2b1e8786c727 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp @@ -79,9 +79,10 @@ ExecutionEngine::~ExecutionEngine() { void ExecutionEngine::DeregisterAllTables() { if (ExceptionTableDeregister) { - for (std::vector::iterator it = AllExceptionTables.begin(), - ie = AllExceptionTables.end(); it != ie; ++it) - ExceptionTableDeregister(*it); + DenseMap::iterator it = AllExceptionTables.begin(); + DenseMap::iterator ite = AllExceptionTables.end(); + for (; it != ite; ++it) + ExceptionTableDeregister(it->second); AllExceptionTables.clear(); } } @@ -310,19 +311,19 @@ void ExecutionEngine::runStaticConstructorsDestructors(Module *module, // it. if (!GV || GV->isDeclaration() || GV->hasLocalLinkage()) return; - // Should be an array of '{ int, void ()* }' structs. The first value is + // Should be an array of '{ i32, void ()* }' structs. The first value is // the init priority, which we ignore. - ConstantArray *InitList = dyn_cast(GV->getInitializer()); - if (!InitList) return; + if (isa(GV->getInitializer())) + return; + ConstantArray *InitList = cast(GV->getInitializer()); for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { - ConstantStruct *CS = - dyn_cast(InitList->getOperand(i)); - if (!CS) continue; - if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + if (isa(InitList->getOperand(i))) + continue; + ConstantStruct *CS = cast(InitList->getOperand(i)); Constant *FP = CS->getOperand(1); if (FP->isNullValue()) - break; // Found a null terminator, exit. + continue; // Found a sentinal value, ignore. // Strip off constant expression casts. if (ConstantExpr *CE = dyn_cast(FP)) @@ -838,7 +839,7 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, case Type::PointerTyID: // Ensure 64 bit target pointers are fully initialized on 32 bit hosts. if (StoreBytes != sizeof(PointerTy)) - memset(Ptr, 0, StoreBytes); + memset(&(Ptr->PointerVal), 0, StoreBytes); *((PointerTy*)Ptr) = Val.PointerVal; break; diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/Intercept.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/Intercept.cpp index 169e1bae547b..fa8bee460427 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/Intercept.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/Intercept.cpp @@ -52,8 +52,8 @@ static void runAtExitHandlers() { #include #endif #include -/* stat functions are redirecting to __xstat with a version number. On x86-64 - * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' +/* stat functions are redirecting to __xstat with a version number. On x86-64 + * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' * available as an exported symbol, so we have to add it explicitly. */ namespace { @@ -119,18 +119,18 @@ void *JIT::getPointerToNamedFunction(const std::string &Name, const char *NameStr = Name.c_str(); // If this is an asm specifier, skip the sentinal. if (NameStr[0] == 1) ++NameStr; - + // If it's an external function, look it up in the process image... void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); if (Ptr) return Ptr; - + // If it wasn't found and if it starts with an underscore ('_') character, // and has an asm specifier, try again without the underscore. if (Name[0] == 1 && NameStr[0] == '_') { Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); if (Ptr) return Ptr; } - + // Darwin/PPC adds $LDBLStub suffixes to various symbols like printf. These // are references to hidden visibility symbols that dlsym cannot resolve. // If we have one of these, strip off $LDBLStub and try again. @@ -147,7 +147,7 @@ void *JIT::getPointerToNamedFunction(const std::string &Name, } #endif } - + /// If a LazyFunctionCreator is installed, use it to get/create the function. if (LazyFunctionCreator) if (void *RP = LazyFunctionCreator(Name)) diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp index cc76b138a8a6..d1f87acd61b0 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp @@ -35,7 +35,7 @@ using namespace llvm; -#ifdef __APPLE__ +#ifdef __APPLE__ // Apple gcc defaults to -fuse-cxa-atexit (i.e. calls __cxa_atexit instead // of atexit). It passes the address of linker generated symbol __dso_handle // to the function. @@ -75,7 +75,7 @@ extern "C" void LLVMLinkInJIT() { #endif #if HAVE_EHTABLE_SUPPORT - + // libgcc defines the __register_frame function to dynamically register new // dwarf frames for exception handling. This functionality is not portable // across compilers and is only provided by GCC. We use the __register_frame @@ -113,10 +113,10 @@ struct LibgccObject { void *unused1; void *unused2; void *unused3; - + /// frame - Pointer to the exception table. void *frame; - + /// encoding - The encoding of the object? union { struct { @@ -124,15 +124,15 @@ struct LibgccObject { unsigned long from_array : 1; unsigned long mixed_encoding : 1; unsigned long encoding : 8; - unsigned long count : 21; + unsigned long count : 21; } b; size_t i; } encoding; - + /// fde_end - libgcc defines this field only if some macro is defined. We /// include this field even if it may not there, to make libgcc happy. char *fde_end; - + /// next - At least we know it's a chained list! struct LibgccObject *next; }; @@ -153,7 +153,7 @@ struct LibgccObjectInfo { /// unseenObjects - LibgccObjects not parsed yet by the unwinding runtime. /// struct LibgccObject* unseenObjects; - + unsigned unused[2]; }; @@ -165,32 +165,32 @@ void DarwinRegisterFrame(void* FrameBegin) { LibgccObjectInfo* LOI = (struct LibgccObjectInfo*) _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); assert(LOI && "This should be preallocated by the runtime"); - + // Allocate a new LibgccObject to represent this frame. Deallocation of this // object may be impossible: since darwin code in libgcc was written after // the ability to dynamically register frames, things may crash if we // deallocate it. struct LibgccObject* ob = (struct LibgccObject*) malloc(sizeof(struct LibgccObject)); - + // Do like libgcc for the values of the field. ob->unused1 = (void *)-1; ob->unused2 = 0; ob->unused3 = 0; ob->frame = FrameBegin; - ob->encoding.i = 0; + ob->encoding.i = 0; ob->encoding.b.encoding = llvm::dwarf::DW_EH_PE_omit; - + // Put the info on both places, as libgcc uses the first or the second // field. Note that we rely on having two pointers here. If fde_end was a // char, things would get complicated. ob->fde_end = (char*)LOI->unseenObjects; ob->next = LOI->unseenObjects; - + // Update the key's unseenObjects list. LOI->unseenObjects = ob; - - // Finally update the "key". Apparently, libgcc requires it. + + // Finally update the "key". Apparently, libgcc requires it. _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, LOI); @@ -312,18 +312,18 @@ JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, if (TM.addPassesToEmitMachineCode(PM, *JCE, OptLevel)) { report_fatal_error("Target does not support machine code emission!"); } - + // Register routine for informing unwinding runtime about new EH frames #if HAVE_EHTABLE_SUPPORT #if USE_KEYMGR struct LibgccObjectInfo* LOI = (struct LibgccObjectInfo*) _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); - + // The key is created on demand, and libgcc creates it the first time an // exception occurs. Since we need the key to register frames, we create // it now. if (!LOI) - LOI = (LibgccObjectInfo*)calloc(sizeof(struct LibgccObjectInfo), 1); + LOI = (LibgccObjectInfo*)calloc(sizeof(struct LibgccObjectInfo), 1); _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, LOI); InstallExceptionTableRegister(DarwinRegisterFrame); // Not sure about how to deregister on Darwin. @@ -332,7 +332,7 @@ JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, InstallExceptionTableDeregister(__deregister_frame); #endif // __APPLE__ #endif // HAVE_EHTABLE_SUPPORT - + // Initialize passes. PM.doInitialization(); } @@ -365,11 +365,11 @@ void JIT::addModule(Module *M) { if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) { report_fatal_error("Target does not support machine code emission!"); } - + // Initialize passes. PM.doInitialization(); } - + ExecutionEngine::addModule(M); } @@ -377,29 +377,29 @@ void JIT::addModule(Module *M) { /// since the PassManager it contains references a released Module. bool JIT::removeModule(Module *M) { bool result = ExecutionEngine::removeModule(M); - + MutexGuard locked(lock); - + if (jitstate->getModule() == M) { delete jitstate; jitstate = 0; } - + if (!jitstate && !Modules.empty()) { jitstate = new JITState(Modules[0]); FunctionPassManager &PM = jitstate->getPM(locked); PM.add(new TargetData(*TM.getTargetData())); - + // Turn the machine code intermediate representation into bytes in memory // that may be executed. if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) { report_fatal_error("Target does not support machine code emission!"); } - + // Initialize passes. PM.doInitialization(); - } + } return result; } @@ -433,7 +433,7 @@ GenericValue JIT::runFunction(Function *F, // Call the function. GenericValue rv; - rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), (char **)GVTOP(ArgValues[1]), (const char **)GVTOP(ArgValues[2]))); return rv; @@ -446,7 +446,7 @@ GenericValue JIT::runFunction(Function *F, // Call the function. GenericValue rv; - rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), (char **)GVTOP(ArgValues[1]))); return rv; } @@ -480,7 +480,7 @@ GenericValue JIT::runFunction(Function *F, rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)()); else if (BitWidth <= 64) rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)()); - else + else llvm_unreachable("Integer types > 64 bits not supported"); return rv; } @@ -542,7 +542,7 @@ GenericValue JIT::runFunction(Function *F, case Type::PointerTyID: void *ArgPtr = GVTOP(AV); if (sizeof(void*) == 4) - C = ConstantInt::get(Type::getInt32Ty(F->getContext()), + C = ConstantInt::get(Type::getInt32Ty(F->getContext()), (int)(intptr_t)ArgPtr); else C = ConstantInt::get(Type::getInt64Ty(F->getContext()), @@ -649,7 +649,7 @@ void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) { "Externally-defined function should not be in pending list."); jitTheFunction(PF, locked); - + // Now that the function has been jitted, ask the JITEmitter to rewrite // the stub with real address of the function. updateFunctionStub(PF); @@ -666,7 +666,7 @@ void JIT::jitTheFunction(Function *F, const MutexGuard &locked) { } /// getPointerToFunction - This method is used to get the address of the -/// specified function, compiling it if neccesary. +/// specified function, compiling it if necessary. /// void *JIT::getPointerToFunction(Function *F) { @@ -703,7 +703,7 @@ void *JIT::getPointerToFunction(Function *F) { void JIT::addPointerToBasicBlock(const BasicBlock *BB, void *Addr) { MutexGuard locked(lock); - + BasicBlockAddressMapTy::iterator I = getBasicBlockAddressMap(locked).find(BB); if (I == getBasicBlockAddressMap(locked).end()) { @@ -724,7 +724,7 @@ void *JIT::getPointerToBasicBlock(BasicBlock *BB) { // resolve basic block address MutexGuard locked(lock); - + BasicBlockAddressMapTy::iterator I = getBasicBlockAddressMap(locked).find(BB); if (I != getBasicBlockAddressMap(locked).end()) { diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.h b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.h index 1d1763edd4db..b576c168f272 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.h +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.h @@ -42,7 +42,7 @@ class JITState { FunctionPassManager &getPM(const MutexGuard &L) { return PM; } - + Module *getModule() const { return M; } std::vector > &getPendingFunctions(const MutexGuard &L){ return PendingFunctions; @@ -86,7 +86,7 @@ class JIT : public ExecutionEngine { static void Register() { JITCtor = createJIT; } - + /// getJITInfo - Return the target JIT information structure. /// TargetJITInfo &getJITInfo() const { return TJI; } @@ -106,7 +106,7 @@ class JIT : public ExecutionEngine { } virtual void addModule(Module *M); - + /// removeModule - Remove a Module from the list of modules. Returns true if /// M is found. virtual bool removeModule(Module *M); @@ -146,7 +146,7 @@ class JIT : public ExecutionEngine { /// getPointerToBasicBlock - This returns the address of the specified basic /// block, assuming function is compiled. void *getPointerToBasicBlock(BasicBlock *BB); - + /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. @@ -172,7 +172,7 @@ class JIT : public ExecutionEngine { void freeMachineCodeForFunction(Function *F); /// addPendingFunction - while jitting non-lazily, a called but non-codegen'd - /// function was encountered. Add it to a pending list to be processed after + /// function was encountered. Add it to a pending list to be processed after /// the current function. /// void addPendingFunction(Function *F); diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp index 3b5acb7ecc48..e71c20b89fda 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp @@ -27,7 +27,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Mutex.h" #include -#include namespace llvm { @@ -143,7 +142,7 @@ void JITDebugRegisterer::RegisterFunction(const Function *F, DebugInfo &I) { // Add a mapping from F to the entry and buffer, so we can delete this // info later. - FnMap[F] = std::make_pair(Buffer, JITCodeEntry); + FnMap[F] = std::make_pair(Buffer, JITCodeEntry); // Acquire the lock and do the registration. { diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp index f54cccadea65..ddb0d5478596 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp @@ -34,7 +34,7 @@ using namespace llvm; JITDwarfEmitter::JITDwarfEmitter(JIT& theJit) : MMI(0), Jit(theJit) {} -unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, +unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, JITCodeEmitter& jce, unsigned char* StartFunction, unsigned char* EndFunction, @@ -47,10 +47,10 @@ unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, RI = TM.getRegisterInfo(); TFI = TM.getFrameLowering(); JCE = &jce; - + unsigned char* ExceptionTable = EmitExceptionTable(&F, StartFunction, EndFunction); - + unsigned char* Result = 0; const std::vector Personalities = MMI->getPersonalities(); @@ -63,7 +63,7 @@ unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, } -void +void JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr, const std::vector &Moves) const { unsigned PointerSize = TD->getPointerSize(); @@ -74,26 +74,26 @@ JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr, for (unsigned i = 0, N = Moves.size(); i < N; ++i) { const MachineMove &Move = Moves[i]; MCSymbol *Label = Move.getLabel(); - + // Throw out move if the label is invalid. if (Label && (*JCE->getLabelLocations())[Label] == 0) continue; - + intptr_t LabelPtr = 0; if (Label) LabelPtr = JCE->getLabelAddress(Label); const MachineLocation &Dst = Move.getDestination(); const MachineLocation &Src = Move.getSource(); - + // Advance row if new location. if (BaseLabelPtr && Label && BaseLabel != Label) { JCE->emitByte(dwarf::DW_CFA_advance_loc4); JCE->emitInt32(LabelPtr - BaseLabelPtr); - - BaseLabel = Label; + + BaseLabel = Label; BaseLabelPtr = LabelPtr; } - + // If advancing cfa. if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { if (!Src.isReg()) { @@ -103,7 +103,7 @@ JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr, JCE->emitByte(dwarf::DW_CFA_def_cfa); JCE->emitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), true)); } - + JCE->emitULEB128Bytes(-Src.getOffset()); } else { llvm_unreachable("Machine move not supported yet."); @@ -119,7 +119,7 @@ JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr, } else { unsigned Reg = RI->getDwarfRegNum(Src.getReg(), true); int Offset = Dst.getOffset() / stackGrowth; - + if (Offset < 0) { JCE->emitByte(dwarf::DW_CFA_offset_extended_sf); JCE->emitULEB128Bytes(Reg); @@ -382,7 +382,7 @@ unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF, unsigned TypeOffset = sizeof(int8_t) + // Call site format // Call-site table length - MCAsmInfo::getULEB128Size(SizeSites) + + MCAsmInfo::getULEB128Size(SizeSites) + SizeSites + SizeActions + SizeTypes; // Begin the exception table. @@ -452,7 +452,7 @@ unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF, // Emit the type ids. for (unsigned M = TypeInfos.size(); M; --M) { const GlobalVariable *GV = TypeInfos[M - 1]; - + if (GV) { if (TD->getPointerSize() == sizeof(int32_t)) JCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV)); @@ -484,7 +484,7 @@ JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const { unsigned PointerSize = TD->getPointerSize(); int stackGrowth = stackGrowthDirection == TargetFrameLowering::StackGrowsUp ? PointerSize : -PointerSize; - + unsigned char* StartCommonPtr = (unsigned char*)JCE->getCurrentPCValue(); // EH Common Frame header JCE->allocateSpace(4, 0); @@ -499,13 +499,13 @@ JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const { if (Personality) { // Augmentation Size: 3 small ULEBs of one byte each, and the personality // function which size is PointerSize. - JCE->emitULEB128Bytes(3 + PointerSize); - + JCE->emitULEB128Bytes(3 + PointerSize); + // We set the encoding of the personality as direct encoding because we use // the function pointer. The encoding is not relative because the current // PC value may be bigger than the personality function pointer. if (PointerSize == 4) { - JCE->emitByte(dwarf::DW_EH_PE_sdata4); + JCE->emitByte(dwarf::DW_EH_PE_sdata4); JCE->emitInt32(((intptr_t)Jit.getPointerToGlobal(Personality))); } else { JCE->emitByte(dwarf::DW_EH_PE_sdata8); @@ -540,11 +540,11 @@ JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const { unsigned char* JITDwarfEmitter::EmitEHFrame(const Function* Personality, unsigned char* StartCommonPtr, - unsigned char* StartFunction, + unsigned char* StartFunction, unsigned char* EndFunction, unsigned char* ExceptionTable) const { unsigned PointerSize = TD->getPointerSize(); - + // EH frame header. unsigned char* StartEHPtr = (unsigned char*)JCE->getCurrentPCValue(); JCE->allocateSpace(4, 0); @@ -558,7 +558,7 @@ JITDwarfEmitter::EmitEHFrame(const Function* Personality, // specific data area in the exception table. if (Personality) { JCE->emitULEB128Bytes(PointerSize == 4 ? 4 : 8); - + if (PointerSize == 4) { if (!MMI->getLandingPads().empty()) JCE->emitInt32(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue()); @@ -573,7 +573,7 @@ JITDwarfEmitter::EmitEHFrame(const Function* Personality, } else { JCE->emitULEB128Bytes(0); } - + // Indicate locations of function specific callee saved registers in // frame. EmitFrameMoves((intptr_t)StartFunction, MMI->getFrameMoves()); @@ -593,6 +593,6 @@ JITDwarfEmitter::EmitEHFrame(const Function* Personality, JCE->emitInt32(0); JCE->emitInt32(0); } - + return StartEHPtr; } diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h index 9495697a1aa4..e1d00454d8d2 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h @@ -35,33 +35,33 @@ class JITDwarfEmitter { MachineModuleInfo* MMI; JIT& Jit; bool stackGrowthDirection; - + unsigned char* EmitExceptionTable(MachineFunction* MF, - unsigned char* StartFunction, + unsigned char* StartFunction, unsigned char* EndFunction) const; - void EmitFrameMoves(intptr_t BaseLabelPtr, + void EmitFrameMoves(intptr_t BaseLabelPtr, const std::vector &Moves) const; - + unsigned char* EmitCommonEHFrame(const Function* Personality) const; - unsigned char* EmitEHFrame(const Function* Personality, + unsigned char* EmitEHFrame(const Function* Personality, unsigned char* StartBufferPtr, - unsigned char* StartFunction, + unsigned char* StartFunction, unsigned char* EndFunction, unsigned char* ExceptionTable) const; - + public: - + JITDwarfEmitter(JIT& jit); - - unsigned char* EmitDwarfTable(MachineFunction& F, + + unsigned char* EmitDwarfTable(MachineFunction& F, JITCodeEmitter& JCE, unsigned char* StartFunction, unsigned char* EndFunction, unsigned char* &EHFramePtr); - - + + void setModuleInfo(MachineModuleInfo* Info) { MMI = Info; } diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp index 4cd8757ad0b8..d046b8aea641 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -123,17 +123,18 @@ namespace { return FunctionToLazyStubMap; } - GlobalToIndirectSymMapTy& getGlobalToIndirectSymMap(const MutexGuard& locked) { - assert(locked.holds(TheJIT->lock)); + GlobalToIndirectSymMapTy& getGlobalToIndirectSymMap(const MutexGuard& lck) { + assert(lck.holds(TheJIT->lock)); return GlobalToIndirectSymMap; } - pair LookupFunctionFromCallSite( + std::pair LookupFunctionFromCallSite( const MutexGuard &locked, void *CallSite) const { assert(locked.holds(TheJIT->lock)); - // The address given to us for the stub may not be exactly right, it might be - // a little bit after the stub. As such, use upper_bound to find it. + // The address given to us for the stub may not be exactly right, it + // might be a little bit after the stub. As such, use upper_bound to + // find it. CallSiteToFunctionMapTy::const_iterator I = CallSiteToFunctionMap.upper_bound(CallSite); assert(I != CallSiteToFunctionMap.begin() && @@ -645,7 +646,7 @@ void *JITResolver::JITCompilerFn(void *Stub) { // The address given to us for the stub may not be exactly right, it might // be a little bit after the stub. As such, use upper_bound to find it. - pair I = + std::pair I = JR->state.LookupFunctionFromCallSite(locked, Stub); F = I.second; ActualPtr = I.first; @@ -659,7 +660,8 @@ void *JITResolver::JITCompilerFn(void *Stub) { // If lazy compilation is disabled, emit a useful error message and abort. if (!JR->TheJIT->isCompilingLazily()) { - report_fatal_error("LLVM JIT requested to do lazy compilation of function '" + report_fatal_error("LLVM JIT requested to do lazy compilation of" + " function '" + F->getName() + "' when lazy compiles are disabled!"); } @@ -745,7 +747,7 @@ void *JITEmitter::getPointerToGVIndirectSym(GlobalValue *V, void *Reference) { void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) { if (DL.isUnknown()) return; if (!BeforePrintingInsn) return; - + const LLVMContext &Context = EmissionDetails.MF->getFunction()->getContext(); if (DL.getScope(Context) != 0 && PrevDL != DL) { @@ -781,7 +783,7 @@ void JITEmitter::startFunction(MachineFunction &F) { uintptr_t ActualSize = 0; // Set the memory writable, if it's not already MemMgr->setMemoryWritable(); - + if (SizeEstimate > 0) { // SizeEstimate will be non-zero on reallocation attempts. ActualSize = SizeEstimate; @@ -859,7 +861,8 @@ bool JITEmitter::finishFunction(MachineFunction &F) { } else if (MR.isBasicBlock()) { ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock()); } else if (MR.isConstantPoolIndex()) { - ResultPtr = (void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex()); + ResultPtr = + (void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex()); } else { assert(MR.isJumpTableIndex()); ResultPtr=(void*)getJumpTableEntryAddress(MR.getJumpTableIndex()); @@ -985,7 +988,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) { CurBufferPtr = SavedCurBufferPtr; if (JITExceptionHandling) { - TheJIT->RegisterTable(FrameRegister); + TheJIT->RegisterTable(F.getFunction(), FrameRegister); } if (JITEmitDebugInfo) { @@ -1033,8 +1036,9 @@ void JITEmitter::deallocateMemForFunction(const Function *F) { EmittedFunctions.erase(Emitted); } - // TODO: Do we need to unregister exception handling information from libgcc - // here? + if(JITExceptionHandling) { + TheJIT->DeregisterTable(F); + } if (JITEmitDebugInfo) { DR->UnregisterFunction(F); @@ -1129,7 +1133,7 @@ void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { const std::vector &JT = MJTI->getJumpTables(); if (JT.empty() || JumpTableBase == 0) return; - + switch (MJTI->getEntryKind()) { case MachineJumpTableInfo::EK_Inline: return; @@ -1138,11 +1142,11 @@ void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { // .word LBB123 assert(MJTI->getEntrySize(*TheJIT->getTargetData()) == sizeof(void*) && "Cross JIT'ing?"); - + // For each jump table, map each target in the jump table to the address of // an emitted MachineBasicBlock. intptr_t *SlotPtr = (intptr_t*)JumpTableBase; - + for (unsigned i = 0, e = JT.size(); i != e; ++i) { const std::vector &MBBs = JT[i].MBBs; // Store the address of the basic block for this jump table slot in the @@ -1152,7 +1156,7 @@ void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { } break; } - + case MachineJumpTableInfo::EK_Custom32: case MachineJumpTableInfo::EK_GPRel32BlockAddress: case MachineJumpTableInfo::EK_LabelDifference32: { diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp index 670fa7da1fed..9a9ed6d33484 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp @@ -108,8 +108,8 @@ void OProfileJITEventListener::NotifyFunctionEmitted( if (op_write_native_code(Agent, F.getName().data(), reinterpret_cast(FnStart), FnStart, FnSize) == -1) { - DEBUG(dbgs() << "Failed to tell OProfile about native function " - << F.getName() << " at [" + DEBUG(dbgs() << "Failed to tell OProfile about native function " + << F.getName() << " at [" << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n"); return; } @@ -153,9 +153,9 @@ void OProfileJITEventListener::NotifyFunctionEmitted( if (op_write_debug_line_info(Agent, FnStart, LineInfo.size(), &*LineInfo.begin()) == -1) { - DEBUG(dbgs() + DEBUG(dbgs() << "Failed to tell OProfile about line numbers for native function " - << F.getName() << " at [" + << F.getName() << " at [" << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n"); } } diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp index 6b7173cece18..8d92ab01c3db 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/TargetSelect.cpp @@ -84,7 +84,7 @@ TargetMachine *JIT::selectTarget(Module *Mod, } // Allocate a target... - TargetMachine *Target = + TargetMachine *Target = TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr); assert(Target && "Could not allocate target machine!"); return Target; diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/Intercept.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/Intercept.cpp new file mode 100644 index 000000000000..e431c848d630 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/Intercept.cpp @@ -0,0 +1,161 @@ +//===-- Intercept.cpp - System function interception routines -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// If a function call occurs to an external function, the JIT is designed to use +// the dynamic loader interface to find a function to call. This is useful for +// calling system calls and library functions that are not available in LLVM. +// Some system calls, however, need to be handled specially. For this reason, +// we intercept some of them here and use our own stubs to handle them. +// +//===----------------------------------------------------------------------===// + +#include "MCJIT.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Config/config.h" +using namespace llvm; + +// AtExitHandlers - List of functions to call when the program exits, +// registered with the atexit() library function. +static std::vector AtExitHandlers; + +/// runAtExitHandlers - Run any functions registered by the program's +/// calls to atexit(3), which we intercept and store in +/// AtExitHandlers. +/// +static void runAtExitHandlers() { + while (!AtExitHandlers.empty()) { + void (*Fn)() = AtExitHandlers.back(); + AtExitHandlers.pop_back(); + Fn(); + } +} + +//===----------------------------------------------------------------------===// +// Function stubs that are invoked instead of certain library calls +//===----------------------------------------------------------------------===// + +// Force the following functions to be linked in to anything that uses the +// JIT. This is a hack designed to work around the all-too-clever Glibc +// strategy of making these functions work differently when inlined vs. when +// not inlined, and hiding their real definitions in a separate archive file +// that the dynamic linker can't see. For more info, search for +// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. +#if defined(__linux__) +#if defined(HAVE_SYS_STAT_H) +#include +#endif +#include +/* stat functions are redirecting to __xstat with a version number. On x86-64 + * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' + * available as an exported symbol, so we have to add it explicitly. + */ +namespace { +class StatSymbols { +public: + StatSymbols() { + sys::DynamicLibrary::AddSymbol("stat", (void*)(intptr_t)stat); + sys::DynamicLibrary::AddSymbol("fstat", (void*)(intptr_t)fstat); + sys::DynamicLibrary::AddSymbol("lstat", (void*)(intptr_t)lstat); + sys::DynamicLibrary::AddSymbol("stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1open64", (void*)(intptr_t)open64); + sys::DynamicLibrary::AddSymbol("\x1lseek64", (void*)(intptr_t)lseek64); + sys::DynamicLibrary::AddSymbol("fstat64", (void*)(intptr_t)fstat64); + sys::DynamicLibrary::AddSymbol("lstat64", (void*)(intptr_t)lstat64); + sys::DynamicLibrary::AddSymbol("atexit", (void*)(intptr_t)atexit); + sys::DynamicLibrary::AddSymbol("mknod", (void*)(intptr_t)mknod); + } +}; +} +static StatSymbols initStatSymbols; +#endif // __linux__ + +// jit_exit - Used to intercept the "exit" library call. +static void jit_exit(int Status) { + runAtExitHandlers(); // Run atexit handlers... + exit(Status); +} + +// jit_atexit - Used to intercept the "atexit" library call. +static int jit_atexit(void (*Fn)()) { + AtExitHandlers.push_back(Fn); // Take note of atexit handler... + return 0; // Always successful +} + +static int jit_noop() { + return 0; +} + +//===----------------------------------------------------------------------===// +// +/// getPointerToNamedFunction - This method returns the address of the specified +/// function by using the dynamic loader interface. As such it is only useful +/// for resolving library symbols, not code generated symbols. +/// +void *MCJIT::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) { + if (!isSymbolSearchingDisabled()) { + // Check to see if this is one of the functions we want to intercept. Note, + // we cast to intptr_t here to silence a -pedantic warning that complains + // about casting a function pointer to a normal pointer. + if (Name == "exit") return (void*)(intptr_t)&jit_exit; + if (Name == "atexit") return (void*)(intptr_t)&jit_atexit; + + // We should not invoke parent's ctors/dtors from generated main()! + // On Mingw and Cygwin, the symbol __main is resolved to + // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors + // (and register wrong callee's dtors with atexit(3)). + // We expect ExecutionEngine::runStaticConstructorsDestructors() + // is called before ExecutionEngine::runFunctionAsMain() is called. + if (Name == "__main") return (void*)(intptr_t)&jit_noop; + + const char *NameStr = Name.c_str(); + // If this is an asm specifier, skip the sentinal. + if (NameStr[0] == 1) ++NameStr; + + // If it's an external function, look it up in the process image... + void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); + if (Ptr) return Ptr; + + // If it wasn't found and if it starts with an underscore ('_') character, + // and has an asm specifier, try again without the underscore. + if (Name[0] == 1 && NameStr[0] == '_') { + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); + if (Ptr) return Ptr; + } + + // Darwin/PPC adds $LDBLStub suffixes to various symbols like printf. These + // are references to hidden visibility symbols that dlsym cannot resolve. + // If we have one of these, strip off $LDBLStub and try again. +#if defined(__APPLE__) && defined(__ppc__) + if (Name.size() > 9 && Name[Name.size()-9] == '$' && + memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) { + // First try turning $LDBLStub into $LDBL128. If that fails, strip it off. + // This mirrors logic in libSystemStubs.a. + std::string Prefix = std::string(Name.begin(), Name.end()-9); + if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128", false)) + return Ptr; + if (void *Ptr = getPointerToNamedFunction(Prefix, false)) + return Ptr; + } +#endif + } + + /// If a LazyFunctionCreator is installed, use it to get/create the function. + if (LazyFunctionCreator) + if (void *RP = LazyFunctionCreator(Name)) + return RP; + + if (AbortOnFailure) { + report_fatal_error("Program used external function '"+Name+ + "' which could not be resolved!"); + } + return 0; +} diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp index f1e9dab250bf..3d4ee369ead0 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -1,4 +1,4 @@ -//===-- JIT.cpp - MC-based Just-in-Time Compiler --------------------------===// +//===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===// // // The LLVM Compiler Infrastructure // @@ -8,10 +8,17 @@ //===----------------------------------------------------------------------===// #include "MCJIT.h" +#include "MCJITMemoryManager.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Target/TargetData.h" using namespace llvm; @@ -51,20 +58,47 @@ ExecutionEngine *MCJIT::createJIT(Module *M, // If the target supports JIT code generation, create the JIT. if (TargetJITInfo *TJ = TM->getJITInfo()) - return new MCJIT(M, *TM, *TJ, JMM, OptLevel, GVsWithCode); + return new MCJIT(M, TM, *TJ, new MCJITMemoryManager(JMM), OptLevel, + GVsWithCode); if (ErrorStr) *ErrorStr = "target does not support JIT code generation"; return 0; } -MCJIT::MCJIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, - JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, +MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji, + RTDyldMemoryManager *MM, CodeGenOpt::Level OptLevel, bool AllocateGVsWithCode) - : ExecutionEngine(M) { + : ExecutionEngine(m), TM(tm), MemMgr(MM), M(m), OS(Buffer), Dyld(MM) { + + PM.add(new TargetData(*TM->getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory + // that may be executed. + if (TM->addPassesToEmitMC(PM, Ctx, OS, CodeGenOpt::Default, false)) { + report_fatal_error("Target does not support MC emission!"); + } + + // Initialize passes. + // FIXME: When we support multiple modules, we'll want to move the code + // gen and finalization out of the constructor here and do it more + // on-demand as part of getPointerToFunction(). + PM.run(*M); + // Flush the output buffer so the SmallVector gets its data. + OS.flush(); + + // Load the object into the dynamic linker. + // FIXME: It would be nice to avoid making yet another copy. + MemoryBuffer *MB = MemoryBuffer::getMemBufferCopy(StringRef(Buffer.data(), + Buffer.size())); + if (Dyld.loadObject(MB)) + report_fatal_error(Dyld.getErrorString()); + // Resolve any relocations. + Dyld.resolveRelocations(); } MCJIT::~MCJIT() { + delete MemMgr; } void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { @@ -73,8 +107,15 @@ void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { } void *MCJIT::getPointerToFunction(Function *F) { - report_fatal_error("not yet implemented"); - return 0; + if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) { + bool AbortOnFailure = !F->hasExternalWeakLinkage(); + void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure); + addGlobalMapping(F, Addr); + return Addr; + } + + Twine Name = TM->getMCAsmInfo()->getGlobalPrefix() + F->getName(); + return (void*)Dyld.getSymbolAddress(Name.str()); } void *MCJIT::recompileAndRelinkFunction(Function *F) { @@ -87,6 +128,102 @@ void MCJIT::freeMachineCodeForFunction(Function *F) { GenericValue MCJIT::runFunction(Function *F, const std::vector &ArgValues) { - report_fatal_error("not yet implemented"); + assert(F && "Function *F was null at entry to run()"); + + void *FPtr = getPointerToFunction(F); + assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); + const FunctionType *FTy = F->getFunctionType(); + const Type *RetTy = FTy->getReturnType(); + + assert((FTy->getNumParams() == ArgValues.size() || + (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && + "Wrong number of arguments passed into function!"); + assert(FTy->getNumParams() == ArgValues.size() && + "This doesn't support passing arguments through varargs (yet)!"); + + // Handle some common cases first. These cases correspond to common `main' + // prototypes. + if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) { + switch (ArgValues.size()) { + case 3: + if (FTy->getParamType(0)->isIntegerTy(32) && + FTy->getParamType(1)->isPointerTy() && + FTy->getParamType(2)->isPointerTy()) { + int (*PF)(int, char **, const char **) = + (int(*)(int, char **, const char **))(intptr_t)FPtr; + + // Call the function. + GenericValue rv; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + (char **)GVTOP(ArgValues[1]), + (const char **)GVTOP(ArgValues[2]))); + return rv; + } + break; + case 2: + if (FTy->getParamType(0)->isIntegerTy(32) && + FTy->getParamType(1)->isPointerTy()) { + int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr; + + // Call the function. + GenericValue rv; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + (char **)GVTOP(ArgValues[1]))); + return rv; + } + break; + case 1: + if (FTy->getNumParams() == 1 && + FTy->getParamType(0)->isIntegerTy(32)) { + GenericValue rv; + int (*PF)(int) = (int(*)(int))(intptr_t)FPtr; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); + return rv; + } + break; + } + } + + // Handle cases where no arguments are passed first. + if (ArgValues.empty()) { + GenericValue rv; + switch (RetTy->getTypeID()) { + default: llvm_unreachable("Unknown return type for function call!"); + case Type::IntegerTyID: { + unsigned BitWidth = cast(RetTy)->getBitWidth(); + if (BitWidth == 1) + rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 8) + rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 16) + rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 32) + rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 64) + rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)()); + else + llvm_unreachable("Integer types > 64 bits not supported"); + return rv; + } + case Type::VoidTyID: + rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)()); + return rv; + case Type::FloatTyID: + rv.FloatVal = ((float(*)())(intptr_t)FPtr)(); + return rv; + case Type::DoubleTyID: + rv.DoubleVal = ((double(*)())(intptr_t)FPtr)(); + return rv; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + llvm_unreachable("long double not supported yet"); + return rv; + case Type::PointerTyID: + return PTOGV(((void*(*)())(intptr_t)FPtr)()); + } + } + + assert("Full-featured argument passing not supported yet!"); return GenericValue(); } diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h index cd1f989b10c7..1b507663e4ae 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -10,14 +10,37 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_H #define LLVM_LIB_EXECUTIONENGINE_MCJIT_H +#include "llvm/PassManager.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { +// FIXME: This makes all kinds of horrible assumptions for the time being, +// like only having one module, not needing to worry about multi-threading, +// blah blah. Purely in get-it-up-and-limping mode for now. + class MCJIT : public ExecutionEngine { - MCJIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, - JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, + MCJIT(Module *M, TargetMachine *tm, TargetJITInfo &tji, + RTDyldMemoryManager *MemMgr, CodeGenOpt::Level OptLevel, bool AllocateGVsWithCode); + + TargetMachine *TM; + MCContext *Ctx; + RTDyldMemoryManager *MemMgr; + + // FIXME: These may need moved to a separate 'jitstate' member like the + // non-MC JIT does for multithreading and such. Just keep them here for now. + PassManager PM; + Module *M; + // FIXME: This really doesn't belong here. + SmallVector Buffer; // Working buffer into which we JIT. + raw_svector_ostream OS; + + RuntimeDyld Dyld; + public: ~MCJIT(); @@ -35,6 +58,16 @@ class MCJIT : public ExecutionEngine { virtual GenericValue runFunction(Function *F, const std::vector &ArgValues); + /// getPointerToNamedFunction - This method returns the address of the + /// specified function by using the dlsym function call. 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. + /// + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); /// @} /// @name (Private) Registration Interfaces /// @{ diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h new file mode 100644 index 000000000000..e3c6fda63b48 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h @@ -0,0 +1,59 @@ +//===-- MCJITMemoryManager.h - Definition for the Memory Manager ---C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_EXECUTIONENGINE_MCJITMEMORYMANAGER_H +#define LLVM_LIB_EXECUTIONENGINE_MCJITMEMORYMANAGER_H + +#include "llvm/Module.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include + +namespace llvm { + +// The MCJIT memory manager is a layer between the standard JITMemoryManager +// and the RuntimeDyld interface that maps objects, by name, onto their +// matching LLVM IR counterparts in the module(s) being compiled. +class MCJITMemoryManager : public RTDyldMemoryManager { + JITMemoryManager *JMM; + + // FIXME: Multiple modules. + Module *M; +public: + MCJITMemoryManager(JITMemoryManager *jmm) : JMM(jmm) {} + + // Allocate ActualSize bytes, or more, for the named function. Return + // a pointer to the allocated memory and update Size to reflect how much + // memory was acutally allocated. + uint8_t *startFunctionBody(const char *Name, uintptr_t &Size) { + // FIXME: This should really reference the MCAsmInfo to get the global + // prefix. + if (Name[0] == '_') ++Name; + Function *F = M->getFunction(Name); + assert(F && "No matching function in JIT IR Module!"); + return JMM->startFunctionBody(F, Size); + } + + // Mark the end of the function, including how much of the allocated + // memory was actually used. + void endFunctionBody(const char *Name, uint8_t *FunctionStart, + uint8_t *FunctionEnd) { + // FIXME: This should really reference the MCAsmInfo to get the global + // prefix. + if (Name[0] == '_') ++Name; + Function *F = M->getFunction(Name); + assert(F && "No matching function in JIT IR Module!"); + JMM->endFunctionBody(F, FunctionStart, FunctionEnd); + } + +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt new file mode 100644 index 000000000000..9e53f8757ec0 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMRuntimeDyld + RuntimeDyld.cpp + ) diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile new file mode 100644 index 000000000000..5d6f26d950fe --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile @@ -0,0 +1,13 @@ +##===- lib/ExecutionEngine/MCJIT/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMRuntimeDyld + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp new file mode 100644 index 000000000000..065e5e3d8a33 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -0,0 +1,669 @@ +//===-- RuntimeDyld.h - Run-time dynamic linker for MC-JIT ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation of the MC-JIT runtime dynamic linker. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dyld" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/Object/MachOObject.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/system_error.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace llvm::object; + +// Empty out-of-line virtual destructor as the key function. +RTDyldMemoryManager::~RTDyldMemoryManager() {} + +namespace llvm { +class RuntimeDyldImpl { + unsigned CPUType; + unsigned CPUSubtype; + + // The MemoryManager to load objects into. + RTDyldMemoryManager *MemMgr; + + // FIXME: This all assumes we're dealing with external symbols for anything + // explicitly referenced. I.e., we can index by name and things + // will work out. In practice, this may not be the case, so we + // should find a way to effectively generalize. + + // For each function, we have a MemoryBlock of it's instruction data. + StringMap Functions; + + // Master symbol table. As modules are loaded and external symbols are + // resolved, their addresses are stored here. + StringMap SymbolTable; + + // For each symbol, keep a list of relocations based on it. Anytime + // its address is reassigned (the JIT re-compiled the function, e.g.), + // the relocations get re-resolved. + struct RelocationEntry { + std::string Target; // Object this relocation is contained in. + uint64_t Offset; // Offset into the object for the relocation. + uint32_t Data; // Second word of the raw macho relocation entry. + int64_t Addend; // Addend encoded in the instruction itself, if any. + bool isResolved; // Has this relocation been resolved previously? + + RelocationEntry(StringRef t, uint64_t offset, uint32_t data, int64_t addend) + : Target(t), Offset(offset), Data(data), Addend(addend), + isResolved(false) {} + }; + typedef SmallVector RelocationList; + StringMap Relocations; + + // FIXME: Also keep a map of all the relocations contained in an object. Use + // this to dynamically answer whether all of the relocations in it have + // been resolved or not. + + bool HasError; + std::string ErrorStr; + + // Set the error state and record an error string. + bool Error(const Twine &Msg) { + ErrorStr = Msg.str(); + HasError = true; + return true; + } + + void extractFunction(StringRef Name, uint8_t *StartAddress, + uint8_t *EndAddress); + bool resolveRelocation(uint8_t *Address, uint8_t *Value, bool isPCRel, + unsigned Type, unsigned Size); + bool resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, bool isPCRel, + unsigned Type, unsigned Size); + bool resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel, + unsigned Type, unsigned Size); + + bool loadSegment32(const MachOObject *Obj, + const MachOObject::LoadCommandInfo *SegmentLCI, + const InMemoryStruct &SymtabLC); + bool loadSegment64(const MachOObject *Obj, + const MachOObject::LoadCommandInfo *SegmentLCI, + const InMemoryStruct &SymtabLC); + +public: + RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {} + + bool loadObject(MemoryBuffer *InputBuffer); + + void *getSymbolAddress(StringRef Name) { + // FIXME: Just look up as a function for now. Overly simple of course. + // Work in progress. + return SymbolTable.lookup(Name); + } + + void resolveRelocations(); + + void reassignSymbolAddress(StringRef Name, uint8_t *Addr); + + // Is the linker in an error state? + bool hasError() { return HasError; } + + // Mark the error condition as handled and continue. + void clearError() { HasError = false; } + + // Get the error message. + StringRef getErrorString() { return ErrorStr; } +}; + +void RuntimeDyldImpl::extractFunction(StringRef Name, uint8_t *StartAddress, + uint8_t *EndAddress) { + // Allocate memory for the function via the memory manager. + uintptr_t Size = EndAddress - StartAddress + 1; + uint8_t *Mem = MemMgr->startFunctionBody(Name.data(), Size); + assert(Size >= (uint64_t)(EndAddress - StartAddress + 1) && + "Memory manager failed to allocate enough memory!"); + // Copy the function payload into the memory block. + memcpy(Mem, StartAddress, EndAddress - StartAddress + 1); + MemMgr->endFunctionBody(Name.data(), Mem, Mem + Size); + // Remember where we put it. + Functions[Name] = sys::MemoryBlock(Mem, Size); + // Default the assigned address for this symbol to wherever this + // allocated it. + SymbolTable[Name] = Mem; + DEBUG(dbgs() << " allocated to " << Mem << "\n"); +} + +bool RuntimeDyldImpl:: +resolveRelocation(uint8_t *Address, uint8_t *Value, bool isPCRel, + unsigned Type, unsigned Size) { + // This just dispatches to the proper target specific routine. + switch (CPUType) { + default: assert(0 && "Unsupported CPU type!"); + case mach::CTM_x86_64: + return resolveX86_64Relocation((uintptr_t)Address, (uintptr_t)Value, + isPCRel, Type, Size); + case mach::CTM_ARM: + return resolveARMRelocation((uintptr_t)Address, (uintptr_t)Value, + isPCRel, Type, Size); + } + llvm_unreachable(""); +} + +bool RuntimeDyldImpl:: +resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, + bool isPCRel, unsigned Type, + unsigned Size) { + // If the relocation is PC-relative, the value to be encoded is the + // pointer difference. + if (isPCRel) + // FIXME: It seems this value needs to be adjusted by 4 for an effective PC + // address. Is that expected? Only for branches, perhaps? + Value -= Address + 4; + + switch(Type) { + default: + llvm_unreachable("Invalid relocation type!"); + case macho::RIT_X86_64_Unsigned: + case macho::RIT_X86_64_Branch: { + // Mask in the target value a byte at a time (we don't have an alignment + // guarantee for the target address, so this is safest). + uint8_t *p = (uint8_t*)Address; + for (unsigned i = 0; i < Size; ++i) { + *p++ = (uint8_t)Value; + Value >>= 8; + } + return false; + } + case macho::RIT_X86_64_Signed: + case macho::RIT_X86_64_GOTLoad: + case macho::RIT_X86_64_GOT: + case macho::RIT_X86_64_Subtractor: + case macho::RIT_X86_64_Signed1: + case macho::RIT_X86_64_Signed2: + case macho::RIT_X86_64_Signed4: + case macho::RIT_X86_64_TLV: + return Error("Relocation type not implemented yet!"); + } + return false; +} + +bool RuntimeDyldImpl::resolveARMRelocation(uintptr_t Address, uintptr_t Value, + bool isPCRel, unsigned Type, + unsigned Size) { + // If the relocation is PC-relative, the value to be encoded is the + // pointer difference. + if (isPCRel) { + Value -= Address; + // ARM PCRel relocations have an effective-PC offset of two instructions + // (four bytes in Thumb mode, 8 bytes in ARM mode). + // FIXME: For now, assume ARM mode. + Value -= 8; + } + + switch(Type) { + default: + llvm_unreachable("Invalid relocation type!"); + case macho::RIT_Vanilla: { + llvm_unreachable("Invalid relocation type!"); + // Mask in the target value a byte at a time (we don't have an alignment + // guarantee for the target address, so this is safest). + uint8_t *p = (uint8_t*)Address; + for (unsigned i = 0; i < Size; ++i) { + *p++ = (uint8_t)Value; + Value >>= 8; + } + break; + } + case macho::RIT_ARM_Branch24Bit: { + // Mask the value into the target address. We know instructions are + // 32-bit aligned, so we can do it all at once. + uint32_t *p = (uint32_t*)Address; + // The low two bits of the value are not encoded. + Value >>= 2; + // Mask the value to 24 bits. + Value &= 0xffffff; + // FIXME: If the destination is a Thumb function (and the instruction + // is a non-predicated BL instruction), we need to change it to a BLX + // instruction instead. + + // Insert the value into the instruction. + *p = (*p & ~0xffffff) | Value; + break; + } + case macho::RIT_ARM_ThumbBranch22Bit: + case macho::RIT_ARM_ThumbBranch32Bit: + case macho::RIT_ARM_Half: + case macho::RIT_ARM_HalfDifference: + case macho::RIT_Pair: + case macho::RIT_Difference: + case macho::RIT_ARM_LocalDifference: + case macho::RIT_ARM_PreboundLazyPointer: + return Error("Relocation type not implemented yet!"); + } + return false; +} + +bool RuntimeDyldImpl:: +loadSegment32(const MachOObject *Obj, + const MachOObject::LoadCommandInfo *SegmentLCI, + const InMemoryStruct &SymtabLC) { + InMemoryStruct SegmentLC; + Obj->ReadSegmentLoadCommand(*SegmentLCI, SegmentLC); + if (!SegmentLC) + return Error("unable to load segment load command"); + + for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) { + InMemoryStruct Sect; + Obj->ReadSection(*SegmentLCI, SectNum, Sect); + if (!Sect) + return Error("unable to load section: '" + Twine(SectNum) + "'"); + + // FIXME: Improve check. + if (Sect->Flags != 0x80000400) + return Error("unsupported section type!"); + + // Address and names of symbols in the section. + typedef std::pair SymbolEntry; + SmallVector Symbols; + // Index of all the names, in this section or not. Used when we're + // dealing with relocation entries. + SmallVector SymbolNames; + for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { + InMemoryStruct STE; + Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE); + if (!STE) + return Error("unable to read symbol: '" + Twine(i) + "'"); + if (STE->SectionIndex > SegmentLC->NumSections) + return Error("invalid section index for symbol: '" + Twine(i) + "'"); + // Get the symbol name. + StringRef Name = Obj->getStringAtIndex(STE->StringIndex); + SymbolNames.push_back(Name); + + // Just skip symbols not defined in this section. + if ((unsigned)STE->SectionIndex - 1 != SectNum) + continue; + + // FIXME: Check the symbol type and flags. + if (STE->Type != 0xF) // external, defined in this section. + return Error("unexpected symbol type!"); + // Flags == 0x8 marks a thumb function for ARM, which is fine as it + // doesn't require any special handling here. + if (STE->Flags != 0x0 && STE->Flags != 0x8) + return Error("unexpected symbol type!"); + + // Remember the symbol. + Symbols.push_back(SymbolEntry(STE->Value, Name)); + + DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << + (Sect->Address + STE->Value) << "\n"); + } + // Sort the symbols by address, just in case they didn't come in that way. + array_pod_sort(Symbols.begin(), Symbols.end()); + + // Extract the function data. + uint8_t *Base = (uint8_t*)Obj->getData(SegmentLC->FileOffset, + SegmentLC->FileSize).data(); + for (unsigned i = 0, e = Symbols.size() - 1; i != e; ++i) { + uint64_t StartOffset = Sect->Address + Symbols[i].first; + uint64_t EndOffset = Symbols[i + 1].first - 1; + DEBUG(dbgs() << "Extracting function: " << Symbols[i].second + << " from [" << StartOffset << ", " << EndOffset << "]\n"); + extractFunction(Symbols[i].second, Base + StartOffset, Base + EndOffset); + } + // The last symbol we do after since the end address is calculated + // differently because there is no next symbol to reference. + uint64_t StartOffset = Symbols[Symbols.size() - 1].first; + uint64_t EndOffset = Sect->Size - 1; + DEBUG(dbgs() << "Extracting function: " << Symbols[Symbols.size()-1].second + << " from [" << StartOffset << ", " << EndOffset << "]\n"); + extractFunction(Symbols[Symbols.size()-1].second, + Base + StartOffset, Base + EndOffset); + + // Now extract the relocation information for each function and process it. + for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) { + InMemoryStruct RE; + Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE); + if (RE->Word0 & macho::RF_Scattered) + return Error("NOT YET IMPLEMENTED: scattered relocations."); + // Word0 of the relocation is the offset into the section where the + // relocation should be applied. We need to translate that into an + // offset into a function since that's our atom. + uint32_t Offset = RE->Word0; + // Look for the function containing the address. This is used for JIT + // code, so the number of functions in section is almost always going + // to be very small (usually just one), so until we have use cases + // where that's not true, just use a trivial linear search. + unsigned SymbolNum; + unsigned NumSymbols = Symbols.size(); + assert(NumSymbols > 0 && Symbols[0].first <= Offset && + "No symbol containing relocation!"); + for (SymbolNum = 0; SymbolNum < NumSymbols - 1; ++SymbolNum) + if (Symbols[SymbolNum + 1].first > Offset) + break; + // Adjust the offset to be relative to the symbol. + Offset -= Symbols[SymbolNum].first; + // Get the name of the symbol containing the relocation. + StringRef TargetName = SymbolNames[SymbolNum]; + + bool isExtern = (RE->Word1 >> 27) & 1; + // Figure out the source symbol of the relocation. If isExtern is true, + // this relocation references the symbol table, otherwise it references + // a section in the same object, numbered from 1 through NumSections + // (SectionBases is [0, NumSections-1]). + // FIXME: Some targets (ARM) use internal relocations even for + // externally visible symbols, if the definition is in the same + // file as the reference. We need to convert those back to by-name + // references. We can resolve the address based on the section + // offset and see if we have a symbol at that address. If we do, + // use that; otherwise, puke. + if (!isExtern) + return Error("Internal relocations not supported."); + uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value + StringRef SourceName = SymbolNames[SourceNum]; + + // FIXME: Get the relocation addend from the target address. + + // Now store the relocation information. Associate it with the source + // symbol. + Relocations[SourceName].push_back(RelocationEntry(TargetName, + Offset, + RE->Word1, + 0 /*Addend*/)); + DEBUG(dbgs() << "Relocation at '" << TargetName << "' + " << Offset + << " from '" << SourceName << "(Word1: " + << format("0x%x", RE->Word1) << ")\n"); + } + } + return false; +} + + +bool RuntimeDyldImpl:: +loadSegment64(const MachOObject *Obj, + const MachOObject::LoadCommandInfo *SegmentLCI, + const InMemoryStruct &SymtabLC) { + InMemoryStruct Segment64LC; + Obj->ReadSegment64LoadCommand(*SegmentLCI, Segment64LC); + if (!Segment64LC) + return Error("unable to load segment load command"); + + for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections; ++SectNum) { + InMemoryStruct Sect; + Obj->ReadSection64(*SegmentLCI, SectNum, Sect); + if (!Sect) + return Error("unable to load section: '" + Twine(SectNum) + "'"); + + // FIXME: Improve check. + if (Sect->Flags != 0x80000400) + return Error("unsupported section type!"); + + // Address and names of symbols in the section. + typedef std::pair SymbolEntry; + SmallVector Symbols; + // Index of all the names, in this section or not. Used when we're + // dealing with relocation entries. + SmallVector SymbolNames; + for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { + InMemoryStruct STE; + Obj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE); + if (!STE) + return Error("unable to read symbol: '" + Twine(i) + "'"); + if (STE->SectionIndex > Segment64LC->NumSections) + return Error("invalid section index for symbol: '" + Twine(i) + "'"); + // Get the symbol name. + StringRef Name = Obj->getStringAtIndex(STE->StringIndex); + SymbolNames.push_back(Name); + + // Just skip symbols not defined in this section. + if ((unsigned)STE->SectionIndex - 1 != SectNum) + continue; + + // FIXME: Check the symbol type and flags. + if (STE->Type != 0xF) // external, defined in this section. + return Error("unexpected symbol type!"); + if (STE->Flags != 0x0) + return Error("unexpected symbol type!"); + + // Remember the symbol. + Symbols.push_back(SymbolEntry(STE->Value, Name)); + + DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << + (Sect->Address + STE->Value) << "\n"); + } + // Sort the symbols by address, just in case they didn't come in that way. + array_pod_sort(Symbols.begin(), Symbols.end()); + + // Extract the function data. + uint8_t *Base = (uint8_t*)Obj->getData(Segment64LC->FileOffset, + Segment64LC->FileSize).data(); + for (unsigned i = 0, e = Symbols.size() - 1; i != e; ++i) { + uint64_t StartOffset = Sect->Address + Symbols[i].first; + uint64_t EndOffset = Symbols[i + 1].first - 1; + DEBUG(dbgs() << "Extracting function: " << Symbols[i].second + << " from [" << StartOffset << ", " << EndOffset << "]\n"); + extractFunction(Symbols[i].second, Base + StartOffset, Base + EndOffset); + } + // The last symbol we do after since the end address is calculated + // differently because there is no next symbol to reference. + uint64_t StartOffset = Symbols[Symbols.size() - 1].first; + uint64_t EndOffset = Sect->Size - 1; + DEBUG(dbgs() << "Extracting function: " << Symbols[Symbols.size()-1].second + << " from [" << StartOffset << ", " << EndOffset << "]\n"); + extractFunction(Symbols[Symbols.size()-1].second, + Base + StartOffset, Base + EndOffset); + + // Now extract the relocation information for each function and process it. + for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) { + InMemoryStruct RE; + Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE); + if (RE->Word0 & macho::RF_Scattered) + return Error("NOT YET IMPLEMENTED: scattered relocations."); + // Word0 of the relocation is the offset into the section where the + // relocation should be applied. We need to translate that into an + // offset into a function since that's our atom. + uint32_t Offset = RE->Word0; + // Look for the function containing the address. This is used for JIT + // code, so the number of functions in section is almost always going + // to be very small (usually just one), so until we have use cases + // where that's not true, just use a trivial linear search. + unsigned SymbolNum; + unsigned NumSymbols = Symbols.size(); + assert(NumSymbols > 0 && Symbols[0].first <= Offset && + "No symbol containing relocation!"); + for (SymbolNum = 0; SymbolNum < NumSymbols - 1; ++SymbolNum) + if (Symbols[SymbolNum + 1].first > Offset) + break; + // Adjust the offset to be relative to the symbol. + Offset -= Symbols[SymbolNum].first; + // Get the name of the symbol containing the relocation. + StringRef TargetName = SymbolNames[SymbolNum]; + + bool isExtern = (RE->Word1 >> 27) & 1; + // Figure out the source symbol of the relocation. If isExtern is true, + // this relocation references the symbol table, otherwise it references + // a section in the same object, numbered from 1 through NumSections + // (SectionBases is [0, NumSections-1]). + if (!isExtern) + return Error("Internal relocations not supported."); + uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value + StringRef SourceName = SymbolNames[SourceNum]; + + // FIXME: Get the relocation addend from the target address. + + // Now store the relocation information. Associate it with the source + // symbol. + Relocations[SourceName].push_back(RelocationEntry(TargetName, + Offset, + RE->Word1, + 0 /*Addend*/)); + DEBUG(dbgs() << "Relocation at '" << TargetName << "' + " << Offset + << " from '" << SourceName << "(Word1: " + << format("0x%x", RE->Word1) << ")\n"); + } + } + return false; +} + +bool RuntimeDyldImpl::loadObject(MemoryBuffer *InputBuffer) { + // If the linker is in an error state, don't do anything. + if (hasError()) + return true; + // Load the Mach-O wrapper object. + std::string ErrorStr; + OwningPtr Obj( + MachOObject::LoadFromBuffer(InputBuffer, &ErrorStr)); + if (!Obj) + return Error("unable to load object: '" + ErrorStr + "'"); + + // Get the CPU type information from the header. + const macho::Header &Header = Obj->getHeader(); + + // FIXME: Error checking that the loaded object is compatible with + // the system we're running on. + CPUType = Header.CPUType; + CPUSubtype = Header.CPUSubtype; + + // Validate that the load commands match what we expect. + const MachOObject::LoadCommandInfo *SegmentLCI = 0, *SymtabLCI = 0, + *DysymtabLCI = 0; + for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { + const MachOObject::LoadCommandInfo &LCI = Obj->getLoadCommandInfo(i); + switch (LCI.Command.Type) { + case macho::LCT_Segment: + case macho::LCT_Segment64: + if (SegmentLCI) + return Error("unexpected input object (multiple segments)"); + SegmentLCI = &LCI; + break; + case macho::LCT_Symtab: + if (SymtabLCI) + return Error("unexpected input object (multiple symbol tables)"); + SymtabLCI = &LCI; + break; + case macho::LCT_Dysymtab: + if (DysymtabLCI) + return Error("unexpected input object (multiple symbol tables)"); + DysymtabLCI = &LCI; + break; + default: + return Error("unexpected input object (unexpected load command"); + } + } + + if (!SymtabLCI) + return Error("no symbol table found in object"); + if (!SegmentLCI) + return Error("no symbol table found in object"); + + // Read and register the symbol table data. + InMemoryStruct SymtabLC; + Obj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC); + if (!SymtabLC) + return Error("unable to load symbol table load command"); + Obj->RegisterStringTable(*SymtabLC); + + // Read the dynamic link-edit information, if present (not present in static + // objects). + if (DysymtabLCI) { + InMemoryStruct DysymtabLC; + Obj->ReadDysymtabLoadCommand(*DysymtabLCI, DysymtabLC); + if (!DysymtabLC) + return Error("unable to load dynamic link-exit load command"); + + // FIXME: We don't support anything interesting yet. +// if (DysymtabLC->LocalSymbolsIndex != 0) +// return Error("NOT YET IMPLEMENTED: local symbol entries"); +// if (DysymtabLC->ExternalSymbolsIndex != 0) +// return Error("NOT YET IMPLEMENTED: non-external symbol entries"); +// if (DysymtabLC->UndefinedSymbolsIndex != SymtabLC->NumSymbolTableEntries) +// return Error("NOT YET IMPLEMENTED: undefined symbol entries"); + } + + // Load the segment load command. + if (SegmentLCI->Command.Type == macho::LCT_Segment) { + if (loadSegment32(Obj.get(), SegmentLCI, SymtabLC)) + return true; + } else { + if (loadSegment64(Obj.get(), SegmentLCI, SymtabLC)) + return true; + } + + return false; +} + +// Resolve the relocations for all symbols we currently know about. +void RuntimeDyldImpl::resolveRelocations() { + // Just iterate over the symbols in our symbol table and assign their + // addresses. + StringMap::iterator i = SymbolTable.begin(); + StringMap::iterator e = SymbolTable.end(); + for (;i != e; ++i) + reassignSymbolAddress(i->getKey(), i->getValue()); +} + +// Assign an address to a symbol name and resolve all the relocations +// associated with it. +void RuntimeDyldImpl::reassignSymbolAddress(StringRef Name, uint8_t *Addr) { + // Assign the address in our symbol table. + SymbolTable[Name] = Addr; + + RelocationList &Relocs = Relocations[Name]; + for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { + RelocationEntry &RE = Relocs[i]; + uint8_t *Target = SymbolTable[RE.Target] + RE.Offset; + bool isPCRel = (RE.Data >> 24) & 1; + unsigned Type = (RE.Data >> 28) & 0xf; + unsigned Size = 1 << ((RE.Data >> 25) & 3); + + DEBUG(dbgs() << "Resolving relocation at '" << RE.Target + << "' + " << RE.Offset << " (" << format("%p", Target) << ")" + << " from '" << Name << " (" << format("%p", Addr) << ")" + << "(" << (isPCRel ? "pcrel" : "absolute") + << ", type: " << Type << ", Size: " << Size << ").\n"); + + resolveRelocation(Target, Addr, isPCRel, Type, Size); + RE.isResolved = true; + } +} + +//===----------------------------------------------------------------------===// +// RuntimeDyld class implementation +RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *MM) { + Dyld = new RuntimeDyldImpl(MM); +} + +RuntimeDyld::~RuntimeDyld() { + delete Dyld; +} + +bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) { + return Dyld->loadObject(InputBuffer); +} + +void *RuntimeDyld::getSymbolAddress(StringRef Name) { + return Dyld->getSymbolAddress(Name); +} + +void RuntimeDyld::resolveRelocations() { + Dyld->resolveRelocations(); +} + +void RuntimeDyld::reassignSymbolAddress(StringRef Name, uint8_t *Addr) { + Dyld->reassignSymbolAddress(Name, Addr); +} + +StringRef RuntimeDyld::getErrorString() { + return Dyld->getErrorString(); +} + +} // end namespace llvm diff --git a/contrib/llvm/lib/Linker/LinkModules.cpp b/contrib/llvm/lib/Linker/LinkModules.cpp index 5aa06abdd989..f372db2403c9 100644 --- a/contrib/llvm/lib/Linker/LinkModules.cpp +++ b/contrib/llvm/lib/Linker/LinkModules.cpp @@ -505,6 +505,7 @@ static bool LinkGlobals(Module *Dest, const Module *Src, SGV->getType()->getAddressSpace()); // Propagate alignment, visibility and section info. CopyGVAttributes(NewDGV, SGV); + NewDGV->setUnnamedAddr(SGV->hasUnnamedAddr()); // If the LLVM runtime renamed the global, but it is an externally visible // symbol, DGV must be an existing global with internal linkage. Rename diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp index ea1629d30565..23c6d4c1e4c3 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp @@ -11,20 +11,14 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "ELFObjectWriter.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -38,39 +32,14 @@ #include using namespace llvm; -static unsigned GetType(const MCSymbolData &SD) { - uint32_t Type = (SD.getFlags() & (0xf << ELF_STT_Shift)) >> ELF_STT_Shift; - assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || - Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || - Type == ELF::STT_FILE || Type == ELF::STT_COMMON || - Type == ELF::STT_TLS); - return Type; +bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { + const MCFixupKindInfo &FKI = + Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind); + + return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; } -static unsigned GetBinding(const MCSymbolData &SD) { - uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift; - assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || - Binding == ELF::STB_WEAK); - return Binding; -} - -static void SetBinding(MCSymbolData &SD, unsigned Binding) { - assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || - Binding == ELF::STB_WEAK); - uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift); - SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift)); -} - -static unsigned GetVisibility(MCSymbolData &SD) { - unsigned Visibility = - (SD.getFlags() & (0xf << ELF_STV_Shift)) >> ELF_STV_Shift; - assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || - Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); - return Visibility; -} - - -static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { +bool ELFObjectWriter::RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { switch (Variant) { default: return false; @@ -90,345 +59,6 @@ static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { } } -static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { - const MCFixupKindInfo &FKI = - Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind); - - return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; -} - -namespace { - class ELFObjectWriter : public MCObjectWriter { - protected: - /*static bool isFixupKindX86RIPRel(unsigned Kind) { - return Kind == X86::reloc_riprel_4byte || - Kind == X86::reloc_riprel_4byte_movq_load; - }*/ - - - /// ELFSymbolData - Helper struct for containing some precomputed information - /// on symbols. - struct ELFSymbolData { - MCSymbolData *SymbolData; - uint64_t StringIndex; - uint32_t SectionIndex; - - // Support lexicographic sorting. - bool operator<(const ELFSymbolData &RHS) const { - if (GetType(*SymbolData) == ELF::STT_FILE) - return true; - if (GetType(*RHS.SymbolData) == ELF::STT_FILE) - return false; - return SymbolData->getSymbol().getName() < - RHS.SymbolData->getSymbol().getName(); - } - }; - - /// @name Relocation Data - /// @{ - - struct ELFRelocationEntry { - // Make these big enough for both 32-bit and 64-bit - uint64_t r_offset; - int Index; - unsigned Type; - const MCSymbol *Symbol; - uint64_t r_addend; - - ELFRelocationEntry() - : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0) {} - - ELFRelocationEntry(uint64_t RelocOffset, int Idx, - unsigned RelType, const MCSymbol *Sym, - uint64_t Addend) - : r_offset(RelocOffset), Index(Idx), Type(RelType), - Symbol(Sym), r_addend(Addend) {} - - // Support lexicographic sorting. - bool operator<(const ELFRelocationEntry &RE) const { - return RE.r_offset < r_offset; - } - }; - - /// The target specific ELF writer instance. - llvm::OwningPtr TargetObjectWriter; - - SmallPtrSet UsedInReloc; - SmallPtrSet WeakrefUsedInReloc; - DenseMap Renames; - - llvm::DenseMap > Relocations; - DenseMap SectionStringTableIndex; - - /// @} - /// @name Symbol Table Data - /// @{ - - SmallString<256> StringTable; - std::vector LocalSymbolData; - std::vector ExternalSymbolData; - std::vector UndefinedSymbolData; - - /// @} - - bool NeedsGOT; - - bool NeedsSymtabShndx; - - // This holds the symbol table index of the last local symbol. - unsigned LastLocalSymbolIndex; - // This holds the .strtab section index. - unsigned StringTableIndex; - // This holds the .symtab section index. - unsigned SymbolTableIndex; - - unsigned ShstrtabIndex; - - - const MCSymbol *SymbolToReloc(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F) const; - - // For arch-specific emission of explicit reloc symbol - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - bool IsBSS) const { - return NULL; - } - - bool is64Bit() const { return TargetObjectWriter->is64Bit(); } - bool hasRelocationAddend() const { - return TargetObjectWriter->hasRelocationAddend(); - } - - public: - ELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_ostream &_OS, bool IsLittleEndian) - : MCObjectWriter(_OS, IsLittleEndian), - TargetObjectWriter(MOTW), - NeedsGOT(false), NeedsSymtabShndx(false){ - } - - virtual ~ELFObjectWriter(); - - void WriteWord(uint64_t W) { - if (is64Bit()) - Write64(W); - else - Write32(W); - } - - void StringLE16(char *buf, uint16_t Value) { - buf[0] = char(Value >> 0); - buf[1] = char(Value >> 8); - } - - void StringLE32(char *buf, uint32_t Value) { - StringLE16(buf, uint16_t(Value >> 0)); - StringLE16(buf + 2, uint16_t(Value >> 16)); - } - - void StringLE64(char *buf, uint64_t Value) { - StringLE32(buf, uint32_t(Value >> 0)); - StringLE32(buf + 4, uint32_t(Value >> 32)); - } - - void StringBE16(char *buf ,uint16_t Value) { - buf[0] = char(Value >> 8); - buf[1] = char(Value >> 0); - } - - void StringBE32(char *buf, uint32_t Value) { - StringBE16(buf, uint16_t(Value >> 16)); - StringBE16(buf + 2, uint16_t(Value >> 0)); - } - - void StringBE64(char *buf, uint64_t Value) { - StringBE32(buf, uint32_t(Value >> 32)); - StringBE32(buf + 4, uint32_t(Value >> 0)); - } - - void String8(MCDataFragment &F, uint8_t Value) { - char buf[1]; - buf[0] = Value; - F.getContents() += StringRef(buf, 1); - } - - void String16(MCDataFragment &F, uint16_t Value) { - char buf[2]; - if (isLittleEndian()) - StringLE16(buf, Value); - else - StringBE16(buf, Value); - F.getContents() += StringRef(buf, 2); - } - - void String32(MCDataFragment &F, uint32_t Value) { - char buf[4]; - if (isLittleEndian()) - StringLE32(buf, Value); - else - StringBE32(buf, Value); - F.getContents() += StringRef(buf, 4); - } - - void String64(MCDataFragment &F, uint64_t Value) { - char buf[8]; - if (isLittleEndian()) - StringLE64(buf, Value); - else - StringBE64(buf, Value); - F.getContents() += StringRef(buf, 8); - } - - virtual void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); - - /// Default e_flags = 0 - virtual void WriteEFlags() { Write32(0); } - - virtual void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF, - uint64_t name, uint8_t info, - uint64_t value, uint64_t size, - uint8_t other, uint32_t shndx, - bool Reserved); - - virtual void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, - ELFSymbolData &MSD, - const MCAsmLayout &Layout); - - typedef DenseMap SectionIndexMapTy; - virtual void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF, - const MCAssembler &Asm, - const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap); - - virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue); - - virtual uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, - const MCSymbol *S); - - // Map from a group section to the signature symbol - typedef DenseMap GroupMapTy; - // Map from a signature symbol to the group section - typedef DenseMap RevGroupMapTy; - - /// 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. - virtual void ComputeSymbolTable(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap, - RevGroupMapTy RevGroupMap); - - virtual void ComputeIndexMap(MCAssembler &Asm, - SectionIndexMapTy &SectionIndexMap); - - virtual void WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, - const MCSectionData &SD); - - virtual void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) { - for (MCAssembler::const_iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) { - WriteRelocation(Asm, Layout, *it); - } - } - - virtual void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap); - - // Create the sections that show up in the symbol table. Currently - // those are the .note.GNU-stack section and the group sections. - virtual void CreateIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout, - GroupMapTy &GroupMap, - RevGroupMapTy &RevGroupMap); - - virtual void ExecutePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout); - - virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, - uint64_t Address, uint64_t Offset, - uint64_t Size, uint32_t Link, uint32_t Info, - uint64_t Alignment, uint64_t EntrySize); - - virtual void WriteRelocationsFragment(const MCAssembler &Asm, - MCDataFragment *F, - const MCSectionData *SD); - - virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); - virtual void WriteSection(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap, - uint32_t GroupSymbolIndex, - uint64_t Offset, uint64_t Size, uint64_t Alignment, - const MCSectionELF &Section); - - protected: - virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, bool IsRelocWithSymbol, - int64_t Addend) = 0; - }; - - //===- X86ELFObjectWriter -------------------------------------------===// - - class X86ELFObjectWriter : public ELFObjectWriter { - public: - X86ELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_ostream &_OS, - bool IsLittleEndian); - - virtual ~X86ELFObjectWriter(); - protected: - virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, bool IsRelocWithSymbol, - int64_t Addend); - }; - - - //===- ARMELFObjectWriter -------------------------------------------===// - - class ARMELFObjectWriter : public ELFObjectWriter { - public: - // FIXME: MCAssembler can't yet return the Subtarget, - enum { DefaultEABIVersion = 0x05000000U }; - - ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_ostream &_OS, - bool IsLittleEndian); - - virtual ~ARMELFObjectWriter(); - - virtual void WriteEFlags(); - protected: - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - bool IsBSS) const; - - virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, bool IsRelocWithSymbol, - int64_t Addend); - }; - - //===- MBlazeELFObjectWriter -------------------------------------------===// - - class MBlazeELFObjectWriter : public ELFObjectWriter { - public: - MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_ostream &_OS, - bool IsLittleEndian); - - virtual ~MBlazeELFObjectWriter(); - protected: - virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, bool IsRelocWithSymbol, - int64_t Addend); - }; -} - ELFObjectWriter::~ELFObjectWriter() {} @@ -533,7 +163,8 @@ void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF, } } -static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) { +uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, + const MCAsmLayout &Layout) { if (Data.isCommon() && Data.isExternal()) return Data.getCommonAlignment(); @@ -579,7 +210,7 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, // Aliases defined with .symvar copy the binding from the symbol they alias. // This is the first place we are able to copy this information. it->setExternal(SD.isExternal()); - SetBinding(*it, GetBinding(SD)); + MCELF::SetBinding(*it, MCELF::GetBinding(SD)); StringRef Rest = AliasName.substr(Pos); if (!Symbol.isUndefined() && !Rest.startswith("@@@")) @@ -605,9 +236,9 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() || Data.getSymbol().isVariable(); - uint8_t Binding = GetBinding(OrigData); - uint8_t Visibility = GetVisibility(OrigData); - uint8_t Type = GetType(Data); + uint8_t Binding = MCELF::GetBinding(OrigData); + uint8_t Visibility = MCELF::GetVisibility(OrigData); + uint8_t Type = MCELF::GetType(Data); uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); uint8_t Other = Visibility; @@ -673,7 +304,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, (Data.getFlags() & ELF_STB_Weak)) && "External symbol requires STB_GLOBAL or STB_WEAK flag"); WriteSymbol(SymtabF, ShndxF, MSD, Layout); - if (GetBinding(Data) == ELF::STB_LOCAL) + if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) LastLocalSymbolIndex++; } @@ -681,7 +312,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, ELFSymbolData &MSD = UndefinedSymbolData[i]; MCSymbolData &Data = *MSD.SymbolData; WriteSymbol(SymtabF, ShndxF, MSD, Layout); - if (GetBinding(Data) == ELF::STB_LOCAL) + if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) LastLocalSymbolIndex++; } } @@ -798,7 +429,7 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, FixedValue = Value; unsigned Type = GetRelocType(Target, Fixup, IsPCRel, (RelocSymbol != 0), Addend); - + uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); @@ -816,8 +447,9 @@ ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm, return SD.getIndex(); } -static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, - bool Used, bool Renamed) { +bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm, + const MCSymbolData &Data, + bool Used, bool Renamed) { if (Data.getFlags() & ELF_Other_Weakref) return false; @@ -836,7 +468,7 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, if (Symbol.isVariable() && !A.isVariable() && A.isUndefined()) return false; - bool IsGlobal = GetBinding(Data) == ELF::STB_GLOBAL; + bool IsGlobal = MCELF::GetBinding(Data) == ELF::STB_GLOBAL; if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal) return false; @@ -849,8 +481,8 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, return true; } -static bool isLocal(const MCSymbolData &Data, bool isSignature, - bool isUsedInReloc) { +bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isSignature, + bool isUsedInReloc) { if (Data.isExternal()) return false; @@ -868,7 +500,8 @@ static bool isLocal(const MCSymbolData &Data, bool isSignature, } void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, - SectionIndexMapTy &SectionIndexMap) { + SectionIndexMapTy &SectionIndexMap, + const RelMapTy &RelMap) { unsigned Index = 1; for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { @@ -883,31 +516,37 @@ void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, ie = Asm.end(); it != ie; ++it) { const MCSectionELF &Section = static_cast(it->getSection()); - if (Section.getType() == ELF::SHT_GROUP) + if (Section.getType() == ELF::SHT_GROUP || + Section.getType() == ELF::SHT_REL || + Section.getType() == ELF::SHT_RELA) continue; SectionIndexMap[&Section] = Index++; + const MCSectionELF *RelSection = RelMap.lookup(&Section); + if (RelSection) + SectionIndexMap[RelSection] = Index++; } } void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, const SectionIndexMapTy &SectionIndexMap, - RevGroupMapTy RevGroupMap) { + RevGroupMapTy RevGroupMap, + unsigned NumRegularSections) { // FIXME: Is this the correct place to do this? if (NeedsGOT) { llvm::StringRef Name = "_GLOBAL_OFFSET_TABLE_"; MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name); MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym); Data.setExternal(true); - SetBinding(Data, ELF::STB_GLOBAL); + MCELF::SetBinding(Data, ELF::STB_GLOBAL); } - // Build section lookup table. - int NumRegularSections = Asm.size(); - // Index 0 is always the empty string. StringMap StringIndexMap; StringTable += '\x00'; + // FIXME: We could optimize suffixes in strtab in the same way we + // optimize them in shstrtab. + // Add the data for the symbols. for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), ie = Asm.symbol_end(); it != ie; ++it) { @@ -929,14 +568,14 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, // Undefined symbols are global, but this is the first place we // are able to set it. bool Local = isLocal(*it, isSignature, Used); - if (!Local && GetBinding(*it) == ELF::STB_LOCAL) { + if (!Local && MCELF::GetBinding(*it) == ELF::STB_LOCAL) { MCSymbolData &SD = Asm.getSymbolData(RefSymbol); - SetBinding(*it, ELF::STB_GLOBAL); - SetBinding(SD, ELF::STB_GLOBAL); + MCELF::SetBinding(*it, ELF::STB_GLOBAL); + MCELF::SetBinding(SD, ELF::STB_GLOBAL); } if (RefSymbol.isUndefined() && !Used && WeakrefUsed) - SetBinding(*it, ELF::STB_WEAK); + MCELF::SetBinding(*it, ELF::STB_WEAK); if (it->isCommon()) { assert(!Local); @@ -1004,11 +643,16 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, UndefinedSymbolData[i].SymbolData->setIndex(Index++); } -void ELFObjectWriter::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, - const MCSectionData &SD) { - if (!Relocations[&SD].empty()) { +void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm, + MCAsmLayout &Layout, + RelMapTy &RelMap) { + for (MCAssembler::const_iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionData &SD = *it; + if (Relocations[&SD].empty()) + continue; + MCContext &Ctx = Asm.getContext(); - const MCSectionELF *RelaSection; const MCSectionELF &Section = static_cast(SD.getSection()); @@ -1022,17 +666,32 @@ void ELFObjectWriter::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, else EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); - RelaSection = Ctx.getELFSection(RelaSectionName, hasRelocationAddend() ? - ELF::SHT_RELA : ELF::SHT_REL, 0, - SectionKind::getReadOnly(), - EntrySize, ""); + const MCSectionELF *RelaSection = + Ctx.getELFSection(RelaSectionName, hasRelocationAddend() ? + ELF::SHT_RELA : ELF::SHT_REL, 0, + SectionKind::getReadOnly(), + EntrySize, ""); + RelMap[&Section] = RelaSection; + Asm.getOrCreateSectionData(*RelaSection); + } +} +void ELFObjectWriter::WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, + const RelMapTy &RelMap) { + for (MCAssembler::const_iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionData &SD = *it; + const MCSectionELF &Section = + static_cast(SD.getSection()); + + const MCSectionELF *RelaSection = RelMap.lookup(&Section); + if (!RelaSection) + continue; MCSectionData &RelaSD = Asm.getOrCreateSectionData(*RelaSection); RelaSD.setAlignment(is64Bit() ? 8 : 4); MCDataFragment *F = new MCDataFragment(&RelaSD); - - WriteRelocationsFragment(Asm, F, &SD); + WriteRelocationsFragment(Asm, F, &*it); } } @@ -1092,9 +751,28 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, } } +static int compareBySuffix(const void *a, const void *b) { + const MCSectionELF *secA = *static_cast(a); + const MCSectionELF *secB = *static_cast(b); + const StringRef &NameA = secA->getSectionName(); + const StringRef &NameB = secB->getSectionName(); + const unsigned sizeA = NameA.size(); + const unsigned sizeB = NameB.size(); + const unsigned len = std::min(sizeA, sizeB); + for (unsigned int i = 0; i < len; ++i) { + char ca = NameA[sizeA - i - 1]; + char cb = NameB[sizeB - i - 1]; + if (ca != cb) + return cb - ca; + } + + return sizeB - sizeA; +} + void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap) { + SectionIndexMapTy &SectionIndexMap, + const RelMapTy &RelMap) { MCContext &Ctx = Asm.getContext(); MCDataFragment *F; @@ -1106,7 +784,6 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, SectionKind::getReadOnly()); MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection); ShstrtabSD.setAlignment(1); - ShstrtabIndex = Asm.size(); const MCSectionELF *SymtabSection = Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, @@ -1114,7 +791,6 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, EntrySize, ""); MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection); SymtabSD.setAlignment(is64Bit() ? 8 : 4); - SymbolTableIndex = Asm.size(); MCSectionData *SymtabShndxSD = NULL; @@ -1126,14 +802,17 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, SymtabShndxSD->setAlignment(4); } - const MCSection *StrtabSection; + const MCSectionELF *StrtabSection; StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0, SectionKind::getReadOnly()); MCSectionData &StrtabSD = Asm.getOrCreateSectionData(*StrtabSection); StrtabSD.setAlignment(1); - StringTableIndex = Asm.size(); - WriteRelocations(Asm, Layout); + ComputeIndexMap(Asm, SectionIndexMap, RelMap); + + ShstrtabIndex = SectionIndexMap.lookup(ShstrtabSection); + SymbolTableIndex = SectionIndexMap.lookup(SymtabSection); + StringTableIndex = SectionIndexMap.lookup(StrtabSection); // Symbol table F = new MCDataFragment(&SymtabSD); @@ -1148,6 +827,15 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, F = new MCDataFragment(&ShstrtabSD); + std::vector Sections; + for (MCAssembler::const_iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionELF &Section = + static_cast(it->getSection()); + Sections.push_back(&Section); + } + array_pod_sort(Sections.begin(), Sections.end(), compareBySuffix); + // Section header string table. // // The first entry of a string table holds a null character so skip @@ -1155,22 +843,20 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, uint64_t Index = 1; F->getContents() += '\x00'; - StringMap SecStringMap; - for (MCAssembler::const_iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) { - const MCSectionELF &Section = - static_cast(it->getSection()); - // FIXME: We could merge suffixes like in .text and .rela.text. + for (unsigned int I = 0, E = Sections.size(); I != E; ++I) { + const MCSectionELF &Section = *Sections[I]; StringRef Name = Section.getSectionName(); - if (SecStringMap.count(Name)) { - SectionStringTableIndex[&Section] = SecStringMap[Name]; - continue; + if (I != 0) { + StringRef PreviousName = Sections[I - 1]->getSectionName(); + if (PreviousName.endswith(Name)) { + SectionStringTableIndex[&Section] = Index - Name.size() - 1; + continue; + } } // Remember the index into the string table so we can write it // into the sh_name field of the section header table. SectionStringTableIndex[&Section] = Index; - SecStringMap[Name] = Index; Index += Name.size() + 1; F->getContents() += Name; @@ -1181,7 +867,9 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout, GroupMapTy &GroupMap, - RevGroupMapTy &RevGroupMap) { + RevGroupMapTy &RevGroupMap, + SectionIndexMapTy &SectionIndexMap, + const RelMapTy &RelMap) { // Create the .note.GNU-stack section if needed. MCContext &Ctx = Asm.getContext(); if (Asm.getNoExecStack()) { @@ -1212,11 +900,11 @@ void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, GroupMap[Group] = SignatureSymbol; } + ComputeIndexMap(Asm, SectionIndexMap, RelMap); + // Add sections to the groups - unsigned Index = 1; - unsigned NumGroups = RevGroupMap.size(); for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); - it != ie; ++it, ++Index) { + it != ie; ++it) { const MCSectionELF &Section = static_cast(it->getSection()); if (!(Section.getFlags() & ELF::SHF_GROUP)) @@ -1225,7 +913,8 @@ void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, MCSectionData &Data = Asm.getOrCreateSectionData(*Group); // FIXME: we could use the previous fragment MCDataFragment *F = new MCDataFragment(&Data); - String32(*F, NumGroups + Index); + unsigned Index = SectionIndexMap.lookup(&Section); + String32(*F, Index); } } @@ -1304,12 +993,12 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, Alignment, Section.getEntrySize()); } -static bool IsELFMetaDataSection(const MCSectionData &SD) { +bool ELFObjectWriter::IsELFMetaDataSection(const MCSectionData &SD) { return SD.getOrdinal() == ~UINT32_C(0) && !SD.getSection().isVirtualSection(); } -static uint64_t DataSectionSize(const MCSectionData &SD) { +uint64_t ELFObjectWriter::DataSectionSize(const MCSectionData &SD) { uint64_t Ret = 0; for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e; ++i) { @@ -1320,112 +1009,60 @@ static uint64_t DataSectionSize(const MCSectionData &SD) { return Ret; } -static uint64_t GetSectionFileSize(const MCAsmLayout &Layout, - const MCSectionData &SD) { +uint64_t ELFObjectWriter::GetSectionFileSize(const MCAsmLayout &Layout, + const MCSectionData &SD) { if (IsELFMetaDataSection(SD)) return DataSectionSize(SD); return Layout.getSectionFileSize(&SD); } -static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout, - const MCSectionData &SD) { +uint64_t ELFObjectWriter::GetSectionAddressSize(const MCAsmLayout &Layout, + const MCSectionData &SD) { if (IsELFMetaDataSection(SD)) return DataSectionSize(SD); return Layout.getSectionAddressSize(&SD); } -static void WriteDataSectionData(ELFObjectWriter *W, const MCSectionData &SD) { - for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e; - ++i) { - const MCFragment &F = *i; - assert(F.getKind() == MCFragment::FT_Data); - W->WriteBytes(cast(F).getContents().str()); +void ELFObjectWriter::WriteDataSectionData(MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCSectionELF &Section) { + uint64_t FileOff = OS.tell(); + const MCSectionData &SD = Asm.getOrCreateSectionData(Section); + + uint64_t Padding = OffsetToAlignment(FileOff, SD.getAlignment()); + WriteZeros(Padding); + FileOff += Padding; + + FileOff += GetSectionFileSize(Layout, SD); + + if (IsELFMetaDataSection(SD)) { + for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e; + ++i) { + const MCFragment &F = *i; + assert(F.getKind() == MCFragment::FT_Data); + WriteBytes(cast(F).getContents().str()); + } + } else { + Asm.WriteSectionData(&SD, Layout); } } -void ELFObjectWriter::WriteObject(MCAssembler &Asm, - const MCAsmLayout &Layout) { - GroupMapTy GroupMap; - RevGroupMapTy RevGroupMap; - CreateIndexedSections(Asm, const_cast(Layout), GroupMap, - RevGroupMap); - - SectionIndexMapTy SectionIndexMap; - - ComputeIndexMap(Asm, SectionIndexMap); - - // Compute symbol table information. - ComputeSymbolTable(Asm, SectionIndexMap, RevGroupMap); - - CreateMetadataSections(const_cast(Asm), - const_cast(Layout), - SectionIndexMap); - - // Update to include the metadata sections. - ComputeIndexMap(Asm, SectionIndexMap); - - // Add 1 for the null section. - unsigned NumSections = Asm.size() + 1; - uint64_t NaturalAlignment = is64Bit() ? 8 : 4; - uint64_t HeaderSize = is64Bit() ? sizeof(ELF::Elf64_Ehdr) : - sizeof(ELF::Elf32_Ehdr); - uint64_t FileOff = HeaderSize; +void ELFObjectWriter::WriteSectionHeader(MCAssembler &Asm, + const GroupMapTy &GroupMap, + const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + const SectionOffsetMapTy &SectionOffsetMap) { + const unsigned NumSections = Asm.size() + 1; std::vector Sections; - Sections.resize(NumSections); + Sections.resize(NumSections - 1); for (SectionIndexMapTy::const_iterator i= SectionIndexMap.begin(), e = SectionIndexMap.end(); i != e; ++i) { const std::pair &p = *i; - Sections[p.second] = p.first; + Sections[p.second - 1] = p.first; } - for (unsigned i = 1; i < NumSections; ++i) { - const MCSectionELF &Section = *Sections[i]; - const MCSectionData &SD = Asm.getOrCreateSectionData(Section); - - FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); - - // Get the size of the section in the output file (including padding). - FileOff += GetSectionFileSize(Layout, SD); - } - - FileOff = RoundUpToAlignment(FileOff, NaturalAlignment); - - // Write out the ELF header ... - WriteHeader(FileOff - HeaderSize, NumSections); - - FileOff = HeaderSize; - - // ... then all of the sections ... - DenseMap SectionOffsetMap; - - for (unsigned i = 1; i < NumSections; ++i) { - const MCSectionELF &Section = *Sections[i]; - const MCSectionData &SD = Asm.getOrCreateSectionData(Section); - - uint64_t Padding = OffsetToAlignment(FileOff, SD.getAlignment()); - WriteZeros(Padding); - FileOff += Padding; - - // Remember the offset into the file for this section. - SectionOffsetMap[&Section] = FileOff; - - FileOff += GetSectionFileSize(Layout, SD); - - if (IsELFMetaDataSection(SD)) - WriteDataSectionData(this, SD); - else - Asm.WriteSectionData(&SD, Layout); - } - - uint64_t Padding = OffsetToAlignment(FileOff, NaturalAlignment); - WriteZeros(Padding); - FileOff += Padding; - - // ... and then the section header table. - // Should we align the section header table? - // // Null section first. uint64_t FirstSectionSize = NumSections >= ELF::SHN_LORESERVE ? NumSections : 0; @@ -1433,23 +1070,162 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0; WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0); - for (unsigned i = 1; i < NumSections; ++i) { + for (unsigned i = 0; i < NumSections - 1; ++i) { const MCSectionELF &Section = *Sections[i]; const MCSectionData &SD = Asm.getOrCreateSectionData(Section); uint32_t GroupSymbolIndex; if (Section.getType() != ELF::SHT_GROUP) GroupSymbolIndex = 0; else - GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, GroupMap[&Section]); + GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, + GroupMap.lookup(&Section)); uint64_t Size = GetSectionAddressSize(Layout, SD); WriteSection(Asm, SectionIndexMap, GroupSymbolIndex, - SectionOffsetMap[&Section], Size, + SectionOffsetMap.lookup(&Section), Size, SD.getAlignment(), Section); } } +void ELFObjectWriter::ComputeSectionOrder(MCAssembler &Asm, + std::vector &Sections) { + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionELF &Section = + static_cast(it->getSection()); + if (Section.getType() == ELF::SHT_GROUP) + Sections.push_back(&Section); + } + + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionELF &Section = + static_cast(it->getSection()); + if (Section.getType() != ELF::SHT_GROUP && + Section.getType() != ELF::SHT_REL && + Section.getType() != ELF::SHT_RELA) + Sections.push_back(&Section); + } + + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionELF &Section = + static_cast(it->getSection()); + if (Section.getType() == ELF::SHT_REL || + Section.getType() == ELF::SHT_RELA) + Sections.push_back(&Section); + } +} + +void ELFObjectWriter::WriteObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { + GroupMapTy GroupMap; + RevGroupMapTy RevGroupMap; + SectionIndexMapTy SectionIndexMap; + + unsigned NumUserSections = Asm.size(); + + DenseMap RelMap; + CreateRelocationSections(Asm, const_cast(Layout), RelMap); + + const unsigned NumUserAndRelocSections = Asm.size(); + CreateIndexedSections(Asm, const_cast(Layout), GroupMap, + RevGroupMap, SectionIndexMap, RelMap); + const unsigned AllSections = Asm.size(); + const unsigned NumIndexedSections = AllSections - NumUserAndRelocSections; + + unsigned NumRegularSections = NumUserSections + NumIndexedSections; + + // Compute symbol table information. + ComputeSymbolTable(Asm, SectionIndexMap, RevGroupMap, NumRegularSections); + + + WriteRelocations(Asm, const_cast(Layout), RelMap); + + CreateMetadataSections(const_cast(Asm), + const_cast(Layout), + SectionIndexMap, + RelMap); + + uint64_t NaturalAlignment = is64Bit() ? 8 : 4; + uint64_t HeaderSize = is64Bit() ? sizeof(ELF::Elf64_Ehdr) : + sizeof(ELF::Elf32_Ehdr); + uint64_t FileOff = HeaderSize; + + std::vector Sections; + ComputeSectionOrder(Asm, Sections); + unsigned NumSections = Sections.size(); + SectionOffsetMapTy SectionOffsetMap; + for (unsigned i = 0; i < NumRegularSections + 1; ++i) { + const MCSectionELF &Section = *Sections[i]; + const MCSectionData &SD = Asm.getOrCreateSectionData(Section); + + FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); + + // Remember the offset into the file for this section. + SectionOffsetMap[&Section] = FileOff; + + // Get the size of the section in the output file (including padding). + FileOff += GetSectionFileSize(Layout, SD); + } + + FileOff = RoundUpToAlignment(FileOff, NaturalAlignment); + + const unsigned SectionHeaderOffset = FileOff - HeaderSize; + + uint64_t SectionHeaderEntrySize = is64Bit() ? + sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr); + FileOff += (NumSections + 1) * SectionHeaderEntrySize; + + for (unsigned i = NumRegularSections + 1; i < NumSections; ++i) { + const MCSectionELF &Section = *Sections[i]; + const MCSectionData &SD = Asm.getOrCreateSectionData(Section); + + FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); + + // Remember the offset into the file for this section. + SectionOffsetMap[&Section] = FileOff; + + // Get the size of the section in the output file (including padding). + FileOff += GetSectionFileSize(Layout, SD); + } + + // Write out the ELF header ... + WriteHeader(SectionHeaderOffset, NumSections + 1); + + // ... then the regular sections ... + // + because of .shstrtab + for (unsigned i = 0; i < NumRegularSections + 1; ++i) + WriteDataSectionData(Asm, Layout, *Sections[i]); + + FileOff = OS.tell(); + uint64_t Padding = OffsetToAlignment(FileOff, NaturalAlignment); + WriteZeros(Padding); + + // ... then the section header table ... + WriteSectionHeader(Asm, GroupMap, Layout, SectionIndexMap, + SectionOffsetMap); + + FileOff = OS.tell(); + + // ... and then the remainting sections ... + for (unsigned i = NumRegularSections + 1; i < NumSections; ++i) + WriteDataSectionData(Asm, Layout, *Sections[i]); +} + +bool +ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const { + if (DataA.getFlags() & ELF_STB_Weak) + return false; + return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( + Asm, DataA, FB,InSet, IsPCRel); +} + MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &OS, bool IsLittleEndian) { @@ -1700,13 +1476,17 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, if (IsPCRel) { switch ((unsigned)Fixup.getKind()) { default: llvm_unreachable("invalid fixup kind!"); + + case FK_Data_8: Type = ELF::R_X86_64_PC64; break; + case FK_Data_4: Type = ELF::R_X86_64_PC32; break; + case FK_Data_2: Type = ELF::R_X86_64_PC16; break; + case FK_PCRel_8: assert(Modifier == MCSymbolRefExpr::VK_None); Type = ELF::R_X86_64_PC64; break; case X86::reloc_signed_4byte: case X86::reloc_riprel_4byte_movq_load: - case FK_Data_4: // FIXME? case X86::reloc_riprel_4byte: case FK_PCRel_4: switch (Modifier) { diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.h b/contrib/llvm/lib/MC/ELFObjectWriter.h new file mode 100644 index 000000000000..f1d514a89988 --- /dev/null +++ b/contrib/llvm/lib/MC/ELFObjectWriter.h @@ -0,0 +1,406 @@ +//===- lib/MC/ELFObjectWriter.h - ELF File Writer -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF object file writer information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_ELFOBJECTWRITER_H +#define LLVM_MC_ELFOBJECTWRITER_H + +#include "MCELF.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCELFSymbolFlags.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" + +#include + +namespace llvm { + +class MCSection; +class MCDataFragment; +class MCSectionELF; + +class ELFObjectWriter : public MCObjectWriter { + protected: + + static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); + static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant); + static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout); + static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, + bool Used, bool Renamed); + static bool isLocal(const MCSymbolData &Data, bool isSignature, + bool isUsedInReloc); + static bool IsELFMetaDataSection(const MCSectionData &SD); + static uint64_t DataSectionSize(const MCSectionData &SD); + static uint64_t GetSectionFileSize(const MCAsmLayout &Layout, + const MCSectionData &SD); + static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout, + const MCSectionData &SD); + + void WriteDataSectionData(MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCSectionELF &Section); + + /*static bool isFixupKindX86RIPRel(unsigned Kind) { + return Kind == X86::reloc_riprel_4byte || + Kind == X86::reloc_riprel_4byte_movq_load; + }*/ + + /// ELFSymbolData - Helper struct for containing some precomputed + /// information on symbols. + struct ELFSymbolData { + MCSymbolData *SymbolData; + uint64_t StringIndex; + uint32_t SectionIndex; + + // Support lexicographic sorting. + bool operator<(const ELFSymbolData &RHS) const { + if (MCELF::GetType(*SymbolData) == ELF::STT_FILE) + return true; + if (MCELF::GetType(*RHS.SymbolData) == ELF::STT_FILE) + return false; + return SymbolData->getSymbol().getName() < + RHS.SymbolData->getSymbol().getName(); + } + }; + + /// @name Relocation Data + /// @{ + + struct ELFRelocationEntry { + // Make these big enough for both 32-bit and 64-bit + uint64_t r_offset; + int Index; + unsigned Type; + const MCSymbol *Symbol; + uint64_t r_addend; + + ELFRelocationEntry() + : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0) {} + + ELFRelocationEntry(uint64_t RelocOffset, int Idx, + unsigned RelType, const MCSymbol *Sym, + uint64_t Addend) + : r_offset(RelocOffset), Index(Idx), Type(RelType), + Symbol(Sym), r_addend(Addend) {} + + // Support lexicographic sorting. + bool operator<(const ELFRelocationEntry &RE) const { + return RE.r_offset < r_offset; + } + }; + + /// The target specific ELF writer instance. + llvm::OwningPtr TargetObjectWriter; + + SmallPtrSet UsedInReloc; + SmallPtrSet WeakrefUsedInReloc; + DenseMap Renames; + + llvm::DenseMap > Relocations; + DenseMap SectionStringTableIndex; + + /// @} + /// @name Symbol Table Data + /// @{ + + SmallString<256> StringTable; + std::vector LocalSymbolData; + std::vector ExternalSymbolData; + std::vector UndefinedSymbolData; + + /// @} + + bool NeedsGOT; + + bool NeedsSymtabShndx; + + // This holds the symbol table index of the last local symbol. + unsigned LastLocalSymbolIndex; + // This holds the .strtab section index. + unsigned StringTableIndex; + // This holds the .symtab section index. + unsigned SymbolTableIndex; + + unsigned ShstrtabIndex; + + + const MCSymbol *SymbolToReloc(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F) const; + + // For arch-specific emission of explicit reloc symbol + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + bool IsBSS) const { + return NULL; + } + + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + bool hasRelocationAddend() const { + return TargetObjectWriter->hasRelocationAddend(); + } + + public: + ELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, bool IsLittleEndian) + : MCObjectWriter(_OS, IsLittleEndian), + TargetObjectWriter(MOTW), + NeedsGOT(false), NeedsSymtabShndx(false){ + } + + virtual ~ELFObjectWriter(); + + void WriteWord(uint64_t W) { + if (is64Bit()) + Write64(W); + else + Write32(W); + } + + void StringLE16(char *buf, uint16_t Value) { + buf[0] = char(Value >> 0); + buf[1] = char(Value >> 8); + } + + void StringLE32(char *buf, uint32_t Value) { + StringLE16(buf, uint16_t(Value >> 0)); + StringLE16(buf + 2, uint16_t(Value >> 16)); + } + + void StringLE64(char *buf, uint64_t Value) { + StringLE32(buf, uint32_t(Value >> 0)); + StringLE32(buf + 4, uint32_t(Value >> 32)); + } + + void StringBE16(char *buf ,uint16_t Value) { + buf[0] = char(Value >> 8); + buf[1] = char(Value >> 0); + } + + void StringBE32(char *buf, uint32_t Value) { + StringBE16(buf, uint16_t(Value >> 16)); + StringBE16(buf + 2, uint16_t(Value >> 0)); + } + + void StringBE64(char *buf, uint64_t Value) { + StringBE32(buf, uint32_t(Value >> 32)); + StringBE32(buf + 4, uint32_t(Value >> 0)); + } + + void String8(MCDataFragment &F, uint8_t Value) { + char buf[1]; + buf[0] = Value; + F.getContents() += StringRef(buf, 1); + } + + void String16(MCDataFragment &F, uint16_t Value) { + char buf[2]; + if (isLittleEndian()) + StringLE16(buf, Value); + else + StringBE16(buf, Value); + F.getContents() += StringRef(buf, 2); + } + + void String32(MCDataFragment &F, uint32_t Value) { + char buf[4]; + if (isLittleEndian()) + StringLE32(buf, Value); + else + StringBE32(buf, Value); + F.getContents() += StringRef(buf, 4); + } + + void String64(MCDataFragment &F, uint64_t Value) { + char buf[8]; + if (isLittleEndian()) + StringLE64(buf, Value); + else + StringBE64(buf, Value); + F.getContents() += StringRef(buf, 8); + } + + virtual void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); + + /// Default e_flags = 0 + virtual void WriteEFlags() { Write32(0); } + + virtual void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF, + uint64_t name, uint8_t info, + uint64_t value, uint64_t size, + uint8_t other, uint32_t shndx, + bool Reserved); + + virtual void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, + ELFSymbolData &MSD, + const MCAsmLayout &Layout); + + typedef DenseMap SectionIndexMapTy; + virtual void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap); + + virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue); + + virtual uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, + const MCSymbol *S); + + // Map from a group section to the signature symbol + typedef DenseMap GroupMapTy; + // Map from a signature symbol to the group section + typedef DenseMap RevGroupMapTy; + // Map from a section to the section with the relocations + typedef DenseMap RelMapTy; + // Map from a section to its offset + typedef DenseMap SectionOffsetMapTy; + + /// 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. + virtual void ComputeSymbolTable(MCAssembler &Asm, + const SectionIndexMapTy &SectionIndexMap, + RevGroupMapTy RevGroupMap, + unsigned NumRegularSections); + + virtual void ComputeIndexMap(MCAssembler &Asm, + SectionIndexMapTy &SectionIndexMap, + const RelMapTy &RelMap); + + void CreateRelocationSections(MCAssembler &Asm, MCAsmLayout &Layout, + RelMapTy &RelMap); + + void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, + const RelMapTy &RelMap); + + virtual void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, + SectionIndexMapTy &SectionIndexMap, + const RelMapTy &RelMap); + + // Create the sections that show up in the symbol table. Currently + // those are the .note.GNU-stack section and the group sections. + virtual void CreateIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout, + GroupMapTy &GroupMap, + RevGroupMapTy &RevGroupMap, + SectionIndexMapTy &SectionIndexMap, + const RelMapTy &RelMap); + + virtual void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout); + + void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap, + const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + const SectionOffsetMapTy &SectionOffsetMap); + + void ComputeSectionOrder(MCAssembler &Asm, + std::vector &Sections); + + virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, + uint64_t Address, uint64_t Offset, + uint64_t Size, uint32_t Link, uint32_t Info, + uint64_t Alignment, uint64_t EntrySize); + + virtual void WriteRelocationsFragment(const MCAssembler &Asm, + MCDataFragment *F, + const MCSectionData *SD); + + virtual bool + IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); + virtual void WriteSection(MCAssembler &Asm, + const SectionIndexMapTy &SectionIndexMap, + uint32_t GroupSymbolIndex, + uint64_t Offset, uint64_t Size, uint64_t Alignment, + const MCSectionELF &Section); + + protected: + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend) = 0; + }; + + //===- X86ELFObjectWriter -------------------------------------------===// + + class X86ELFObjectWriter : public ELFObjectWriter { + public: + X86ELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian); + + virtual ~X86ELFObjectWriter(); + protected: + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend); + }; + + + //===- ARMELFObjectWriter -------------------------------------------===// + + class ARMELFObjectWriter : public ELFObjectWriter { + public: + // FIXME: MCAssembler can't yet return the Subtarget, + enum { DefaultEABIVersion = 0x05000000U }; + + ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian); + + virtual ~ARMELFObjectWriter(); + + virtual void WriteEFlags(); + protected: + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + bool IsBSS) const; + + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend); + }; + + //===- MBlazeELFObjectWriter -------------------------------------------===// + + class MBlazeELFObjectWriter : public ELFObjectWriter { + public: + MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian); + + virtual ~MBlazeELFObjectWriter(); + protected: + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend); + }; +} + +#endif diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp index 8199fb2e158a..541dd080accf 100644 --- a/contrib/llvm/lib/MC/MCAsmInfo.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfo.cpp @@ -13,7 +13,11 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Dwarf.h" #include #include using namespace llvm; @@ -26,7 +30,7 @@ MCAsmInfo::MCAsmInfo() { LinkerRequiresNonEmptyDwarfLines = false; MaxInstLength = 4; PCSymbol = "$"; - SeparatorChar = ';'; + SeparatorString = ";"; CommentColumn = 40; CommentString = "#"; LabelSuffix = ":"; @@ -106,3 +110,25 @@ unsigned MCAsmInfo::getSLEB128Size(int Value) { } while (IsMore); return Size; } + +const MCExpr * +MCAsmInfo::getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const { + return getExprForFDESymbol(Sym, Encoding, Streamer); +} + +const MCExpr * +MCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const { + if (!(Encoding & dwarf::DW_EH_PE_pcrel)) + return MCSymbolRefExpr::Create(Sym, Streamer.getContext()); + + MCContext &Context = Streamer.getContext(); + const MCExpr *Res = MCSymbolRefExpr::Create(Sym, Context); + MCSymbol *PCSym = Context.CreateTempSymbol(); + Streamer.EmitLabel(PCSym); + const MCExpr *PC = MCSymbolRefExpr::Create(PCSym, Context); + return MCBinaryExpr::CreateSub(Res, PC, Context); +} diff --git a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp index 526ad0da42aa..4dd1d44af5d2 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp @@ -13,6 +13,9 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAsmInfoDarwin.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCStreamer.h" using namespace llvm; MCAsmInfoDarwin::MCAsmInfoDarwin() { @@ -56,4 +59,3 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { DwarfUsesAbsoluteLabelForStmtList = false; DwarfUsesLabelOffsetForRanges = false; } - diff --git a/contrib/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm/lib/MC/MCAsmStreamer.cpp index 8d0698216f60..9717c016a92b 100644 --- a/contrib/llvm/lib/MC/MCAsmStreamer.cpp +++ b/contrib/llvm/lib/MC/MCAsmStreamer.cpp @@ -45,20 +45,25 @@ class MCAsmStreamer : public MCStreamer { unsigned IsVerboseAsm : 1; unsigned ShowInst : 1; unsigned UseLoc : 1; + unsigned UseCFI : 1; + + enum EHSymbolFlags { EHGlobal = 1, + EHWeakDefinition = 1 << 1, + EHPrivateExtern = 1 << 2 }; + DenseMap FlagMap; bool needsSet(const MCExpr *Value); public: MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, - bool isVerboseAsm, - bool useLoc, + bool isVerboseAsm, bool useLoc, bool useCFI, MCInstPrinter *printer, MCCodeEmitter *emitter, TargetAsmBackend *asmbackend, bool showInst) : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend), CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm), - ShowInst(showInst), UseLoc(useLoc) { + ShowInst(showInst), UseLoc(useLoc), UseCFI(useCFI) { if (InstPrinter && IsVerboseAsm) InstPrinter->setCommentStream(CommentStream); } @@ -118,7 +123,8 @@ class MCAsmStreamer : public MCStreamer { } virtual void EmitLabel(MCSymbol *Symbol); - + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, + MCSymbol *EHSymbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitThumbFunc(MCSymbol *Func); @@ -127,6 +133,8 @@ class MCAsmStreamer : public MCStreamer { virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label); + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); @@ -154,13 +162,13 @@ class MCAsmStreamer : public MCStreamer { virtual void EmitBytes(StringRef Data, unsigned AddrSpace); virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - bool isPCRel, unsigned AddrSpace); + unsigned AddrSpace); virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace = 0); - virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + virtual void EmitULEB128Value(const MCExpr *Value); - virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + virtual void EmitSLEB128Value(const MCExpr *Value); virtual void EmitGPRel32Value(const MCExpr *Value); @@ -182,15 +190,32 @@ class MCAsmStreamer : public MCStreamer { virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Filename); virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, - unsigned Isa, unsigned Discriminator); + unsigned Isa, unsigned Discriminator, + StringRef FileName); + + virtual void EmitCFIStartProc(); + virtual void EmitCFIEndProc(); + virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual void EmitCFIDefCfaOffset(int64_t Offset); + virtual void EmitCFIDefCfaRegister(int64_t Register); + virtual void EmitCFIOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFIRememberState(); + virtual void EmitCFIRestoreState(); + virtual void EmitCFISameValue(int64_t Register); + virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); + + virtual void EmitFnStart(); + virtual void EmitFnEnd(); + virtual void EmitCantUnwind(); + virtual void EmitPersonality(const MCSymbol *Personality); + virtual void EmitHandlerData(); + virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); + virtual void EmitPad(int64_t Offset); + virtual void EmitRegSave(const SmallVectorImpl &RegList, bool); - virtual bool EmitCFIStartProc(); - virtual bool EmitCFIEndProc(); - virtual bool EmitCFIDefCfaOffset(int64_t Offset); - virtual bool EmitCFIDefCfaRegister(int64_t Register); - virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); - virtual bool EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); - virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); virtual void EmitInstruction(const MCInst &Inst); @@ -259,14 +284,27 @@ void MCAsmStreamer::ChangeSection(const MCSection *Section) { Section->PrintSwitchToSection(MAI, OS); } +void MCAsmStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, + MCSymbol *EHSymbol) { + if (UseCFI) + return; + + unsigned Flags = FlagMap.lookup(Symbol); + + if (Flags & EHGlobal) + EmitSymbolAttribute(EHSymbol, MCSA_Global); + if (Flags & EHWeakDefinition) + EmitSymbolAttribute(EHSymbol, MCSA_WeakDefinition); + if (Flags & EHPrivateExtern) + EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern); +} + void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); + MCStreamer::EmitLabel(Symbol); OS << *Symbol << MAI.getLabelSuffix(); EmitEOL(); - Symbol->setSection(*getCurrentSection()); } void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { @@ -309,6 +347,15 @@ void MCAsmStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, getContext().getTargetAsmInfo().getPointerSize()); } +void MCAsmStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) { + EmitIntValue(dwarf::DW_CFA_advance_loc4, 1); + const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel); + AddrDelta = ForceExpAbs(this, getContext(), AddrDelta); + EmitValue(AddrDelta, 4); +} + + void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { switch (Attribute) { @@ -337,6 +384,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, return; case MCSA_Global: // .globl/.global OS << MAI.getGlobalDirective(); + FlagMap[Symbol] |= EHGlobal; break; case MCSA_Hidden: OS << "\t.hidden\t"; break; case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break; @@ -345,11 +393,17 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_Local: OS << "\t.local\t"; break; case MCSA_NoDeadStrip: OS << "\t.no_dead_strip\t"; break; case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; - case MCSA_PrivateExtern: OS << "\t.private_extern\t"; break; + case MCSA_PrivateExtern: + OS << "\t.private_extern\t"; + FlagMap[Symbol] |= EHPrivateExtern; + break; case MCSA_Protected: OS << "\t.protected\t"; break; case MCSA_Reference: OS << "\t.reference\t"; break; case MCSA_Weak: OS << "\t.weak\t"; break; - case MCSA_WeakDefinition: OS << "\t.weak_definition\t"; break; + case MCSA_WeakDefinition: + OS << "\t.weak_definition\t"; + FlagMap[Symbol] |= EHWeakDefinition; + break; // .weak_reference case MCSA_WeakReference: OS << MAI.getWeakRefDirective(); break; case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; @@ -512,9 +566,8 @@ void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, } void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - bool isPCRel, unsigned AddrSpace) { + unsigned AddrSpace) { assert(getCurrentSection() && "Cannot emit contents before setting section!"); - assert(!isPCRel && "Cannot emit pc relative relocations!"); const char *Directive = 0; switch (Size) { default: break; @@ -543,10 +596,10 @@ void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, EmitEOL(); } -void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace) { +void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { int64_t IntValue; if (Value->EvaluateAsAbsolute(IntValue)) { - EmitULEB128IntValue(IntValue, AddrSpace); + EmitULEB128IntValue(IntValue); return; } assert(MAI.hasLEB128() && "Cannot print a .uleb"); @@ -554,10 +607,10 @@ void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace) { EmitEOL(); } -void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace) { +void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { int64_t IntValue; if (Value->EvaluateAsAbsolute(IntValue)) { - EmitSLEB128IntValue(IntValue, AddrSpace); + EmitSLEB128IntValue(IntValue); return; } assert(MAI.hasLEB128() && "Cannot print a .sleb"); @@ -673,9 +726,10 @@ bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, - unsigned Discriminator) { + unsigned Discriminator, + StringRef FileName) { this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, - Isa, Discriminator); + Isa, Discriminator, FileName); if (!UseLoc) return; @@ -701,78 +755,144 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, OS << "isa " << Isa; if (Discriminator) OS << "discriminator " << Discriminator; + + if (IsVerboseAsm) { + OS.PadToColumn(MAI.getCommentColumn()); + OS << MAI.getCommentString() << ' ' << FileName << ':' + << Line << ':' << Column; + } EmitEOL(); } -bool MCAsmStreamer::EmitCFIStartProc() { - if (this->MCStreamer::EmitCFIStartProc()) - return true; +void MCAsmStreamer::EmitCFIStartProc() { + MCStreamer::EmitCFIStartProc(); + + if (!UseCFI) + return; OS << "\t.cfi_startproc"; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFIEndProc() { - if (this->MCStreamer::EmitCFIEndProc()) - return true; +void MCAsmStreamer::EmitCFIEndProc() { + MCStreamer::EmitCFIEndProc(); + + if (!UseCFI) + return; OS << "\t.cfi_endproc"; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { - if (this->MCStreamer::EmitCFIDefCfaOffset(Offset)) - return true; +void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { + MCStreamer::EmitCFIDefCfa(Register, Offset); + + if (!UseCFI) + return; + + OS << ".cfi_def_cfa " << Register << ", " << Offset; + EmitEOL(); +} + +void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { + MCStreamer::EmitCFIDefCfaOffset(Offset); + + if (!UseCFI) + return; OS << "\t.cfi_def_cfa_offset " << Offset; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { - if (this->MCStreamer::EmitCFIDefCfaRegister(Register)) - return true; +void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { + MCStreamer::EmitCFIDefCfaRegister(Register); + + if (!UseCFI) + return; OS << "\t.cfi_def_cfa_register " << Register; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { - if (this->MCStreamer::EmitCFIOffset(Register, Offset)) - return true; +void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { + this->MCStreamer::EmitCFIOffset(Register, Offset); + + if (!UseCFI) + return; OS << "\t.cfi_offset " << Register << ", " << Offset; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, +void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) { - if (this->MCStreamer::EmitCFIPersonality(Sym, Encoding)) - return true; + MCStreamer::EmitCFIPersonality(Sym, Encoding); + + if (!UseCFI) + return; OS << "\t.cfi_personality " << Encoding << ", " << *Sym; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { - if (this->MCStreamer::EmitCFILsda(Sym, Encoding)) - return true; +void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { + MCStreamer::EmitCFILsda(Sym, Encoding); + + if (!UseCFI) + return; OS << "\t.cfi_lsda " << Encoding << ", " << *Sym; EmitEOL(); +} - return false; +void MCAsmStreamer::EmitCFIRememberState() { + MCStreamer::EmitCFIRememberState(); + + if (!UseCFI) + return; + + OS << "\t.cfi_remember_state"; + EmitEOL(); +} + +void MCAsmStreamer::EmitCFIRestoreState() { + MCStreamer::EmitCFIRestoreState(); + + if (!UseCFI) + return; + + OS << "\t.cfi_restore_state"; + EmitEOL(); +} + +void MCAsmStreamer::EmitCFISameValue(int64_t Register) { + MCStreamer::EmitCFISameValue(Register); + + if (!UseCFI) + return; + + OS << "\t.cfi_same_value " << Register; + EmitEOL(); +} + +void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { + MCStreamer::EmitCFIRelOffset(Register, Offset); + + if (!UseCFI) + return; + + OS << "\t.cfi_rel_offset " << Register << ", " << Offset; + EmitEOL(); +} + +void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { + MCStreamer::EmitCFIAdjustCfaOffset(Adjustment); + + if (!UseCFI) + return; + + OS << "\t.cfi_adjust_cfa_offset " << Adjustment; + EmitEOL(); } void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { @@ -834,13 +954,13 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { OS << "0b"; for (unsigned j = 8; j--;) { unsigned Bit = (Code[i] >> j) & 1; - + unsigned FixupBit; if (getContext().getTargetAsmInfo().isLittleEndian()) FixupBit = i * 8 + j; else FixupBit = i * 8 + (7-j); - + if (uint8_t MapEntry = FixupMap[FixupBit]) { assert(Bit == 0 && "Encoder wrote into fixed up bit!"); OS << char('A' + MapEntry - 1); @@ -859,12 +979,64 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { } } +void MCAsmStreamer::EmitFnStart() { + OS << "\t.fnstart"; + EmitEOL(); +} + +void MCAsmStreamer::EmitFnEnd() { + OS << "\t.fnend"; + EmitEOL(); +} + +void MCAsmStreamer::EmitCantUnwind() { + OS << "\t.cantunwind"; + EmitEOL(); +} + +void MCAsmStreamer::EmitHandlerData() { + OS << "\t.handlerdata"; + EmitEOL(); +} + +void MCAsmStreamer::EmitPersonality(const MCSymbol *Personality) { + OS << "\t.personality " << Personality->getName(); + EmitEOL(); +} + +void MCAsmStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { + OS << "\t.setfp\t" << InstPrinter->getRegName(FpReg) + << ", " << InstPrinter->getRegName(SpReg); + if (Offset) + OS << ", #" << Offset; + EmitEOL(); +} + +void MCAsmStreamer::EmitPad(int64_t Offset) { + OS << "\t.pad\t#" << Offset; + EmitEOL(); +} + +void MCAsmStreamer::EmitRegSave(const SmallVectorImpl &RegList, + bool isVector) { + assert(RegList.size() && "RegList should not be empty"); + if (isVector) + OS << "\t.vsave\t{"; + else + OS << "\t.save\t{"; + + OS << InstPrinter->getRegName(RegList[0]); + + for (unsigned i = 1, e = RegList.size(); i != e; ++i) + OS << ", " << InstPrinter->getRegName(RegList[i]); + + OS << "}"; + EmitEOL(); +} + void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { assert(getCurrentSection() && "Cannot emit contents before setting section!"); - if (!UseLoc) - MCLineEntry::Make(this, getCurrentSection()); - // Show the encoding in a comment if we have a code emitter. if (Emitter) AddEncodingComment(Inst); @@ -897,13 +1069,17 @@ void MCAsmStreamer::Finish() { // Dump out the dwarf file & directory tables and line tables. if (getContext().hasDwarfFiles() && !UseLoc) MCDwarfFileTable::Emit(this); + + if (getNumFrameInfos() && !UseCFI) + MCDwarfFrameEmitter::Emit(*this, false); } MCStreamer *llvm::createAsmStreamer(MCContext &Context, formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, + bool useCFI, MCInstPrinter *IP, MCCodeEmitter *CE, TargetAsmBackend *TAB, bool ShowInst) { - return new MCAsmStreamer(Context, OS, isVerboseAsm, useLoc, + return new MCAsmStreamer(Context, OS, isVerboseAsm, useLoc, useCFI, IP, CE, TAB, ShowInst); } diff --git a/contrib/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm/lib/MC/MCAssembler.cpp index 999264604224..8360fc9f414e 100644 --- a/contrib/llvm/lib/MC/MCAssembler.cpp +++ b/contrib/llvm/lib/MC/MCAssembler.cpp @@ -28,7 +28,6 @@ #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetAsmBackend.h" -#include using namespace llvm; namespace { @@ -103,6 +102,33 @@ uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { } uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { + const MCSymbol &S = SD->getSymbol(); + + // If this is a variable, then recursively evaluate now. + if (S.isVariable()) { + MCValue Target; + if (!S.getVariableValue()->EvaluateAsRelocatable(Target, *this)) + report_fatal_error("unable to evaluate offset for variable '" + + S.getName() + "'"); + + // Verify that any used symbols are defined. + if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined()) + report_fatal_error("unable to evaluate offset to undefined symbol '" + + Target.getSymA()->getSymbol().getName() + "'"); + if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined()) + report_fatal_error("unable to evaluate offset to undefined symbol '" + + Target.getSymB()->getSymbol().getName() + "'"); + + uint64_t Offset = Target.getConstant(); + if (Target.getSymA()) + Offset += getSymbolOffset(&Assembler.getSymbolData( + Target.getSymA()->getSymbol())); + if (Target.getSymB()) + Offset -= getSymbolOffset(&Assembler.getSymbolData( + Target.getSymB()->getSymbol())); + return Offset; + } + assert(SD->getFragment() && "Invalid getOffset() on undefined symbol!"); return getFragmentOffset(SD->getFragment()) + SD->getOffset(); } @@ -692,7 +718,9 @@ bool MCAssembler::RelaxInstruction(MCAsmLayout &Layout, bool MCAssembler::RelaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { int64_t Value = 0; uint64_t OldSize = LF.getContents().size(); - LF.getValue().EvaluateAsAbsolute(Value, Layout); + bool IsAbs = LF.getValue().EvaluateAsAbsolute(Value, Layout); + (void)IsAbs; + assert(IsAbs); SmallString<8> &Data = LF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); @@ -731,7 +759,8 @@ bool MCAssembler::RelaxDwarfCallFrameFragment(MCAsmLayout &Layout, SmallString<8> &Data = DF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); - MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OSE); + const TargetAsmInfo &AsmInfo = getContext().getTargetAsmInfo(); + MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OSE, AsmInfo); OSE.flush(); return OldSize != Data.size(); } diff --git a/contrib/llvm/lib/MC/MCContext.cpp b/contrib/llvm/lib/MC/MCContext.cpp index 018f00c08f6f..8faa72ecb4e8 100644 --- a/contrib/llvm/lib/MC/MCContext.cpp +++ b/contrib/llvm/lib/MC/MCContext.cpp @@ -27,8 +27,11 @@ typedef StringMap COFFUniqueMapTy; MCContext::MCContext(const MCAsmInfo &mai, const TargetAsmInfo *tai) : - MAI(mai), TAI(tai), NextUniqueID(0), - CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0) { + MAI(mai), TAI(tai), + Allocator(), Symbols(Allocator), UsedNames(Allocator), + NextUniqueID(0), + CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0), + AllowTemporaryLabels(true) { MachOUniquingMap = 0; ELFUniquingMap = 0; COFFUniquingMap = 0; @@ -76,18 +79,19 @@ MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) { } MCSymbol *MCContext::CreateSymbol(StringRef Name) { - // Determine whether this is an assembler temporary or normal label. - bool isTemporary = Name.startswith(MAI.getPrivateGlobalPrefix()); + // Determine whether this is an assembler temporary or normal label, if used. + bool isTemporary = false; + if (AllowTemporaryLabels) + isTemporary = Name.startswith(MAI.getPrivateGlobalPrefix()); StringMapEntry *NameEntry = &UsedNames.GetOrCreateValue(Name); if (NameEntry->getValue()) { assert(isTemporary && "Cannot rename non temporary symbols"); - SmallString<128> NewName; + SmallString<128> NewName = Name; do { - Twine T = Name + Twine(NextUniqueID++); - T.toVector(NewName); - StringRef foo = NewName; - NameEntry = &UsedNames.GetOrCreateValue(foo); + NewName.resize(Name.size()); + raw_svector_ostream(NewName) << NextUniqueID++; + NameEntry = &UsedNames.GetOrCreateValue(NewName); } while (NameEntry->getValue()); } NameEntry->setValue(true); @@ -107,9 +111,8 @@ MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { MCSymbol *MCContext::CreateTempSymbol() { SmallString<128> NameSV; - Twine Name = Twine(MAI.getPrivateGlobalPrefix()) + "tmp" + - Twine(NextUniqueID++); - Name.toVector(NameSV); + raw_svector_ostream(NameSV) + << MAI.getPrivateGlobalPrefix() << "tmp" << NextUniqueID++; return CreateSymbol(NameSV); } diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp new file mode 100644 index 000000000000..ced57e8ca2de --- /dev/null +++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp @@ -0,0 +1,171 @@ +//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface -*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "Disassembler.h" +#include +#include "llvm-c/Disassembler.h" + +#include +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmInfo.h" // FIXME. +#include "llvm/Target/TargetMachine.h" // FIXME. +#include "llvm/Target/TargetSelect.h" +#include "llvm/Support/MemoryObject.h" + +namespace llvm { +class Target; +} // namespace llvm +using namespace llvm; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// +// LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic +// disassembly is supported by passing a block of information in the DisInfo +// parameter and specifing the TagType and call back functions as described in +// the header llvm-c/Disassembler.h . The pointer to the block and the +// functions can all be passed as NULL. If successful this returns a +// disassembler context if not it returns NULL. +// +LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, + int TagType, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp) { + // Initialize targets and assembly printers/parsers. + llvm::InitializeAllTargetInfos(); + // FIXME: We shouldn't need to initialize the Target(Machine)s. + llvm::InitializeAllTargets(); + llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllAsmParsers(); + llvm::InitializeAllDisassemblers(); + + // Get the target. + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); + assert(TheTarget && "Unable to create target!"); + + // Get the assembler info needed to setup the MCContext. + const MCAsmInfo *MAI = TheTarget->createAsmInfo(TripleName); + assert(MAI && "Unable to create target asm info!"); + + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + + // FIXME: We shouldn't need to do this (and link in codegen). + // When we split this out, we should do it in a way that makes + // it straightforward to switch subtargets on the fly. + TargetMachine *TM = TheTarget->createTargetMachine(TripleName, FeaturesStr); + assert(TM && "Unable to create target machine!"); + + // Get the target assembler info needed to setup the context. + const TargetAsmInfo *tai = new TargetAsmInfo(*TM); + assert(tai && "Unable to create target assembler!"); + + // Set up the MCContext for creating symbols and MCExpr's. + MCContext *Ctx = new MCContext(*MAI, tai); + assert(Ctx && "Unable to create MCContext!"); + + // Set up disassembler. + MCDisassembler *DisAsm = TheTarget->createMCDisassembler(); + assert(DisAsm && "Unable to create disassembler!"); + DisAsm->setupForSymbolicDisassembly(GetOpInfo, DisInfo, Ctx); + + // Set up the instruction printer. + int AsmPrinterVariant = MAI->getAssemblerDialect(); + MCInstPrinter *IP = TheTarget->createMCInstPrinter(*TM, AsmPrinterVariant, + *MAI); + assert(IP && "Unable to create instruction printer!"); + + LLVMDisasmContext *DC = new LLVMDisasmContext(TripleName, DisInfo, TagType, + GetOpInfo, SymbolLookUp, + TheTarget, MAI, TM, tai, Ctx, + DisAsm, IP); + assert(DC && "Allocation failure!"); + return DC; +} + +// +// LLVMDisasmDispose() disposes of the disassembler specified by the context. +// +void LLVMDisasmDispose(LLVMDisasmContextRef DCR){ + LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; + delete DC; +} + +namespace { +// +// The memory object created by LLVMDisasmInstruction(). +// +class DisasmMemoryObject : public MemoryObject { +private: + uint8_t *Bytes; + uint64_t Size; + uint64_t BasePC; +public: + DisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) : + Bytes(bytes), Size(size), BasePC(basePC) {} + + uint64_t getBase() const { return BasePC; } + uint64_t getExtent() const { return Size; } + + int readByte(uint64_t Addr, uint8_t *Byte) const { + if (Addr - BasePC >= Size) + return -1; + *Byte = Bytes[Addr - BasePC]; + return 0; + } +}; +} // namespace + +// +// LLVMDisasmInstruction() disassembles a single instruction using the +// disassembler context specified in the parameter DC. The bytes of the +// instruction are specified in the parameter Bytes, and contains at least +// BytesSize number of bytes. The instruction is at the address specified by +// the PC parameter. If a valid instruction can be disassembled its string is +// returned indirectly in OutString which whos size is specified in the +// parameter OutStringSize. This function returns the number of bytes in the +// instruction or zero if there was no valid instruction. If this function +// returns zero the caller will have to pick how many bytes they want to step +// over by printing a .byte, .long etc. to continue. +// +size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, + uint64_t BytesSize, uint64_t PC, char *OutString, + size_t OutStringSize){ + LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; + // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject. + DisasmMemoryObject MemoryObject(Bytes, BytesSize, PC); + + uint64_t Size; + MCInst Inst; + const MCDisassembler *DisAsm = DC->getDisAsm(); + MCInstPrinter *IP = DC->getIP(); + if (!DisAsm->getInstruction(Inst, Size, MemoryObject, PC, /*REMOVE*/ nulls())) + return 0; + + std::string InsnStr; + raw_string_ostream OS(InsnStr); + IP->printInst(&Inst, OS); + OS.flush(); + + size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); + std::memcpy(OutString, InsnStr.data(), OutputSize); + OutString[OutputSize] = '\0'; // Terminate string. + + return Size; +} + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h new file mode 100644 index 000000000000..f0ec42a017a4 --- /dev/null +++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h @@ -0,0 +1,96 @@ +//===------------- Disassembler.h - LLVM Disassembler -----------*- 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 interface for the Disassembly library's disassembler +// context. The disassembler is responsible for producing strings for +// individual instructions according to a given architecture and disassembly +// syntax. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_DISASSEMBLER_H +#define LLVM_MC_DISASSEMBLER_H + +#include "llvm-c/Disassembler.h" +#include +#include "llvm/ADT/OwningPtr.h" + +namespace llvm { +class TargetAsmInfo; +class MCContext; +class MCAsmInfo; +class MCDisassembler; +class MCInstPrinter; +class Target; +class TargetMachine; + +// +// This is the disassembler context returned by LLVMCreateDisasm(). +// +class LLVMDisasmContext { +private: + // + // The passed parameters when the disassembler context is created. + // + // The TripleName for this disassembler. + std::string TripleName; + // The pointer to the caller's block of symbolic information. + void *DisInfo; + // The Triple specific symbolic information type returned by GetOpInfo. + int TagType; + // The function to get the symbolic information for operands. + LLVMOpInfoCallback GetOpInfo; + // The function to look up a symbol name. + LLVMSymbolLookupCallback SymbolLookUp; + // + // The objects created and saved by LLVMCreateDisasm() then used by + // LLVMDisasmInstruction(). + // + // The LLVM target corresponding to the disassembler. + // FIXME: using llvm::OwningPtr causes a malloc error + // when this LLVMDisasmContext is deleted. + const Target *TheTarget; + // The assembly information for the target architecture. + llvm::OwningPtr MAI; + // The target machine instance. + llvm::OwningPtr TM; + // The disassembler for the target architecture. + // FIXME: using llvm::OwningPtr causes a malloc + // error when this LLVMDisasmContext is deleted. + const TargetAsmInfo *Tai; + // The assembly context for creating symbols and MCExprs. + llvm::OwningPtr Ctx; + // The disassembler for the target architecture. + llvm::OwningPtr DisAsm; + // The instruction printer for the target architecture. + llvm::OwningPtr IP; + +public: + LLVMDisasmContext(std::string tripleName, void *disInfo, int tagType, + LLVMOpInfoCallback getOpInfo, + LLVMSymbolLookupCallback symbolLookUp, + const Target *theTarget, const MCAsmInfo *mAI, + llvm::TargetMachine *tM, const TargetAsmInfo *tai, + llvm::MCContext *ctx, const MCDisassembler *disAsm, + MCInstPrinter *iP) : TripleName(tripleName), + DisInfo(disInfo), TagType(tagType), GetOpInfo(getOpInfo), + SymbolLookUp(symbolLookUp), TheTarget(theTarget), Tai(tai) { + TM.reset(tM); + MAI.reset(mAI); + Ctx.reset(ctx); + DisAsm.reset(disAsm); + IP.reset(iP); + } + const MCDisassembler *getDisAsm() const { return DisAsm.get(); } + MCInstPrinter *getIP() { return IP.get(); } +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.cpp index 2fd14db2a45d..91c5284892a5 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.cpp @@ -193,7 +193,8 @@ EDDisassembler::EDDisassembler(CPUKey &key) : InstString.reset(new std::string); InstStream.reset(new raw_string_ostream(*InstString)); - InstPrinter.reset(Tgt->createMCInstPrinter(LLVMSyntaxVariant, *AsmInfo)); + InstPrinter.reset(Tgt->createMCInstPrinter(*TargetMachine, LLVMSyntaxVariant, + *AsmInfo)); if (!InstPrinter) return; @@ -253,9 +254,11 @@ EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader, delete inst; return NULL; } else { - const llvm::EDInstInfo *thisInstInfo; + const llvm::EDInstInfo *thisInstInfo = NULL; - thisInstInfo = &InstInfos[inst->getOpcode()]; + if (InstInfos) { + thisInstInfo = &InstInfos[inst->getOpcode()]; + } EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo); return sdInst; @@ -331,6 +334,15 @@ int EDDisassembler::printInst(std::string &str, MCInst &inst) { return 0; } +static void diag_handler(const SMDiagnostic &diag, + void *context) +{ + if (context) { + EDDisassembler *disassembler = static_cast(context); + diag.Print("", disassembler->ErrorStream); + } +} + int EDDisassembler::parseInst(SmallVectorImpl &operands, SmallVectorImpl &tokens, const std::string &str) { @@ -353,6 +365,7 @@ int EDDisassembler::parseInst(SmallVectorImpl &operands, SMLoc instLoc; SourceMgr sourceMgr; + sourceMgr.setDiagHandler(diag_handler, static_cast(this)); sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over MCContext context(*AsmInfo, NULL); OwningPtr streamer(createNullStreamer(context)); diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.h b/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.h index 71e45f0b042f..2fcc09d4bef0 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.h +++ b/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.h @@ -87,13 +87,8 @@ struct EDDisassembler { /// operator< - Less-than operator bool operator<(const CPUKey &key) const { - if(Arch > key.Arch) - return false; - else if (Arch == key.Arch) { - if(Syntax > key.Syntax) - return false; - } - return true; + return ((Arch < key.Arch) || + ((Arch == key.Arch) && Syntax < (key.Syntax))); } }; diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDInfo.h b/contrib/llvm/lib/MC/MCDisassembler/EDInfo.h index 627c06641dbc..ad5728263133 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDInfo.h +++ b/contrib/llvm/lib/MC/MCDisassembler/EDInfo.h @@ -35,6 +35,7 @@ enum OperandTypes { kOperandTypeARMAddrMode5, kOperandTypeARMAddrMode6, kOperandTypeARMAddrMode6Offset, + kOperandTypeARMAddrMode7, kOperandTypeARMAddrModePC, kOperandTypeARMRegisterList, kOperandTypeARMTBAddrMode, @@ -51,7 +52,8 @@ enum OperandTypes { kOperandTypeThumb2AddrModeImm12, kOperandTypeThumb2AddrModeSoReg, kOperandTypeThumb2AddrModeImm8s4, - kOperandTypeThumb2AddrModeImm8s4Offset + kOperandTypeThumb2AddrModeImm8s4Offset, + kOperandTypeThumb2AddrModeReg }; enum OperandFlags { diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDInst.cpp b/contrib/llvm/lib/MC/MCDisassembler/EDInst.cpp index 63b049fe40fd..6057e169e347 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDInst.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/EDInst.cpp @@ -165,6 +165,9 @@ int EDInst::getOperand(EDOperand *&operand, unsigned int index) { int EDInst::tokenize() { if (TokenizeResult.valid()) return TokenizeResult.result(); + + if (ThisInstInfo == NULL) + return TokenizeResult.setResult(-1); if (stringify()) return TokenizeResult.setResult(-1); diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp b/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp index 2b0c73e80593..492bb08f336a 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp @@ -73,6 +73,8 @@ EDOperand::EDOperand(const EDDisassembler &disassembler, case kOperandTypeThumb2AddrModeImm8Offset: case kOperandTypeARMTBAddrMode: case kOperandTypeThumb2AddrModeImm8s4Offset: + case kOperandTypeARMAddrMode7: + case kOperandTypeThumb2AddrModeReg: numMCOperands = 1; break; case kOperandTypeThumb2SoReg: @@ -196,15 +198,24 @@ int EDOperand::evaluate(uint64_t &result, default: return -1; case kOperandTypeImmediate: + if (!Inst.Inst->getOperand(MCOpIndex).isImm()) + return -1; + result = Inst.Inst->getOperand(MCOpIndex).getImm(); return 0; case kOperandTypeRegister: { + if (!Inst.Inst->getOperand(MCOpIndex).isReg()) + return -1; + unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg(); return callback(&result, reg, arg); } case kOperandTypeARMBranchTarget: { + if (!Inst.Inst->getOperand(MCOpIndex).isImm()) + return -1; + int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm(); uint64_t pcVal; @@ -256,6 +267,7 @@ int EDOperand::isMemory() { case kOperandTypeARMAddrMode4: case kOperandTypeARMAddrMode5: case kOperandTypeARMAddrMode6: + case kOperandTypeARMAddrMode7: case kOperandTypeARMAddrModePC: case kOperandTypeARMBranchTarget: case kOperandTypeThumbAddrModeS1: @@ -269,6 +281,7 @@ int EDOperand::isMemory() { case kOperandTypeThumb2AddrModeImm12: case kOperandTypeThumb2AddrModeSoReg: case kOperandTypeThumb2AddrModeImm8s4: + case kOperandTypeThumb2AddrModeReg: return 1; } } diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp index 112d7d887a2d..f61f0c24cf6c 100644 --- a/contrib/llvm/lib/MC/MCDwarf.cpp +++ b/contrib/llvm/lib/MC/MCDwarf.cpp @@ -17,6 +17,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -439,14 +440,100 @@ static int getDataAlignmentFactor(MCStreamer &streamer) { return -size; } -static void EmitCFIInstruction(MCStreamer &Streamer, - const MCCFIInstruction &Instr) { +static unsigned getSizeForEncoding(MCStreamer &streamer, + unsigned symbolEncoding) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + unsigned format = symbolEncoding & 0x0f; + switch (format) { + default: + assert(0 && "Unknown Encoding"); + case dwarf::DW_EH_PE_absptr: + case dwarf::DW_EH_PE_signed: + return asmInfo.getPointerSize(); + case dwarf::DW_EH_PE_udata2: + case dwarf::DW_EH_PE_sdata2: + return 2; + case dwarf::DW_EH_PE_udata4: + case dwarf::DW_EH_PE_sdata4: + return 4; + case dwarf::DW_EH_PE_udata8: + case dwarf::DW_EH_PE_sdata8: + return 8; + } +} + +static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, + unsigned symbolEncoding) { + MCContext &context = streamer.getContext(); + const MCAsmInfo &asmInfo = context.getAsmInfo(); + const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol, + symbolEncoding, + streamer); + unsigned size = getSizeForEncoding(streamer, symbolEncoding); + streamer.EmitAbsValue(v, size); +} + +static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, + unsigned symbolEncoding) { + MCContext &context = streamer.getContext(); + const MCAsmInfo &asmInfo = context.getAsmInfo(); + const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol, + symbolEncoding, + streamer); + unsigned size = getSizeForEncoding(streamer, symbolEncoding); + streamer.EmitValue(v, size); +} + +static const MachineLocation TranslateMachineLocation( + const TargetAsmInfo &AsmInfo, + const MachineLocation &Loc) { + unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? + MachineLocation::VirtualFP : + unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true)); + const MachineLocation &NewLoc = Loc.isReg() ? + MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); + return NewLoc; +} + +namespace { + class FrameEmitterImpl { + int CFAOffset; + int CIENum; + bool UsingCFI; + + public: + FrameEmitterImpl(bool usingCFI) : CFAOffset(0), CIENum(0), + UsingCFI(usingCFI) { + } + + const MCSymbol &EmitCIE(MCStreamer &streamer, + const MCSymbol *personality, + unsigned personalityEncoding, + const MCSymbol *lsda, + unsigned lsdaEncoding); + MCSymbol *EmitFDE(MCStreamer &streamer, + const MCSymbol &cieStart, + const MCDwarfFrameInfo &frame, + bool forceLsda); + void EmitCFIInstructions(MCStreamer &streamer, + const std::vector &Instrs, + MCSymbol *BaseLabel); + void EmitCFIInstruction(MCStreamer &Streamer, + const MCCFIInstruction &Instr); + }; +} + +void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, + const MCCFIInstruction &Instr) { int dataAlignmentFactor = getDataAlignmentFactor(Streamer); switch (Instr.getOperation()) { - case MCCFIInstruction::Move: { + case MCCFIInstruction::Move: + case MCCFIInstruction::RelMove: { const MachineLocation &Dst = Instr.getDestination(); const MachineLocation &Src = Instr.getSource(); + const bool IsRelative = Instr.getOperation() == MCCFIInstruction::RelMove; // If advancing cfa. if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { @@ -459,7 +546,12 @@ static void EmitCFIInstruction(MCStreamer &Streamer, Streamer.EmitULEB128IntValue(Src.getReg()); } - Streamer.EmitULEB128IntValue(-Src.getOffset(), 1); + if (IsRelative) + CFAOffset += Src.getOffset(); + else + CFAOffset = -Src.getOffset(); + + Streamer.EmitULEB128IntValue(CFAOffset); return; } @@ -471,7 +563,11 @@ static void EmitCFIInstruction(MCStreamer &Streamer, } unsigned Reg = Src.getReg(); - int Offset = Dst.getOffset() / dataAlignmentFactor; + + int Offset = Dst.getOffset(); + if (IsRelative) + Offset -= CFAOffset; + Offset = Offset / dataAlignmentFactor; if (Offset < 0) { Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); @@ -479,11 +575,11 @@ static void EmitCFIInstruction(MCStreamer &Streamer, Streamer.EmitSLEB128IntValue(Offset); } else if (Reg < 64) { Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); - Streamer.EmitULEB128IntValue(Offset, 1); + Streamer.EmitULEB128IntValue(Offset); } else { Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); - Streamer.EmitULEB128IntValue(Reg, 1); - Streamer.EmitULEB128IntValue(Offset, 1); + Streamer.EmitULEB128IntValue(Reg); + Streamer.EmitULEB128IntValue(Offset); } return; } @@ -493,15 +589,21 @@ static void EmitCFIInstruction(MCStreamer &Streamer, case MCCFIInstruction::Restore: Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); return; + case MCCFIInstruction::SameValue: { + unsigned Reg = Instr.getDestination().getReg(); + Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); + Streamer.EmitULEB128IntValue(Reg); + return; + } } llvm_unreachable("Unhandled case in switch"); } /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. -static void EmitCFIInstructions(MCStreamer &streamer, - const std::vector &Instrs, - MCSymbol *BaseLabel) { +void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, + const std::vector &Instrs, + MCSymbol *BaseLabel) { for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { const MCCFIInstruction &Instr = Instrs[i]; MCSymbol *Label = Instr.getLabel(); @@ -521,74 +623,31 @@ static void EmitCFIInstructions(MCStreamer &streamer, } } -static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, - unsigned symbolEncoding) { - MCContext &context = streamer.getContext(); - const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); - unsigned format = symbolEncoding & 0x0f; - unsigned application = symbolEncoding & 0x70; - unsigned size; - switch (format) { - default: - assert(0 && "Unknown Encoding"); - case dwarf::DW_EH_PE_absptr: - case dwarf::DW_EH_PE_signed: - size = asmInfo.getPointerSize(); - break; - case dwarf::DW_EH_PE_udata2: - case dwarf::DW_EH_PE_sdata2: - size = 2; - break; - case dwarf::DW_EH_PE_udata4: - case dwarf::DW_EH_PE_sdata4: - size = 4; - break; - case dwarf::DW_EH_PE_udata8: - case dwarf::DW_EH_PE_sdata8: - size = 8; - break; - } - switch (application) { - default: - assert(0 && "Unknown Encoding"); - break; - case 0: - streamer.EmitSymbolValue(&symbol, size); - break; - case dwarf::DW_EH_PE_pcrel: - streamer.EmitPCRelSymbolValue(&symbol, size); - break; - } -} - -static const MachineLocation TranslateMachineLocation( - const TargetAsmInfo &AsmInfo, - const MachineLocation &Loc) { - unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? - MachineLocation::VirtualFP : - unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true)); - const MachineLocation &NewLoc = Loc.isReg() ? - MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); - return NewLoc; -} - -static const MCSymbol &EmitCIE(MCStreamer &streamer, - const MCSymbol *personality, - unsigned personalityEncoding, - const MCSymbol *lsda, - unsigned lsdaEncoding) { +const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, + const MCSymbol *personality, + unsigned personalityEncoding, + const MCSymbol *lsda, + unsigned lsdaEncoding) { MCContext &context = streamer.getContext(); const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); const MCSection §ion = *asmInfo.getEHFrameSection(); streamer.SwitchSection(§ion); - MCSymbol *sectionStart = streamer.getContext().CreateTempSymbol(); + + MCSymbol *sectionStart; + if (asmInfo.isFunctionEHFrameSymbolPrivate()) + sectionStart = context.CreateTempSymbol(); + else + sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); + + CIENum++; + MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol(); // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, *sectionEnd, 4); streamer.EmitLabel(sectionStart); - streamer.EmitValue(Length, 4); + streamer.EmitAbsValue(Length, 4); // CIE ID streamer.EmitIntValue(0, 4); @@ -617,28 +676,35 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer, streamer.EmitULEB128IntValue(asmInfo.getDwarfRARegNum(true)); // Augmentation Data Length (optional) - MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol(); - MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol(); - const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer, - *augmentationStart, - *augmentationEnd, 0); - streamer.EmitULEB128Value(augmentationLength); + + unsigned augmentationLength = 0; + if (personality) { + // Personality Encoding + augmentationLength += 1; + // Personality + augmentationLength += getSizeForEncoding(streamer, personalityEncoding); + } + if (lsda) { + augmentationLength += 1; + } + // Encoding of the FDE pointers + augmentationLength += 1; + + streamer.EmitULEB128IntValue(augmentationLength); // Augmentation Data (optional) - streamer.EmitLabel(augmentationStart); if (personality) { // Personality Encoding streamer.EmitIntValue(personalityEncoding, 1); // Personality - EmitSymbol(streamer, *personality, personalityEncoding); + EmitPersonality(streamer, *personality, personalityEncoding); } if (lsda) { // LSDA Encoding streamer.EmitIntValue(lsdaEncoding, 1); } // Encoding of the FDE pointers - streamer.EmitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1); - streamer.EmitLabel(augmentationEnd); + streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1); // Initial Instructions @@ -664,50 +730,66 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer, return *sectionStart; } -static MCSymbol *EmitFDE(MCStreamer &streamer, - const MCSymbol &cieStart, - const MCDwarfFrameInfo &frame) { +MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, + const MCSymbol &cieStart, + const MCDwarfFrameInfo &frame, + bool forceLsda) { MCContext &context = streamer.getContext(); MCSymbol *fdeStart = context.CreateTempSymbol(); MCSymbol *fdeEnd = context.CreateTempSymbol(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + + if (!asmInfo.isFunctionEHFrameSymbolPrivate()) { + Twine EHName = frame.Function->getName() + Twine(".eh"); + MCSymbol *EHSym = context.GetOrCreateSymbol(EHName); + streamer.EmitEHSymAttributes(frame.Function, EHSym); + streamer.EmitLabel(EHSym); + } // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); - streamer.EmitValue(Length, 4); + streamer.EmitAbsValue(Length, 4); streamer.EmitLabel(fdeStart); // CIE Pointer const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, 0); - streamer.EmitValue(offset, 4); + streamer.EmitAbsValue(offset, 4); + unsigned fdeEncoding = asmInfo.getFDEEncoding(UsingCFI); + unsigned size = getSizeForEncoding(streamer, fdeEncoding); // PC Begin - streamer.EmitPCRelSymbolValue(frame.Begin, 4); + EmitSymbol(streamer, *frame.Begin, fdeEncoding); // PC Range const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, *frame.End, 0); - streamer.EmitValue(Range, 4); + streamer.EmitAbsValue(Range, size); // Augmentation Data Length - MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol(); - MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol(); - const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer, - *augmentationStart, - *augmentationEnd, 0); - streamer.EmitULEB128Value(augmentationLength); + unsigned augmentationLength = 0; + + if (frame.Lsda || forceLsda) + augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); + + streamer.EmitULEB128IntValue(augmentationLength); // Augmentation Data - streamer.EmitLabel(augmentationStart); + + // When running in "CodeGen compatibility mode" a FDE with no LSDA can be + // assigned to a CIE that requires one. In that case we output a 0 (as does + // CodeGen). if (frame.Lsda) EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding); - streamer.EmitLabel(augmentationEnd); + else if (forceLsda) + streamer.EmitIntValue(0, getSizeForEncoding(streamer, frame.LsdaEncoding)); + // Call Frame Instructions EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); // Padding - streamer.EmitValueToAlignment(4); + streamer.EmitValueToAlignment(size); return fdeEnd; } @@ -753,11 +835,78 @@ namespace llvm { }; } -void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) { +// This is an implementation of CIE and FDE emission that is bug by bug +// compatible with the one in CodeGen. It is useful during the transition +// to make it easy to compare the outputs, but should probably be removed +// afterwards. +void MCDwarfFrameEmitter::EmitDarwin(MCStreamer &streamer, + bool usingCFI) { + FrameEmitterImpl Emitter(usingCFI); + DenseMap Personalities; + const MCSymbol *aCIE = NULL; + const MCDwarfFrameInfo *aFrame = NULL; + + for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { + const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); + if (!frame.Personality) + continue; + if (Personalities.count(frame.Personality)) + continue; + + const MCSymbol *cieStart = &Emitter.EmitCIE(streamer, frame.Personality, + frame.PersonalityEncoding, + frame.Lsda, + frame.LsdaEncoding); + aCIE = cieStart; + aFrame = &frame; + Personalities[frame.Personality] = cieStart; + } + + if (Personalities.empty()) { + const MCDwarfFrameInfo &frame = streamer.getFrameInfo(0); + aCIE = &Emitter.EmitCIE(streamer, frame.Personality, + frame.PersonalityEncoding, frame.Lsda, + frame.LsdaEncoding); + aFrame = &frame; + } + + MCSymbol *fdeEnd = NULL; + for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { + const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); + const MCSymbol *cieStart = Personalities[frame.Personality]; + bool hasLSDA; + if (!cieStart) { + cieStart = aCIE; + hasLSDA = aFrame->Lsda; + } else { + hasLSDA = true; + } + + fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame, + hasLSDA); + if (i != n - 1) + streamer.EmitLabel(fdeEnd); + } + const MCContext &context = streamer.getContext(); const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + streamer.EmitValueToAlignment(asmInfo.getPointerSize()); + if (fdeEnd) + streamer.EmitLabel(fdeEnd); +} + +void MCDwarfFrameEmitter::Emit(MCStreamer &streamer, + bool usingCFI) { + const MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + if (!asmInfo.isFunctionEHFrameSymbolPrivate()) { + EmitDarwin(streamer, usingCFI); + return; + } + MCSymbol *fdeEnd = NULL; DenseMap CIEStarts; + FrameEmitterImpl Emitter(usingCFI); for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); @@ -765,10 +914,10 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) { frame.LsdaEncoding); const MCSymbol *&cieStart = CIEStarts[key]; if (!cieStart) - cieStart = &EmitCIE(streamer, frame.Personality, - frame.PersonalityEncoding, frame.Lsda, - frame.LsdaEncoding); - fdeEnd = EmitFDE(streamer, *cieStart, frame); + cieStart = &Emitter.EmitCIE(streamer, frame.Personality, + frame.PersonalityEncoding, frame.Lsda, + frame.LsdaEncoding); + fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame, false); if (i != n - 1) streamer.EmitLabel(fdeEnd); } @@ -782,21 +931,28 @@ void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta) { SmallString<256> Tmp; raw_svector_ostream OS(Tmp); - MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS); + const TargetAsmInfo &AsmInfo = Streamer.getContext().getTargetAsmInfo(); + MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS, AsmInfo); Streamer.EmitBytes(OS.str(), /*AddrSpace=*/0); } void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta, - raw_ostream &OS) { + raw_ostream &OS, + const TargetAsmInfo &AsmInfo) { + // This is a small hack to facilitate the transition to CFI on OS X. It + // relaxes all address advances which lets us produces identical output + // to the one produce by CodeGen. + const bool Relax = !AsmInfo.isFunctionEHFrameSymbolPrivate(); + // FIXME: Assumes the code alignment factor is 1. if (AddrDelta == 0) { - } else if (isUIntN(6, AddrDelta)) { + } else if (isUIntN(6, AddrDelta) && !Relax) { uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; OS << Opcode; - } else if (isUInt<8>(AddrDelta)) { + } else if (isUInt<8>(AddrDelta) && !Relax) { OS << uint8_t(dwarf::DW_CFA_advance_loc1); OS << uint8_t(AddrDelta); - } else if (isUInt<16>(AddrDelta)) { + } else if (isUInt<16>(AddrDelta) && !Relax) { // FIXME: check what is the correct behavior on a big endian machine. OS << uint8_t(dwarf::DW_CFA_advance_loc2); OS << uint8_t( AddrDelta & 0xff); diff --git a/contrib/llvm/lib/MC/MCELF.cpp b/contrib/llvm/lib/MC/MCELF.cpp new file mode 100644 index 000000000000..ce7783e2862b --- /dev/null +++ b/contrib/llvm/lib/MC/MCELF.cpp @@ -0,0 +1,72 @@ +//===- lib/MC/MCELF.cpp - MC ELF ------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF object file writer information. +// +//===----------------------------------------------------------------------===// + +#include "MCELF.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCELFSymbolFlags.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/Support/ELF.h" +#include "llvm/Target/TargetAsmBackend.h" + +namespace llvm { + +void MCELF::SetBinding(MCSymbolData &SD, unsigned Binding) { + assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || + Binding == ELF::STB_WEAK); + uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift); + SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift)); +} + +unsigned MCELF::GetBinding(const MCSymbolData &SD) { + uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift; + assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || + Binding == ELF::STB_WEAK); + return Binding; +} + +void MCELF::SetType(MCSymbolData &SD, unsigned Type) { + assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || + Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || + Type == ELF::STT_FILE || Type == ELF::STT_COMMON || + Type == ELF::STT_TLS); + + uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift); + SD.setFlags(OtherFlags | (Type << ELF_STT_Shift)); +} + +unsigned MCELF::GetType(const MCSymbolData &SD) { + uint32_t Type = (SD.getFlags() & (0xf << ELF_STT_Shift)) >> ELF_STT_Shift; + assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || + Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || + Type == ELF::STT_FILE || Type == ELF::STT_COMMON || + Type == ELF::STT_TLS); + return Type; +} + +void MCELF::SetVisibility(MCSymbolData &SD, unsigned Visibility) { + assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || + Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); + + uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STV_Shift); + SD.setFlags(OtherFlags | (Visibility << ELF_STV_Shift)); +} + +unsigned MCELF::GetVisibility(MCSymbolData &SD) { + unsigned Visibility = + (SD.getFlags() & (0xf << ELF_STV_Shift)) >> ELF_STV_Shift; + assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || + Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); + return Visibility; +} + +} diff --git a/contrib/llvm/lib/MC/MCELF.h b/contrib/llvm/lib/MC/MCELF.h new file mode 100644 index 000000000000..e08f1e65429a --- /dev/null +++ b/contrib/llvm/lib/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/contrib/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm/lib/MC/MCELFStreamer.cpp index e49074da3994..be8e2e3891fe 100644 --- a/contrib/llvm/lib/MC/MCELFStreamer.cpp +++ b/contrib/llvm/lib/MC/MCELFStreamer.cpp @@ -11,18 +11,14 @@ // //===----------------------------------------------------------------------===// +#include "MCELFStreamer.h" +#include "MCELF.h" #include "llvm/MC/MCStreamer.h" - -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" @@ -34,148 +30,6 @@ using namespace llvm; -namespace { - -static void SetBinding(MCSymbolData &SD, unsigned Binding) { - assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || - Binding == ELF::STB_WEAK); - uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift); - SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift)); -} - -static unsigned GetBinding(const MCSymbolData &SD) { - uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift; - assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || - Binding == ELF::STB_WEAK); - return Binding; -} - -static void SetType(MCSymbolData &SD, unsigned Type) { - assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || - Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || - Type == ELF::STT_FILE || Type == ELF::STT_COMMON || - Type == ELF::STT_TLS); - - uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift); - SD.setFlags(OtherFlags | (Type << ELF_STT_Shift)); -} - -static void SetVisibility(MCSymbolData &SD, unsigned Visibility) { - assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || - Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); - - uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STV_Shift); - SD.setFlags(OtherFlags | (Visibility << ELF_STV_Shift)); -} - -class MCELFStreamer : public MCObjectStreamer { -public: - MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter) {} - - ~MCELFStreamer() {} - - /// @name MCStreamer Interface - /// @{ - - virtual void InitSections(); - virtual void ChangeSection(const MCSection *Section); - virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); - virtual void EmitThumbFunc(MCSymbol *Func); - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - assert(0 && "ELF doesn't support this directive"); - } - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { - assert(0 && "ELF doesn't support this directive"); - } - - virtual void EmitCOFFSymbolStorageClass(int StorageClass) { - assert(0 && "ELF doesn't support this directive"); - } - - virtual void EmitCOFFSymbolType(int Type) { - assert(0 && "ELF doesn't support this directive"); - } - - virtual void EndCOFFSymbolDef() { - assert(0 && "ELF doesn't support this directive"); - } - - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { - MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); - SD.setSize(Value); - } - - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); - - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - unsigned Size = 0, unsigned ByteAlignment = 0) { - assert(0 && "ELF doesn't support this directive"); - } - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) { - assert(0 && "ELF doesn't support this directive"); - } - 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 void EmitFileDirective(StringRef Filename); - - virtual void Finish(); - -private: - virtual void EmitInstToFragment(const MCInst &Inst); - virtual void EmitInstToData(const MCInst &Inst); - - void fixSymbolsInTLSFixups(const MCExpr *expr); - - struct LocalCommon { - MCSymbolData *SD; - uint64_t Size; - unsigned ByteAlignment; - }; - std::vector LocalCommons; - - SmallPtrSet BindingExplicitlySet; - /// @} - void SetSection(StringRef Section, unsigned Type, unsigned Flags, - SectionKind Kind) { - SwitchSection(getContext().getELFSection(Section, Type, Flags, Kind)); - } - - void SetSectionData() { - SetSection(".data", ELF::SHT_PROGBITS, - ELF::SHF_WRITE |ELF::SHF_ALLOC, - SectionKind::getDataRel()); - EmitCodeAlignment(4, 0); - } - void SetSectionText() { - SetSection(".text", ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | - ELF::SHF_ALLOC, SectionKind::getText()); - EmitCodeAlignment(4, 0); - } - void SetSectionBss() { - SetSection(".bss", ELF::SHT_NOBITS, - ELF::SHF_WRITE | - ELF::SHF_ALLOC, SectionKind::getBSS()); - EmitCodeAlignment(4, 0); - } -}; - -} // end anonymous namespace. - void MCELFStreamer::InitSections() { // This emulates the same behavior of GNU as. This makes it easier // to compare the output as the major sections are in the same order. @@ -194,7 +48,7 @@ void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { static_cast(Symbol->getSection()); MCSymbolData &SD = getAssembler().getSymbolData(*Symbol); if (Section.getFlags() & ELF::SHF_TLS) - SetType(SD, ELF::STT_TLS); + MCELF::SetType(SD, ELF::STT_TLS); } void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { @@ -281,54 +135,54 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, break; case MCSA_Global: - SetBinding(SD, ELF::STB_GLOBAL); + MCELF::SetBinding(SD, ELF::STB_GLOBAL); SD.setExternal(true); BindingExplicitlySet.insert(Symbol); break; case MCSA_WeakReference: case MCSA_Weak: - SetBinding(SD, ELF::STB_WEAK); + MCELF::SetBinding(SD, ELF::STB_WEAK); SD.setExternal(true); BindingExplicitlySet.insert(Symbol); break; case MCSA_Local: - SetBinding(SD, ELF::STB_LOCAL); + MCELF::SetBinding(SD, ELF::STB_LOCAL); SD.setExternal(false); BindingExplicitlySet.insert(Symbol); break; case MCSA_ELF_TypeFunction: - SetType(SD, ELF::STT_FUNC); + MCELF::SetType(SD, ELF::STT_FUNC); break; case MCSA_ELF_TypeObject: - SetType(SD, ELF::STT_OBJECT); + MCELF::SetType(SD, ELF::STT_OBJECT); break; case MCSA_ELF_TypeTLS: - SetType(SD, ELF::STT_TLS); + MCELF::SetType(SD, ELF::STT_TLS); break; case MCSA_ELF_TypeCommon: - SetType(SD, ELF::STT_COMMON); + MCELF::SetType(SD, ELF::STT_COMMON); break; case MCSA_ELF_TypeNoType: - SetType(SD, ELF::STT_NOTYPE); + MCELF::SetType(SD, ELF::STT_NOTYPE); break; case MCSA_Protected: - SetVisibility(SD, ELF::STV_PROTECTED); + MCELF::SetVisibility(SD, ELF::STV_PROTECTED); break; case MCSA_Hidden: - SetVisibility(SD, ELF::STV_HIDDEN); + MCELF::SetVisibility(SD, ELF::STV_HIDDEN); break; case MCSA_Internal: - SetVisibility(SD, ELF::STV_INTERNAL); + MCELF::SetVisibility(SD, ELF::STV_INTERNAL); break; } } @@ -338,13 +192,13 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); if (!BindingExplicitlySet.count(Symbol)) { - SetBinding(SD, ELF::STB_GLOBAL); + MCELF::SetBinding(SD, ELF::STB_GLOBAL); SD.setExternal(true); } - SetType(SD, ELF::STT_OBJECT); + MCELF::SetType(SD, ELF::STT_OBJECT); - if (GetBinding(SD) == ELF_STB_Local) { + if (MCELF::GetBinding(SD) == ELF_STB_Local) { const MCSection *Section = getAssembler().getContext().getELFSection(".bss", ELF::SHT_NOBITS, ELF::SHF_WRITE | @@ -364,7 +218,7 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { // FIXME: Should this be caught and done earlier? MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); - SetBinding(SD, ELF::STB_LOCAL); + MCELF::SetBinding(SD, ELF::STB_LOCAL); SD.setExternal(false); BindingExplicitlySet.insert(Symbol); // FIXME: ByteAlignment is not needed here, but is required. @@ -437,19 +291,22 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { switch (symRef.getKind()) { default: return; + case MCSymbolRefExpr::VK_GOTTPOFF: + case MCSymbolRefExpr::VK_INDNTPOFF: case MCSymbolRefExpr::VK_NTPOFF: case MCSymbolRefExpr::VK_GOTNTPOFF: case MCSymbolRefExpr::VK_TLSGD: + case MCSymbolRefExpr::VK_TLSLD: case MCSymbolRefExpr::VK_TLSLDM: case MCSymbolRefExpr::VK_TPOFF: case MCSymbolRefExpr::VK_DTPOFF: - case MCSymbolRefExpr::VK_GOTTPOFF: - case MCSymbolRefExpr::VK_TLSLD: case MCSymbolRefExpr::VK_ARM_TLSGD: + case MCSymbolRefExpr::VK_ARM_TPOFF: + case MCSymbolRefExpr::VK_ARM_GOTTPOFF: break; } MCSymbolData &SD = getAssembler().getOrCreateSymbolData(symRef.getSymbol()); - SetType(SD, ELF::STT_TLS); + MCELF::SetType(SD, ELF::STT_TLS); break; } @@ -489,7 +346,7 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) { void MCELFStreamer::Finish() { if (getNumFrameInfos()) - MCDwarfFrameEmitter::Emit(*this); + MCDwarfFrameEmitter::Emit(*this, true); for (std::vector::const_iterator i = LocalCommons.begin(), e = LocalCommons.end(); diff --git a/contrib/llvm/lib/MC/MCELFStreamer.h b/contrib/llvm/lib/MC/MCELFStreamer.h new file mode 100644 index 000000000000..db34d58ec600 --- /dev/null +++ b/contrib/llvm/lib/MC/MCELFStreamer.h @@ -0,0 +1,274 @@ +//===- lib/MC/MCELFStreamer.h - ELF Object Output -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file assembles .s files and emits ELF .o object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFSTREAMER_H +#define LLVM_MC_MCELFSTREAMER_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSectionELF.h" + +namespace llvm { + +class MCELFStreamer : public MCObjectStreamer { +public: + MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TAB, OS, Emitter) {} + + MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter, + MCAssembler *Assembler) + : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler) {} + + + ~MCELFStreamer() {} + + /// @name MCStreamer Interface + /// @{ + + virtual void InitSections(); + virtual void ChangeSection(const MCSection *Section); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitThumbFunc(MCSymbol *Func); + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolStorageClass(int StorageClass) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolType(int Type) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EndCOFFSymbolDef() { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.setSize(Value); + } + + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) { + assert(0 && "ELF doesn't support this directive"); + } + 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 void EmitFileDirective(StringRef Filename); + + virtual void Finish(); + +private: + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitInstToData(const MCInst &Inst); + + void fixSymbolsInTLSFixups(const MCExpr *expr); + + struct LocalCommon { + MCSymbolData *SD; + uint64_t Size; + unsigned ByteAlignment; + }; + std::vector LocalCommons; + + SmallPtrSet BindingExplicitlySet; + /// @} + void SetSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind) { + SwitchSection(getContext().getELFSection(Section, Type, Flags, Kind)); + } + + void SetSectionData() { + SetSection(".data", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getDataRel()); + EmitCodeAlignment(4, 0); + } + void SetSectionText() { + SetSection(".text", ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | + ELF::SHF_ALLOC, SectionKind::getText()); + EmitCodeAlignment(4, 0); + } + void SetSectionBss() { + SetSection(".bss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, SectionKind::getBSS()); + EmitCodeAlignment(4, 0); + } +}; + +} // end llvm namespace + +#endif +//===- lib/MC/MCELFStreamer.h - ELF Object Output -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file assembles .s files and emits ELF .o object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFSTREAMER_H +#define LLVM_MC_MCELFSTREAMER_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSectionELF.h" + +namespace llvm { + +class MCELFStreamer : public MCObjectStreamer { +public: + MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TAB, OS, Emitter) {} + + ~MCELFStreamer() {} + + /// @name MCStreamer Interface + /// @{ + + virtual void InitSections(); + virtual void ChangeSection(const MCSection *Section); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitThumbFunc(MCSymbol *Func); + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolStorageClass(int StorageClass) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolType(int Type) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EndCOFFSymbolDef() { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.setSize(Value); + } + + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) { + assert(0 && "ELF doesn't support this directive"); + } + 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 void EmitFileDirective(StringRef Filename); + + virtual void Finish(); + +private: + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitInstToData(const MCInst &Inst); + + void fixSymbolsInTLSFixups(const MCExpr *expr); + + struct LocalCommon { + MCSymbolData *SD; + uint64_t Size; + unsigned ByteAlignment; + }; + std::vector LocalCommons; + + SmallPtrSet BindingExplicitlySet; + /// @} + void SetSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind) { + SwitchSection(getContext().getELFSection(Section, Type, Flags, Kind)); + } + + void SetSectionData() { + SetSection(".data", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getDataRel()); + EmitCodeAlignment(4, 0); + } + void SetSectionText() { + SetSection(".text", ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | + ELF::SHF_ALLOC, SectionKind::getText()); + EmitCodeAlignment(4, 0); + } + void SetSectionBss() { + SetSection(".bss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, SectionKind::getBSS()); + EmitCodeAlignment(4, 0); + } +}; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/lib/MC/MCExpr.cpp b/contrib/llvm/lib/MC/MCExpr.cpp index 54d3743e68e4..3a674d75ed71 100644 --- a/contrib/llvm/lib/MC/MCExpr.cpp +++ b/contrib/llvm/lib/MC/MCExpr.cpp @@ -310,6 +310,11 @@ static void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, if (AD.getFragment() == BD.getFragment()) { Addend += (AD.getOffset() - BD.getOffset()); + // Pointers to Thumb symbols need to have their low-bit set to allow + // for interworking. + if (Asm->isThumbFunc(&SA)) + Addend |= 1; + // Clear the symbol expr pointers to indicate we have folded these // operands. A = B = 0; @@ -384,7 +389,7 @@ static bool EvaluateSymbolicAdd(const MCAssembler *Asm, // (LHS_A - RHS_B), // (RHS_A - LHS_B), // (RHS_A - RHS_B). - // Since we are attempting to be as aggresive as possible about folding, we + // Since we are attempting to be as aggressive as possible about folding, we // attempt to evaluate each possible alternative. AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, Result_Cst); @@ -554,3 +559,45 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, assert(0 && "Invalid assembly expression kind!"); return false; } + +const MCSection *MCExpr::FindAssociatedSection() const { + switch (getKind()) { + case Target: + // We never look through target specific expressions. + return cast(this)->FindAssociatedSection(); + + case Constant: + return MCSymbol::AbsolutePseudoSection; + + case SymbolRef: { + const MCSymbolRefExpr *SRE = cast(this); + const MCSymbol &Sym = SRE->getSymbol(); + + if (Sym.isDefined()) + return &Sym.getSection(); + + return 0; + } + + case Unary: + return cast(this)->getSubExpr()->FindAssociatedSection(); + + case Binary: { + const MCBinaryExpr *BE = cast(this); + const MCSection *LHS_S = BE->getLHS()->FindAssociatedSection(); + const MCSection *RHS_S = BE->getRHS()->FindAssociatedSection(); + + // If either section is absolute, return the other. + if (LHS_S == MCSymbol::AbsolutePseudoSection) + return RHS_S; + if (RHS_S == MCSymbol::AbsolutePseudoSection) + return LHS_S; + + // Otherwise, return the first non-null section. + return LHS_S ? LHS_S : RHS_S; + } + } + + assert(0 && "Invalid assembly expression kind!"); + return 0; +} diff --git a/contrib/llvm/lib/MC/MCInstPrinter.cpp b/contrib/llvm/lib/MC/MCInstPrinter.cpp index 92a71541f5ad..212b85eb1fe0 100644 --- a/contrib/llvm/lib/MC/MCInstPrinter.cpp +++ b/contrib/llvm/lib/MC/MCInstPrinter.cpp @@ -19,3 +19,8 @@ MCInstPrinter::~MCInstPrinter() { StringRef MCInstPrinter::getOpcodeName(unsigned Opcode) const { return ""; } + +StringRef MCInstPrinter::getRegName(unsigned RegNo) const { + assert(0 && "Target should implement this"); + return ""; +} diff --git a/contrib/llvm/lib/MC/MCLoggingStreamer.cpp b/contrib/llvm/lib/MC/MCLoggingStreamer.cpp index 012c7f62f8af..46ea9b844a6a 100644 --- a/contrib/llvm/lib/MC/MCLoggingStreamer.cpp +++ b/contrib/llvm/lib/MC/MCLoggingStreamer.cpp @@ -154,21 +154,19 @@ class MCLoggingStreamer : public MCStreamer { } virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - bool isPCRel, unsigned AddrSpace){ + unsigned AddrSpace){ LogCall("EmitValue"); - return Child->EmitValueImpl(Value, Size, isPCRel, AddrSpace); + return Child->EmitValueImpl(Value, Size, AddrSpace); } - virtual void EmitULEB128Value(const MCExpr *Value, - unsigned AddrSpace = 0) { + virtual void EmitULEB128Value(const MCExpr *Value) { LogCall("EmitULEB128Value"); - return Child->EmitULEB128Value(Value, AddrSpace); + return Child->EmitULEB128Value(Value); } - virtual void EmitSLEB128Value(const MCExpr *Value, - unsigned AddrSpace = 0) { + virtual void EmitSLEB128Value(const MCExpr *Value) { LogCall("EmitSLEB128Value"); - return Child->EmitSLEB128Value(Value, AddrSpace); + return Child->EmitSLEB128Value(Value); } virtual void EmitGPRel32Value(const MCExpr *Value) { @@ -215,13 +213,14 @@ class MCLoggingStreamer : public MCStreamer { virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, - unsigned Isa, unsigned Discriminator) { + unsigned Isa, unsigned Discriminator, + StringRef FileName) { LogCall("EmitDwarfLocDirective", "FileNo:" + Twine(FileNo) + " Line:" + Twine(Line) + " Column:" + Twine(Column) + " Flags:" + Twine(Flags) + " Isa:" + Twine(Isa) + " Discriminator:" + Twine(Discriminator)); return Child->EmitDwarfLocDirective(FileNo, Line, Column, Flags, - Isa, Discriminator); + Isa, Discriminator, FileName); } virtual void EmitInstruction(const MCInst &Inst) { diff --git a/contrib/llvm/lib/MC/MCMachOStreamer.cpp b/contrib/llvm/lib/MC/MCMachOStreamer.cpp index d1f9f5cd568e..3da5b49f5405 100644 --- a/contrib/llvm/lib/MC/MCMachOStreamer.cpp +++ b/contrib/llvm/lib/MC/MCMachOStreamer.cpp @@ -44,6 +44,8 @@ class MCMachOStreamer : public MCObjectStreamer { virtual void InitSections(); virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, + MCSymbol *EHSymbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); @@ -101,6 +103,18 @@ void MCMachOStreamer::InitSections() { } +void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, + MCSymbol *EHSymbol) { + MCSymbolData &SD = + getAssembler().getOrCreateSymbolData(*Symbol); + if (SD.isExternal()) + EmitSymbolAttribute(EHSymbol, MCSA_Global); + if (SD.getFlags() & SF_WeakDefinition) + EmitSymbolAttribute(EHSymbol, MCSA_WeakDefinition); + if (SD.isPrivateExtern()) + EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern); +} + void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); @@ -363,6 +377,9 @@ void MCMachOStreamer::EmitInstToData(const MCInst &Inst) { } void MCMachOStreamer::Finish() { + if (getNumFrameInfos()) + MCDwarfFrameEmitter::Emit(*this, true); + // We have to set the fragment atom associations so we can relax properly for // Mach-O. diff --git a/contrib/llvm/lib/MC/MCNullStreamer.cpp b/contrib/llvm/lib/MC/MCNullStreamer.cpp index 08ddf01d1a36..f38b82231207 100644 --- a/contrib/llvm/lib/MC/MCNullStreamer.cpp +++ b/contrib/llvm/lib/MC/MCNullStreamer.cpp @@ -67,11 +67,9 @@ namespace { virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {} virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - bool isPCRel, unsigned AddrSpace) {} - virtual void EmitULEB128Value(const MCExpr *Value, - unsigned AddrSpace = 0) {} - virtual void EmitSLEB128Value(const MCExpr *Value, - unsigned AddrSpace = 0) {} + unsigned AddrSpace) {} + virtual void EmitULEB128Value(const MCExpr *Value) {} + virtual void EmitSLEB128Value(const MCExpr *Value) {} virtual void EmitGPRel32Value(const MCExpr *Value) {} virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, @@ -89,7 +87,8 @@ namespace { } virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, - unsigned Isa, unsigned Discriminator) {} + unsigned Isa, unsigned Discriminator, + StringRef FileName) {} virtual void EmitInstruction(const MCInst &Inst) {} virtual void Finish() {} diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp index e67d9b03a95a..0f349d0d0b36 100644 --- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp +++ b/contrib/llvm/lib/MC/MCObjectStreamer.cpp @@ -31,6 +31,13 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, { } +MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter_, + MCAssembler *_Assembler) + : MCStreamer(Context), Assembler(_Assembler), CurSectionData(0) +{ +} + MCObjectStreamer::~MCObjectStreamer() { delete &Assembler->getBackend(); delete &Assembler->getEmitter(); @@ -83,7 +90,7 @@ const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) { } void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - bool isPCRel, unsigned AddrSpace) { + unsigned AddrSpace) { assert(AddrSpace == 0 && "Address space must be 0!"); MCDataFragment *DF = getOrCreateDataFragment(); @@ -95,15 +102,12 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, } DF->addFixup(MCFixup::Create(DF->getContents().size(), Value, - MCFixup::getKindForSize(Size, isPCRel))); + MCFixup::getKindForSize(Size, false))); DF->getContents().resize(DF->getContents().size() + Size, 0); } void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { - assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); - - Symbol->setSection(*getCurrentSection()); + MCStreamer::EmitLabel(Symbol); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); @@ -117,23 +121,23 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { SD.setOffset(F->getContents().size()); } -void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value, - unsigned AddrSpace) { +void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { int64_t IntValue; if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) { - EmitULEB128IntValue(IntValue, AddrSpace); + EmitULEB128IntValue(IntValue); return; } + Value = ForceExpAbs(this, getContext(), Value); new MCLEBFragment(*Value, false, getCurrentSectionData()); } -void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value, - unsigned AddrSpace) { +void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) { int64_t IntValue; if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) { - EmitSLEB128IntValue(IntValue, AddrSpace); + EmitSLEB128IntValue(IntValue); return; } + Value = ForceExpAbs(this, getContext(), Value); new MCLEBFragment(*Value, true, getCurrentSectionData()); } @@ -184,30 +188,11 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst) { void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) { MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData()); - raw_svector_ostream VecOS(IF->getCode()); + SmallString<128> Code; + raw_svector_ostream VecOS(Code); getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups()); -} - -static const MCExpr *BuildSymbolDiff(MCContext &Context, - const MCSymbol *A, const MCSymbol *B) { - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - const MCExpr *ARef = - MCSymbolRefExpr::Create(A, Variant, Context); - const MCExpr *BRef = - MCSymbolRefExpr::Create(B, Variant, Context); - const MCExpr *AddrDelta = - MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context); - return AddrDelta; -} - -static const MCExpr *ForceExpAbs(MCObjectStreamer *Streamer, - MCContext &Context, const MCExpr* Expr) { - if (Context.getAsmInfo().hasAggressiveSymbolFolding()) - return Expr; - - MCSymbol *ABS = Context.CreateTempSymbol(); - Streamer->EmitAssignment(ABS, Expr); - return MCSymbolRefExpr::Create(ABS, Context); + VecOS.flush(); + IF->getCode().append(Code.begin(), Code.end()); } void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, diff --git a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp index 89374d0c3fb9..a3d3a492ec8a 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp @@ -213,13 +213,13 @@ AsmToken AsmLexer::LexDigit() { // Requires at least one binary digit. if (CurPtr == NumStart) - return ReturnError(TokStart, "Invalid binary number"); + return ReturnError(TokStart, "invalid binary number"); StringRef Result(TokStart, CurPtr - TokStart); long long Value; if (Result.substr(2).getAsInteger(2, Value)) - return ReturnError(TokStart, "Invalid binary number"); + return ReturnError(TokStart, "invalid binary number"); // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL // suffixes on integer literals. @@ -236,11 +236,11 @@ AsmToken AsmLexer::LexDigit() { // Requires at least one hex digit. if (CurPtr == NumStart) - return ReturnError(CurPtr-2, "Invalid hexadecimal number"); + return ReturnError(CurPtr-2, "invalid hexadecimal number"); unsigned long long Result; if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result)) - return ReturnError(TokStart, "Invalid hexadecimal number"); + return ReturnError(TokStart, "invalid hexadecimal number"); // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL // suffixes on integer literals. @@ -251,13 +251,13 @@ AsmToken AsmLexer::LexDigit() { } // Must be an octal number, it starts with 0. - while (*CurPtr >= '0' && *CurPtr <= '7') + while (*CurPtr >= '0' && *CurPtr <= '9') ++CurPtr; StringRef Result(TokStart, CurPtr - TokStart); long long Value; if (Result.getAsInteger(8, Value)) - return ReturnError(TokStart, "Invalid octal number"); + return ReturnError(TokStart, "invalid octal number"); // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL // suffixes on integer literals. @@ -324,8 +324,8 @@ AsmToken AsmLexer::LexQuote() { StringRef AsmLexer::LexUntilEndOfStatement() { TokStart = CurPtr; - while (!isAtStartOfComment(*CurPtr) && // Start of line comment. - *CurPtr != ';' && // End of statement marker. + while (!isAtStartOfComment(*CurPtr) && // Start of line comment. + !isAtStatementSeparator(CurPtr) && // End of statement marker. *CurPtr != '\n' && *CurPtr != '\r' && (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) { @@ -339,6 +339,11 @@ bool AsmLexer::isAtStartOfComment(char Char) { return Char == *MAI.getCommentString(); } +bool AsmLexer::isAtStatementSeparator(const char *Ptr) { + return strncmp(Ptr, MAI.getSeparatorString(), + strlen(MAI.getSeparatorString())) == 0; +} + AsmToken AsmLexer::LexToken() { TokStart = CurPtr; // This always consumes at least one character. @@ -346,6 +351,11 @@ AsmToken AsmLexer::LexToken() { if (isAtStartOfComment(CurChar)) return LexLineComment(); + if (isAtStatementSeparator(TokStart)) { + CurPtr += strlen(MAI.getSeparatorString()) - 1; + return AsmToken(AsmToken::EndOfStatement, + StringRef(TokStart, strlen(MAI.getSeparatorString()))); + } switch (CurChar) { default: @@ -362,8 +372,8 @@ AsmToken AsmLexer::LexToken() { // Ignore whitespace. return LexToken(); case '\n': // FALL THROUGH. - case '\r': // FALL THROUGH. - case ';': return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); + case '\r': + return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1)); case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1)); case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1)); diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp index a84917ffb86a..d8fd27d873f6 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp @@ -251,10 +251,14 @@ class GenericAsmParser : public MCAsmParserExtension { ".cfi_def_cfa"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaOffset>( ".cfi_def_cfa_offset"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset>( + ".cfi_adjust_cfa_offset"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaRegister>( ".cfi_def_cfa_register"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIOffset>( ".cfi_offset"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIRelOffset>( + ".cfi_rel_offset"); AddDirectiveHandler< &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_personality"); AddDirectiveHandler< @@ -263,6 +267,8 @@ class GenericAsmParser : public MCAsmParserExtension { &GenericAsmParser::ParseDirectiveCFIRememberState>(".cfi_remember_state"); AddDirectiveHandler< &GenericAsmParser::ParseDirectiveCFIRestoreState>(".cfi_restore_state"); + AddDirectiveHandler< + &GenericAsmParser::ParseDirectiveCFISameValue>(".cfi_same_value"); // Macro directives. AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( @@ -287,11 +293,14 @@ class GenericAsmParser : public MCAsmParserExtension { bool ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfa(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfaOffset(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIAdjustCfaOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIRelOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIRememberState(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIRestoreState(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFISameValue(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc); @@ -517,6 +526,9 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { switch (Lexer.getKind()) { default: return TokError("unknown token in expression"); + // If we have an error assume that we've already handled it. + case AsmToken::Error: + return true; case AsmToken::Exclaim: Lex(); // Eat the operator. if (ParsePrimaryExpr(Res, EndLoc)) @@ -880,6 +892,7 @@ bool AsmParser::ParseStatement() { EatToEndOfStatement(); return false; } + // Allow an integer followed by a ':' as a directional local label. if (Lexer.is(AsmToken::Integer)) { LocalLabelVal = getTok().getIntVal(); @@ -896,13 +909,19 @@ bool AsmParser::ParseStatement() { return TokError("unexpected token at start of statement"); } } - } - else if (ParseIdentifier(IDVal)) { + + } else if (Lexer.is(AsmToken::Dot)) { + // Treat '.' as a valid identifier in this context. + Lex(); + IDVal = "."; + + } else if (ParseIdentifier(IDVal)) { if (!TheCondState.Ignore) return TokError("unexpected token at start of statement"); IDVal = ""; } + // Handle conditional assembly here before checking for skipping. We // have to do this so that .endif isn't skipped in a ".if 0" block for // example. @@ -935,6 +954,10 @@ bool AsmParser::ParseStatement() { // identifier ':' -> Label. Lex(); + // Diagnose attempt to use '.' as a label. + if (IDVal == ".") + return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label"); + // Diagnose attempt to use a variable as a label. // // FIXME: Diagnostics. Note the location of the definition as a label. @@ -978,7 +1001,7 @@ bool AsmParser::ParseStatement() { return HandleMacroEntry(IDVal, IDLoc, M); // Otherwise, we have a normal instruction or directive. - if (IDVal[0] == '.') { + if (IDVal[0] == '.' && IDVal != ".") { // Assembler features if (IDVal == ".set" || IDVal == ".equ") return ParseDirectiveSet(IDVal, true); @@ -1041,7 +1064,7 @@ bool AsmParser::ParseStatement() { if (IDVal == ".fill") return ParseDirectiveFill(); - if (IDVal == ".space") + if (IDVal == ".space" || IDVal == ".skip") return ParseDirectiveSpace(); if (IDVal == ".zero") return ParseDirectiveZero(); @@ -1306,6 +1329,12 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef) { if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in assignment"); + // Error on assignment to '.'. + if (Name == ".") { + return Error(EqualLoc, ("assignment to pseudo-symbol '.' is unsupported " + "(use '.space' or '.org').)")); + } + // Eat the end of statement marker. Lex(); @@ -1319,7 +1348,7 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef) { // FIXME: Diagnose assignment to protected identifier (e.g., register name). if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable()) ; // Allow redefinitions of undefined symbols only used in directives. - else if (!Sym->isUndefined() && (!Sym->isAbsolute() || !allow_redef)) + else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef)) return Error(EqualLoc, "redefinition of '" + Name + "'"); else if (!Sym->isVariable()) return Error(EqualLoc, "invalid assignment to '" + Name + "'"); @@ -1535,13 +1564,21 @@ bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) { Lex(); if (getLexer().isNot(AsmToken::Integer) && - getLexer().isNot(AsmToken::Real)) + getLexer().isNot(AsmToken::Real) && + getLexer().isNot(AsmToken::Identifier)) return TokError("unexpected token in directive"); // Convert to an APFloat. APFloat Value(Semantics); - if (Value.convertFromString(getTok().getString(), - APFloat::rmNearestTiesToEven) == + StringRef IDVal = getTok().getString(); + if (getLexer().is(AsmToken::Identifier)) { + if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf")) + Value = APFloat::getInf(Semantics); + else if (!IDVal.compare_lower("nan")) + Value = APFloat::getNaN(Semantics, false, ~0); + else + return TokError("invalid floating point literal"); + } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) == APFloat::opInvalidOp) return TokError("invalid floating point literal"); if (IsNeg) @@ -2216,7 +2253,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { } getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags, - Isa, Discriminator); + Isa, Discriminator, StringRef()); return false; } @@ -2232,13 +2269,15 @@ bool GenericAsmParser::ParseDirectiveStabs(StringRef Directive, /// ::= .cfi_startproc bool GenericAsmParser::ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIStartProc(); + getStreamer().EmitCFIStartProc(); + return false; } /// ParseDirectiveCFIEndProc /// ::= .cfi_endproc bool GenericAsmParser::ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIEndProc(); + getStreamer().EmitCFIEndProc(); + return false; } /// ParseRegisterOrRegisterNumber - parse register name or number. @@ -2273,7 +2312,8 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, if (getParser().ParseAbsoluteExpression(Offset)) return true; - return getStreamer().EmitCFIDefCfa(Register, Offset); + getStreamer().EmitCFIDefCfa(Register, Offset); + return false; } /// ParseDirectiveCFIDefCfaOffset @@ -2284,7 +2324,20 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfaOffset(StringRef, if (getParser().ParseAbsoluteExpression(Offset)) return true; - return getStreamer().EmitCFIDefCfaOffset(Offset); + getStreamer().EmitCFIDefCfaOffset(Offset); + return false; +} + +/// ParseDirectiveCFIAdjustCfaOffset +/// ::= .cfi_adjust_cfa_offset adjustment +bool GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset(StringRef, + SMLoc DirectiveLoc) { + int64_t Adjustment = 0; + if (getParser().ParseAbsoluteExpression(Adjustment)) + return true; + + getStreamer().EmitCFIAdjustCfaOffset(Adjustment); + return false; } /// ParseDirectiveCFIDefCfaRegister @@ -2295,11 +2348,12 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfaRegister(StringRef, if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; - return getStreamer().EmitCFIDefCfaRegister(Register); + getStreamer().EmitCFIDefCfaRegister(Register); + return false; } /// ParseDirectiveCFIOffset -/// ::= .cfi_off register, offset +/// ::= .cfi_offset register, offset bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { int64_t Register = 0; int64_t Offset = 0; @@ -2314,7 +2368,29 @@ bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { if (getParser().ParseAbsoluteExpression(Offset)) return true; - return getStreamer().EmitCFIOffset(Register, Offset); + getStreamer().EmitCFIOffset(Register, Offset); + return false; +} + +/// ParseDirectiveCFIRelOffset +/// ::= .cfi_rel_offset register, offset +bool GenericAsmParser::ParseDirectiveCFIRelOffset(StringRef, + SMLoc DirectiveLoc) { + int64_t Register = 0; + + if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Offset = 0; + if (getParser().ParseAbsoluteExpression(Offset)) + return true; + + getStreamer().EmitCFIRelOffset(Register, Offset); + return false; } static bool isValidEncoding(int64_t Encoding) { @@ -2364,25 +2440,42 @@ bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal, MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); if (IDVal == ".cfi_personality") - return getStreamer().EmitCFIPersonality(Sym, Encoding); + getStreamer().EmitCFIPersonality(Sym, Encoding); else { assert(IDVal == ".cfi_lsda"); - return getStreamer().EmitCFILsda(Sym, Encoding); + getStreamer().EmitCFILsda(Sym, Encoding); } + return false; } /// ParseDirectiveCFIRememberState /// ::= .cfi_remember_state bool GenericAsmParser::ParseDirectiveCFIRememberState(StringRef IDVal, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIRememberState(); + getStreamer().EmitCFIRememberState(); + return false; } /// ParseDirectiveCFIRestoreState /// ::= .cfi_remember_state bool GenericAsmParser::ParseDirectiveCFIRestoreState(StringRef IDVal, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIRestoreState(); + getStreamer().EmitCFIRestoreState(); + return false; +} + +/// ParseDirectiveCFISameValue +/// ::= .cfi_same_value register +bool GenericAsmParser::ParseDirectiveCFISameValue(StringRef IDVal, + SMLoc DirectiveLoc) { + int64_t Register = 0; + + if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + + getStreamer().EmitCFISameValue(Register); + + return false; } /// ParseDirectiveMacrosOnOff diff --git a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp index 44f234566afd..3c092cdb19bb 100644 --- a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp @@ -100,6 +100,8 @@ class DarwinAsmParser : public MCAsmParserExtension { AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveText>(".text"); AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveThreadInitFunc>(".thread_init_func"); AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTLV>(".tlv"); + + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveIdent>(".ident"); } bool ParseDirectiveDesc(StringRef, SMLoc); @@ -277,6 +279,11 @@ class DarwinAsmParser : public MCAsmParserExtension { return ParseSectionSwitch("__DATA", "__thread_vars", MCSectionMachO::S_THREAD_LOCAL_VARIABLES); } + bool ParseSectionDirectiveIdent(StringRef, SMLoc) { + // Darwin silently ignores the .ident directive. + getParser().EatToEndOfStatement(); + return false; + } bool ParseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { return ParseSectionSwitch("__DATA", "__thread_init", MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); @@ -427,10 +434,12 @@ bool DarwinAsmParser::ParseDirectiveSection(StringRef, SMLoc) { StringRef Segment, Section; - unsigned TAA, StubSize; + unsigned StubSize; + unsigned TAA; + bool TAAParsed; std::string ErrorStr = MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section, - TAA, StubSize); + TAA, TAAParsed, StubSize); if (!ErrorStr.empty()) return Error(Loc, ErrorStr.c_str()); diff --git a/contrib/llvm/lib/MC/MCSectionELF.cpp b/contrib/llvm/lib/MC/MCSectionELF.cpp index d32aea144e6e..dfd77c3fe813 100644 --- a/contrib/llvm/lib/MC/MCSectionELF.cpp +++ b/contrib/llvm/lib/MC/MCSectionELF.cpp @@ -39,8 +39,28 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, return; } - OS << "\t.section\t" << getSectionName(); - + StringRef name = getSectionName(); + if (name.find_first_not_of("0123456789_." + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == name.npos) { + OS << "\t.section\t" << name; + } else { + OS << "\t.section\t\""; + for (const char *b = name.begin(), *e = name.end(); b < e; ++b) { + if (*b == '"') // Unquoted " + OS << "\\\""; + else if (*b != '\\') // Neither " or backslash + OS << *b; + else if (b + 1 == e) // Trailing backslash + OS << "\\\\"; + else { + OS << b[0] << b[1]; // Quoted character + ++b; + } + } + OS << '"'; + } + // Handle the weird solaris syntax if desired. if (MAI.usesSunStyleELFSectionSwitchSyntax() && !(Flags & ELF::SHF_MERGE)) { diff --git a/contrib/llvm/lib/MC/MCSectionMachO.cpp b/contrib/llvm/lib/MC/MCSectionMachO.cpp index 577e93aed6bc..e771556262a8 100644 --- a/contrib/llvm/lib/MC/MCSectionMachO.cpp +++ b/contrib/llvm/lib/MC/MCSectionMachO.cpp @@ -180,7 +180,9 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. StringRef &Segment, // Out. StringRef &Section, // Out. unsigned &TAA, // Out. + bool &TAAParsed, // Out. unsigned &StubSize) { // Out. + TAAParsed = false; // Find the first comma. std::pair Comma = Spec.split(','); @@ -211,6 +213,7 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. "between 1 and 16 characters"; // If there is no comma after the section, we're done. + TAA = 0; StubSize = 0; if (Comma.second.empty()) return ""; @@ -235,6 +238,7 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. // Remember the TypeID. TAA = TypeID; + TAAParsed = true; // If we have no comma after the section type, there are no attributes. if (Comma.second.empty()) { diff --git a/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp index 4b302c8602c9..fa245b11ade2 100644 --- a/contrib/llvm/lib/MC/MCStreamer.cpp +++ b/contrib/llvm/lib/MC/MCStreamer.cpp @@ -12,6 +12,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallString.h" @@ -27,6 +28,29 @@ MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx) { MCStreamer::~MCStreamer() { } +const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context, + const MCSymbol *A, + const MCSymbol *B) { + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *ARef = + MCSymbolRefExpr::Create(A, Variant, Context); + const MCExpr *BRef = + MCSymbolRefExpr::Create(B, Variant, Context); + const MCExpr *AddrDelta = + MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context); + return AddrDelta; +} + +const MCExpr *MCStreamer::ForceExpAbs(MCStreamer *Streamer, + MCContext &Context, const MCExpr* Expr) { + if (Context.getAsmInfo().hasAggressiveSymbolFolding()) + return Expr; + + MCSymbol *ABS = Context.CreateTempSymbol(); + Streamer->EmitAssignment(ABS, Expr); + return MCSymbolRefExpr::Create(ABS, Context); +} + raw_ostream &MCStreamer::GetCommentOS() { // By default, discard comments. return nulls(); @@ -90,30 +114,15 @@ void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size, void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, unsigned AddrSpace) { - EmitValueImpl(Value, Size, false, AddrSpace); -} - -void MCStreamer::EmitPCRelValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { - EmitValueImpl(Value, Size, true, AddrSpace); + EmitValueImpl(Value, Size, AddrSpace); } void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - bool isPCRel, unsigned AddrSpace) { - EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size, isPCRel, + unsigned AddrSpace) { + EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size, AddrSpace); } -void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - unsigned AddrSpace) { - EmitSymbolValue(Sym, Size, false, AddrSpace); -} - -void MCStreamer::EmitPCRelSymbolValue(const MCSymbol *Sym, unsigned Size, - unsigned AddrSpace) { - EmitSymbolValue(Sym, Size, true, AddrSpace); -} - void MCStreamer::EmitGPRel32Value(const MCExpr *Value) { report_fatal_error("unsupported directive in streamer"); } @@ -135,7 +144,8 @@ bool MCStreamer::EmitDwarfFileDirective(unsigned FileNo, void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, - unsigned Discriminator) { + unsigned Discriminator, + StringRef FileName) { getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa, Discriminator); } @@ -152,28 +162,39 @@ void MCStreamer::EnsureValidFrame() { report_fatal_error("No open frame"); } -bool MCStreamer::EmitCFIStartProc() { - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); - if (CurFrame && !CurFrame->End) { - report_fatal_error("Starting a frame before finishing the previous one!"); - return true; - } - MCDwarfFrameInfo Frame; - Frame.Begin = getContext().CreateTempSymbol(); - EmitLabel(Frame.Begin); - FrameInfos.push_back(Frame); - return false; +void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, + MCSymbol *EHSymbol) { } -bool MCStreamer::EmitCFIEndProc() { +void MCStreamer::EmitLabel(MCSymbol *Symbol) { + assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); + assert(getCurrentSection() && "Cannot emit before setting section!"); + Symbol->setSection(*getCurrentSection()); + + StringRef Prefix = getContext().getAsmInfo().getPrivateGlobalPrefix(); + if (!Symbol->getName().startswith(Prefix)) + LastNonPrivate = Symbol; +} + +void MCStreamer::EmitCFIStartProc() { + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + if (CurFrame && !CurFrame->End) + report_fatal_error("Starting a frame before finishing the previous one!"); + MCDwarfFrameInfo Frame; + Frame.Begin = getContext().CreateTempSymbol(); + Frame.Function = LastNonPrivate; + EmitLabel(Frame.Begin); + FrameInfos.push_back(Frame); +} + +void MCStreamer::EmitCFIEndProc() { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); CurFrame->End = getContext().CreateTempSymbol(); EmitLabel(CurFrame->End); - return false; } -bool MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { +void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); @@ -182,10 +203,9 @@ bool MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { MachineLocation Source(Register, -Offset); MCCFIInstruction Instruction(Label, Dest, Source); CurFrame->Instructions.push_back(Instruction); - return false; } -bool MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { +void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); @@ -194,10 +214,20 @@ bool MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { MachineLocation Source(MachineLocation::VirtualFP, -Offset); MCCFIInstruction Instruction(Label, Dest, Source); CurFrame->Instructions.push_back(Instruction); - return false; } -bool MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { +void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MachineLocation Dest(MachineLocation::VirtualFP); + MachineLocation Source(MachineLocation::VirtualFP, Adjustment); + MCCFIInstruction Instruction(MCCFIInstruction::RelMove, Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); +} + +void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); @@ -206,10 +236,9 @@ bool MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { MachineLocation Source(MachineLocation::VirtualFP); MCCFIInstruction Instruction(Label, Dest, Source); CurFrame->Instructions.push_back(Instruction); - return false; } -bool MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { +void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); @@ -218,37 +247,44 @@ bool MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { MachineLocation Source(Register, Offset); MCCFIInstruction Instruction(Label, Dest, Source); CurFrame->Instructions.push_back(Instruction); - return false; } -bool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym, +void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MachineLocation Dest(Register, Offset); + MachineLocation Source(Register, Offset); + MCCFIInstruction Instruction(MCCFIInstruction::RelMove, Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); +} + +void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); CurFrame->Personality = Sym; CurFrame->PersonalityEncoding = Encoding; - return false; } -bool MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { +void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); CurFrame->Lsda = Sym; CurFrame->LsdaEncoding = Encoding; - return false; } -bool MCStreamer::EmitCFIRememberState() { +void MCStreamer::EmitCFIRememberState() { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); EmitLabel(Label); MCCFIInstruction Instruction(MCCFIInstruction::Remember, Label); CurFrame->Instructions.push_back(Instruction); - return false; } -bool MCStreamer::EmitCFIRestoreState() { +void MCStreamer::EmitCFIRestoreState() { // FIXME: Error if there is no matching cfi_remember_state. EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); @@ -256,7 +292,55 @@ bool MCStreamer::EmitCFIRestoreState() { EmitLabel(Label); MCCFIInstruction Instruction(MCCFIInstruction::Restore, Label); CurFrame->Instructions.push_back(Instruction); - return false; +} + +void MCStreamer::EmitCFISameValue(int64_t Register) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MCCFIInstruction Instruction(MCCFIInstruction::SameValue, Label, Register); + CurFrame->Instructions.push_back(Instruction); +} + +void MCStreamer::EmitFnStart() { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitFnEnd() { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitCantUnwind() { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitHandlerData() { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitPersonality(const MCSymbol *Personality) { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitPad(int64_t Offset) { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitRegSave(const SmallVectorImpl &RegList, bool) { + errs() << "Not implemented yet\n"; + abort(); } /// EmitRawText - If this file is backed by an assembly streamer, this dumps diff --git a/contrib/llvm/lib/MC/MCSymbol.cpp b/contrib/llvm/lib/MC/MCSymbol.cpp index 1c71f267a4b5..c2fad1674aa4 100644 --- a/contrib/llvm/lib/MC/MCSymbol.cpp +++ b/contrib/llvm/lib/MC/MCSymbol.cpp @@ -58,9 +58,13 @@ void MCSymbol::setVariableValue(const MCExpr *Value) { "Invalid redefinition!"); this->Value = Value; - // Mark the variable as absolute as appropriate. - if (isa(Value)) - setAbsolute(); + // Variables should always be marked as in the same "section" as the value. + const MCSection *Section = Value->FindAssociatedSection(); + if (Section) { + setSection(*Section); + } else { + setUndefined(); + } } void MCSymbol::print(raw_ostream &OS) const { diff --git a/contrib/llvm/lib/MC/MachObjectWriter.cpp b/contrib/llvm/lib/MC/MachObjectWriter.cpp index 8af07c74fdfe..f049b1c6e2a4 100644 --- a/contrib/llvm/lib/MC/MachObjectWriter.cpp +++ b/contrib/llvm/lib/MC/MachObjectWriter.cpp @@ -121,6 +121,33 @@ class MachObjectWriter : public MCObjectWriter { } uint64_t getSymbolAddress(const MCSymbolData* SD, const MCAsmLayout &Layout) const { + const MCSymbol &S = SD->getSymbol(); + + // If this is a variable, then recursively evaluate now. + if (S.isVariable()) { + MCValue Target; + if (!S.getVariableValue()->EvaluateAsRelocatable(Target, Layout)) + report_fatal_error("unable to evaluate offset for variable '" + + S.getName() + "'"); + + // Verify that any used symbols are defined. + if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined()) + report_fatal_error("unable to evaluate offset to undefined symbol '" + + Target.getSymA()->getSymbol().getName() + "'"); + if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined()) + report_fatal_error("unable to evaluate offset to undefined symbol '" + + Target.getSymB()->getSymbol().getName() + "'"); + + uint64_t Address = Target.getConstant(); + if (Target.getSymA()) + Address += getSymbolAddress(&Layout.getAssembler().getSymbolData( + Target.getSymA()->getSymbol()), Layout); + if (Target.getSymB()) + Address += getSymbolAddress(&Layout.getAssembler().getSymbolData( + Target.getSymB()->getSymbol()), Layout); + return Address; + } + return getSectionAddress(SD->getFragment()->getParent()) + Layout.getSymbolOffset(SD); } @@ -274,8 +301,8 @@ class MachObjectWriter : public MCObjectWriter { if (is64Bit()) Write32(0); // reserved3 - assert(OS.tell() - Start == is64Bit() ? macho::Section64Size : - macho::Section32Size); + assert(OS.tell() - Start == (is64Bit() ? macho::Section64Size : + macho::Section32Size)); } void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, @@ -440,7 +467,7 @@ class MachObjectWriter : public MCObjectWriter { // Compensate for the relocation offset, Darwin x86_64 relocations only // have the addend and appear to have attempted to define it to be the // actual expression addend without the PCrel bias. However, instructions - // with data following the relocation are not accomodated for (see comment + // with data following the relocation are not accommodated for (see comment // below regarding SIGNED{1,2,4}), so it isn't exactly that either. Value += 1LL << Log2Size; } @@ -541,7 +568,7 @@ class MachObjectWriter : public MCObjectWriter { } // x86_64 almost always uses external relocations, except when there is no - // symbol to use as a base address (a local symbol with no preceeding + // symbol to use as a base address (a local symbol with no preceding // non-local symbol). if (Base) { Index = Base->getIndex(); @@ -550,7 +577,7 @@ class MachObjectWriter : public MCObjectWriter { // Add the local offset, if needed. if (Base != &SD) Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base); - } else if (Symbol->isInSection()) { + } else if (Symbol->isInSection() && !Symbol->isVariable()) { // The index is the section ordinal (1-based). Index = SD.getFragment()->getParent()->getOrdinal() + 1; IsExtern = 0; @@ -821,12 +848,12 @@ class MachObjectWriter : public MCObjectWriter { // 1 - :upper16: for movt instructions // high bit of r_length: // 0 - arm instructions - // 1 - thumb instructions + // 1 - thumb instructions // the other half of the relocated expression is in the following pair // relocation entry in the the low 16 bits of r_address field. unsigned ThumbBit = 0; unsigned MovtBit = 0; - switch (Fixup.getKind()) { + switch ((unsigned)Fixup.getKind()) { default: break; case ARM::fixup_arm_movt_hi16: case ARM::fixup_arm_movt_hi16_pcrel: @@ -952,15 +979,10 @@ class MachObjectWriter : public MCObjectWriter { RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); Log2Size = llvm::Log2_32(2); return true; - + case ARM::fixup_arm_thumb_bl: - RelocType = unsigned(macho::RIT_ARM_ThumbBranch32Bit); - Log2Size = llvm::Log2_32(4); - return true; - case ARM::fixup_arm_thumb_blx: RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); - // Report as 'long', even though that is not quite accurate. Log2Size = llvm::Log2_32(4); return true; @@ -1033,17 +1055,17 @@ class MachObjectWriter : public MCObjectWriter { // FIXME! report_fatal_error("FIXME: relocations to absolute targets " "not yet implemented"); - } else if (SD->getSymbol().isVariable()) { - int64_t Res; - if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( - Res, Layout, SectionAddress)) { - FixedValue = Res; - return; + } else { + // Resolve constant variables. + if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, SectionAddress)) { + FixedValue = Res; + return; + } } - report_fatal_error("unsupported relocation of variable '" + - SD->getSymbol().getName() + "'"); - } else { // Check whether we need an external or internal relocation. if (doesSymbolRequireExternRelocation(SD)) { IsExtern = 1; @@ -1055,8 +1077,10 @@ class MachObjectWriter : public MCObjectWriter { FixedValue -= Layout.getSymbolOffset(SD); } else { // The index is the section ordinal (1-based). - Index = SD->getFragment()->getParent()->getOrdinal() + 1; - FixedValue += getSectionAddress(SD->getFragment()->getParent()); + const MCSectionData &SymSD = Asm.getSectionData( + SD->getSymbol().getSection()); + Index = SymSD.getOrdinal() + 1; + FixedValue += getSectionAddress(&SymSD); } if (IsPCRel) FixedValue -= getSectionAddress(Fragment->getParent()); @@ -1132,17 +1156,17 @@ class MachObjectWriter : public MCObjectWriter { // FIXME: Currently, these are never generated (see code below). I cannot // find a case where they are actually emitted. Type = macho::RIT_Vanilla; - } else if (SD->getSymbol().isVariable()) { - int64_t Res; - if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( - Res, Layout, SectionAddress)) { - FixedValue = Res; - return; + } else { + // Resolve constant variables. + if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, SectionAddress)) { + FixedValue = Res; + return; + } } - report_fatal_error("unsupported relocation of variable '" + - SD->getSymbol().getName() + "'"); - } else { // Check whether we need an external or internal relocation. if (doesSymbolRequireExternRelocation(SD)) { IsExtern = 1; @@ -1154,8 +1178,10 @@ class MachObjectWriter : public MCObjectWriter { FixedValue -= Layout.getSymbolOffset(SD); } else { // The index is the section ordinal (1-based). - Index = SD->getFragment()->getParent()->getOrdinal() + 1; - FixedValue += getSectionAddress(SD->getFragment()->getParent()); + const MCSectionData &SymSD = Asm.getSectionData( + SD->getSymbol().getSection()); + Index = SymSD.getOrdinal() + 1; + FixedValue += getSectionAddress(&SymSD); } if (IsPCRel) FixedValue -= getSectionAddress(Fragment->getParent()); diff --git a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp index 6ca5d37fc32e..101237aabb02 100644 --- a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -647,22 +647,27 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, COFFSection *coff_section = SectionMap[&SectionData->getSection()]; COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()]; + const MCSymbolRefExpr *SymA = Target.getSymA(); + const MCSymbolRefExpr *SymB = Target.getSymB(); + const bool CrossSection = SymB && + &SymA->getSymbol().getSection() != &SymB->getSymbol().getSection(); if (Target.getSymB()) { - if (&Target.getSymA()->getSymbol().getSection() - != &Target.getSymB()->getSymbol().getSection()) { - llvm_unreachable("Symbol relative relocations are only allowed between " - "symbols in the same section"); - } const MCSymbol *B = &Target.getSymB()->getSymbol(); MCSymbolData &B_SD = Asm.getSymbolData(*B); - FixedValue = Layout.getSymbolOffset(&A_SD) - Layout.getSymbolOffset(&B_SD); + // Offset of the symbol in the section + int64_t a = Layout.getSymbolOffset(&B_SD); + // Ofeset of the relocation in the section + int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + + FixedValue = b - a; // In the case where we have SymbA and SymB, we just need to store the delta // between the two symbols. Update FixedValue to account for the delta, and // skip recording the relocation. - return; + if (!CrossSection) + return; } else { FixedValue = Target.getConstant(); } @@ -673,7 +678,7 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment); // Turn relocations for temporary symbols into section relocations. - if (coff_symbol->MCData->getSymbol().isTemporary()) { + if (coff_symbol->MCData->getSymbol().isTemporary() || CrossSection) { Reloc.Symb = coff_symbol->Section->Symbol; FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment) + coff_symbol->MCData->getOffset(); @@ -684,7 +689,12 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, Reloc.Data.VirtualAddress += Fixup.getOffset(); - switch ((unsigned)Fixup.getKind()) { + unsigned FixupKind = Fixup.getKind(); + + if (CrossSection) + FixupKind = FK_PCRel_4; + + switch (FixupKind) { case FK_PCRel_4: case X86::reloc_riprel_4byte: case X86::reloc_riprel_4byte_movq_load: diff --git a/contrib/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm/lib/Object/COFFObjectFile.cpp index cfee82a0b217..86bf44baaeb6 100644 --- a/contrib/llvm/lib/Object/COFFObjectFile.cpp +++ b/contrib/llvm/lib/Object/COFFObjectFile.cpp @@ -91,6 +91,7 @@ extern char coff_coff_section_layout_static_assert namespace { class COFFObjectFile : public ObjectFile { private: + uint64_t HeaderOff; const coff_file_header *Header; const coff_section *SectionTable; const coff_symbol *SymbolTable; @@ -185,11 +186,8 @@ char COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb) const { return ret; uint32_t Characteristics = 0; - uint32_t PointerToRawData = 0; - const coff_section *Section = getSection(symb->SectionNumber); - if (Section) { + if (const coff_section *Section = getSection(symb->SectionNumber)) { Characteristics = Section->Characteristics; - PointerToRawData = Section->PointerToRawData; } switch (symb->SectionNumber) { @@ -256,7 +254,7 @@ StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const { // Check for string table entry. First byte is '/'. if (name[0] == '/') { uint32_t Offset; - name.getAsInteger(10, Offset); + name.substr(1).getAsInteger(10, Offset); return StringRef(getString(Offset)); } @@ -287,9 +285,20 @@ bool COFFObjectFile::isSectionText(DataRefImpl Sec) const { COFFObjectFile::COFFObjectFile(MemoryBuffer *Object) : ObjectFile(Object) { - Header = reinterpret_cast(base); + + HeaderOff = 0; + + if (base[0] == 0x4d && base[1] == 0x5a) { + // PE/COFF, seek through MS-DOS compatibility stub and 4-byte + // PE signature to find 'normal' COFF header. + HeaderOff += *reinterpret_cast(base + 0x3c); + HeaderOff += 4; + } + + Header = reinterpret_cast(base + HeaderOff); SectionTable = reinterpret_cast( base + + HeaderOff + sizeof(coff_file_header) + Header->SizeOfOptionalHeader); SymbolTable = @@ -303,6 +312,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object) ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { DataRefImpl ret; + memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SymbolTable); return symbol_iterator(SymbolRef(ret, this)); } @@ -310,18 +320,21 @@ ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const { // The symbol table ends where the string table begins. DataRefImpl ret; + memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(StringTable); return symbol_iterator(SymbolRef(ret, this)); } ObjectFile::section_iterator COFFObjectFile::begin_sections() const { DataRefImpl ret; + memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable); return section_iterator(SectionRef(ret, this)); } ObjectFile::section_iterator COFFObjectFile::end_sections() const { DataRefImpl ret; + memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable + Header->NumberOfSections); return section_iterator(SectionRef(ret, this)); } diff --git a/contrib/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm/lib/Object/ELFObjectFile.cpp index 682be770f48f..d2a2726ce739 100644 --- a/contrib/llvm/lib/Object/ELFObjectFile.cpp +++ b/contrib/llvm/lib/Object/ELFObjectFile.cpp @@ -547,6 +547,7 @@ template ObjectFile::section_iterator ELFObjectFile ::begin_sections() const { DataRefImpl ret; + memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(base + Header->e_shoff); return section_iterator(SectionRef(ret, this)); } @@ -555,6 +556,7 @@ template ObjectFile::section_iterator ELFObjectFile ::end_sections() const { DataRefImpl ret; + memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(base + Header->e_shoff + (Header->e_shentsize * Header->e_shnum)); diff --git a/contrib/llvm/lib/Object/MachOObject.cpp b/contrib/llvm/lib/Object/MachOObject.cpp index 5e64d6323288..9890febfb616 100644 --- a/contrib/llvm/lib/Object/MachOObject.cpp +++ b/contrib/llvm/lib/Object/MachOObject.cpp @@ -12,6 +12,8 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Host.h" #include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" using namespace llvm; using namespace llvm::object; @@ -340,3 +342,29 @@ void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset, Index * sizeof(macho::Symbol64TableEntry)); ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); } + +/* ** */ +// Object Dumping Facilities +void MachOObject::dump() const { print(dbgs()); dbgs() << '\n'; } +void MachOObject::dumpHeader() const { printHeader(dbgs()); dbgs() << '\n'; } + +void MachOObject::printHeader(raw_ostream &O) const { + O << "('cputype', " << Header.CPUType << ")\n"; + O << "('cpusubtype', " << Header.CPUSubtype << ")\n"; + O << "('filetype', " << Header.FileType << ")\n"; + O << "('num_load_commands', " << Header.NumLoadCommands << ")\n"; + O << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n"; + O << "('flag', " << Header.Flags << ")\n"; + + // Print extended header if 64-bit. + if (is64Bit()) + O << "('reserved', " << Header64Ext.Reserved << ")\n"; +} + +void MachOObject::print(raw_ostream &O) const { + O << "Header:\n"; + printHeader(O); + O << "Load Commands:\n"; + + O << "Buffer:\n"; +} diff --git a/contrib/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm/lib/Object/MachOObjectFile.cpp new file mode 100644 index 000000000000..877cbfbdb808 --- /dev/null +++ b/contrib/llvm/lib/Object/MachOObjectFile.cpp @@ -0,0 +1,327 @@ +//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- 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 MachOObjectFile class, which binds the MachOObject +// class to the generic ObjectFile wrapper. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Triple.h" +#include "llvm/Object/MachOFormat.h" +#include "llvm/Object/MachOObject.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/MachO.h" + +#include +#include +#include + +using namespace llvm; +using namespace object; + +namespace llvm { + +typedef MachOObject::LoadCommandInfo LoadCommandInfo; + +class MachOObjectFile : public ObjectFile { +public: + MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO) + : ObjectFile(Object), + MachOObj(MOO), + RegisteredStringTable(std::numeric_limits::max()) {} + + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; + +protected: + virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; + virtual StringRef getSymbolName(DataRefImpl Symb) const; + virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; + virtual uint64_t getSymbolSize(DataRefImpl Symb) const; + virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; + virtual bool isSymbolInternal(DataRefImpl Symb) const; + + virtual SectionRef getSectionNext(DataRefImpl Sec) const; + virtual StringRef getSectionName(DataRefImpl Sec) const; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const; + virtual uint64_t getSectionSize(DataRefImpl Sec) const; + virtual StringRef getSectionContents(DataRefImpl Sec) const; + virtual bool isSectionText(DataRefImpl Sec) const; + +private: + MachOObject *MachOObj; + mutable uint32_t RegisteredStringTable; + + void moveToNextSection(DataRefImpl &DRI) const; + void getSymbolTableEntry(DataRefImpl DRI, + InMemoryStruct &Res) const; + void moveToNextSymbol(DataRefImpl &DRI) const; + void getSection(DataRefImpl DRI, InMemoryStruct &Res) const; +}; + +ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { + std::string Err; + MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); + if (!MachOObj) + return NULL; + return new MachOObjectFile(Buffer, MachOObj); +} + +/*===-- Symbols -----------------------------------------------------------===*/ + +void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { + uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + if (LCI.Command.Type == macho::LCT_Symtab) { + InMemoryStruct SymtabLoadCmd; + MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); + if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) + return; + } + + DRI.d.a++; + DRI.d.b = 0; + } +} + +void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, + InMemoryStruct &Res) const { + InMemoryStruct SymtabLoadCmd; + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); + + if (RegisteredStringTable != DRI.d.a) { + MachOObj->RegisterStringTable(*SymtabLoadCmd); + RegisteredStringTable = DRI.d.a; + } + + MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, + Res); +} + + +SymbolRef MachOObjectFile::getSymbolNext(DataRefImpl DRI) const { + DRI.d.b++; + moveToNextSymbol(DRI); + return SymbolRef(DRI, this); +} + +StringRef MachOObjectFile::getSymbolName(DataRefImpl DRI) const { + InMemoryStruct Entry; + getSymbolTableEntry(DRI, Entry); + return MachOObj->getStringAtIndex(Entry->StringIndex); +} + +uint64_t MachOObjectFile::getSymbolAddress(DataRefImpl DRI) const { + InMemoryStruct Entry; + getSymbolTableEntry(DRI, Entry); + return Entry->Value; +} + +uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const { + return UnknownAddressOrSize; +} + +char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const { + InMemoryStruct Entry; + getSymbolTableEntry(DRI, Entry); + + char Char; + switch (Entry->Type & macho::STF_TypeMask) { + case macho::STT_Undefined: + Char = 'u'; + break; + case macho::STT_Absolute: + case macho::STT_Section: + Char = 's'; + break; + default: + Char = '?'; + break; + } + + if (Entry->Flags & (macho::STF_External | macho::STF_PrivateExtern)) + Char = toupper(Char); + return Char; +} + +bool MachOObjectFile::isSymbolInternal(DataRefImpl DRI) const { + InMemoryStruct Entry; + getSymbolTableEntry(DRI, Entry); + return Entry->Flags & macho::STF_StabsEntryMask; +} + +ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const { + // DRI.d.a = segment number; DRI.d.b = symbol index. + DataRefImpl DRI; + DRI.d.a = DRI.d.b = 0; + moveToNextSymbol(DRI); + return symbol_iterator(SymbolRef(DRI, this)); +} + +ObjectFile::symbol_iterator MachOObjectFile::end_symbols() const { + DataRefImpl DRI; + DRI.d.a = MachOObj->getHeader().NumLoadCommands; + DRI.d.b = 0; + return symbol_iterator(SymbolRef(DRI, this)); +} + + +/*===-- Sections ----------------------------------------------------------===*/ + +void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { + uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + if (LCI.Command.Type == macho::LCT_Segment) { + InMemoryStruct SegmentLoadCmd; + MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); + if (DRI.d.b < SegmentLoadCmd->NumSections) + return; + } else if (LCI.Command.Type == macho::LCT_Segment64) { + InMemoryStruct Segment64LoadCmd; + MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); + if (DRI.d.b < Segment64LoadCmd->NumSections) + return; + } + + DRI.d.a++; + DRI.d.b = 0; + } +} + +SectionRef MachOObjectFile::getSectionNext(DataRefImpl DRI) const { + DRI.d.b++; + moveToNextSection(DRI); + return SectionRef(DRI, this); +} + +void +MachOObjectFile::getSection(DataRefImpl DRI, + InMemoryStruct &Res) const { + InMemoryStruct SLC; + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + MachOObj->ReadSegmentLoadCommand(LCI, SLC); + MachOObj->ReadSection(LCI, DRI.d.b, Res); +} + +StringRef MachOObjectFile::getSectionName(DataRefImpl DRI) const { + InMemoryStruct SLC; + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + MachOObj->ReadSegmentLoadCommand(LCI, SLC); + InMemoryStruct Sect; + MachOObj->ReadSection(LCI, DRI.d.b, Sect); + + static char Result[34]; + strcpy(Result, SLC->Name); + strcat(Result, ","); + strcat(Result, Sect->Name); + return StringRef(Result); +} + +uint64_t MachOObjectFile::getSectionAddress(DataRefImpl DRI) const { + InMemoryStruct Sect; + getSection(DRI, Sect); + return Sect->Address; +} + +uint64_t MachOObjectFile::getSectionSize(DataRefImpl DRI) const { + InMemoryStruct Sect; + getSection(DRI, Sect); + return Sect->Size; +} + +StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const { + InMemoryStruct Sect; + getSection(DRI, Sect); + return MachOObj->getData(Sect->Offset, Sect->Size); +} + +bool MachOObjectFile::isSectionText(DataRefImpl DRI) const { + InMemoryStruct SLC; + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + MachOObj->ReadSegmentLoadCommand(LCI, SLC); + return !strcmp(SLC->Name, "__TEXT"); +} + +ObjectFile::section_iterator MachOObjectFile::begin_sections() const { + DataRefImpl DRI; + DRI.d.a = DRI.d.b = 0; + moveToNextSection(DRI); + return section_iterator(SectionRef(DRI, this)); +} + +ObjectFile::section_iterator MachOObjectFile::end_sections() const { + DataRefImpl DRI; + DRI.d.a = MachOObj->getHeader().NumLoadCommands; + DRI.d.b = 0; + return section_iterator(SectionRef(DRI, this)); +} + +/*===-- Miscellaneous -----------------------------------------------------===*/ + +uint8_t MachOObjectFile::getBytesInAddress() const { + return MachOObj->is64Bit() ? 8 : 4; +} + +StringRef MachOObjectFile::getFileFormatName() const { + if (!MachOObj->is64Bit()) { + switch (MachOObj->getHeader().CPUType) { + case llvm::MachO::CPUTypeI386: + return "Mach-O 32-bit i386"; + case llvm::MachO::CPUTypeARM: + return "Mach-O arm"; + case llvm::MachO::CPUTypePowerPC: + return "Mach-O 32-bit ppc"; + default: + assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && + "64-bit object file when we're not 64-bit?"); + return "Mach-O 32-bit unknown"; + } + } + + switch (MachOObj->getHeader().CPUType) { + case llvm::MachO::CPUTypeX86_64: + return "Mach-O 64-bit x86-64"; + case llvm::MachO::CPUTypePowerPC64: + return "Mach-O 64-bit ppc64"; + default: + assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 && + "32-bit object file when we're 64-bit?"); + return "Mach-O 64-bit unknown"; + } +} + +unsigned MachOObjectFile::getArch() const { + switch (MachOObj->getHeader().CPUType) { + case llvm::MachO::CPUTypeI386: + return Triple::x86; + case llvm::MachO::CPUTypeX86_64: + return Triple::x86_64; + case llvm::MachO::CPUTypeARM: + return Triple::arm; + case llvm::MachO::CPUTypePowerPC: + return Triple::ppc; + case llvm::MachO::CPUTypePowerPC64: + return Triple::ppc64; + default: + return Triple::UnknownArch; + } +} + +} // end namespace llvm + diff --git a/contrib/llvm/lib/Object/Object.cpp b/contrib/llvm/lib/Object/Object.cpp new file mode 100644 index 000000000000..603b23c74e93 --- /dev/null +++ b/contrib/llvm/lib/Object/Object.cpp @@ -0,0 +1,59 @@ +//===- Object.cpp - C bindings to the object file library--------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the C bindings to the file-format-independent object +// library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ObjectFile.h" +#include "llvm-c/Object.h" + +using namespace llvm; +using namespace object; + +LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { + return wrap(ObjectFile::createObjectFile(unwrap(MemBuf))); +} + +void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { + delete unwrap(ObjectFile); +} + +LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) { + ObjectFile::section_iterator SI = unwrap(ObjectFile)->begin_sections(); + return wrap(new ObjectFile::section_iterator(SI)); +} + +void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { + delete unwrap(SI); +} + +LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile, + LLVMSectionIteratorRef SI) { + return (*unwrap(SI) == unwrap(ObjectFile)->end_sections()) ? 1 : 0; +} + +void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { + // We can't use unwrap() here because the argument to ++ must be an lvalue. + ++*reinterpret_cast(SI); +} + +const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { + return (*unwrap(SI))->getName().data(); +} + +uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { + return (*unwrap(SI))->getSize(); +} + +const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { + return (*unwrap(SI))->getContents().data(); +} + diff --git a/contrib/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm/lib/Object/ObjectFile.cpp index 161ae3a083f1..47b63115a94c 100644 --- a/contrib/llvm/lib/Object/ObjectFile.cpp +++ b/contrib/llvm/lib/Object/ObjectFile.cpp @@ -55,7 +55,7 @@ ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { case sys::Mach_O_DynamicLinker_FileType: case sys::Mach_O_Bundle_FileType: case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: - return 0; + return createMachOObjectFile(Object); case sys::COFF_FileType: return createCOFFObjectFile(Object); default: diff --git a/contrib/llvm/lib/Support/APFloat.cpp b/contrib/llvm/lib/Support/APFloat.cpp index e765ba0a27bb..c3169acabbc7 100644 --- a/contrib/llvm/lib/Support/APFloat.cpp +++ b/contrib/llvm/lib/Support/APFloat.cpp @@ -726,7 +726,7 @@ APFloat::bitwiseIsEqual(const APFloat &rhs) const { } APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) -{ + : exponent2(0), sign2(0) { assertArithmeticOK(ourSemantics); initialize(&ourSemantics); sign = 0; @@ -736,14 +736,15 @@ APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) normalize(rmNearestTiesToEven, lfExactlyZero); } -APFloat::APFloat(const fltSemantics &ourSemantics) { +APFloat::APFloat(const fltSemantics &ourSemantics) : exponent2(0), sign2(0) { assertArithmeticOK(ourSemantics); initialize(&ourSemantics); category = fcZero; sign = false; } -APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) { +APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) + : exponent2(0), sign2(0) { assertArithmeticOK(ourSemantics); // Allocates storage if necessary but does not initialize it. initialize(&ourSemantics); @@ -751,7 +752,7 @@ APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) { APFloat::APFloat(const fltSemantics &ourSemantics, fltCategory ourCategory, bool negative) -{ + : exponent2(0), sign2(0) { assertArithmeticOK(ourSemantics); initialize(&ourSemantics); category = ourCategory; @@ -763,14 +764,13 @@ APFloat::APFloat(const fltSemantics &ourSemantics, } APFloat::APFloat(const fltSemantics &ourSemantics, StringRef text) -{ + : exponent2(0), sign2(0) { assertArithmeticOK(ourSemantics); initialize(&ourSemantics); convertFromString(text, rmNearestTiesToEven); } -APFloat::APFloat(const APFloat &rhs) -{ +APFloat::APFloat(const APFloat &rhs) : exponent2(0), sign2(0) { initialize(rhs.semantics); assign(rhs); } @@ -3257,18 +3257,15 @@ APFloat APFloat::getSmallestNormalized(const fltSemantics &Sem, bool Negative) { return Val; } -APFloat::APFloat(const APInt& api, bool isIEEE) -{ +APFloat::APFloat(const APInt& api, bool isIEEE) : exponent2(0), sign2(0) { initFromAPInt(api, isIEEE); } -APFloat::APFloat(float f) -{ +APFloat::APFloat(float f) : exponent2(0), sign2(0) { initFromAPInt(APInt::floatToBits(f)); } -APFloat::APFloat(double d) -{ +APFloat::APFloat(double d) : exponent2(0), sign2(0) { initFromAPInt(APInt::doubleToBits(d)); } @@ -3565,3 +3562,37 @@ void APFloat::toString(SmallVectorImpl &Str, for (; I != NDigits; ++I) Str.push_back(buffer[NDigits-I-1]); } + +bool APFloat::getExactInverse(APFloat *inv) const { + // We can only guarantee the existence of an exact inverse for IEEE floats. + if (semantics != &IEEEhalf && semantics != &IEEEsingle && + semantics != &IEEEdouble && semantics != &IEEEquad) + return false; + + // Special floats and denormals have no exact inverse. + if (category != fcNormal) + return false; + + // Check that the number is a power of two by making sure that only the + // integer bit is set in the significand. + if (significandLSB() != semantics->precision - 1) + return false; + + // Get the inverse. + APFloat reciprocal(*semantics, 1ULL); + if (reciprocal.divide(*this, rmNearestTiesToEven) != opOK) + return false; + + // Avoid multiplication with a denormal, it is not safe on all platforms and + // may be slower than a normal division. + if (reciprocal.significandMSB() + 1 < reciprocal.semantics->precision) + return false; + + assert(reciprocal.category == fcNormal && + reciprocal.significandLSB() == reciprocal.semantics->precision - 1); + + if (inv) + *inv = reciprocal; + + return true; +} diff --git a/contrib/llvm/lib/Support/APInt.cpp b/contrib/llvm/lib/Support/APInt.cpp index 08f36d2af3a1..23a22ac68f3f 100644 --- a/contrib/llvm/lib/Support/APInt.cpp +++ b/contrib/llvm/lib/Support/APInt.cpp @@ -1517,13 +1517,15 @@ APInt::ms APInt::magic() const { /// division by a constant as a sequence of multiplies, adds and shifts. /// Requires that the divisor not be 0. Taken from "Hacker's Delight", Henry /// S. Warren, Jr., chapter 10. -APInt::mu APInt::magicu() const { +/// LeadingZeros can be used to simplify the calculation if the upper bits +/// of the divided value are known zero. +APInt::mu APInt::magicu(unsigned LeadingZeros) const { const APInt& d = *this; unsigned p; APInt nc, delta, q1, r1, q2, r2; struct mu magu; magu.a = 0; // initialize "add" indicator - APInt allOnes = APInt::getAllOnesValue(d.getBitWidth()); + APInt allOnes = APInt::getAllOnesValue(d.getBitWidth()).lshr(LeadingZeros); APInt signedMin = APInt::getSignedMinValue(d.getBitWidth()); APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth()); @@ -2076,6 +2078,16 @@ APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const { return Res; } +APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this * RHS; + + if (*this != 0 && RHS != 0) + Overflow = Res.udiv(RHS) != *this || Res.udiv(*this) != RHS; + else + Overflow = false; + return Res; +} + APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const { Overflow = ShAmt >= getBitWidth(); if (Overflow) diff --git a/contrib/llvm/lib/Support/Allocator.cpp b/contrib/llvm/lib/Support/Allocator.cpp index 5e27df6628eb..215b0f249d96 100644 --- a/contrib/llvm/lib/Support/Allocator.cpp +++ b/contrib/llvm/lib/Support/Allocator.cpp @@ -136,6 +136,14 @@ unsigned BumpPtrAllocator::GetNumSlabs() const { return NumSlabs; } +size_t BumpPtrAllocator::getTotalMemory() const { + size_t TotalMemory = 0; + for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) { + TotalMemory += Slab->Size; + } + return TotalMemory; +} + void BumpPtrAllocator::PrintStats() const { unsigned NumSlabs = 0; size_t TotalMemory = 0; diff --git a/contrib/llvm/lib/Support/CommandLine.cpp b/contrib/llvm/lib/Support/CommandLine.cpp index 7e744993a7cb..7f1c0d320b11 100644 --- a/contrib/llvm/lib/Support/CommandLine.cpp +++ b/contrib/llvm/lib/Support/CommandLine.cpp @@ -186,12 +186,14 @@ static Option *LookupOption(StringRef &Arg, StringRef &Value, /// have already been stripped. static Option *LookupNearestOption(StringRef Arg, const StringMap &OptionsMap, - const char *&NearestString) { + std::string &NearestString) { // Reject all dashes. if (Arg.empty()) return 0; // Split on any equal sign. - StringRef LHS = Arg.split('=').first; + std::pair SplitArg = Arg.split('='); + StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present. + StringRef &RHS = SplitArg.second; // Find the closest match. Option *Best = 0; @@ -204,14 +206,19 @@ static Option *LookupNearestOption(StringRef Arg, if (O->ArgStr[0]) OptionNames.push_back(O->ArgStr); + bool PermitValue = O->getValueExpectedFlag() != cl::ValueDisallowed; + StringRef Flag = PermitValue ? LHS : Arg; for (size_t i = 0, e = OptionNames.size(); i != e; ++i) { StringRef Name = OptionNames[i]; unsigned Distance = StringRef(Name).edit_distance( - Arg, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance); + Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance); if (!Best || Distance < BestDistance) { Best = O; - NearestString = OptionNames[i]; BestDistance = Distance; + if (RHS.empty() || !PermitValue) + NearestString = OptionNames[i]; + else + NearestString = std::string(OptionNames[i]) + "=" + RHS.str(); } } } @@ -611,7 +618,7 @@ void cl::ParseCommandLineOptions(int argc, char **argv, for (int i = 1; i < argc; ++i) { Option *Handler = 0; Option *NearestHandler = 0; - const char *NearestHandlerString = 0; + std::string NearestHandlerString; StringRef Value; StringRef ArgName = ""; @@ -908,8 +915,6 @@ void alias::printOptionInfo(size_t GlobalWidth) const { errs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n"; } - - //===----------------------------------------------------------------------===// // Parser Implementation code... // @@ -939,7 +944,11 @@ void basic_parser_impl::printOptionInfo(const Option &O, outs().indent(GlobalWidth-getOptionWidth(O)) << " - " << O.HelpStr << '\n'; } - +void basic_parser_impl::printOptionName(const Option &O, + size_t GlobalWidth) const { + outs() << " -" << O.ArgStr; + outs().indent(GlobalWidth-std::strlen(O.ArgStr)); +} // parser implementation @@ -1083,6 +1092,89 @@ void generic_parser_base::printOptionInfo(const Option &O, } } +static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff + +// printGenericOptionDiff - Print the value of this option and it's default. +// +// "Generic" options have each value mapped to a name. +void generic_parser_base:: +printGenericOptionDiff(const Option &O, const GenericOptionValue &Value, + const GenericOptionValue &Default, + size_t GlobalWidth) const { + outs() << " -" << O.ArgStr; + outs().indent(GlobalWidth-std::strlen(O.ArgStr)); + + unsigned NumOpts = getNumOptions(); + for (unsigned i = 0; i != NumOpts; ++i) { + if (Value.compare(getOptionValue(i))) + continue; + + outs() << "= " << getOption(i); + size_t L = std::strlen(getOption(i)); + size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0; + outs().indent(NumSpaces) << " (default: "; + for (unsigned j = 0; j != NumOpts; ++j) { + if (Default.compare(getOptionValue(j))) + continue; + outs() << getOption(j); + break; + } + outs() << ")\n"; + return; + } + outs() << "= *unknown option value*\n"; +} + +// printOptionDiff - Specializations for printing basic value types. +// +#define PRINT_OPT_DIFF(T) \ + void parser:: \ + printOptionDiff(const Option &O, T V, OptionValue D, \ + size_t GlobalWidth) const { \ + printOptionName(O, GlobalWidth); \ + std::string Str; \ + { \ + raw_string_ostream SS(Str); \ + SS << V; \ + } \ + outs() << "= " << Str; \ + size_t NumSpaces = MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0;\ + outs().indent(NumSpaces) << " (default: "; \ + if (D.hasValue()) \ + outs() << D.getValue(); \ + else \ + outs() << "*no default*"; \ + outs() << ")\n"; \ + } \ + +PRINT_OPT_DIFF(bool) +PRINT_OPT_DIFF(boolOrDefault) +PRINT_OPT_DIFF(int) +PRINT_OPT_DIFF(unsigned) +PRINT_OPT_DIFF(double) +PRINT_OPT_DIFF(float) +PRINT_OPT_DIFF(char) + +void parser:: +printOptionDiff(const Option &O, StringRef V, OptionValue D, + size_t GlobalWidth) const { + printOptionName(O, GlobalWidth); + outs() << "= " << V; + size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0; + outs().indent(NumSpaces) << " (default: "; + if (D.hasValue()) + outs() << D.getValue(); + else + outs() << "*no default*"; + outs() << ")\n"; +} + +// Print a placeholder for options that don't yet support printOptionDiff(). +void basic_parser_impl:: +printOptionNoValue(const Option &O, size_t GlobalWidth) const { + printOptionName(O, GlobalWidth); + outs() << "= *cannot print option value*\n"; +} //===----------------------------------------------------------------------===// // -help and -help-hidden option implementation @@ -1094,6 +1186,35 @@ static int OptNameCompare(const void *LHS, const void *RHS) { return strcmp(((pair_ty*)LHS)->first, ((pair_ty*)RHS)->first); } +// Copy Options into a vector so we can sort them as we like. +static void +sortOpts(StringMap &OptMap, + SmallVectorImpl< std::pair > &Opts, + bool ShowHidden) { + SmallPtrSet OptionSet; // Duplicate option detection. + + for (StringMap::iterator I = OptMap.begin(), E = OptMap.end(); + I != E; ++I) { + // Ignore really-hidden options. + if (I->second->getOptionHiddenFlag() == ReallyHidden) + continue; + + // Unless showhidden is set, ignore hidden flags. + if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden) + continue; + + // If we've already seen this option, don't add it to the list again. + if (!OptionSet.insert(I->second)) + continue; + + Opts.push_back(std::pair(I->getKey().data(), + I->second)); + } + + // Sort the options list alphabetically. + qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare); +} + namespace { class HelpPrinter { @@ -1115,30 +1236,8 @@ class HelpPrinter { StringMap OptMap; GetOptionInfo(PositionalOpts, SinkOpts, OptMap); - // Copy Options into a vector so we can sort them as we like. SmallVector, 128> Opts; - SmallPtrSet OptionSet; // Duplicate option detection. - - for (StringMap::iterator I = OptMap.begin(), E = OptMap.end(); - I != E; ++I) { - // Ignore really-hidden options. - if (I->second->getOptionHiddenFlag() == ReallyHidden) - continue; - - // Unless showhidden is set, ignore hidden flags. - if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden) - continue; - - // If we've already seen this option, don't add it to the list again. - if (!OptionSet.insert(I->second)) - continue; - - Opts.push_back(std::pair(I->getKey().data(), - I->second)); - } - - // Sort the options list alphabetically. - qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare); + sortOpts(OptMap, Opts, ShowHidden); if (ProgramOverview) outs() << "OVERVIEW: " << ProgramOverview << "\n"; @@ -1197,6 +1296,38 @@ static cl::opt > HHOp("help-hidden", cl::desc("Display all available options"), cl::location(HiddenPrinter), cl::Hidden, cl::ValueDisallowed); +static cl::opt +PrintOptions("print-options", + cl::desc("Print non-default options after command line parsing"), + cl::Hidden, cl::init(false)); + +static cl::opt +PrintAllOptions("print-all-options", + cl::desc("Print all option values after command line parsing"), + cl::Hidden, cl::init(false)); + +// Print the value of each option. +void cl::PrintOptionValues() { + if (!PrintOptions && !PrintAllOptions) return; + + // Get all the options. + SmallVector PositionalOpts; + SmallVector SinkOpts; + StringMap OptMap; + GetOptionInfo(PositionalOpts, SinkOpts, OptMap); + + SmallVector, 128> Opts; + sortOpts(OptMap, Opts, /*ShowHidden*/true); + + // Compute the maximum argument length... + size_t MaxArgLen = 0; + for (size_t i = 0, e = Opts.size(); i != e; ++i) + MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth()); + + for (size_t i = 0, e = Opts.size(); i != e; ++i) + Opts[i].second->printOptionValue(MaxArgLen, PrintAllOptions); +} + static void (*OverrideVersionPrinter)() = 0; static int TargetArraySortFn(const void *LHS, const void *RHS) { diff --git a/contrib/llvm/lib/Support/CrashRecoveryContext.cpp b/contrib/llvm/lib/Support/CrashRecoveryContext.cpp index bf8ca3f844b4..899c3890d78a 100644 --- a/contrib/llvm/lib/Support/CrashRecoveryContext.cpp +++ b/contrib/llvm/lib/Support/CrashRecoveryContext.cpp @@ -57,12 +57,36 @@ struct CrashRecoveryContextImpl { static sys::Mutex gCrashRecoveryContexMutex; static bool gCrashRecoveryEnabled = false; +static sys::ThreadLocal + tlIsRecoveringFromCrash; + +CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {} + CrashRecoveryContext::~CrashRecoveryContext() { + // Reclaim registered resources. + CrashRecoveryContextCleanup *i = head; + tlIsRecoveringFromCrash.set(head); + while (i) { + CrashRecoveryContextCleanup *tmp = i; + i = tmp->next; + tmp->cleanupFired = true; + tmp->recoverResources(); + delete tmp; + } + tlIsRecoveringFromCrash.erase(); + CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl; delete CRCI; } +bool CrashRecoveryContext::isRecoveringFromCrash() { + return tlIsRecoveringFromCrash.get() != 0; +} + CrashRecoveryContext *CrashRecoveryContext::GetCurrent() { + if (!gCrashRecoveryEnabled) + return 0; + const CrashRecoveryContextImpl *CRCI = CurrentContext.get(); if (!CRCI) return 0; @@ -70,6 +94,33 @@ CrashRecoveryContext *CrashRecoveryContext::GetCurrent() { return CRCI->CRC; } +void CrashRecoveryContext::registerCleanup(CrashRecoveryContextCleanup *cleanup) +{ + if (!cleanup) + return; + if (head) + head->prev = cleanup; + cleanup->next = head; + head = cleanup; +} + +void +CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) { + if (!cleanup) + return; + if (cleanup == head) { + head = cleanup->next; + if (head) + head->prev = 0; + } + else { + cleanup->prev->next = cleanup->next; + if (cleanup->next) + cleanup->next->prev = cleanup->prev; + } + delete cleanup; +} + #ifdef LLVM_ON_WIN32 // FIXME: No real Win32 implementation currently. diff --git a/contrib/llvm/lib/Support/Dwarf.cpp b/contrib/llvm/lib/Support/Dwarf.cpp index 9799ef54792b..74a9fda7ab64 100644 --- a/contrib/llvm/lib/Support/Dwarf.cpp +++ b/contrib/llvm/lib/Support/Dwarf.cpp @@ -203,6 +203,10 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) { case DW_AT_APPLE_major_runtime_vers: return "DW_AT_APPLE_major_runtime_vers"; case DW_AT_APPLE_runtime_class: return "DW_AT_APPLE_runtime_class"; case DW_AT_APPLE_omit_frame_ptr: return "DW_AT_APPLE_omit_frame_ptr"; + case DW_AT_APPLE_property_name: return "DW_AT_APPLE_property_name"; + case DW_AT_APPLE_property_getter: return "DW_AT_APPLE_property_getter"; + case DW_AT_APPLE_property_setter: return "DW_AT_APPLE_property_setter"; + case DW_AT_APPLE_property_attribute: return "DW_AT_APPLE_property_attribute"; } return 0; } @@ -391,6 +395,7 @@ const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) { case DW_OP_call_ref: return "DW_OP_call_ref"; case DW_OP_form_tls_address: return "DW_OP_form_tls_address"; case DW_OP_call_frame_cfa: return "DW_OP_call_frame_cfa"; + case DW_OP_bit_piece: return "DW_OP_bit_piece"; case DW_OP_lo_user: return "DW_OP_lo_user"; case DW_OP_hi_user: return "DW_OP_hi_user"; } diff --git a/contrib/llvm/lib/Support/ErrorHandling.cpp b/contrib/llvm/lib/Support/ErrorHandling.cpp index 3579546d757d..e6cc57db8243 100644 --- a/contrib/llvm/lib/Support/ErrorHandling.cpp +++ b/contrib/llvm/lib/Support/ErrorHandling.cpp @@ -32,7 +32,6 @@ #endif using namespace llvm; -using namespace std; static fatal_error_handler_t ErrorHandler = 0; static void *ErrorHandlerUserData = 0; diff --git a/contrib/llvm/lib/Support/FileUtilities.cpp b/contrib/llvm/lib/Support/FileUtilities.cpp index 5dbabee7a7ed..4c8c0c63ffc4 100644 --- a/contrib/llvm/lib/Support/FileUtilities.cpp +++ b/contrib/llvm/lib/Support/FileUtilities.cpp @@ -198,7 +198,7 @@ int llvm::DiffFilesWithTolerance(const sys::PathWithStatus &FileA, return 1; } - // Now its safe to mmap the files into memory becasue both files + // Now its safe to mmap the files into memory because both files // have a non-zero size. error_code ec; OwningPtr F1; diff --git a/contrib/llvm/lib/Support/FoldingSet.cpp b/contrib/llvm/lib/Support/FoldingSet.cpp index a4f80a90d6d0..d2e35b8eb676 100644 --- a/contrib/llvm/lib/Support/FoldingSet.cpp +++ b/contrib/llvm/lib/Support/FoldingSet.cpp @@ -147,6 +147,11 @@ void FoldingSetNodeID::AddString(StringRef String) { Bits.push_back(V); } +// AddNodeID - Adds the Bit data of another ID to *this. +void FoldingSetNodeID::AddNodeID(const FoldingSetNodeID &ID) { + Bits.append(ID.Bits.begin(), ID.Bits.end()); +} + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to /// lookup the node in the FoldingSetImpl. unsigned FoldingSetNodeID::ComputeHash() const { diff --git a/contrib/llvm/lib/Support/Host.cpp b/contrib/llvm/lib/Support/Host.cpp index 4dacf9691d6e..911c64accec3 100644 --- a/contrib/llvm/lib/Support/Host.cpp +++ b/contrib/llvm/lib/Support/Host.cpp @@ -214,6 +214,8 @@ std::string sys::getHostCPUName() { // As found in a Summer 2010 model iMac. case 37: // Intel Core i7, laptop version. return "corei7"; + case 42: // SandyBridge + return "sandybridge"; case 28: // Intel Atom processor. All processors are manufactured using // the 45 nm process diff --git a/contrib/llvm/lib/Support/MemoryBuffer.cpp b/contrib/llvm/lib/Support/MemoryBuffer.cpp index a0c650d6820b..e2b5b7a58523 100644 --- a/contrib/llvm/lib/Support/MemoryBuffer.cpp +++ b/contrib/llvm/lib/Support/MemoryBuffer.cpp @@ -46,8 +46,10 @@ MemoryBuffer::~MemoryBuffer() { } /// init - Initialize this MemoryBuffer as a reference to externally allocated /// memory, memory that we know is already null terminated. -void MemoryBuffer::init(const char *BufStart, const char *BufEnd) { - assert(BufEnd[0] == 0 && "Buffer is not null terminated!"); +void MemoryBuffer::init(const char *BufStart, const char *BufEnd, + bool RequiresNullTerminator) { + assert((!RequiresNullTerminator || BufEnd[0] == 0) && + "Buffer is not null terminated!"); BufferStart = BufStart; BufferEnd = BufEnd; } @@ -65,32 +67,39 @@ static void CopyStringRef(char *Memory, StringRef Data) { /// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it. template -static T* GetNamedBuffer(StringRef Buffer, StringRef Name) { +static T* GetNamedBuffer(StringRef Buffer, StringRef Name, + bool RequiresNullTerminator) { char *Mem = static_cast(operator new(sizeof(T) + Name.size() + 1)); CopyStringRef(Mem + sizeof(T), Name); - return new (Mem) T(Buffer); + return new (Mem) T(Buffer, RequiresNullTerminator); } namespace { /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory. class MemoryBufferMem : public MemoryBuffer { public: - MemoryBufferMem(StringRef InputData) { - init(InputData.begin(), InputData.end()); + MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) { + init(InputData.begin(), InputData.end(), RequiresNullTerminator); } virtual const char *getBufferIdentifier() const { // The name is stored after the class itself. return reinterpret_cast(this + 1); } + + virtual BufferKind getBufferKind() const { + return MemoryBuffer_Malloc; + } }; } /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that EndPtr[0] must be a null byte and be accessible! MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData, - StringRef BufferName) { - return GetNamedBuffer(InputData, BufferName); + StringRef BufferName, + bool RequiresNullTerminator) { + return GetNamedBuffer(InputData, BufferName, + RequiresNullTerminator); } /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, @@ -127,7 +136,7 @@ MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size, char *Buf = Mem + AlignedStringLen; Buf[Size] = 0; // Null terminate buffer. - return new (Mem) MemoryBufferMem(StringRef(Buf, Size)); + return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true); } /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that @@ -172,26 +181,41 @@ namespace { /// sys::Path::UnMapFilePages method. class MemoryBufferMMapFile : public MemoryBufferMem { public: - MemoryBufferMMapFile(StringRef Buffer) - : MemoryBufferMem(Buffer) { } + MemoryBufferMMapFile(StringRef Buffer, bool RequiresNullTerminator) + : MemoryBufferMem(Buffer, RequiresNullTerminator) { } ~MemoryBufferMMapFile() { - sys::Path::UnMapFilePages(getBufferStart(), getBufferSize()); + static int PageSize = sys::Process::GetPageSize(); + + uintptr_t Start = reinterpret_cast(getBufferStart()); + size_t Size = getBufferSize(); + uintptr_t RealStart = Start & ~(PageSize - 1); + size_t RealSize = Size + (Start - RealStart); + + sys::Path::UnMapFilePages(reinterpret_cast(RealStart), + RealSize); + } + + virtual BufferKind getBufferKind() const { + return MemoryBuffer_MMap; } }; } error_code MemoryBuffer::getFile(StringRef Filename, OwningPtr &result, - int64_t FileSize) { + int64_t FileSize, + bool RequiresNullTerminator) { // Ensure the path is null terminated. SmallString<256> PathBuf(Filename.begin(), Filename.end()); - return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize); + return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize, + RequiresNullTerminator); } error_code MemoryBuffer::getFile(const char *Filename, OwningPtr &result, - int64_t FileSize) { + int64_t FileSize, + bool RequiresNullTerminator) { int OpenFlags = O_RDONLY; #ifdef O_BINARY OpenFlags |= O_BINARY; // Open input file in binary mode on win32. @@ -200,17 +224,32 @@ error_code MemoryBuffer::getFile(const char *Filename, if (FD == -1) { return error_code(errno, posix_category()); } - error_code ret = getOpenFile(FD, Filename, result, FileSize); + error_code ret = getOpenFile(FD, Filename, result, FileSize, FileSize, + 0, RequiresNullTerminator); close(FD); return ret; } -error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, - OwningPtr &result, - int64_t FileSize) { +static bool shouldUseMmap(int FD, + size_t FileSize, + size_t MapSize, + off_t Offset, + bool RequiresNullTerminator, + int PageSize) { + // We don't use mmap for small files because this can severely fragment our + // address space. + if (MapSize < 4096*4) + return false; + + if (!RequiresNullTerminator) + return true; + + // If we don't know the file size, use fstat to find out. fstat on an open // file descriptor is cheaper than stat on a random path. - if (FileSize == -1) { + // FIXME: this chunk of code is duplicated, but it avoids a fstat when + // RequiresNullTerminator = false and MapSize != -1. + if (FileSize == size_t(-1)) { struct stat FileInfo; // TODO: This should use fstat64 when available. if (fstat(FD, &FileInfo) == -1) { @@ -219,23 +258,59 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, FileSize = FileInfo.st_size; } + // If we need a null terminator and the end of the map is inside the file, + // we cannot use mmap. + size_t End = Offset + MapSize; + assert(End <= FileSize); + if (End != FileSize) + return false; - // If the file is large, try to use mmap to read it in. We don't use mmap - // for small files, because this can severely fragment our address space. Also - // don't try to map files that are exactly a multiple of the system page size, - // as the file would not have the required null terminator. - // - // FIXME: Can we just mmap an extra page in the latter case? - if (FileSize >= 4096*4 && - (FileSize & (sys::Process::GetPageSize()-1)) != 0) { - if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) { + // Don't try to map files that are exactly a multiple of the system page size + // if we need a null terminator. + if ((FileSize & (PageSize -1)) == 0) + return false; + + return true; +} + +error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, + OwningPtr &result, + size_t FileSize, size_t MapSize, + off_t Offset, + bool RequiresNullTerminator) { + static int PageSize = sys::Process::GetPageSize(); + + // Default is to map the full file. + if (MapSize == size_t(-1)) { + // If we don't know the file size, use fstat to find out. fstat on an open + // file descriptor is cheaper than stat on a random path. + if (FileSize == size_t(-1)) { + struct stat FileInfo; + // TODO: This should use fstat64 when available. + if (fstat(FD, &FileInfo) == -1) { + return error_code(errno, posix_category()); + } + FileSize = FileInfo.st_size; + } + MapSize = FileSize; + } + + if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator, + PageSize)) { + off_t RealMapOffset = Offset & ~(PageSize - 1); + off_t Delta = Offset - RealMapOffset; + size_t RealMapSize = MapSize + Delta; + + if (const char *Pages = sys::Path::MapInFilePages(FD, + RealMapSize, + RealMapOffset)) { result.reset(GetNamedBuffer( - StringRef(Pages, FileSize), Filename)); + StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator)); return success; } } - MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename); + MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); if (!Buf) { // Failed to create a buffer. The only way it can fail is if // new(std::nothrow) returns 0. @@ -245,7 +320,10 @@ error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, OwningPtr SB(Buf); char *BufPtr = const_cast(SB->getBufferStart()); - size_t BytesLeft = FileSize; + size_t BytesLeft = MapSize; + if (lseek(FD, Offset, SEEK_SET) == -1) + return error_code(errno, posix_category()); + while (BytesLeft) { ssize_t NumRead = ::read(FD, BufPtr, BytesLeft); if (NumRead == -1) { diff --git a/contrib/llvm/lib/Support/Path.cpp b/contrib/llvm/lib/Support/Path.cpp index e5e875bc54d7..8fbaf2d42bf9 100644 --- a/contrib/llvm/lib/Support/Path.cpp +++ b/contrib/llvm/lib/Support/Path.cpp @@ -15,11 +15,15 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Config/config.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Endian.h" #include #include #include using namespace llvm; using namespace sys; +namespace { +using support::ulittle32_t; +} //===----------------------------------------------------------------------===// //=== WARNING: Implementation here must contain only TRULY operating system @@ -88,15 +92,21 @@ sys::IdentifyFileType(const char *magic, unsigned length) { } break; + // The two magic numbers for mach-o are: + // 0xfeedface - 32-bit mach-o + // 0xfeedfacf - 64-bit mach-o case 0xFE: - case 0xCE: { + case 0xCE: + case 0xCF: { uint16_t type = 0; if (magic[0] == char(0xFE) && magic[1] == char(0xED) && - magic[2] == char(0xFA) && magic[3] == char(0xCE)) { + magic[2] == char(0xFA) && + (magic[3] == char(0xCE) || magic[3] == char(0xCF))) { /* Native endian */ if (length >= 16) type = magic[14] << 8 | magic[15]; - } else if (magic[0] == char(0xCE) && magic[1] == char(0xFA) && - magic[2] == char(0xED) && magic[3] == char(0xFE)) { + } else if ((magic[0] == char(0xCE) || magic[0] == char(0xCF)) && + magic[1] == char(0xFA) && magic[2] == char(0xED) && + magic[3] == char(0xFE)) { /* Reverse endian */ if (length >= 14) type = magic[13] << 8 | magic[12]; } @@ -129,6 +139,16 @@ sys::IdentifyFileType(const char *magic, unsigned length) { if (magic[1] == 0x02) return COFF_FileType; break; + + case 0x4d: // Possible MS-DOS stub on Windows PE file + if (magic[1] == 0x5a) { + uint32_t off = *reinterpret_cast(magic + 0x3c); + // PE/COFF file, either EXE or DLL. + if (off < length && memcmp(magic + off, "PE\0\0",4) == 0) + return COFF_FileType; + } + break; + case 0x64: // x86-64 Windows. if (magic[1] == char(0x86)) return COFF_FileType; diff --git a/contrib/llvm/lib/Support/PrettyStackTrace.cpp b/contrib/llvm/lib/Support/PrettyStackTrace.cpp index a9f4709e4b93..082b7012eb23 100644 --- a/contrib/llvm/lib/Support/PrettyStackTrace.cpp +++ b/contrib/llvm/lib/Support/PrettyStackTrace.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines some helpful functions for dealing with the possibility of -// Unix signals occuring while your program is running. +// Unix signals occurring while your program is running. // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Support/Regex.cpp b/contrib/llvm/lib/Support/Regex.cpp index 309ffb02dec6..d293da07d684 100644 --- a/contrib/llvm/lib/Support/Regex.cpp +++ b/contrib/llvm/lib/Support/Regex.cpp @@ -82,7 +82,7 @@ bool Regex::match(StringRef String, SmallVectorImpl *Matches){ Matches->push_back(StringRef()); continue; } - assert(pm[i].rm_eo > pm[i].rm_so); + assert(pm[i].rm_eo >= pm[i].rm_so); Matches->push_back(StringRef(String.data()+pm[i].rm_so, pm[i].rm_eo-pm[i].rm_so)); } diff --git a/contrib/llvm/lib/Support/Signals.cpp b/contrib/llvm/lib/Support/Signals.cpp index a3af37d5fe6a..a11789372d93 100644 --- a/contrib/llvm/lib/Support/Signals.cpp +++ b/contrib/llvm/lib/Support/Signals.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines some helpful functions for dealing with the possibility of -// Unix signals occuring while your program is running. +// Unix signals occurring while your program is running. // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Support/SmallPtrSet.cpp b/contrib/llvm/lib/Support/SmallPtrSet.cpp index 504e6497a3cb..997ce0b74cd2 100644 --- a/contrib/llvm/lib/Support/SmallPtrSet.cpp +++ b/contrib/llvm/lib/Support/SmallPtrSet.cpp @@ -52,10 +52,14 @@ bool SmallPtrSetImpl::insert_imp(const void * Ptr) { // Otherwise, hit the big set case, which will call grow. } - // If more than 3/4 of the array is full, grow. - if (NumElements*4 >= CurArraySize*3 || - CurArraySize-(NumElements+NumTombstones) < CurArraySize/8) - Grow(); + if (NumElements*4 >= CurArraySize*3) { + // If more than 3/4 of the array is full, grow. + Grow(CurArraySize < 64 ? 128 : CurArraySize*2); + } else if (CurArraySize-(NumElements+NumTombstones) < CurArraySize/8) { + // If fewer of 1/8 of the array is empty (meaning that many are filled with + // tombstones), rehash. + Grow(CurArraySize); + } // Okay, we know we have space. Find a hash bucket. const void **Bucket = const_cast(FindBucketFor(Ptr)); @@ -125,10 +129,9 @@ const void * const *SmallPtrSetImpl::FindBucketFor(const void *Ptr) const { /// Grow - Allocate a larger backing store for the buckets and move it over. /// -void SmallPtrSetImpl::Grow() { +void SmallPtrSetImpl::Grow(unsigned NewSize) { // Allocate at twice as many buckets, but at least 128. unsigned OldSize = CurArraySize; - unsigned NewSize = OldSize < 64 ? 128 : OldSize*2; const void **OldBuckets = CurArray; bool WasSmall = isSmall(); diff --git a/contrib/llvm/lib/Support/Statistic.cpp b/contrib/llvm/lib/Support/Statistic.cpp index f0ed62690fd3..1e733d92e610 100644 --- a/contrib/llvm/lib/Support/Statistic.cpp +++ b/contrib/llvm/lib/Support/Statistic.cpp @@ -101,6 +101,10 @@ void llvm::EnableStatistics() { Enabled.setValue(true); } +bool llvm::AreStatisticsEnabled() { + return Enabled; +} + void llvm::PrintStatistics(raw_ostream &OS) { StatisticInfo &Stats = *StatInfo; diff --git a/contrib/llvm/lib/Support/StringMap.cpp b/contrib/llvm/lib/Support/StringMap.cpp index 90ec29950262..a1ac512fa244 100644 --- a/contrib/llvm/lib/Support/StringMap.cpp +++ b/contrib/llvm/lib/Support/StringMap.cpp @@ -169,6 +169,8 @@ StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { TheTable[Bucket].Item = getTombstoneVal(); --NumItems; ++NumTombstones; + assert(NumItems + NumTombstones <= NumBuckets); + return Result; } @@ -177,7 +179,19 @@ StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { /// RehashTable - Grow the table, redistributing values into the buckets with /// the appropriate mod-of-hashtable-size. void StringMapImpl::RehashTable() { - unsigned NewSize = NumBuckets*2; + unsigned NewSize; + + // If the hash table is now more than 3/4 full, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow/rehash the table. + if (NumItems*4 > NumBuckets*3) { + NewSize = NumBuckets*2; + } else if (NumBuckets-(NumItems+NumTombstones) < NumBuckets/8) { + NewSize = NumBuckets; + } else { + return; + } + // Allocate one extra bucket which will always be non-empty. This allows the // iterators to stop at end. ItemBucket *NewTableArray =(ItemBucket*)calloc(NewSize+1, sizeof(ItemBucket)); @@ -212,4 +226,5 @@ void StringMapImpl::RehashTable() { TheTable = NewTableArray; NumBuckets = NewSize; + NumTombstones = 0; } diff --git a/contrib/llvm/lib/Support/StringRef.cpp b/contrib/llvm/lib/Support/StringRef.cpp index 539805196450..8c3fc094cd11 100644 --- a/contrib/llvm/lib/Support/StringRef.cpp +++ b/contrib/llvm/lib/Support/StringRef.cpp @@ -131,7 +131,7 @@ unsigned StringRef::edit_distance(llvm::StringRef Other, /// find - Search for the first string \arg Str in the string. /// -/// \return - The index of the first occurence of \arg Str, or npos if not +/// \return - The index of the first occurrence of \arg Str, or npos if not /// found. size_t StringRef::find(StringRef Str, size_t From) const { size_t N = Str.size(); @@ -145,7 +145,7 @@ size_t StringRef::find(StringRef Str, size_t From) const { /// rfind - Search for the last string \arg Str in the string. /// -/// \return - The index of the last occurence of \arg Str, or npos if not +/// \return - The index of the last occurrence of \arg Str, or npos if not /// found. size_t StringRef::rfind(StringRef Str) const { size_t N = Str.size(); diff --git a/contrib/llvm/lib/Support/Triple.cpp b/contrib/llvm/lib/Support/Triple.cpp index 36edf6eefa70..dbdb303a4fdd 100644 --- a/contrib/llvm/lib/Support/Triple.cpp +++ b/contrib/llvm/lib/Support/Triple.cpp @@ -41,7 +41,8 @@ const char *Triple::getArchTypeName(ArchType Kind) { case x86_64: return "x86_64"; case xcore: return "xcore"; case mblaze: return "mblaze"; - case ptx: return "ptx"; + case ptx32: return "ptx32"; + case ptx64: return "ptx64"; } return ""; @@ -74,7 +75,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case xcore: return "xcore"; - case ptx: return "ptx"; + case ptx32: return "ptx"; + case ptx64: return "ptx"; } } @@ -84,6 +86,7 @@ const char *Triple::getVendorTypeName(VendorType Kind) { case Apple: return "apple"; case PC: return "pc"; + case SCEI: return "scei"; } return ""; @@ -98,8 +101,10 @@ const char *Triple::getOSTypeName(OSType Kind) { case Darwin: return "darwin"; case DragonFly: return "dragonfly"; case FreeBSD: return "freebsd"; + case IOS: return "ios"; case Linux: return "linux"; case Lv2: return "lv2"; + case MacOSX: return "macosx"; case MinGW32: return "mingw32"; case NetBSD: return "netbsd"; case OpenBSD: return "openbsd"; @@ -162,8 +167,10 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { return x86_64; if (Name == "xcore") return xcore; - if (Name == "ptx") - return ptx; + if (Name == "ptx32") + return ptx32; + if (Name == "ptx64") + return ptx64; return UnknownArch; } @@ -202,15 +209,17 @@ Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) { Str == "armv6" || Str == "armv7") return Triple::arm; - if (Str == "ptx") - return Triple::ptx; + if (Str == "ptx32") + return Triple::ptx32; + if (Str == "ptx64") + return Triple::ptx64; return Triple::UnknownArch; } // Returns architecture name that is understood by the target assembler. const char *Triple::getArchNameForAssembler() { - if (getOS() != Triple::Darwin && getVendor() != Triple::Apple) + if (!isOSDarwin() && getVendor() != Triple::Apple) return NULL; StringRef Str = getArchName(); @@ -235,8 +244,10 @@ const char *Triple::getArchNameForAssembler() { return "armv6"; if (Str == "armv7" || Str == "thumbv7") return "armv7"; - if (Str == "ptx") - return "ptx"; + if (Str == "ptx32") + return "ptx32"; + if (Str == "ptx64") + return "ptx64"; return NULL; } @@ -285,8 +296,10 @@ Triple::ArchType Triple::ParseArch(StringRef ArchName) { return tce; else if (ArchName == "xcore") return xcore; - else if (ArchName == "ptx") - return ptx; + else if (ArchName == "ptx32") + return ptx32; + else if (ArchName == "ptx64") + return ptx64; else return UnknownArch; } @@ -296,6 +309,8 @@ Triple::VendorType Triple::ParseVendor(StringRef VendorName) { return Apple; else if (VendorName == "pc") return PC; + else if (VendorName == "scei") + return SCEI; else return UnknownVendor; } @@ -311,10 +326,14 @@ Triple::OSType Triple::ParseOS(StringRef OSName) { return DragonFly; else if (OSName.startswith("freebsd")) return FreeBSD; + else if (OSName.startswith("ios")) + return IOS; else if (OSName.startswith("linux")) return Linux; else if (OSName.startswith("lv2")) return Lv2; + else if (OSName.startswith("macosx")) + return MacOSX; else if (OSName.startswith("mingw32")) return MinGW32; else if (OSName.startswith("netbsd")) @@ -523,67 +542,44 @@ StringRef Triple::getOSAndEnvironmentName() const { static unsigned EatNumber(StringRef &Str) { assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number"); - unsigned Result = Str[0]-'0'; + unsigned Result = 0; - // Eat the digit. - Str = Str.substr(1); - - // Handle "darwin11". - if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') { + do { + // Consume the leading digit. Result = Result*10 + (Str[0] - '0'); + // Eat the digit. Str = Str.substr(1); - } + } while (!Str.empty() && Str[0] >= '0' && Str[0] <= '9'); return Result; } -/// getDarwinNumber - Parse the 'darwin number' out of the specific target -/// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is -/// not defined, return 0's. This requires that the triple have an OSType of -/// darwin before it is called. -void Triple::getDarwinNumber(unsigned &Maj, unsigned &Min, - unsigned &Revision) const { - assert(getOS() == Darwin && "Not a darwin target triple!"); +void Triple::getOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const { StringRef OSName = getOSName(); - assert(OSName.startswith("darwin") && "Unknown darwin target triple!"); - // Strip off "darwin". - OSName = OSName.substr(6); + // Assume that the OS portion of the triple starts with the canonical name. + StringRef OSTypeName = getOSTypeName(getOS()); + if (OSName.startswith(OSTypeName)) + OSName = OSName.substr(OSTypeName.size()); - Maj = Min = Revision = 0; + // Any unset version defaults to 0. + Major = Minor = Micro = 0; - if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') - return; + // Parse up to three components. + unsigned *Components[3] = { &Major, &Minor, &Micro }; + for (unsigned i = 0; i != 3; ++i) { + if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') + break; - // The major version is the first digit. - Maj = EatNumber(OSName); - if (OSName.empty()) return; + // Consume the leading number. + *Components[i] = EatNumber(OSName); - // Handle minor version: 10.4.9 -> darwin8.9. - if (OSName[0] != '.') - return; - - // Eat the '.'. - OSName = OSName.substr(1); - - if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') - return; - - Min = EatNumber(OSName); - if (OSName.empty()) return; - - // Handle revision darwin8.9.1 - if (OSName[0] != '.') - return; - - // Eat the '.'. - OSName = OSName.substr(1); - - if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') - return; - - Revision = EatNumber(OSName); + // Consume the separator, if present. + if (OSName.startswith(".")) + OSName = OSName.substr(1); + } } void Triple::setTriple(const Twine &Str) { diff --git a/contrib/llvm/lib/Support/Unix/Host.inc b/contrib/llvm/lib/Support/Unix/Host.inc index ed74b6759901..8cbec8cd7ee8 100644 --- a/contrib/llvm/lib/Support/Unix/Host.inc +++ b/contrib/llvm/lib/Support/Unix/Host.inc @@ -87,10 +87,7 @@ std::string sys::getHostTriple() { std::string::size_type DarwinDashIdx = Triple.find("-darwin"); if (DarwinDashIdx != std::string::npos) { Triple.resize(DarwinDashIdx + strlen("-darwin")); - - // Only add the major part of the os version. - std::string Version = getOSVersion(); - Triple += Version.substr(0, Version.find('.')); + Triple += getOSVersion(); } return Triple; diff --git a/contrib/llvm/lib/Support/Unix/Memory.inc b/contrib/llvm/lib/Support/Unix/Memory.inc index 4312d67183c4..5a57a2870636 100644 --- a/contrib/llvm/lib/Support/Unix/Memory.inc +++ b/contrib/llvm/lib/Support/Unix/Memory.inc @@ -124,7 +124,7 @@ bool llvm::sys::Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) { (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); return KERN_SUCCESS == kr; #else - return false; + return true; #endif } diff --git a/contrib/llvm/lib/Support/Unix/Path.inc b/contrib/llvm/lib/Support/Unix/Path.inc index 0f6e800505e1..430cf2ed8e8f 100644 --- a/contrib/llvm/lib/Support/Unix/Path.inc +++ b/contrib/llvm/lib/Support/Unix/Path.inc @@ -869,18 +869,18 @@ Path::makeUnique(bool reuse_current, std::string* ErrMsg) { return false; } -const char *Path::MapInFilePages(int FD, uint64_t FileSize) { +const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) { int Flags = MAP_PRIVATE; #ifdef MAP_FILE Flags |= MAP_FILE; #endif - void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, 0); + void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, Offset); if (BasePtr == MAP_FAILED) return 0; return (const char*)BasePtr; } -void Path::UnMapFilePages(const char *BasePtr, uint64_t FileSize) { +void Path::UnMapFilePages(const char *BasePtr, size_t FileSize) { ::munmap((void*)BasePtr, FileSize); } diff --git a/contrib/llvm/lib/Support/Unix/Program.inc b/contrib/llvm/lib/Support/Unix/Program.inc index 1104bc7503e1..9f0a9ef0523f 100644 --- a/contrib/llvm/lib/Support/Unix/Program.inc +++ b/contrib/llvm/lib/Support/Unix/Program.inc @@ -132,7 +132,7 @@ static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { #ifdef HAVE_POSIX_SPAWN static bool RedirectIO_PS(const Path *Path, int FD, std::string *ErrMsg, - posix_spawn_file_actions_t &FileActions) { + posix_spawn_file_actions_t *FileActions) { if (Path == 0) // Noop return false; const char *File; @@ -142,7 +142,7 @@ static bool RedirectIO_PS(const Path *Path, int FD, std::string *ErrMsg, else File = Path->c_str(); - if (int Err = posix_spawn_file_actions_addopen(&FileActions, FD, + if (int Err = posix_spawn_file_actions_addopen(FileActions, FD, File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666)) return MakeErrMsg(ErrMsg, "Cannot dup2", Err); return false; @@ -185,10 +185,13 @@ Program::Execute(const Path &path, const char **args, const char **envp, // posix_spawn. It is more efficient than fork/exec. #ifdef HAVE_POSIX_SPAWN if (memoryLimit == 0) { - posix_spawn_file_actions_t FileActions; - posix_spawn_file_actions_init(&FileActions); + posix_spawn_file_actions_t FileActionsStore; + posix_spawn_file_actions_t *FileActions = 0; if (redirects) { + FileActions = &FileActionsStore; + posix_spawn_file_actions_init(FileActions); + // Redirect stdin/stdout. if (RedirectIO_PS(redirects[0], 0, ErrMsg, FileActions) || RedirectIO_PS(redirects[1], 1, ErrMsg, FileActions)) @@ -200,7 +203,7 @@ Program::Execute(const Path &path, const char **args, const char **envp, } else { // If stdout and stderr should go to the same place, redirect stderr // to the FD already open for stdout. - if (int Err = posix_spawn_file_actions_adddup2(&FileActions, 1, 2)) + if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2)) return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err); } } @@ -216,10 +219,11 @@ Program::Execute(const Path &path, const char **args, const char **envp, // Explicitly initialized to prevent what appears to be a valgrind false // positive. pid_t PID = 0; - int Err = posix_spawn(&PID, path.c_str(), &FileActions, /*attrp*/0, + int Err = posix_spawn(&PID, path.c_str(), FileActions, /*attrp*/0, const_cast(args), const_cast(envp)); - posix_spawn_file_actions_destroy(&FileActions); + if (FileActions) + posix_spawn_file_actions_destroy(FileActions); if (Err) return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); @@ -232,7 +236,7 @@ Program::Execute(const Path &path, const char **args, const char **envp, // Create a child process. int child = fork(); switch (child) { - // An error occured: Return to the caller. + // An error occurred: Return to the caller. case -1: MakeErrMsg(ErrMsg, "Couldn't fork"); return false; diff --git a/contrib/llvm/lib/Support/Unix/Signals.inc b/contrib/llvm/lib/Support/Unix/Signals.inc index 0a617591551d..e286869e775d 100644 --- a/contrib/llvm/lib/Support/Unix/Signals.inc +++ b/contrib/llvm/lib/Support/Unix/Signals.inc @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines some helpful functions for dealing with the possibility of -// Unix signals occuring while your program is running. +// Unix signals occurring while your program is running. // //===----------------------------------------------------------------------===// @@ -274,6 +274,9 @@ void llvm::sys::PrintStackTraceOnErrorSignal() { #ifdef __APPLE__ +#include +#include + int raise(int sig) { return pthread_kill(pthread_self(), sig); } @@ -291,9 +294,6 @@ void __assert_rtn(const char *func, abort(); } -#include -#include - void abort() { raise(SIGABRT); usleep(1000); diff --git a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc index 2c14366c0761..4227844ae506 100644 --- a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc +++ b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc @@ -41,41 +41,12 @@ using namespace sys; static std::vector OpenedHandles; -#ifdef _WIN64 - typedef DWORD64 ModuleBaseType; -#else - typedef ULONG ModuleBaseType; -#endif - extern "C" { -// Use old callback if: -// - Not using Visual Studio -// - Visual Studio 2005 or earlier but only if we are not using the Windows SDK -// or Windows SDK version is older than 6.0 -// Use new callback if: -// - Newer Visual Studio (comes with newer SDK). -// - Visual Studio 2005 with Windows SDK 6.0+ -#if defined(_MSC_VER) - #if _MSC_VER < 1500 && (!defined(VER_PRODUCTBUILD) || VER_PRODUCTBUILD < 6000) - #define OLD_ELM_CALLBACK_DECL 1 - #endif -#elif defined(__MINGW64__) - // Use new callback. -#elif defined(__MINGW32__) - #define OLD_ELM_CALLBACK_DECL 1 -#endif -#ifdef OLD_ELM_CALLBACK_DECL - static BOOL CALLBACK ELM_Callback(PSTR ModuleName, - ModuleBaseType ModuleBase, + static BOOL CALLBACK ELM_Callback(WIN32_ELMCB_PCSTR ModuleName, + ULONG_PTR ModuleBase, ULONG ModuleSize, PVOID UserContext) -#else - static BOOL CALLBACK ELM_Callback(PCSTR ModuleName, - ModuleBaseType ModuleBase, - ULONG ModuleSize, - PVOID UserContext) -#endif { // Ignore VC++ runtimes prior to 7.1. Somehow some of them get loaded // into the process. diff --git a/contrib/llvm/lib/Support/Windows/Path.inc b/contrib/llvm/lib/Support/Windows/Path.inc index 625f67aa912a..42a92f9c6dfe 100644 --- a/contrib/llvm/lib/Support/Windows/Path.inc +++ b/contrib/llvm/lib/Support/Windows/Path.inc @@ -882,7 +882,17 @@ Path::makeUnique(bool reuse_current, std::string* ErrMsg) { // Find a numeric suffix that isn't used by an existing file. Assume there // won't be more than 1 million files with the same prefix. Probably a safe // bet. - static unsigned FCounter = 0; + static int FCounter = -1; + if (FCounter < 0) { + // Give arbitrary initial seed. + // FIXME: We should use sys::fs::unique_file() in future. + LARGE_INTEGER cnt64; + DWORD x = GetCurrentProcessId(); + x = (x << 16) | (x >> 16); + if (QueryPerformanceCounter(&cnt64)) // RDTSC + x ^= cnt64.HighPart ^ cnt64.LowPart; + FCounter = x % 1000000; + } do { sprintf(FNBuffer+offset, "-%06u", FCounter); if (++FCounter > 999999) @@ -908,12 +918,12 @@ Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) { } /// MapInFilePages - Not yet implemented on win32. -const char *Path::MapInFilePages(int FD, uint64_t FileSize) { +const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) { return 0; } /// MapInFilePages - Not yet implemented on win32. -void Path::UnMapFilePages(const char *Base, uint64_t FileSize) { +void Path::UnMapFilePages(const char *Base, size_t FileSize) { assert(0 && "NOT IMPLEMENTED"); } diff --git a/contrib/llvm/lib/Support/Windows/PathV2.inc b/contrib/llvm/lib/Support/Windows/PathV2.inc index 8effb0c737dd..af71b73cd693 100644 --- a/contrib/llvm/lib/Support/Windows/PathV2.inc +++ b/contrib/llvm/lib/Support/Windows/PathV2.inc @@ -449,7 +449,14 @@ error_code status(const Twine &path, file_status &result) { SmallString<128> path_storage; SmallVector path_utf16; - if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + StringRef path8 = path.toStringRef(path_storage); + // FIXME: We should detect as many "special file name" as possible. + if (path8.compare_lower("nul") == 0) { + result = file_status(file_type::character_file); + return success; + } + + if (error_code ec = UTF8ToUTF16(path8, path_utf16)) return ec; @@ -649,7 +656,7 @@ error_code get_magic(const Twine &path, uint32_t len, ::CloseHandle(file); if (!read_success || (bytes_read != len)) { // Set result size to the number of bytes read if it's valid. - if (bytes_read >= 0 && bytes_read <= len) + if (bytes_read <= len) result.set_size(bytes_read); // ERROR_HANDLE_EOF is mapped to errc::value_too_large. return ec; diff --git a/contrib/llvm/lib/Support/raw_ostream.cpp b/contrib/llvm/lib/Support/raw_ostream.cpp index 80ea7407b44e..5a71fa3d8cea 100644 --- a/contrib/llvm/lib/Support/raw_ostream.cpp +++ b/contrib/llvm/lib/Support/raw_ostream.cpp @@ -220,6 +220,36 @@ raw_ostream &raw_ostream::operator<<(const void *P) { } raw_ostream &raw_ostream::operator<<(double N) { +#ifdef _WIN32 + // On MSVCRT and compatible, output of %e is incompatible to Posix + // by default. Number of exponent digits should be at least 2. "%+03d" + // FIXME: Implement our formatter to here or Support/Format.h! + int fpcl = _fpclass(N); + + // negative zero + if (fpcl == _FPCLASS_NZ) + return *this << "-0.000000e+00"; + + char buf[16]; + unsigned len; + len = snprintf(buf, sizeof(buf), "%e", N); + if (len <= sizeof(buf) - 2) { + if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') { + int cs = buf[len - 4]; + if (cs == '+' || cs == '-') { + int c1 = buf[len - 2]; + int c0 = buf[len - 1]; + if (isdigit(c1) && isdigit(c0)) { + // Trim leading '0': "...e+012" -> "...e+12\0" + buf[len - 3] = c1; + buf[len - 2] = c0; + buf[--len] = 0; + } + } + } + return this->operator<<(buf); + } +#endif return this->operator<<(format("%e", N)); } @@ -265,15 +295,23 @@ raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { return write(Ptr, Size); } - // Write out the data in buffer-sized blocks until the remainder - // fits within the buffer. - do { - size_t NumBytes = OutBufEnd - OutBufCur; - copy_to_buffer(Ptr, NumBytes); - flush_nonempty(); - Ptr += NumBytes; - Size -= NumBytes; - } while (OutBufCur+Size > OutBufEnd); + size_t NumBytes = OutBufEnd - OutBufCur; + + // If the buffer is empty at this point we have a string that is larger + // than the buffer. Directly write the chunk that is a multiple of the + // preferred buffer size and put the remainder in the buffer. + if (BUILTIN_EXPECT(OutBufCur == OutBufStart, false)) { + size_t BytesToWrite = Size - (Size % NumBytes); + write_impl(Ptr, BytesToWrite); + copy_to_buffer(Ptr + BytesToWrite, Size - BytesToWrite); + return *this; + } + + // We don't have enough space in the buffer to fit the string in. Insert as + // much as possible, flush and start over with the remainder. + copy_to_buffer(Ptr, NumBytes); + flush_nonempty(); + return write(Ptr + NumBytes, Size - NumBytes); } copy_to_buffer(Ptr, Size); @@ -458,6 +496,14 @@ raw_fd_ostream::~raw_fd_ostream() { } } +#ifdef __MINGW32__ + // On mingw, global dtors should not call exit(). + // report_fatal_error() invokes exit(). We know report_fatal_error() + // might not write messages to stderr when any errors were detected + // on FD == 2. + if (FD == 2) return; +#endif + // If there are any pending errors, report them now. Clients wishing // to avoid report_fatal_error calls should check for errors with // has_error() and clear the error flag with clear_error() before diff --git a/contrib/llvm/lib/Support/regcomp.c b/contrib/llvm/lib/Support/regcomp.c index cd018d5dc5bc..46c91a9c497c 100644 --- a/contrib/llvm/lib/Support/regcomp.c +++ b/contrib/llvm/lib/Support/regcomp.c @@ -780,7 +780,7 @@ p_b_cclass(struct parse *p, cset *cs) const char *u; char c; - while (MORE() && isalpha(PEEK())) + while (MORE() && isalpha((uch)PEEK())) NEXT(); len = p->next - sp; for (cp = cclasses; cp->name != NULL; cp++) diff --git a/contrib/llvm/lib/Target/ARM/ARM.td b/contrib/llvm/lib/Target/ARM/ARM.td index bf4315fc6c3e..6af5f85e8a85 100644 --- a/contrib/llvm/lib/Target/ARM/ARM.td +++ b/contrib/llvm/lib/Target/ARM/ARM.td @@ -51,6 +51,12 @@ def FeatureVFPOnlySP : SubtargetFeature<"fp-only-sp", "FPOnlySP", "true", // to just not use them. def FeatureHasSlowFPVMLx : SubtargetFeature<"slowfpvmlx", "SlowFPVMLx", "true", "Disable VFP / NEON MAC instructions">; + +// Cortex-A8 / A9 Advanced SIMD has multiplier accumulator forwarding. +def FeatureVMLxForwarding : SubtargetFeature<"vmlx-forwarding", + "HasVMLxForwarding", "true", + "Has multiplier accumulator forwarding">; + // Some processors benefit from using NEON instructions for scalar // single-precision FP operations. def FeatureNEONForFP : SubtargetFeature<"neonfp", "UseNEONForSinglePrecisionFP", @@ -61,6 +67,14 @@ def FeatureNEONForFP : SubtargetFeature<"neonfp", "UseNEONForSinglePrecisionFP", def FeaturePref32BitThumb : SubtargetFeature<"32bit", "Pref32BitThumb", "true", "Prefer 32-bit Thumb instrs">; +/// Some instructions update CPSR partially, which can add false dependency for +/// out-of-order implementation, e.g. Cortex-A9, unless each individual bit is +/// mapped to a separate physical register. Avoid partial CPSR update for these +/// processors. +def FeatureAvoidPartialCPSR : SubtargetFeature<"avoid-partial-cpsr", + "AvoidCPSRPartialUpdate", "true", + "Avoid CPSR partial update for OOO execution">; + // Multiprocessing extension. def FeatureMP : SubtargetFeature<"mp", "HasMPExtension", "true", "Supports Multiprocessing extension">; @@ -100,11 +114,13 @@ def ProcOthers : SubtargetFeature<"others", "ARMProcFamily", "Others", def ProcA8 : SubtargetFeature<"a8", "ARMProcFamily", "CortexA8", "Cortex-A8 ARM processors", [FeatureSlowFPBrcc, FeatureNEONForFP, - FeatureHasSlowFPVMLx, FeatureT2XtPk]>; + FeatureHasSlowFPVMLx, FeatureVMLxForwarding, + FeatureT2XtPk]>; def ProcA9 : SubtargetFeature<"a9", "ARMProcFamily", "CortexA9", "Cortex-A9 ARM processors", - [FeatureHasSlowFPVMLx, FeatureT2XtPk, - FeatureFP16]>; + [FeatureVMLxForwarding, + FeatureT2XtPk, FeatureFP16, + FeatureAvoidPartialCPSR]>; class ProcNoItin Features> : Processor; @@ -171,6 +187,8 @@ def : Processor<"cortex-a8", CortexA8Itineraries, [ArchV7A, ProcA8]>; def : Processor<"cortex-a9", CortexA9Itineraries, [ArchV7A, ProcA9]>; +def : Processor<"cortex-a9-mp", CortexA9Itineraries, + [ArchV7A, ProcA9, FeatureMP]>; // V7M Processors. def : ProcNoItin<"cortex-m3", [ArchV7M]>; diff --git a/contrib/llvm/lib/Target/ARM/ARMAddressingModes.h b/contrib/llvm/lib/Target/ARM/ARMAddressingModes.h index 19fbf0548b02..595708fa7881 100644 --- a/contrib/llvm/lib/Target/ARM/ARMAddressingModes.h +++ b/contrib/llvm/lib/Target/ARM/ARMAddressingModes.h @@ -408,16 +408,18 @@ namespace ARM_AM { // // The first operand is always a Reg. The second operand is a reg if in // reg/reg form, otherwise it's reg#0. The third field encodes the operation - // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. + // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The + // fourth operand 16-17 encodes the index mode. // // If this addressing mode is a frame index (before prolog/epilog insertion // and code rewriting), this operand will have the form: FI#, reg0, // with no shift amount for the frame offset. // - static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO) { + static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, + unsigned IdxMode = 0) { assert(Imm12 < (1 << 12) && "Imm too large!"); bool isSub = Opc == sub; - return Imm12 | ((int)isSub << 12) | (SO << 13); + return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ; } static inline unsigned getAM2Offset(unsigned AM2Opc) { return AM2Opc & ((1 << 12)-1); @@ -426,7 +428,10 @@ namespace ARM_AM { return ((AM2Opc >> 12) & 1) ? sub : add; } static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) { - return (ShiftOpc)(AM2Opc >> 13); + return (ShiftOpc)((AM2Opc >> 13) & 7); + } + static inline unsigned getAM2IdxMode(unsigned AM2Opc) { + return (AM2Opc >> 16); } @@ -441,12 +446,14 @@ namespace ARM_AM { // // The first operand is always a Reg. The second operand is a reg if in // reg/reg form, otherwise it's reg#0. The third field encodes the operation - // in bit 8, the immediate in bits 0-7. + // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the + // index mode. /// getAM3Opc - This function encodes the addrmode3 opc field. - static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset) { + static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, + unsigned IdxMode = 0) { bool isSub = Opc == sub; - return ((int)isSub << 8) | Offset; + return ((int)isSub << 8) | Offset | (IdxMode << 9); } static inline unsigned char getAM3Offset(unsigned AM3Opc) { return AM3Opc & 0xFF; @@ -454,6 +461,9 @@ namespace ARM_AM { static inline AddrOpc getAM3Op(unsigned AM3Opc) { return ((AM3Opc >> 8) & 1) ? sub : add; } + static inline unsigned getAM3IdxMode(unsigned AM3Opc) { + return (AM3Opc >> 9); + } //===--------------------------------------------------------------------===// // Addressing Mode #4 diff --git a/contrib/llvm/lib/Target/ARM/ARMAsmBackend.cpp b/contrib/llvm/lib/Target/ARM/ARMAsmBackend.cpp index ec23449d7d42..f0628192308f 100644 --- a/contrib/llvm/lib/Target/ARM/ARMAsmBackend.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMAsmBackend.cpp @@ -246,7 +246,7 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { } uint32_t out = (opc << 21); - out |= (Value & 0x800) << 14; + out |= (Value & 0x800) << 15; out |= (Value & 0x700) << 4; out |= (Value & 0x0FF); @@ -416,21 +416,22 @@ void ELFARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, // FIXME: This should be in a separate file. class DarwinARMAsmBackend : public ARMAsmBackend { public: - DarwinARMAsmBackend(const Target &T) : ARMAsmBackend(T) { } - - void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const; + const object::mach::CPUSubtypeARM Subtype; + DarwinARMAsmBackend(const Target &T, object::mach::CPUSubtypeARM st) + : ARMAsmBackend(T), Subtype(st) { } MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - // FIXME: Subtarget info should be derived. Force v7 for now. return createMachObjectWriter(new ARMMachObjectWriter( /*Is64Bit=*/false, object::mach::CTM_ARM, - object::mach::CSARM_V7), + Subtype), OS, /*IsLittleEndian=*/true); } + void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value) const; + virtual bool doesSectionRequireSymbols(const MCSection &Section) const { return false; } @@ -499,14 +500,17 @@ void DarwinARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, TargetAsmBackend *llvm::createARMAsmBackend(const Target &T, const std::string &TT) { - switch (Triple(TT).getOS()) { - case Triple::Darwin: - return new DarwinARMAsmBackend(T); - case Triple::MinGW32: - case Triple::Cygwin: - case Triple::Win32: - assert(0 && "Windows not supported on ARM"); - default: - return new ELFARMAsmBackend(T, Triple(TT).getOS()); + Triple TheTriple(TT); + + if (TheTriple.isOSDarwin()) { + if (TheTriple.getArchName() == "armv6" || + TheTriple.getArchName() == "thumbv6") + return new DarwinARMAsmBackend(T, object::mach::CSARM_V6); + return new DarwinARMAsmBackend(T, object::mach::CSARM_V7); } + + if (TheTriple.isOSWindows()) + assert(0 && "Windows not supported on ARM"); + + return new ELFARMAsmBackend(T, Triple(TT).getOS()); } diff --git a/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index db12b8e4fc2d..c428e1852a46 100644 --- a/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -88,6 +88,11 @@ namespace { case ARMBuildAttrs::CPU_name: Streamer.EmitRawText(StringRef("\t.cpu ") + LowercaseString(String)); break; + /* GAS requires .fpu to be emitted regardless of EABI attribute */ + case ARMBuildAttrs::Advanced_SIMD_arch: + case ARMBuildAttrs::VFP_arch: + Streamer.EmitRawText(StringRef("\t.fpu ") + LowercaseString(String)); + break; default: assert(0 && "Unsupported Text attribute in ASM Mode"); break; } } @@ -167,6 +172,117 @@ getDebugValueLocation(const MachineInstr *MI) const { return Location; } +/// getDwarfRegOpSize - get size required to emit given machine location using +/// dwarf encoding. +unsigned ARMAsmPrinter::getDwarfRegOpSize(const MachineLocation &MLoc) const { + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + if (RI->getDwarfRegNum(MLoc.getReg(), false) != -1) + return AsmPrinter::getDwarfRegOpSize(MLoc); + else { + unsigned Reg = MLoc.getReg(); + if (Reg >= ARM::S0 && Reg <= ARM::S31) { + assert(ARM::S0 + 31 == ARM::S31 && "Unexpected ARM S register numbering"); + // S registers are described as bit-pieces of a register + // S[2x] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 0) + // S[2x+1] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 32) + + unsigned SReg = Reg - ARM::S0; + unsigned Rx = 256 + (SReg >> 1); + OutStreamer.AddComment("Loc expr size"); + // DW_OP_regx + ULEB + DW_OP_bit_piece + ULEB + ULEB + // 1 + ULEB(Rx) + 1 + 1 + 1 + return 4 + MCAsmInfo::getULEB128Size(Rx); + } + + if (Reg >= ARM::Q0 && Reg <= ARM::Q15) { + assert(ARM::Q0 + 15 == ARM::Q15 && "Unexpected ARM Q register numbering"); + // Q registers Q0-Q15 are described by composing two D registers together. + // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1) DW_OP_piece(8) + + unsigned QReg = Reg - ARM::Q0; + unsigned D1 = 256 + 2 * QReg; + unsigned D2 = D1 + 1; + + OutStreamer.AddComment("Loc expr size"); + // DW_OP_regx + ULEB + DW_OP_piece + ULEB(8) + + // DW_OP_regx + ULEB + DW_OP_piece + ULEB(8); + // 6 + ULEB(D1) + ULEB(D2) + return 6 + MCAsmInfo::getULEB128Size(D1) + MCAsmInfo::getULEB128Size(D2); + } + } + return 0; +} + +/// EmitDwarfRegOp - Emit dwarf register operation. +void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const { + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + if (RI->getDwarfRegNum(MLoc.getReg(), false) != -1) + AsmPrinter::EmitDwarfRegOp(MLoc); + else { + unsigned Reg = MLoc.getReg(); + if (Reg >= ARM::S0 && Reg <= ARM::S31) { + assert(ARM::S0 + 31 == ARM::S31 && "Unexpected ARM S register numbering"); + // S registers are described as bit-pieces of a register + // S[2x] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 0) + // S[2x+1] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 32) + + unsigned SReg = Reg - ARM::S0; + bool odd = SReg & 0x1; + unsigned Rx = 256 + (SReg >> 1); + OutStreamer.AddComment("Loc expr size"); + // DW_OP_regx + ULEB + DW_OP_bit_piece + ULEB + ULEB + // 1 + ULEB(Rx) + 1 + 1 + 1 + EmitInt16(4 + MCAsmInfo::getULEB128Size(Rx)); + + OutStreamer.AddComment("DW_OP_regx for S register"); + EmitInt8(dwarf::DW_OP_regx); + + OutStreamer.AddComment(Twine(SReg)); + EmitULEB128(Rx); + + if (odd) { + OutStreamer.AddComment("DW_OP_bit_piece 32 32"); + EmitInt8(dwarf::DW_OP_bit_piece); + EmitULEB128(32); + EmitULEB128(32); + } else { + OutStreamer.AddComment("DW_OP_bit_piece 32 0"); + EmitInt8(dwarf::DW_OP_bit_piece); + EmitULEB128(32); + EmitULEB128(0); + } + } else if (Reg >= ARM::Q0 && Reg <= ARM::Q15) { + assert(ARM::Q0 + 15 == ARM::Q15 && "Unexpected ARM Q register numbering"); + // Q registers Q0-Q15 are described by composing two D registers together. + // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1) DW_OP_piece(8) + + unsigned QReg = Reg - ARM::Q0; + unsigned D1 = 256 + 2 * QReg; + unsigned D2 = D1 + 1; + + OutStreamer.AddComment("Loc expr size"); + // DW_OP_regx + ULEB + DW_OP_piece + ULEB(8) + + // DW_OP_regx + ULEB + DW_OP_piece + ULEB(8); + // 6 + ULEB(D1) + ULEB(D2) + EmitInt16(6 + MCAsmInfo::getULEB128Size(D1) + MCAsmInfo::getULEB128Size(D2)); + + OutStreamer.AddComment("DW_OP_regx for Q register: D1"); + EmitInt8(dwarf::DW_OP_regx); + EmitULEB128(D1); + OutStreamer.AddComment("DW_OP_piece 8"); + EmitInt8(dwarf::DW_OP_piece); + EmitULEB128(8); + + OutStreamer.AddComment("DW_OP_regx for Q register: D2"); + EmitInt8(dwarf::DW_OP_regx); + EmitULEB128(D2); + OutStreamer.AddComment("DW_OP_piece 8"); + EmitInt8(dwarf::DW_OP_piece); + EmitULEB128(8); + } + } +} + void ARMAsmPrinter::EmitFunctionEntryLabel() { if (AFI->isThumbFunction()) { OutStreamer.EmitAssemblerFlag(MCAF_Code16); @@ -453,10 +569,13 @@ void ARMAsmPrinter::emitAttributes() { emitARMAttributeSection(); + /* GAS expect .fpu to be emitted, regardless of VFP build attribute */ + bool emitFPU = false; AttributeEmitter *AttrEmitter; - if (OutStreamer.hasRawTextSupport()) + if (OutStreamer.hasRawTextSupport()) { AttrEmitter = new AsmAttributeEmitter(OutStreamer); - else { + emitFPU = true; + } else { MCObjectStreamer &O = static_cast(OutStreamer); AttrEmitter = new ObjectAttributeEmitter(O); } @@ -490,10 +609,36 @@ void ARMAsmPrinter::emitAttributes() { ARMBuildAttrs::Allowed); } - // FIXME: Emit FPU type - if (Subtarget->hasVFP2()) + if (Subtarget->hasNEON() && emitFPU) { + /* NEON is not exactly a VFP architecture, but GAS emit one of + * neon/vfpv3/vfpv2 for .fpu parameters */ + AttrEmitter->EmitTextAttribute(ARMBuildAttrs::Advanced_SIMD_arch, "neon"); + /* If emitted for NEON, omit from VFP below, since you can have both + * NEON and VFP in build attributes but only one .fpu */ + emitFPU = false; + } + + /* VFPv3 + .fpu */ + if (Subtarget->hasVFP3()) { + AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, + ARMBuildAttrs::AllowFPv3A); + if (emitFPU) + AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv3"); + + /* VFPv2 + .fpu */ + } else if (Subtarget->hasVFP2()) { AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, ARMBuildAttrs::AllowFPv2); + if (emitFPU) + AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv2"); + } + + /* TODO: ARMBuildAttrs::Allowed is not completely accurate, + * since NEON can have 1 (allowed) or 2 (fused MAC operations) */ + if (Subtarget->hasNEON()) { + AttrEmitter->EmitAttribute(ARMBuildAttrs::Advanced_SIMD_arch, + ARMBuildAttrs::Allowed); + } // Signal various FP modes. if (!UnsafeFPMath) { @@ -777,10 +922,161 @@ void ARMAsmPrinter::EmitPatchedInstruction(const MachineInstr *MI, OutStreamer.EmitInstruction(TmpInst); } +void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { + assert(MI->getFlag(MachineInstr::FrameSetup) && + "Only instruction which are involved into frame setup code are allowed"); + + const MachineFunction &MF = *MI->getParent()->getParent(); + const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); + const ARMFunctionInfo &AFI = *MF.getInfo(); + + unsigned FramePtr = RegInfo->getFrameRegister(MF); + unsigned Opc = MI->getOpcode(); + unsigned SrcReg, DstReg; + + if (Opc == ARM::tPUSH || Opc == ARM::tLDRpci) { + // Two special cases: + // 1) tPUSH does not have src/dst regs. + // 2) for Thumb1 code we sometimes materialize the constant via constpool + // load. Yes, this is pretty fragile, but for now I don't see better + // way... :( + SrcReg = DstReg = ARM::SP; + } else { + SrcReg = MI->getOperand(1).getReg(); + DstReg = MI->getOperand(0).getReg(); + } + + // Try to figure out the unwinding opcode out of src / dst regs. + if (MI->getDesc().mayStore()) { + // Register saves. + assert(DstReg == ARM::SP && + "Only stack pointer as a destination reg is supported"); + + SmallVector RegList; + // Skip src & dst reg, and pred ops. + unsigned StartOp = 2 + 2; + // Use all the operands. + unsigned NumOffset = 0; + + switch (Opc) { + default: + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + case ARM::tPUSH: + // Special case here: no src & dst reg, but two extra imp ops. + StartOp = 2; NumOffset = 2; + case ARM::STMDB_UPD: + case ARM::t2STMDB_UPD: + case ARM::VSTMDDB_UPD: + assert(SrcReg == ARM::SP && + "Only stack pointer as a source reg is supported"); + for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset; + i != NumOps; ++i) + RegList.push_back(MI->getOperand(i).getReg()); + break; + case ARM::STR_PRE: + assert(MI->getOperand(2).getReg() == ARM::SP && + "Only stack pointer as a source reg is supported"); + RegList.push_back(SrcReg); + break; + } + OutStreamer.EmitRegSave(RegList, Opc == ARM::VSTMDDB_UPD); + } else { + // Changes of stack / frame pointer. + if (SrcReg == ARM::SP) { + int64_t Offset = 0; + switch (Opc) { + default: + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + case ARM::MOVr: + case ARM::tMOVgpr2gpr: + case ARM::tMOVgpr2tgpr: + Offset = 0; + break; + case ARM::ADDri: + Offset = -MI->getOperand(2).getImm(); + break; + case ARM::SUBri: + case ARM::t2SUBrSPi: + Offset = MI->getOperand(2).getImm(); + break; + case ARM::tSUBspi: + Offset = MI->getOperand(2).getImm()*4; + break; + case ARM::tADDspi: + case ARM::tADDrSPi: + Offset = -MI->getOperand(2).getImm()*4; + break; + case ARM::tLDRpci: { + // Grab the constpool index and check, whether it corresponds to + // original or cloned constpool entry. + unsigned CPI = MI->getOperand(1).getIndex(); + const MachineConstantPool *MCP = MF.getConstantPool(); + if (CPI >= MCP->getConstants().size()) + CPI = AFI.getOriginalCPIdx(CPI); + assert(CPI != -1U && "Invalid constpool index"); + + // Derive the actual offset. + const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI]; + assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry"); + // FIXME: Check for user, it should be "add" instruction! + Offset = -cast(CPE.Val.ConstVal)->getSExtValue(); + break; + } + } + + if (DstReg == FramePtr && FramePtr != ARM::SP) + // Set-up of the frame pointer. Positive values correspond to "add" + // instruction. + OutStreamer.EmitSetFP(FramePtr, ARM::SP, -Offset); + else if (DstReg == ARM::SP) { + // Change of SP by an offset. Positive values correspond to "sub" + // instruction. + OutStreamer.EmitPad(Offset); + } else { + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + } + } else if (DstReg == ARM::SP) { + // FIXME: .movsp goes here + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + } + else { + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + } + } +} + +extern cl::opt EnableARMEHABI; + void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { unsigned Opc = MI->getOpcode(); switch (Opc) { default: break; + case ARM::B: { + // B is just a Bcc with an 'always' predicate. + MCInst TmpInst; + LowerARMMachineInstrToMCInst(MI, TmpInst, *this); + TmpInst.setOpcode(ARM::Bcc); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + return; + } + case ARM::LDMIA_RET: { + // LDMIA_RET is just a normal LDMIA_UPD instruction that targets PC and as + // such has additional code-gen properties and scheduling information. + // To emit it, we just construct as normal and set the opcode to LDMIA_UPD. + MCInst TmpInst; + LowerARMMachineInstrToMCInst(MI, TmpInst, *this); + TmpInst.setOpcode(ARM::LDMIA_UPD); + OutStreamer.EmitInstruction(TmpInst); + return; + } case ARM::t2ADDrSPi: case ARM::t2ADDrSPi12: case ARM::t2SUBrSPi: @@ -850,6 +1146,26 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitInstruction(TmpInst); return; } + // Darwin call instructions are just normal call instructions with different + // clobber semantics (they clobber R9). + case ARM::BLr9: + case ARM::BLr9_pred: + case ARM::BLXr9: + case ARM::BLXr9_pred: { + unsigned newOpc; + switch (Opc) { + default: assert(0); + case ARM::BLr9: newOpc = ARM::BL; break; + case ARM::BLr9_pred: newOpc = ARM::BL_pred; break; + case ARM::BLXr9: newOpc = ARM::BLX; break; + case ARM::BLXr9_pred: newOpc = ARM::BLX_pred; break; + } + MCInst TmpInst; + LowerARMMachineInstrToMCInst(MI, TmpInst, *this); + TmpInst.setOpcode(newOpc); + OutStreamer.EmitInstruction(TmpInst); + return; + } case ARM::BXr9_CALL: case ARM::BX_CALL: { { @@ -1502,6 +1818,49 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } return; } + // Tail jump branches are really just branch instructions with additional + // code-gen attributes. Convert them to the canonical form here. + case ARM::TAILJMPd: + case ARM::TAILJMPdND: { + MCInst TmpInst, TmpInst2; + // Lower the instruction as-is to get the operands properly converted. + LowerARMMachineInstrToMCInst(MI, TmpInst2, *this); + TmpInst.setOpcode(ARM::Bcc); + TmpInst.addOperand(TmpInst2.getOperand(0)); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.AddComment("TAILCALL"); + OutStreamer.EmitInstruction(TmpInst); + return; + } + case ARM::tTAILJMPd: + case ARM::tTAILJMPdND: { + MCInst TmpInst, TmpInst2; + LowerARMMachineInstrToMCInst(MI, TmpInst2, *this); + TmpInst.setOpcode(ARM::tB); + TmpInst.addOperand(TmpInst2.getOperand(0)); + OutStreamer.AddComment("TAILCALL"); + OutStreamer.EmitInstruction(TmpInst); + return; + } + case ARM::TAILJMPrND: + case ARM::tTAILJMPrND: + case ARM::TAILJMPr: + case ARM::tTAILJMPr: { + unsigned newOpc = (Opc == ARM::TAILJMPr || Opc == ARM::TAILJMPrND) + ? ARM::BX : ARM::tBX; + MCInst TmpInst; + TmpInst.setOpcode(newOpc); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.AddComment("TAILCALL"); + OutStreamer.EmitInstruction(TmpInst); + return; + } + // These are the pseudos created to comply with stricter operand restrictions // on ARMv5. Lower them now to "normal" instructions, since all the // restrictions are already satisfied. @@ -1530,6 +1889,11 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCInst TmpInst; LowerARMMachineInstrToMCInst(MI, TmpInst, *this); + + // Emit unwinding stuff for frame-related instructions + if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup)) + EmitUnwindingInstruction(MI); + OutStreamer.EmitInstruction(TmpInst); } @@ -1538,10 +1902,11 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { //===----------------------------------------------------------------------===// static MCInstPrinter *createARMMCInstPrinter(const Target &T, + TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new ARMInstPrinter(MAI); + return new ARMInstPrinter(TM, MAI); return 0; } diff --git a/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.h b/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.h index 585268442ce4..1ee1b7024d15 100644 --- a/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.h +++ b/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.h @@ -82,11 +82,20 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { // Generic helper used to emit e.g. ARMv5 mul pseudos void EmitPatchedInstruction(const MachineInstr *MI, unsigned TargetOpc); + void EmitUnwindingInstruction(const MachineInstr *MI); + public: void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); MachineLocation getDebugValueLocation(const MachineInstr *MI) const; + /// getDwarfRegOpSize - get size required to emit given machine location + /// using dwarf encoding. + virtual unsigned getDwarfRegOpSize(const MachineLocation &MLoc) const; + + /// EmitDwarfRegOp - Emit dwarf register operation. + virtual void EmitDwarfRegOp(const MachineLocation &MLoc) const; + virtual unsigned getISAEncoding() { // ARM/Darwin adds ISA to the DWARF info for each function. if (!Subtarget->isTargetDarwin()) diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseInfo.h b/contrib/llvm/lib/Target/ARM/ARMBaseInfo.h index a56cc1a9f249..36edbad7a601 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseInfo.h +++ b/contrib/llvm/lib/Target/ARM/ARMBaseInfo.h @@ -200,6 +200,59 @@ inline static unsigned getARMRegisterNumbering(unsigned Reg) { } namespace ARMII { + + /// ARM Index Modes + enum IndexMode { + IndexModeNone = 0, + IndexModePre = 1, + IndexModePost = 2, + IndexModeUpd = 3 + }; + + /// ARM Addressing Modes + enum AddrMode { + AddrModeNone = 0, + AddrMode1 = 1, + AddrMode2 = 2, + AddrMode3 = 3, + AddrMode4 = 4, + AddrMode5 = 5, + AddrMode6 = 6, + AddrModeT1_1 = 7, + AddrModeT1_2 = 8, + AddrModeT1_4 = 9, + AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data + AddrModeT2_i12 = 11, + AddrModeT2_i8 = 12, + AddrModeT2_so = 13, + AddrModeT2_pc = 14, // +/- i12 for pc relative data + AddrModeT2_i8s4 = 15, // i8 * 4 + AddrMode_i12 = 16 + }; + + inline static const char *AddrModeToString(AddrMode addrmode) { + switch (addrmode) { + default: llvm_unreachable("Unknown memory operation"); + case AddrModeNone: return "AddrModeNone"; + case AddrMode1: return "AddrMode1"; + case AddrMode2: return "AddrMode2"; + case AddrMode3: return "AddrMode3"; + case AddrMode4: return "AddrMode4"; + case AddrMode5: return "AddrMode5"; + case AddrMode6: return "AddrMode6"; + case AddrModeT1_1: return "AddrModeT1_1"; + case AddrModeT1_2: return "AddrModeT1_2"; + case AddrModeT1_4: return "AddrModeT1_4"; + case AddrModeT1_s: return "AddrModeT1_s"; + case AddrModeT2_i12: return "AddrModeT2_i12"; + case AddrModeT2_i8: return "AddrModeT2_i8"; + case AddrModeT2_so: return "AddrModeT2_so"; + case AddrModeT2_pc: return "AddrModeT2_pc"; + case AddrModeT2_i8s4: return "AddrModeT2_i8s4"; + case AddrMode_i12: return "AddrMode_i12"; + } + } + /// Target Operand Flag enum. enum TOF { //===------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index 2268e59ea7b1..44a397611526 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1021,7 +1021,7 @@ reMaterialize(MachineBasicBlock &MBB, MachineInstrBuilder MIB = BuildMI(MBB, I, Orig->getDebugLoc(), get(Opcode), DestReg) .addConstantPoolIndex(CPI).addImm(PCLabelId); - (*MIB).setMemRefs(Orig->memoperands_begin(), Orig->memoperands_end()); + MIB->setMemRefs(Orig->memoperands_begin(), Orig->memoperands_end()); break; } } @@ -1080,11 +1080,18 @@ bool ARMBaseInstrInfo::produceSameValue(const MachineInstr *MI0, int CPI1 = MO1.getIndex(); const MachineConstantPoolEntry &MCPE0 = MCP->getConstants()[CPI0]; const MachineConstantPoolEntry &MCPE1 = MCP->getConstants()[CPI1]; - ARMConstantPoolValue *ACPV0 = - static_cast(MCPE0.Val.MachineCPVal); - ARMConstantPoolValue *ACPV1 = - static_cast(MCPE1.Val.MachineCPVal); - return ACPV0->hasSameValue(ACPV1); + bool isARMCP0 = MCPE0.isMachineConstantPoolEntry(); + bool isARMCP1 = MCPE1.isMachineConstantPoolEntry(); + if (isARMCP0 && isARMCP1) { + ARMConstantPoolValue *ACPV0 = + static_cast(MCPE0.Val.MachineCPVal); + ARMConstantPoolValue *ACPV1 = + static_cast(MCPE1.Val.MachineCPVal); + return ACPV0->hasSameValue(ACPV1); + } else if (!isARMCP0 && !isARMCP1) { + return MCPE0.Val.ConstVal == MCPE1.Val.ConstVal; + } + return false; } else if (Opcode == ARM::PICLDR) { if (MI1->getOpcode() != Opcode) return false; @@ -1194,7 +1201,7 @@ bool ARMBaseInstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, } /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to -/// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should +/// determine (in conjunction with areLoadsFromSameBasePtr) if two loads should /// be scheduled togther. On some targets if two loads are loading from /// addresses in the same cache line, it's better if they are scheduled /// together. This function takes two integers that represent the load offsets @@ -1263,19 +1270,19 @@ bool ARMBaseInstrInfo::isSchedulingBoundary(const MachineInstr *MI, } bool ARMBaseInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, - unsigned NumCyles, + unsigned NumCycles, unsigned ExtraPredCycles, float Probability, float Confidence) const { - if (!NumCyles) + if (!NumCycles) return false; // Attempt to estimate the relative costs of predication versus branching. - float UnpredCost = Probability * NumCyles; + float UnpredCost = Probability * NumCycles; UnpredCost += 1.0; // The branch itself UnpredCost += (1.0 - Confidence) * Subtarget.getMispredictionPenalty(); - return (float)(NumCyles + ExtraPredCycles) < UnpredCost; + return (float)(NumCycles + ExtraPredCycles) < UnpredCost; } bool ARMBaseInstrInfo:: @@ -1328,7 +1335,7 @@ void llvm::emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, ARMCC::CondCodes Pred, unsigned PredReg, - const ARMBaseInstrInfo &TII) { + const ARMBaseInstrInfo &TII, unsigned MIFlags) { bool isSub = NumBytes < 0; if (isSub) NumBytes = -NumBytes; @@ -1346,7 +1353,8 @@ void llvm::emitARMRegPlusImmediate(MachineBasicBlock &MBB, unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri; BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) .addReg(BaseReg, RegState::Kill).addImm(ThisVal) - .addImm((unsigned)Pred).addReg(PredReg).addReg(0); + .addImm((unsigned)Pred).addReg(PredReg).addReg(0) + .setMIFlags(MIFlags); BaseReg = DestReg; } } @@ -1610,18 +1618,84 @@ OptimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, int CmpMask, // Set the "zero" bit in CPSR. switch (MI->getOpcode()) { default: break; + case ARM::RSBrr: + case ARM::RSBri: + case ARM::RSCrr: + case ARM::RSCri: + case ARM::ADDrr: case ARM::ADDri: - case ARM::ANDri: - case ARM::t2ANDri: + case ARM::ADCrr: + case ARM::ADCri: + case ARM::SUBrr: case ARM::SUBri: + case ARM::SBCrr: + case ARM::SBCri: + case ARM::t2RSBri: + case ARM::t2ADDrr: case ARM::t2ADDri: + case ARM::t2ADCrr: + case ARM::t2ADCri: + case ARM::t2SUBrr: case ARM::t2SUBri: + case ARM::t2SBCrr: + case ARM::t2SBCri: + case ARM::ANDrr: + case ARM::ANDri: + case ARM::t2ANDrr: + case ARM::t2ANDri: + case ARM::ORRrr: + case ARM::ORRri: + case ARM::t2ORRrr: + case ARM::t2ORRri: + case ARM::EORrr: + case ARM::EORri: + case ARM::t2EORrr: + case ARM::t2EORri: { + // Scan forward for the use of CPSR, if it's a conditional code requires + // checking of V bit, then this is not safe to do. If we can't find the + // CPSR use (i.e. used in another block), then it's not safe to perform + // the optimization. + bool isSafe = false; + I = CmpInstr; + E = MI->getParent()->end(); + while (!isSafe && ++I != E) { + const MachineInstr &Instr = *I; + for (unsigned IO = 0, EO = Instr.getNumOperands(); + !isSafe && IO != EO; ++IO) { + const MachineOperand &MO = Instr.getOperand(IO); + if (!MO.isReg() || MO.getReg() != ARM::CPSR) + continue; + if (MO.isDef()) { + isSafe = true; + break; + } + // Condition code is after the operand before CPSR. + ARMCC::CondCodes CC = (ARMCC::CondCodes)Instr.getOperand(IO-1).getImm(); + switch (CC) { + default: + isSafe = true; + break; + case ARMCC::VS: + case ARMCC::VC: + case ARMCC::GE: + case ARMCC::LT: + case ARMCC::GT: + case ARMCC::LE: + return false; + } + } + } + + if (!isSafe) + return false; + // Toggle the optional operand to CPSR. MI->getOperand(5).setReg(ARM::CPSR); MI->getOperand(5).setIsDef(true); CmpInstr->eraseFromParent(); return true; } + } return false; } @@ -1741,9 +1815,7 @@ ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, llvm_unreachable("Unexpected multi-uops instruction!"); break; case ARM::VLDMQIA: - case ARM::VLDMQDB: case ARM::VSTMQIA: - case ARM::VSTMQDB: return 2; // The number of uOps for load / store multiple are determined by the number @@ -1757,19 +1829,15 @@ ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, // is not 64-bit aligned, then AGU would take an extra cycle. For VFP / NEON // load / store multiple, the formula is (#reg / 2) + (#reg % 2) + 1. case ARM::VLDMDIA: - case ARM::VLDMDDB: case ARM::VLDMDIA_UPD: case ARM::VLDMDDB_UPD: case ARM::VLDMSIA: - case ARM::VLDMSDB: case ARM::VLDMSIA_UPD: case ARM::VLDMSDB_UPD: case ARM::VSTMDIA: - case ARM::VSTMDDB: case ARM::VSTMDIA_UPD: case ARM::VSTMDDB_UPD: case ARM::VSTMSIA: - case ARM::VSTMSDB: case ARM::VSTMSIA_UPD: case ARM::VSTMSDB_UPD: { unsigned NumRegs = MI->getNumOperands() - Desc.getNumOperands(); @@ -1859,7 +1927,6 @@ ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, switch (DefTID.getOpcode()) { default: break; case ARM::VLDMSIA: - case ARM::VLDMSDB: case ARM::VLDMSIA_UPD: case ARM::VLDMSDB_UPD: isSLoad = true; @@ -1935,7 +2002,6 @@ ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData, switch (UseTID.getOpcode()) { default: break; case ARM::VSTMSIA: - case ARM::VSTMSDB: case ARM::VSTMSIA_UPD: case ARM::VSTMSDB_UPD: isSStore = true; @@ -2006,11 +2072,9 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, break; case ARM::VLDMDIA: - case ARM::VLDMDDB: case ARM::VLDMDIA_UPD: case ARM::VLDMDDB_UPD: case ARM::VLDMSIA: - case ARM::VLDMSDB: case ARM::VLDMSIA_UPD: case ARM::VLDMSDB_UPD: DefCycle = getVLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign); @@ -2049,11 +2113,9 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, break; case ARM::VSTMDIA: - case ARM::VSTMDDB: case ARM::VSTMDIA_UPD: case ARM::VSTMDDB_UPD: case ARM::VSTMSIA: - case ARM::VSTMSDB: case ARM::VSTMSIA_UPD: case ARM::VSTMSDB_UPD: UseCycle = getVSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign); @@ -2160,6 +2222,101 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, } } + if (DefAlign < 8 && Subtarget.isCortexA9()) + switch (DefTID.getOpcode()) { + default: break; + case ARM::VLD1q8: + case ARM::VLD1q16: + case ARM::VLD1q32: + case ARM::VLD1q64: + case ARM::VLD1q8_UPD: + case ARM::VLD1q16_UPD: + case ARM::VLD1q32_UPD: + case ARM::VLD1q64_UPD: + case ARM::VLD2d8: + case ARM::VLD2d16: + case ARM::VLD2d32: + case ARM::VLD2q8: + case ARM::VLD2q16: + case ARM::VLD2q32: + case ARM::VLD2d8_UPD: + case ARM::VLD2d16_UPD: + case ARM::VLD2d32_UPD: + case ARM::VLD2q8_UPD: + case ARM::VLD2q16_UPD: + case ARM::VLD2q32_UPD: + case ARM::VLD3d8: + case ARM::VLD3d16: + case ARM::VLD3d32: + case ARM::VLD1d64T: + case ARM::VLD3d8_UPD: + case ARM::VLD3d16_UPD: + case ARM::VLD3d32_UPD: + case ARM::VLD1d64T_UPD: + case ARM::VLD3q8_UPD: + case ARM::VLD3q16_UPD: + case ARM::VLD3q32_UPD: + case ARM::VLD4d8: + case ARM::VLD4d16: + case ARM::VLD4d32: + case ARM::VLD1d64Q: + case ARM::VLD4d8_UPD: + case ARM::VLD4d16_UPD: + case ARM::VLD4d32_UPD: + case ARM::VLD1d64Q_UPD: + case ARM::VLD4q8_UPD: + case ARM::VLD4q16_UPD: + case ARM::VLD4q32_UPD: + case ARM::VLD1DUPq8: + case ARM::VLD1DUPq16: + case ARM::VLD1DUPq32: + case ARM::VLD1DUPq8_UPD: + case ARM::VLD1DUPq16_UPD: + case ARM::VLD1DUPq32_UPD: + case ARM::VLD2DUPd8: + case ARM::VLD2DUPd16: + case ARM::VLD2DUPd32: + case ARM::VLD2DUPd8_UPD: + case ARM::VLD2DUPd16_UPD: + case ARM::VLD2DUPd32_UPD: + case ARM::VLD4DUPd8: + case ARM::VLD4DUPd16: + case ARM::VLD4DUPd32: + case ARM::VLD4DUPd8_UPD: + case ARM::VLD4DUPd16_UPD: + case ARM::VLD4DUPd32_UPD: + case ARM::VLD1LNd8: + case ARM::VLD1LNd16: + case ARM::VLD1LNd32: + case ARM::VLD1LNd8_UPD: + case ARM::VLD1LNd16_UPD: + case ARM::VLD1LNd32_UPD: + case ARM::VLD2LNd8: + case ARM::VLD2LNd16: + case ARM::VLD2LNd32: + case ARM::VLD2LNq16: + case ARM::VLD2LNq32: + case ARM::VLD2LNd8_UPD: + case ARM::VLD2LNd16_UPD: + case ARM::VLD2LNd32_UPD: + case ARM::VLD2LNq16_UPD: + case ARM::VLD2LNq32_UPD: + case ARM::VLD4LNd8: + case ARM::VLD4LNd16: + case ARM::VLD4LNd32: + case ARM::VLD4LNq16: + case ARM::VLD4LNq32: + case ARM::VLD4LNd8_UPD: + case ARM::VLD4LNd16_UPD: + case ARM::VLD4LNd32_UPD: + case ARM::VLD4LNq16_UPD: + case ARM::VLD4LNq32_UPD: + // If the address is not 64-bit aligned, the latencies of these + // instructions increases by one. + ++Latency; + break; + } + return Latency; } @@ -2226,6 +2383,113 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, } } + if (DefAlign < 8 && Subtarget.isCortexA9()) + switch (DefTID.getOpcode()) { + default: break; + case ARM::VLD1q8Pseudo: + case ARM::VLD1q16Pseudo: + case ARM::VLD1q32Pseudo: + case ARM::VLD1q64Pseudo: + case ARM::VLD1q8Pseudo_UPD: + case ARM::VLD1q16Pseudo_UPD: + case ARM::VLD1q32Pseudo_UPD: + case ARM::VLD1q64Pseudo_UPD: + case ARM::VLD2d8Pseudo: + case ARM::VLD2d16Pseudo: + case ARM::VLD2d32Pseudo: + case ARM::VLD2q8Pseudo: + case ARM::VLD2q16Pseudo: + case ARM::VLD2q32Pseudo: + case ARM::VLD2d8Pseudo_UPD: + case ARM::VLD2d16Pseudo_UPD: + case ARM::VLD2d32Pseudo_UPD: + case ARM::VLD2q8Pseudo_UPD: + case ARM::VLD2q16Pseudo_UPD: + case ARM::VLD2q32Pseudo_UPD: + case ARM::VLD3d8Pseudo: + case ARM::VLD3d16Pseudo: + case ARM::VLD3d32Pseudo: + case ARM::VLD1d64TPseudo: + case ARM::VLD3d8Pseudo_UPD: + case ARM::VLD3d16Pseudo_UPD: + case ARM::VLD3d32Pseudo_UPD: + case ARM::VLD1d64TPseudo_UPD: + case ARM::VLD3q8Pseudo_UPD: + case ARM::VLD3q16Pseudo_UPD: + case ARM::VLD3q32Pseudo_UPD: + case ARM::VLD3q8oddPseudo: + case ARM::VLD3q16oddPseudo: + case ARM::VLD3q32oddPseudo: + case ARM::VLD3q8oddPseudo_UPD: + case ARM::VLD3q16oddPseudo_UPD: + case ARM::VLD3q32oddPseudo_UPD: + case ARM::VLD4d8Pseudo: + case ARM::VLD4d16Pseudo: + case ARM::VLD4d32Pseudo: + case ARM::VLD1d64QPseudo: + case ARM::VLD4d8Pseudo_UPD: + case ARM::VLD4d16Pseudo_UPD: + case ARM::VLD4d32Pseudo_UPD: + case ARM::VLD1d64QPseudo_UPD: + case ARM::VLD4q8Pseudo_UPD: + case ARM::VLD4q16Pseudo_UPD: + case ARM::VLD4q32Pseudo_UPD: + case ARM::VLD4q8oddPseudo: + case ARM::VLD4q16oddPseudo: + case ARM::VLD4q32oddPseudo: + case ARM::VLD4q8oddPseudo_UPD: + case ARM::VLD4q16oddPseudo_UPD: + case ARM::VLD4q32oddPseudo_UPD: + case ARM::VLD1DUPq8Pseudo: + case ARM::VLD1DUPq16Pseudo: + case ARM::VLD1DUPq32Pseudo: + case ARM::VLD1DUPq8Pseudo_UPD: + case ARM::VLD1DUPq16Pseudo_UPD: + case ARM::VLD1DUPq32Pseudo_UPD: + case ARM::VLD2DUPd8Pseudo: + case ARM::VLD2DUPd16Pseudo: + case ARM::VLD2DUPd32Pseudo: + case ARM::VLD2DUPd8Pseudo_UPD: + case ARM::VLD2DUPd16Pseudo_UPD: + case ARM::VLD2DUPd32Pseudo_UPD: + case ARM::VLD4DUPd8Pseudo: + case ARM::VLD4DUPd16Pseudo: + case ARM::VLD4DUPd32Pseudo: + case ARM::VLD4DUPd8Pseudo_UPD: + case ARM::VLD4DUPd16Pseudo_UPD: + case ARM::VLD4DUPd32Pseudo_UPD: + case ARM::VLD1LNq8Pseudo: + case ARM::VLD1LNq16Pseudo: + case ARM::VLD1LNq32Pseudo: + case ARM::VLD1LNq8Pseudo_UPD: + case ARM::VLD1LNq16Pseudo_UPD: + case ARM::VLD1LNq32Pseudo_UPD: + case ARM::VLD2LNd8Pseudo: + case ARM::VLD2LNd16Pseudo: + case ARM::VLD2LNd32Pseudo: + case ARM::VLD2LNq16Pseudo: + case ARM::VLD2LNq32Pseudo: + case ARM::VLD2LNd8Pseudo_UPD: + case ARM::VLD2LNd16Pseudo_UPD: + case ARM::VLD2LNd32Pseudo_UPD: + case ARM::VLD2LNq16Pseudo_UPD: + case ARM::VLD2LNq32Pseudo_UPD: + case ARM::VLD4LNd8Pseudo: + case ARM::VLD4LNd16Pseudo: + case ARM::VLD4LNd32Pseudo: + case ARM::VLD4LNq16Pseudo: + case ARM::VLD4LNq32Pseudo: + case ARM::VLD4LNd8Pseudo_UPD: + case ARM::VLD4LNd16Pseudo_UPD: + case ARM::VLD4LNd32Pseudo_UPD: + case ARM::VLD4LNq16Pseudo_UPD: + case ARM::VLD4LNq32Pseudo_UPD: + // If the address is not 64-bit aligned, the latencies of these + // instructions increases by one. + ++Latency; + break; + } + return Latency; } @@ -2264,9 +2528,7 @@ int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, default: return ItinData->getStageLatency(get(Opcode).getSchedClass()); case ARM::VLDMQIA: - case ARM::VLDMQDB: case ARM::VSTMQIA: - case ARM::VSTMQDB: return 2; } } diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h index 7e2183d7cd5e..9a2faf8f9aae 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -34,25 +34,7 @@ namespace ARMII { //===------------------------------------------------------------------===// // This four-bit field describes the addressing mode used. - - AddrModeMask = 0x1f, - AddrModeNone = 0, - AddrMode1 = 1, - AddrMode2 = 2, - AddrMode3 = 3, - AddrMode4 = 4, - AddrMode5 = 5, - AddrMode6 = 6, - AddrModeT1_1 = 7, - AddrModeT1_2 = 8, - AddrModeT1_4 = 9, - AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data - AddrModeT2_i12 = 11, - AddrModeT2_i8 = 12, - AddrModeT2_so = 13, - AddrModeT2_pc = 14, // +/- i12 for pc relative data - AddrModeT2_i8s4 = 15, // i8 * 4 - AddrMode_i12 = 16, + AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h // Size* - Flags to keep track of the size of an instruction. SizeShift = 5, @@ -64,11 +46,9 @@ namespace ARMII { // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load // and store ops only. Generic "updating" flag is used for ld/st multiple. + // The index mode enums are declared in ARMBaseInfo.h IndexModeShift = 8, IndexModeMask = 3 << IndexModeShift, - IndexModePre = 1, - IndexModePost = 2, - IndexModeUpd = 3, //===------------------------------------------------------------------===// // Instruction encoding formats. @@ -311,7 +291,7 @@ class ARMBaseInstrInfo : public TargetInstrInfoImpl { int64_t &Offset1, int64_t &Offset2)const; /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to - /// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should + /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads should /// be scheduled togther. On some targets if two loads are loading from /// addresses in the same cache line, it's better if they are scheduled /// together. This function takes two integers that represent the load offsets @@ -327,7 +307,7 @@ class ARMBaseInstrInfo : public TargetInstrInfoImpl { const MachineFunction &MF) const; virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, - unsigned NumCyles, unsigned ExtraPredCycles, + unsigned NumCycles, unsigned ExtraPredCycles, float Prob, float Confidence) const; virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB, @@ -337,10 +317,10 @@ class ARMBaseInstrInfo : public TargetInstrInfoImpl { float Probability, float Confidence) const; virtual bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, - unsigned NumCyles, + unsigned NumCycles, float Probability, float Confidence) const { - return NumCyles == 1; + return NumCycles == 1; } /// AnalyzeCompare - For a comparison instruction, return the source register @@ -496,19 +476,19 @@ void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, ARMCC::CondCodes Pred, unsigned PredReg, - const ARMBaseInstrInfo &TII); + const ARMBaseInstrInfo &TII, unsigned MIFlags = 0); void emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, ARMCC::CondCodes Pred, unsigned PredReg, - const ARMBaseInstrInfo &TII); + const ARMBaseInstrInfo &TII, unsigned MIFlags = 0); void emitThumbRegPlusImmediate(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, + MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, const TargetInstrInfo &TII, const ARMBaseRegisterInfo& MRI, - DebugLoc dl); + unsigned MIFlags = 0); /// rewriteARMFrameIndex / rewriteT2FrameIndex - diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 67a4b7d49398..ea1f08a7da8d 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -88,7 +88,7 @@ BitVector ARMBaseRegisterInfo:: getReservedRegs(const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); - // FIXME: avoid re-calculating this everytime. + // FIXME: avoid re-calculating this every time. BitVector Reserved(getNumRegs()); Reserved.set(ARM::SP); Reserved.set(ARM::PC); @@ -342,12 +342,51 @@ ARMBaseRegisterInfo::canCombineSubRegIndices(const TargetRegisterClass *RC, return false; } +const TargetRegisterClass* +ARMBaseRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) + const { + const TargetRegisterClass *Super = RC; + TargetRegisterClass::sc_iterator I = RC->superclasses_begin(); + do { + switch (Super->getID()) { + case ARM::GPRRegClassID: + case ARM::SPRRegClassID: + case ARM::DPRRegClassID: + case ARM::QPRRegClassID: + case ARM::QQPRRegClassID: + case ARM::QQQQPRRegClassID: + return Super; + } + Super = *I++; + } while (Super); + return RC; +} const TargetRegisterClass * ARMBaseRegisterInfo::getPointerRegClass(unsigned Kind) const { return ARM::GPRRegisterClass; } +unsigned +ARMBaseRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, + MachineFunction &MF) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + switch (RC->getID()) { + default: + return 0; + case ARM::tGPRRegClassID: + return TFI->hasFP(MF) ? 4 : 5; + case ARM::GPRRegClassID: { + unsigned FP = TFI->hasFP(MF) ? 1 : 0; + return 10 - FP - (STI.isR9Reserved() ? 1 : 0); + } + case ARM::SPRRegClassID: // Currently not used as 'rep' register class. + case ARM::DPRRegClassID: + return 32 - 10; + } +} + /// getAllocationOrder - Returns the register allocation order for a specified /// register class in the form of a pair of TargetRegisterClass iterators. std::pair @@ -428,6 +467,10 @@ ARMBaseRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC, ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8 }; + // We only support even/odd hints for GPR and rGPR. + if (RC != ARM::GPRRegisterClass && RC != ARM::rGPRRegisterClass) + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); if (HintType == ARMRI::RegPairEven) { if (isPhysicalRegister(HintReg) && getRegisterPairEven(HintReg, MF) == 0) @@ -530,6 +573,29 @@ ARMBaseRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg, } } +bool +ARMBaseRegisterInfo::avoidWriteAfterWrite(const TargetRegisterClass *RC) const { + // CortexA9 has a Write-after-write hazard for NEON registers. + if (!STI.isCortexA9()) + return false; + + switch (RC->getID()) { + case ARM::DPRRegClassID: + case ARM::DPR_8RegClassID: + case ARM::DPR_VFP2RegClassID: + case ARM::QPRRegClassID: + case ARM::QPR_8RegClassID: + case ARM::QPR_VFP2RegClassID: + case ARM::SPRRegClassID: + case ARM::SPR_8RegClassID: + // Avoid reusing S, D, and Q registers. + // Don't increase register pressure for QQ and QQQQ. + return true; + default: + return false; + } +} + bool ARMBaseRegisterInfo::hasBasePointer(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); const ARMFunctionInfo *AFI = MF.getInfo(); @@ -806,7 +872,7 @@ emitLoadConstPool(MachineBasicBlock &MBB, DebugLoc dl, unsigned DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred, - unsigned PredReg) const { + unsigned PredReg, unsigned MIFlags) const { MachineFunction &MF = *MBB.getParent(); MachineConstantPool *ConstantPool = MF.getConstantPool(); const Constant *C = @@ -816,7 +882,8 @@ emitLoadConstPool(MachineBasicBlock &MBB, BuildMI(MBB, MBBI, dl, TII.get(ARM::LDRcp)) .addReg(DestReg, getDefRegState(true), SubIdx) .addConstantPoolIndex(Idx) - .addImm(0).addImm(Pred).addReg(PredReg); + .addImm(0).addImm(Pred).addReg(PredReg) + .setMIFlags(MIFlags); } bool ARMBaseRegisterInfo:: diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h b/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h index ba6bd2b32082..9edf72df2158 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -128,6 +128,12 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo { const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const; + const TargetRegisterClass* + getLargestLegalSuperClass(const TargetRegisterClass *RC) const; + + unsigned getRegPressureLimit(const TargetRegisterClass *RC, + MachineFunction &MF) const; + std::pair getAllocationOrder(const TargetRegisterClass *RC, unsigned HintType, unsigned HintReg, @@ -139,6 +145,8 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo { void UpdateRegAllocHint(unsigned Reg, unsigned NewReg, MachineFunction &MF) const; + virtual bool avoidWriteAfterWrite(const TargetRegisterClass *RC) const; + bool hasBasePointer(const MachineFunction &MF) const; bool canRealignStack(const MachineFunction &MF) const; @@ -176,7 +184,8 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo { unsigned DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred = ARMCC::AL, - unsigned PredReg = 0) const; + unsigned PredReg = 0, + unsigned MIFlags = MachineInstr::NoFlags)const; /// Code Generation virtual methods... virtual bool isReservedReg(const MachineFunction &MF, unsigned Reg) const; diff --git a/contrib/llvm/lib/Target/ARM/ARMCallingConv.td b/contrib/llvm/lib/Target/ARM/ARMCallingConv.td index 426ba13a8e11..d2981c0af8ca 100644 --- a/contrib/llvm/lib/Target/ARM/ARMCallingConv.td +++ b/contrib/llvm/lib/Target/ARM/ARMCallingConv.td @@ -22,6 +22,9 @@ class CCIfAlign: //===----------------------------------------------------------------------===// def CC_ARM_APCS : CallingConv<[ + // Handles byval parameters. + CCIfByVal>, + CCIfType<[i8, i16], CCPromoteToType>, // Handle all vector types as either f64 or v2f64. diff --git a/contrib/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/contrib/llvm/lib/Target/ARM/ARMCodeEmitter.cpp index 9bbf6a030687..fa7371626f29 100644 --- a/contrib/llvm/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMCodeEmitter.cpp @@ -312,6 +312,15 @@ namespace { unsigned getRegisterListOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getShiftRight8Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getShiftRight16Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getShiftRight32Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getShiftRight64Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + /// getMovi32Value - Return binary encoding of operand for movw/movt. If the /// machine operand requires relocation, record the relocation and return /// zero. @@ -969,7 +978,7 @@ unsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) { unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, const TargetInstrDesc &TID) const { - for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i != e; --i){ + for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i >= e; --i){ const MachineOperand &MO = MI.getOperand(i-1); if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) return 1 << ARMII::S_BitShift; diff --git a/contrib/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/contrib/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp index 13d1b33d1165..baf95a33dd4b 100644 --- a/contrib/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -1650,24 +1650,27 @@ bool ARMConstantIslands::OptimizeThumb2Branches(MachineFunction &MF) { unsigned BrOffset = GetOffsetOf(Br.MI) + 4 - 2; unsigned DestOffset = BBOffsets[DestBB->getNumber()]; if (BrOffset < DestOffset && (DestOffset - BrOffset) <= 126) { - MachineBasicBlock::iterator CmpMI = Br.MI; --CmpMI; - if (CmpMI->getOpcode() == ARM::tCMPi8) { - unsigned Reg = CmpMI->getOperand(0).getReg(); - Pred = llvm::getInstrPredicate(CmpMI, PredReg); - if (Pred == ARMCC::AL && - CmpMI->getOperand(1).getImm() == 0 && - isARMLowRegister(Reg)) { - MachineBasicBlock *MBB = Br.MI->getParent(); - MachineInstr *NewBR = - BuildMI(*MBB, CmpMI, Br.MI->getDebugLoc(), TII->get(NewOpc)) - .addReg(Reg).addMBB(DestBB, Br.MI->getOperand(0).getTargetFlags()); - CmpMI->eraseFromParent(); - Br.MI->eraseFromParent(); - Br.MI = NewBR; - BBSizes[MBB->getNumber()] -= 2; - AdjustBBOffsetsAfter(MBB, -2); - ++NumCBZ; - MadeChange = true; + MachineBasicBlock::iterator CmpMI = Br.MI; + if (CmpMI != Br.MI->getParent()->begin()) { + --CmpMI; + if (CmpMI->getOpcode() == ARM::tCMPi8) { + unsigned Reg = CmpMI->getOperand(0).getReg(); + Pred = llvm::getInstrPredicate(CmpMI, PredReg); + if (Pred == ARMCC::AL && + CmpMI->getOperand(1).getImm() == 0 && + isARMLowRegister(Reg)) { + MachineBasicBlock *MBB = Br.MI->getParent(); + MachineInstr *NewBR = + BuildMI(*MBB, CmpMI, Br.MI->getDebugLoc(), TII->get(NewOpc)) + .addReg(Reg).addMBB(DestBB,Br.MI->getOperand(0).getTargetFlags()); + CmpMI->eraseFromParent(); + Br.MI->eraseFromParent(); + Br.MI = NewBR; + BBSizes[MBB->getNumber()] -= 2; + AdjustBBOffsetsAfter(MBB, -2); + ++NumCBZ; + MadeChange = true; + } } } } diff --git a/contrib/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/contrib/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index bd753d29abde..b6b3c75943b5 100644 --- a/contrib/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -455,6 +455,10 @@ void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) { // Add an implicit def for the super-register. MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead)); TransferImpOps(MI, MIB, MIB); + + // Transfer memoperands. + MIB->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + MI.eraseFromParent(); } @@ -496,10 +500,13 @@ void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) { MIB.addOperand(MI.getOperand(OpIdx++)); MIB.addOperand(MI.getOperand(OpIdx++)); - if (SrcIsKill) - // Add an implicit kill for the super-reg. - (*MIB).addRegisterKilled(SrcReg, TRI, true); + if (SrcIsKill) // Add an implicit kill for the super-reg. + MIB->addRegisterKilled(SrcReg, TRI, true); TransferImpOps(MI, MIB, MIB); + + // Transfer memoperands. + MIB->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + MI.eraseFromParent(); } @@ -622,9 +629,8 @@ void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI, MIB.addOperand(MI.getOperand(OpIdx++)); MIB.addOperand(MI.getOperand(OpIdx++)); - if (SrcIsKill) - // Add an implicit kill for the super-reg. - (*MIB).addRegisterKilled(SrcReg, TRI, true); + if (SrcIsKill) // Add an implicit kill for the super-reg. + MIB->addRegisterKilled(SrcReg, TRI, true); TransferImpOps(MI, MIB, MIB); MI.eraseFromParent(); } @@ -655,8 +661,8 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal); LO16 = LO16.addImm(SOImmValV1); HI16 = HI16.addImm(SOImmValV2); - (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); - (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + LO16->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + HI16->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); LO16.addImm(Pred).addReg(PredReg).addReg(0); HI16.addImm(Pred).addReg(PredReg).addReg(0); TransferImpOps(MI, LO16, HI16); @@ -692,8 +698,8 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16); } - (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); - (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + LO16->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + HI16->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); LO16.addImm(Pred).addReg(PredReg); HI16.addImm(Pred).addReg(PredReg); @@ -708,6 +714,78 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, switch (Opcode) { default: return false; + case ARM::VMOVScc: + case ARM::VMOVDcc: { + unsigned newOpc = Opcode == ARM::VMOVScc ? ARM::VMOVS : ARM::VMOVD; + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(newOpc), + MI.getOperand(1).getReg()) + .addReg(MI.getOperand(2).getReg(), + getKillRegState(MI.getOperand(2).isKill())) + .addImm(MI.getOperand(3).getImm()) // 'pred' + .addReg(MI.getOperand(4).getReg()); + + MI.eraseFromParent(); + return true; + } + case ARM::MOVCCr: { + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVr), + MI.getOperand(1).getReg()) + .addReg(MI.getOperand(2).getReg(), + getKillRegState(MI.getOperand(2).isKill())) + .addImm(MI.getOperand(3).getImm()) // 'pred' + .addReg(MI.getOperand(4).getReg()) + .addReg(0); // 's' bit + + MI.eraseFromParent(); + return true; + } + case ARM::MOVCCs: { + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs), + (MI.getOperand(1).getReg())) + .addReg(MI.getOperand(2).getReg(), + getKillRegState(MI.getOperand(2).isKill())) + .addReg(MI.getOperand(3).getReg(), + getKillRegState(MI.getOperand(3).isKill())) + .addImm(MI.getOperand(4).getImm()) + .addImm(MI.getOperand(5).getImm()) // 'pred' + .addReg(MI.getOperand(6).getReg()) + .addReg(0); // 's' bit + + MI.eraseFromParent(); + return true; + } + case ARM::MOVCCi16: { + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi16), + MI.getOperand(1).getReg()) + .addImm(MI.getOperand(2).getImm()) + .addImm(MI.getOperand(3).getImm()) // 'pred' + .addReg(MI.getOperand(4).getReg()); + + MI.eraseFromParent(); + return true; + } + case ARM::MOVCCi: { + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), + MI.getOperand(1).getReg()) + .addImm(MI.getOperand(2).getImm()) + .addImm(MI.getOperand(3).getImm()) // 'pred' + .addReg(MI.getOperand(4).getReg()) + .addReg(0); // 's' bit + + MI.eraseFromParent(); + return true; + } + case ARM::MVNCCi: { + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MVNi), + MI.getOperand(1).getReg()) + .addImm(MI.getOperand(2).getImm()) + .addImm(MI.getOperand(3).getImm()) // 'pred' + .addReg(MI.getOperand(4).getReg()) + .addReg(0); // 's' bit + + MI.eraseFromParent(); + return true; + } case ARM::Int_eh_sjlj_dispatchsetup: { MachineFunction &MF = *MI.getParent()->getParent(); const ARMBaseInstrInfo *AII = @@ -726,9 +804,8 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, llvm::emitT2RegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6, FramePtr, -NumBytes, ARMCC::AL, 0, *TII); } else if (AFI->isThumbFunction()) { - llvm::emitThumbRegPlusImmediate(MBB, MBBI, ARM::R6, - FramePtr, -NumBytes, - *TII, RI, MI.getDebugLoc()); + llvm::emitThumbRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6, + FramePtr, -NumBytes, *TII, RI); } else { llvm::emitARMRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6, FramePtr, -NumBytes, ARMCC::AL, 0, @@ -785,7 +862,7 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, TII->get(ARM::BL)) .addExternalSymbol("__aeabi_read_tp", 0); - (*MIB).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + MIB->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); TransferImpOps(MI, MIB, MIB); MI.eraseFromParent(); return true; @@ -800,7 +877,7 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewLdOpc), DstReg) .addOperand(MI.getOperand(1))); - (*MIB1).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + MIB1->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPICADD)) .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) @@ -823,7 +900,7 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, const MachineOperand &MO1 = MI.getOperand(1); const GlobalValue *GV = MO1.getGlobal(); unsigned TF = MO1.getTargetFlags(); - bool isARM = Opcode != ARM::t2MOV_ga_pcrel; + bool isARM = (Opcode != ARM::t2MOV_ga_pcrel && Opcode != ARM::t2MOV_ga_dyn); bool isPIC = (Opcode != ARM::MOV_ga_dyn && Opcode != ARM::t2MOV_ga_dyn); unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel; unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel : ARM::t2MOVTi16_ga_pcrel; @@ -856,7 +933,7 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, if (isARM) { AddDefaultPred(MIB3); if (Opcode == ARM::MOV_ga_pcrel_ldr) - (*MIB2).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + MIB2->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); } TransferImpOps(MI, MIB1, MIB3); MI.eraseFromParent(); @@ -896,9 +973,8 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, return true; } - case ARM::VLDMQIA: - case ARM::VLDMQDB: { - unsigned NewOpc = (Opcode == ARM::VLDMQIA) ? ARM::VLDMDIA : ARM::VLDMDDB; + case ARM::VLDMQIA: { + unsigned NewOpc = ARM::VLDMDIA; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc)); unsigned OpIdx = 0; @@ -927,9 +1003,8 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, return true; } - case ARM::VSTMQIA: - case ARM::VSTMQDB: { - unsigned NewOpc = (Opcode == ARM::VSTMQIA) ? ARM::VSTMDIA : ARM::VSTMDDB; + case ARM::VSTMQIA: { + unsigned NewOpc = ARM::VSTMDIA; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc)); unsigned OpIdx = 0; @@ -950,9 +1025,8 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, unsigned D1 = TRI->getSubReg(SrcReg, ARM::dsub_1); MIB.addReg(D0).addReg(D1); - if (SrcIsKill) - // Add an implicit kill for the Q register. - (*MIB).addRegisterKilled(SrcReg, TRI, true); + if (SrcIsKill) // Add an implicit kill for the Q register. + MIB->addRegisterKilled(SrcReg, TRI, true); TransferImpOps(MI, MIB, MIB); MI.eraseFromParent(); @@ -960,14 +1034,16 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, } case ARM::VDUPfqf: case ARM::VDUPfdf:{ - unsigned NewOpc = Opcode == ARM::VDUPfqf ? ARM::VDUPLNfq : ARM::VDUPLNfd; + unsigned NewOpc = Opcode == ARM::VDUPfqf ? ARM::VDUPLN32q : + ARM::VDUPLN32d; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc)); unsigned OpIdx = 0; unsigned SrcReg = MI.getOperand(1).getReg(); unsigned Lane = getARMRegisterNumbering(SrcReg) & 1; unsigned DReg = TRI->getMatchingSuperReg(SrcReg, - Lane & 1 ? ARM::ssub_1 : ARM::ssub_0, &ARM::DPR_VFP2RegClass); + Lane & 1 ? ARM::ssub_1 : ARM::ssub_0, + &ARM::DPR_VFP2RegClass); // The lane is [0,1] for the containing DReg superregister. // Copy the dst/src register operands. MIB.addOperand(MI.getOperand(OpIdx++)); diff --git a/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp b/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp index 26f48b308316..3baf274b76b8 100644 --- a/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "ARM.h" +#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMCallingConv.h" #include "ARMRegisterInfo.h" @@ -26,6 +27,7 @@ #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" #include "llvm/Module.h" +#include "llvm/Operator.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" @@ -115,6 +117,11 @@ class ARMFastISel : public FastISel { const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill); + virtual unsigned FastEmitInst_rrr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + unsigned Op2, bool Op2IsKill); virtual unsigned FastEmitInst_ri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, @@ -123,14 +130,18 @@ class ARMFastISel : public FastISel { const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, const ConstantFP *FPImm); - virtual unsigned FastEmitInst_i(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - uint64_t Imm); virtual unsigned FastEmitInst_rri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm); + virtual unsigned FastEmitInst_i(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + uint64_t Imm); + virtual unsigned FastEmitInst_ii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + uint64_t Imm1, uint64_t Imm2); + virtual unsigned FastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill, uint32_t Idx); @@ -193,6 +204,7 @@ class ARMFastISel : public FastISel { // OptionalDef handling routines. private: + bool isARMNEONPred(const MachineInstr *MI); bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR); const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB); void AddLoadStoreOperands(EVT VT, Address &Addr, @@ -221,6 +233,21 @@ bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) { return true; } +bool ARMFastISel::isARMNEONPred(const MachineInstr *MI) { + const TargetInstrDesc &TID = MI->getDesc(); + + // If we're a thumb2 or not NEON function we were handled via isPredicable. + if ((TID.TSFlags & ARMII::DomainMask) != ARMII::DomainNEON || + AFI->isThumb2Function()) + return false; + + for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) + if (TID.OpInfo[i].isPredicate()) + return true; + + return false; +} + // If the machine is predicable go ahead and add the predicate operands, if // it needs default CC operands add those. // TODO: If we want to support thumb1 then we'll need to deal with optional @@ -230,8 +257,10 @@ const MachineInstrBuilder & ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) { MachineInstr *MI = &*MIB; - // Do we use a predicate? - if (TII.isPredicable(MI)) + // Do we use a predicate? or... + // Are we NEON in ARM mode and have a predicate operand? If so, I know + // we're not predicable but add it anyways. + if (TII.isPredicable(MI) || isARMNEONPred(MI)) AddDefaultPred(MIB); // Do we optionally set a predicate? Preds is size > 0 iff the predicate @@ -296,6 +325,31 @@ unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode, return ResultReg; } +unsigned ARMFastISel::FastEmitInst_rrr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + unsigned Op2, bool Op2IsKill) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill) + .addReg(Op2, Op2IsKill * RegState::Kill)); + else { + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill) + .addReg(Op2, Op2IsKill * RegState::Kill)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::COPY), ResultReg) + .addReg(II.ImplicitDefs[0])); + } + return ResultReg; +} + unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, @@ -384,6 +438,26 @@ unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode, return ResultReg; } +unsigned ARMFastISel::FastEmitInst_ii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + uint64_t Imm1, uint64_t Imm2) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addImm(Imm1).addImm(Imm2)); + else { + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addImm(Imm1).addImm(Imm2)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::COPY), + ResultReg) + .addReg(II.ImplicitDefs[0])); + } + return ResultReg; +} + unsigned ARMFastISel::FastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill, uint32_t Idx) { @@ -667,24 +741,29 @@ bool ARMFastISel::ARMComputeAddress(const Value *Obj, Address &Addr) { TmpOffset += SL->getElementOffset(Idx); } else { uint64_t S = TD.getTypeAllocSize(GTI.getIndexedType()); - SmallVector Worklist; - Worklist.push_back(Op); - do { - Op = Worklist.pop_back_val(); + for (;;) { if (const ConstantInt *CI = dyn_cast(Op)) { // Constant-offset addressing. TmpOffset += CI->getSExtValue() * S; - } else if (isa(Op) && - isa(cast(Op)->getOperand(1))) { - // An add with a constant operand. Fold the constant. + break; + } + if (isa(Op) && + (!isa(Op) || + FuncInfo.MBBMap[cast(Op)->getParent()] + == FuncInfo.MBB) && + isa(cast(Op)->getOperand(1))) { + // An add (in the same block) with a constant operand. Fold the + // constant. ConstantInt *CI = - cast(cast(Op)->getOperand(1)); + cast(cast(Op)->getOperand(1)); TmpOffset += CI->getSExtValue() * S; - // Add the other operand back to the work list. - Worklist.push_back(cast(Op)->getOperand(0)); - } else - goto unsupported_gep; - } while (!Worklist.empty()); + // Iterate on the other operand. + Op = cast(Op)->getOperand(0); + continue; + } + // Unsupported + goto unsupported_gep; + } } } @@ -767,26 +846,9 @@ void ARMFastISel::ARMSimplifyAddress(Address &Addr, EVT VT) { // Since the offset is too large for the load/store instruction // get the reg+offset into a register. if (needsLowering) { - ARMCC::CondCodes Pred = ARMCC::AL; - unsigned PredReg = 0; - - TargetRegisterClass *RC = isThumb ? ARM::tGPRRegisterClass : - ARM::GPRRegisterClass; - unsigned BaseReg = createResultReg(RC); - - if (!isThumb) - emitARMRegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL, - BaseReg, Addr.Base.Reg, Addr.Offset, - Pred, PredReg, - static_cast(TII)); - else { - assert(AFI->isThumb2Function()); - emitT2RegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL, - BaseReg, Addr.Base.Reg, Addr.Offset, Pred, PredReg, - static_cast(TII)); - } + Addr.Base.Reg = FastEmit_ri_(MVT::i32, ISD::ADD, Addr.Base.Reg, + /*Op0IsKill*/false, Addr.Offset, MVT::i32); Addr.Offset = 0; - Addr.Base.Reg = BaseReg; } } @@ -797,7 +859,7 @@ void ARMFastISel::AddLoadStoreOperands(EVT VT, Address &Addr, if (VT.getSimpleVT().SimpleTy == MVT::f32 || VT.getSimpleVT().SimpleTy == MVT::f64) Addr.Offset /= 4; - + // Frame base works a bit differently. Handle it separately. if (Addr.BaseType == Address::FrameIndexBase) { int FI = Addr.Base.FI; @@ -819,7 +881,7 @@ void ARMFastISel::AddLoadStoreOperands(EVT VT, Address &Addr, } else { // Now add the rest of the operands. MIB.addReg(Addr.Base.Reg); - + // ARM halfword load/stores need an additional operand. if (!isThumb && VT.getSimpleVT().SimpleTy == MVT::i16) MIB.addReg(0); @@ -1007,18 +1069,16 @@ bool ARMFastISel::SelectBranch(const Instruction *I) { // behavior. // TODO: Factor this out. if (const CmpInst *CI = dyn_cast(BI->getCondition())) { - if (CI->hasOneUse() && (CI->getParent() == I->getParent())) { - MVT VT; - const Type *Ty = CI->getOperand(0)->getType(); - if (!isTypeLegal(Ty, VT)) - return false; - + MVT SourceVT; + const Type *Ty = CI->getOperand(0)->getType(); + if (CI->hasOneUse() && (CI->getParent() == I->getParent()) + && isTypeLegal(Ty, SourceVT)) { bool isFloat = (Ty->isDoubleTy() || Ty->isFloatTy()); if (isFloat && !Subtarget->hasVFP2()) return false; unsigned CmpOpc; - switch (VT.SimpleTy) { + switch (SourceVT.SimpleTy) { default: return false; // TODO: Verify compares. case MVT::f32: @@ -1033,7 +1093,14 @@ bool ARMFastISel::SelectBranch(const Instruction *I) { } // Get the compare predicate. - ARMCC::CondCodes ARMPred = getComparePred(CI->getPredicate()); + // Try to take advantage of fallthrough opportunities. + CmpInst::Predicate Predicate = CI->getPredicate(); + if (FuncInfo.MBB->isLayoutSuccessor(TBB)) { + std::swap(TBB, FBB); + Predicate = CmpInst::getInversePredicate(Predicate); + } + + ARMCC::CondCodes ARMPred = getComparePred(Predicate); // We may not handle every CC for now. if (ARMPred == ARMCC::AL) return false; @@ -1057,6 +1124,30 @@ bool ARMFastISel::SelectBranch(const Instruction *I) { unsigned BrOpc = isThumb ? ARM::t2Bcc : ARM::Bcc; BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(BrOpc)) .addMBB(TBB).addImm(ARMPred).addReg(ARM::CPSR); + FastEmitBranch(FBB, DL); + FuncInfo.MBB->addSuccessor(TBB); + return true; + } + } else if (TruncInst *TI = dyn_cast(BI->getCondition())) { + MVT SourceVT; + if (TI->hasOneUse() && TI->getParent() == I->getParent() && + (isTypeLegal(TI->getOperand(0)->getType(), SourceVT))) { + unsigned TstOpc = isThumb ? ARM::t2TSTri : ARM::TSTri; + unsigned OpReg = getRegForValue(TI->getOperand(0)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TstOpc)) + .addReg(OpReg).addImm(1)); + + unsigned CCMode = ARMCC::NE; + if (FuncInfo.MBB->isLayoutSuccessor(TBB)) { + std::swap(TBB, FBB); + CCMode = ARMCC::EQ; + } + + unsigned BrOpc = isThumb ? ARM::t2Bcc : ARM::Bcc; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(BrOpc)) + .addMBB(TBB).addImm(CCMode).addReg(ARM::CPSR); + FastEmitBranch(FBB, DL); FuncInfo.MBB->addSuccessor(TBB); return true; @@ -1066,14 +1157,26 @@ bool ARMFastISel::SelectBranch(const Instruction *I) { unsigned CmpReg = getRegForValue(BI->getCondition()); if (CmpReg == 0) return false; - // Re-set the flags just in case. - unsigned CmpOpc = isThumb ? ARM::t2CMPri : ARM::CMPri; - AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CmpOpc)) - .addReg(CmpReg).addImm(0)); + // We've been divorced from our compare! Our block was split, and + // now our compare lives in a predecessor block. We musn't + // re-compare here, as the children of the compare aren't guaranteed + // live across the block boundary (we *could* check for this). + // Regardless, the compare has been done in the predecessor block, + // and it left a value for us in a virtual register. Ergo, we test + // the one-bit value left in the virtual register. + unsigned TstOpc = isThumb ? ARM::t2TSTri : ARM::TSTri; + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TstOpc)) + .addReg(CmpReg).addImm(1)); + + unsigned CCMode = ARMCC::NE; + if (FuncInfo.MBB->isLayoutSuccessor(TBB)) { + std::swap(TBB, FBB); + CCMode = ARMCC::EQ; + } unsigned BrOpc = isThumb ? ARM::t2Bcc : ARM::Bcc; BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(BrOpc)) - .addMBB(TBB).addImm(ARMCC::NE).addReg(ARM::CPSR); + .addMBB(TBB).addImm(CCMode).addReg(ARM::CPSR); FastEmitBranch(FBB, DL); FuncInfo.MBB->addSuccessor(TBB); return true; @@ -1636,17 +1739,9 @@ bool ARMFastISel::SelectRet(const Instruction *I) { unsigned ARMFastISel::ARMSelectCallOp(const GlobalValue *GV) { - // Depend our opcode for thumb on whether or not we're targeting an - // externally callable function. For libcalls we'll just pass a NULL GV - // in here. - bool isExternal = false; - if (!GV || GV->hasExternalLinkage()) isExternal = true; - // Darwin needs the r9 versions of the opcodes. bool isDarwin = Subtarget->isTargetDarwin(); - if (isThumb && isExternal) { - return isDarwin ? ARM::tBLXi_r9 : ARM::tBLXi; - } else if (isThumb) { + if (isThumb) { return isDarwin ? ARM::tBLr9 : ARM::tBL; } else { return isDarwin ? ARM::BLr9 : ARM::BL; @@ -1671,9 +1766,6 @@ bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) { else if (!isTypeLegal(RetTy, RetVT)) return false; - // For now we're using BLX etc on the assumption that we have v5t ops. - if (!Subtarget->hasV5TOps()) return false; - // TODO: For now if we have long calls specified we don't handle the call. if (EnableARMLongCalls) return false; @@ -1711,7 +1803,7 @@ bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) { if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags, RegArgs, CC, NumBytes)) return false; - // Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops. + // Issue the call, BLr9 for darwin, BL otherwise. // TODO: Turn this into the table of arm call ops. MachineInstrBuilder MIB; unsigned CallOpc = ARMSelectCallOp(NULL); @@ -1772,13 +1864,9 @@ bool ARMFastISel::SelectCall(const Instruction *I) { else if (!isTypeLegal(RetTy, RetVT)) return false; - // For now we're using BLX etc on the assumption that we have v5t ops. - // TODO: Maybe? - if (!Subtarget->hasV5TOps()) return false; - // TODO: For now if we have long calls specified we don't handle the call. if (EnableARMLongCalls) return false; - + // Set up the argument vectors. SmallVector Args; SmallVector ArgRegs; @@ -1827,7 +1915,7 @@ bool ARMFastISel::SelectCall(const Instruction *I) { if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags, RegArgs, CC, NumBytes)) return false; - // Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops. + // Issue the call, BLr9 for darwin, BL otherwise. // TODO: Turn this into the table of arm call ops. MachineInstrBuilder MIB; unsigned CallOpc = ARMSelectCallOp(GV); @@ -1842,7 +1930,7 @@ bool ARMFastISel::SelectCall(const Instruction *I) { MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CallOpc)) .addGlobalAddress(GV, 0, 0)); - + // Add implicit physical register uses to the call. for (unsigned i = 0, e = RegArgs.size(); i != e; ++i) MIB.addReg(RegArgs[i]); diff --git a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp index 68c33f098ec9..e2e95d47b37b 100644 --- a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -106,14 +106,13 @@ static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, const ARMBaseInstrInfo &TII, - int NumBytes, - ARMCC::CondCodes Pred = ARMCC::AL, unsigned PredReg = 0) { + int NumBytes, unsigned MIFlags = MachineInstr::NoFlags) { if (isARM) emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, - Pred, PredReg, TII); + ARMCC::AL, 0, TII, MIFlags); else emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, - Pred, PredReg, TII); + ARMCC::AL, 0, TII, MIFlags); } void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { @@ -141,11 +140,13 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { // Allocate the vararg register save area. This is not counted in NumBytes. if (VARegSaveSize) - emitSPUpdate(isARM, MBB, MBBI, dl, TII, -VARegSaveSize); + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -VARegSaveSize, + MachineInstr::FrameSetup); if (!AFI->hasStackFrame()) { if (NumBytes != 0) - emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes); + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes, + MachineInstr::FrameSetup); return; } @@ -196,7 +197,8 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(ADDriOpc), FramePtr) - .addFrameIndex(FramePtrSpillFI).addImm(0); + .addFrameIndex(FramePtrSpillFI).addImm(0) + .setMIFlag(MachineInstr::FrameSetup); AddDefaultCC(AddDefaultPred(MIB)); } @@ -226,7 +228,8 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { NumBytes = DPRCSOffset; if (NumBytes) { // Adjust SP after all the callee-save spills. - emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes); + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes, + MachineInstr::FrameSetup); if (HasFP && isARM) // Restore from fp only in ARM mode: e.g. sub sp, r7, #24 // Note it's not safe to do this in Thumb2 mode because it would have @@ -282,6 +285,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { // of the stack pointer is at this point. Any variable size objects // will be allocated after this, so we can still use the base pointer // to reference locals. + // FIXME: Clarify FrameSetup flags here. if (RegInfo->hasBasePointer(MF)) { if (isARM) BuildMI(MBB, MBBI, dl, @@ -396,8 +400,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, // Jump to label or value in register. if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND) { unsigned TCOpcode = (RetOpcode == ARM::TCRETURNdi) - ? (STI.isThumb() ? ARM::TAILJMPdt : ARM::TAILJMPd) - : (STI.isThumb() ? ARM::TAILJMPdNDt : ARM::TAILJMPdND); + ? (STI.isThumb() ? ARM::tTAILJMPd : ARM::TAILJMPd) + : (STI.isThumb() ? ARM::tTAILJMPdND : ARM::TAILJMPdND); MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode)); if (JumpTarget.isGlobal()) MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(), @@ -408,10 +412,12 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, JumpTarget.getTargetFlags()); } } else if (RetOpcode == ARM::TCRETURNri) { - BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPr)). + BuildMI(MBB, MBBI, dl, + TII.get(STI.isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr)). addReg(JumpTarget.getReg(), RegState::Kill); } else if (RetOpcode == ARM::TCRETURNriND) { - BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPrND)). + BuildMI(MBB, MBBI, dl, + TII.get(STI.isThumb() ? ARM::tTAILJMPrND : ARM::TAILJMPrND)). addReg(JumpTarget.getReg(), RegState::Kill); } @@ -439,8 +445,7 @@ ARMFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, int ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF, - int FI, - unsigned &FrameReg, + int FI, unsigned &FrameReg, int SPAdj) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); const ARMBaseRegisterInfo *RegInfo = @@ -484,19 +489,23 @@ ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF, return FPOffset; } else if (MFI->hasVarSizedObjects()) { assert(RegInfo->hasBasePointer(MF) && "missing base pointer!"); - // Try to use the frame pointer if we can, else use the base pointer - // since it's available. This is handy for the emergency spill slot, in - // particular. if (AFI->isThumb2Function()) { + // Try to use the frame pointer if we can, else use the base pointer + // since it's available. This is handy for the emergency spill slot, in + // particular. if (FPOffset >= -255 && FPOffset < 0) { FrameReg = RegInfo->getFrameRegister(MF); return FPOffset; } - } else - FrameReg = RegInfo->getBaseRegister(); + } } else if (AFI->isThumb2Function()) { + // Use add , sp, # + // ldr , [sp, #] + // if at all possible to save space. + if (Offset >= 0 && (Offset & 3) == 0 && Offset <= 1020) + return Offset; // In Thumb2 mode, the negative offset is very limited. Try to avoid - // out of range references. + // out of range references. ldr ,[, #-] if (FPOffset >= -255 && FPOffset < 0) { FrameReg = RegInfo->getFrameRegister(MF); return FPOffset; @@ -524,7 +533,8 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, const std::vector &CSI, unsigned StmOpc, unsigned StrOpc, bool NoGap, - bool(*Func)(unsigned, bool)) const { + bool(*Func)(unsigned, bool), + unsigned MIFlags) const { MachineFunction &MF = *MBB.getParent(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); @@ -567,14 +577,14 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, if (Regs.size() > 1 || StrOpc== 0) { MachineInstrBuilder MIB = AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(StmOpc), ARM::SP) - .addReg(ARM::SP)); + .addReg(ARM::SP).setMIFlags(MIFlags)); for (unsigned i = 0, e = Regs.size(); i < e; ++i) MIB.addReg(Regs[i].first, getKillRegState(Regs[i].second)); } else if (Regs.size() == 1) { MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc), ARM::SP) .addReg(Regs[0].first, getKillRegState(Regs[0].second)) - .addReg(ARM::SP); + .addReg(ARM::SP).setMIFlags(MIFlags); // ARM mode needs an extra reg0 here due to addrmode2. Will go away once // that refactoring is complete (eventually). if (StrOpc == ARM::STR_PRE) { @@ -676,9 +686,12 @@ bool ARMFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD; unsigned PushOneOpc = AFI->isThumbFunction() ? ARM::t2STR_PRE : ARM::STR_PRE; unsigned FltOpc = ARM::VSTMDDB_UPD; - emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register); - emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea2Register); - emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register); + emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register, + MachineInstr::FrameSetup); + emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea2Register, + MachineInstr::FrameSetup); + emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register, + MachineInstr::FrameSetup); return true; } diff --git a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.h b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.h index 1288b706c599..61bb8afa40f2 100644 --- a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.h +++ b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.h @@ -51,7 +51,8 @@ class ARMFrameLowering : public TargetFrameLowering { bool canSimplifyCallFramePseudos(const MachineFunction &MF) const; int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const; - int ResolveFrameIndexReference(const MachineFunction &MF, int FI, + int ResolveFrameIndexReference(const MachineFunction &MF, + int FI, unsigned &FrameReg, int SPAdj) const; int getFrameIndexOffset(const MachineFunction &MF, int FI) const; @@ -62,7 +63,8 @@ class ARMFrameLowering : public TargetFrameLowering { void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector &CSI, unsigned StmOpc, unsigned StrOpc, bool NoGap, - bool(*Func)(unsigned, bool)) const; + bool(*Func)(unsigned, bool), + unsigned MIFlags = 0) const; void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector &CSI, unsigned LdmOpc, unsigned LdrOpc, bool isVarArg, bool NoGap, diff --git a/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp b/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp index e97ce50bc429..517bba8cee8e 100644 --- a/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp @@ -49,6 +49,8 @@ ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { const TargetInstrDesc &LastTID = LastMI->getDesc(); // Skip over one non-VFP / NEON instruction. if (!LastTID.isBarrier() && + // On A9, AGU and NEON/FPU are muxed. + !(STI.isCortexA9() && (LastTID.mayLoad() || LastTID.mayStore())) && (LastTID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { MachineBasicBlock::iterator I = LastMI; if (I != LastMI->getParent()->begin()) { diff --git a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp index f0d5a7d7c2e7..abe5a316a45b 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -45,7 +45,7 @@ DisableShifterOp("disable-shifter-op", cl::Hidden, static cl::opt CheckVMLxHazard("check-vmlx-hazard", cl::Hidden, cl::desc("Check fp vmla / vmls hazard at isel time"), - cl::init(false)); + cl::init(true)); //===--------------------------------------------------------------------===// /// ARMDAGToDAGISel - ARM specific code to select ARM machine @@ -91,9 +91,14 @@ class ARMDAGToDAGISel : public SelectionDAGISel { bool isShifterOpProfitable(const SDValue &Shift, ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt); bool SelectShifterOperandReg(SDValue N, SDValue &A, - SDValue &B, SDValue &C); + SDValue &B, SDValue &C, + bool CheckProfitability = true); bool SelectShiftShifterOperandReg(SDValue N, SDValue &A, - SDValue &B, SDValue &C); + SDValue &B, SDValue &C) { + // Don't apply the profitability check + return SelectShifterOperandReg(N, A, B, C, false); + } + bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); @@ -174,16 +179,6 @@ class ARMDAGToDAGISel : public SelectionDAGISel { return ARM_AM::getT2SOImmVal(~Imm) != -1; } - inline bool Pred_so_imm(SDNode *inN) const { - ConstantSDNode *N = cast(inN); - return is_so_imm(N->getZExtValue()); - } - - inline bool Pred_t2_so_imm(SDNode *inN) const { - ConstantSDNode *N = cast(inN); - return is_t2_so_imm(N->getZExtValue()); - } - // Include the pieces autogenerated from the target description. #include "ARMGenDAGISel.inc" @@ -373,7 +368,8 @@ bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift, bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N, SDValue &BaseReg, SDValue &ShReg, - SDValue &Opc) { + SDValue &Opc, + bool CheckProfitability) { if (DisableShifterOp) return false; @@ -390,7 +386,7 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N, ShImmVal = RHS->getZExtValue() & 31; } else { ShReg = N.getOperand(1); - if (!isShifterOpProfitable(N, ShOpcVal, ShImmVal)) + if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal)) return false; } Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), @@ -398,30 +394,6 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N, return true; } -bool ARMDAGToDAGISel::SelectShiftShifterOperandReg(SDValue N, - SDValue &BaseReg, - SDValue &ShReg, - SDValue &Opc) { - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); - - // Don't match base register only case. That is matched to a separate - // lower complexity pattern with explicit register operand. - if (ShOpcVal == ARM_AM::no_shift) return false; - - BaseReg = N.getOperand(0); - unsigned ShImmVal = 0; - // Do not check isShifterOpProfitable. This must return true. - if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { - ShReg = CurDAG->getRegister(0, MVT::i32); - ShImmVal = RHS->getZExtValue() & 31; - } else { - ShReg = N.getOperand(1); - } - Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), - MVT::i32); - return true; -} - bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm) { @@ -437,7 +409,7 @@ bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N, OffImm = CurDAG->getTargetConstant(0, MVT::i32); return true; } - + if (N.getOpcode() == ARMISD::Wrapper && !(Subtarget->useMovt() && N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { @@ -1138,7 +1110,7 @@ bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N, OffImm = CurDAG->getTargetConstant(0, MVT::i32); return true; } - + if (N.getOpcode() == ARMISD::Wrapper && !(Subtarget->useMovt() && N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { @@ -1183,7 +1155,7 @@ bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N, if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && !CurDAG->isBaseWithConstantOffset(N)) return false; - + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { int RHSC = (int)RHS->getSExtValue(); if (N.getOpcode() == ISD::SUB) @@ -1571,6 +1543,11 @@ SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, Ops.data(), Ops.size()); } + // Transfer memoperands. + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = cast(N)->getMemOperand(); + cast(VLd)->setMemRefs(MemOp, MemOp + 1); + if (NumVecs == 1) return VLd; @@ -1600,6 +1577,9 @@ SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) return NULL; + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = cast(N)->getMemOperand(); + SDValue Chain = N->getOperand(0); EVT VT = N->getOperand(Vec0Idx).getValueType(); bool is64BitVector = VT.is64BitVector(); @@ -1672,7 +1652,13 @@ SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, Ops.push_back(Pred); Ops.push_back(Reg0); Ops.push_back(Chain); - return CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size()); + SDNode *VSt = + CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size()); + + // Transfer memoperands. + cast(VSt)->setMemRefs(MemOp, MemOp + 1); + + return VSt; } // Otherwise, quad registers are stored with two separate instructions, @@ -1693,6 +1679,7 @@ SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, MemAddr.getValueType(), MVT::Other, OpsA, 7); + cast(VStA)->setMemRefs(MemOp, MemOp + 1); Chain = SDValue(VStA, 1); // Store the odd D registers. @@ -1709,8 +1696,10 @@ SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, Ops.push_back(Pred); Ops.push_back(Reg0); Ops.push_back(Chain); - return CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, - Ops.data(), Ops.size()); + SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, + Ops.data(), Ops.size()); + cast(VStB)->setMemRefs(MemOp, MemOp + 1); + return VStB; } SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, @@ -1726,6 +1715,9 @@ SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) return NULL; + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = cast(N)->getMemOperand(); + SDValue Chain = N->getOperand(0); unsigned Lane = cast(N->getOperand(Vec0Idx + NumVecs))->getZExtValue(); @@ -1812,6 +1804,7 @@ SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, QOpcodes[OpcodeIndex]); SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size()); + cast(VLdLn)->setMemRefs(MemOp, MemOp + 1); if (!IsLoad) return VLdLn; @@ -1838,6 +1831,9 @@ SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align)) return NULL; + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = cast(N)->getMemOperand(); + SDValue Chain = N->getOperand(0); EVT VT = N->getValueType(0); @@ -1882,12 +1878,13 @@ SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; std::vector ResTys; - ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts)); + ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts)); if (isUpdating) ResTys.push_back(MVT::i32); ResTys.push_back(MVT::Other); SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size()); + cast(VLdDup)->setMemRefs(MemOp, MemOp + 1); SuperReg = SDValue(VLdDup, 0); // Extract the subregisters. @@ -2168,7 +2165,7 @@ SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) // Pattern complexity = 6 cost = 11 size = 0 // - // Also FCPYScc and FCPYDcc. + // Also VMOVScc and VMOVDcc. SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; unsigned Opc = 0; @@ -2450,34 +2447,6 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { } case ARMISD::CMOV: return SelectCMOVOp(N); - case ARMISD::CNEG: { - EVT VT = N->getValueType(0); - SDValue N0 = N->getOperand(0); - SDValue N1 = N->getOperand(1); - SDValue N2 = N->getOperand(2); - SDValue N3 = N->getOperand(3); - SDValue InFlag = N->getOperand(4); - assert(N2.getOpcode() == ISD::Constant); - assert(N3.getOpcode() == ISD::Register); - - SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) - cast(N2)->getZExtValue()), - MVT::i32); - SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; - unsigned Opc = 0; - switch (VT.getSimpleVT().SimpleTy) { - default: assert(false && "Illegal conditional move type!"); - break; - case MVT::f32: - Opc = ARM::VNEGScc; - break; - case MVT::f64: - Opc = ARM::VNEGDcc; - break; - } - return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); - } - case ARMISD::VZIP: { unsigned Opc = 0; EVT VT = N->getValueType(0); @@ -2870,6 +2839,35 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { break; } + case ARMISD::VTBL1: { + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + SmallVector Ops; + + Ops.push_back(N->getOperand(0)); + Ops.push_back(N->getOperand(1)); + Ops.push_back(getAL(CurDAG)); // Predicate + Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register + return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops.data(), Ops.size()); + } + case ARMISD::VTBL2: { + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + + // Form a REG_SEQUENCE to force register allocation. + SDValue V0 = N->getOperand(0); + SDValue V1 = N->getOperand(1); + SDValue RegSeq = SDValue(PairDRegs(MVT::v16i8, V0, V1), 0); + + SmallVector Ops; + Ops.push_back(RegSeq); + Ops.push_back(N->getOperand(2)); + Ops.push_back(getAL(CurDAG)); // Predicate + Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register + return CurDAG->getMachineNode(ARM::VTBL2Pseudo, dl, VT, + Ops.data(), Ops.size()); + } + case ISD::CONCAT_VECTORS: return SelectConcatVector(N); } diff --git a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp index ab9f9e1571e3..0a31b87c4b56 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -72,6 +72,11 @@ ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true)); +// The APCS parameter registers. +static const unsigned GPRArgRegs[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3 +}; + void ARMTargetLowering::addTypeForNEON(EVT VT, EVT PromotedLdStVT, EVT PromotedBitwiseVT) { if (VT != PromotedLdStVT) { @@ -393,6 +398,12 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setLibcallCallingConv(RTLIB::UDIV_I32, CallingConv::ARM_AAPCS); } + // Use divmod iOS compiler-rt calls. + if (Subtarget->getTargetTriple().getOS() == Triple::IOS) { + setLibcallName(RTLIB::SDIVREM_I32, "__divmodsi4"); + setLibcallName(RTLIB::UDIVREM_I32, "__udivmodsi4"); + } + if (Subtarget->isThumb1Only()) addRegisterClass(MVT::i32, ARM::tGPRRegisterClass); else @@ -461,6 +472,10 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::UDIV, MVT::v8i8, Custom); setOperationAction(ISD::VSETCC, MVT::v1i64, Expand); setOperationAction(ISD::VSETCC, MVT::v2i64, Expand); + // Neon does not have single instruction SINT_TO_FP and UINT_TO_FP with + // a destination type that is wider than the source. + setOperationAction(ISD::SINT_TO_FP, MVT::v4i16, Custom); + setOperationAction(ISD::UINT_TO_FP, MVT::v4i16, Custom); setTargetDAGCombine(ISD::INTRINSIC_VOID); setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN); @@ -502,18 +517,15 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) } // i64 operation support. + setOperationAction(ISD::MUL, MVT::i64, Expand); + setOperationAction(ISD::MULHU, MVT::i32, Expand); if (Subtarget->isThumb1Only()) { - setOperationAction(ISD::MUL, MVT::i64, Expand); - setOperationAction(ISD::MULHU, MVT::i32, Expand); - setOperationAction(ISD::MULHS, MVT::i32, Expand); setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); - } else { - setOperationAction(ISD::MUL, MVT::i64, Expand); - setOperationAction(ISD::MULHU, MVT::i32, Expand); - if (!Subtarget->hasV6Ops()) - setOperationAction(ISD::MULHS, MVT::i32, Expand); } + if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()) + setOperationAction(ISD::MULHS, MVT::i32, Expand); + setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); @@ -597,6 +609,18 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i8, Expand); setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, Expand); // Since the libcalls include locking, fold in the fences setShouldFoldAtomicFences(true); } @@ -716,7 +740,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) // pressure of the register class's representative and all of it's super // classes' representatives transitively. We have not implemented this because // of the difficulty prior to coalescing of modeling operand register classes -// due to the common occurence of cross class copies and subregister insertions +// due to the common occurrence of cross class copies and subregister insertions // and extractions. std::pair ARMTargetLowering::findRepresentativeClass(EVT VT) const{ @@ -778,7 +802,6 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { case ARMISD::BCC_i64: return "ARMISD::BCC_i64"; case ARMISD::FMSTAT: return "ARMISD::FMSTAT"; case ARMISD::CMOV: return "ARMISD::CMOV"; - case ARMISD::CNEG: return "ARMISD::CNEG"; case ARMISD::RBIT: return "ARMISD::RBIT"; @@ -853,6 +876,8 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { case ARMISD::VZIP: return "ARMISD::VZIP"; case ARMISD::VUZP: return "ARMISD::VUZP"; case ARMISD::VTRN: return "ARMISD::VTRN"; + case ARMISD::VTBL1: return "ARMISD::VTBL1"; + case ARMISD::VTBL2: return "ARMISD::VTBL2"; case ARMISD::VMULLs: return "ARMISD::VMULLs"; case ARMISD::VMULLu: return "ARMISD::VMULLu"; case ARMISD::BUILD_VECTOR: return "ARMISD::BUILD_VECTOR"; @@ -861,6 +886,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { case ARMISD::BFI: return "ARMISD::BFI"; case ARMISD::VORRIMM: return "ARMISD::VORRIMM"; case ARMISD::VBICIMM: return "ARMISD::VBICIMM"; + case ARMISD::VBSL: return "ARMISD::VBSL"; case ARMISD::VLD2DUP: return "ARMISD::VLD2DUP"; case ARMISD::VLD3DUP: return "ARMISD::VLD3DUP"; case ARMISD::VLD4DUP: return "ARMISD::VLD4DUP"; @@ -946,27 +972,6 @@ Sched::Preference ARMTargetLowering::getSchedulingPreference(SDNode *N) const { return Sched::RegPressure; } -// FIXME: Move to RegInfo -unsigned -ARMTargetLowering::getRegPressureLimit(const TargetRegisterClass *RC, - MachineFunction &MF) const { - const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); - - switch (RC->getID()) { - default: - return 0; - case ARM::tGPRRegClassID: - return TFI->hasFP(MF) ? 4 : 5; - case ARM::GPRRegClassID: { - unsigned FP = TFI->hasFP(MF) ? 1 : 0; - return 10 - FP - (Subtarget->isR9Reserved() ? 1 : 0); - } - case ARM::SPRRegClassID: // Currently not used as 'rep' register class. - case ARM::DPRRegClassID: - return 32 - 10; - } -} - //===----------------------------------------------------------------------===// // Lowering Code //===----------------------------------------------------------------------===// @@ -1130,22 +1135,6 @@ ARMTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, return Chain; } -/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified -/// by "Src" to address "Dst" of size "Size". Alignment information is -/// specified by the specific parameter attribute. The copy will be passed as -/// a byval function parameter. -/// Sometimes what we are copying is the end of a larger object, the part that -/// does not fit in registers. -static SDValue -CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, - ISD::ArgFlagsTy Flags, SelectionDAG &DAG, - DebugLoc dl) { - SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); - return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), - /*isVolatile=*/false, /*AlwaysInline=*/false, - MachinePointerInfo(0), MachinePointerInfo(0)); -} - /// LowerMemOpCallTo - Store the argument to the stack. SDValue ARMTargetLowering::LowerMemOpCallTo(SDValue Chain, @@ -1156,9 +1145,6 @@ ARMTargetLowering::LowerMemOpCallTo(SDValue Chain, unsigned LocMemOffset = VA.getLocMemOffset(); SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); - if (Flags.isByVal()) - return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, dl); - return DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo::getStack(LocMemOffset), false, false, 0); @@ -1224,6 +1210,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SmallVector ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); + CCInfo.setCallOrPrologue(Call); CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForNode(CallConv, /* Return*/ false, isVarArg)); @@ -1253,6 +1240,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, CCValAssign &VA = ArgLocs[i]; SDValue Arg = OutVals[realArgIdx]; ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; + bool isByVal = Flags.isByVal(); // Promote the value if needed. switch (VA.getLocInfo()) { @@ -1299,6 +1287,43 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, } } else if (VA.isRegLoc()) { RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else if (isByVal) { + assert(VA.isMemLoc()); + unsigned offset = 0; + + // True if this byval aggregate will be split between registers + // and memory. + if (CCInfo.isFirstByValRegValid()) { + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + unsigned int i, j; + for (i = 0, j = CCInfo.getFirstByValReg(); j < ARM::R4; i++, j++) { + SDValue Const = DAG.getConstant(4*i, MVT::i32); + SDValue AddArg = DAG.getNode(ISD::ADD, dl, PtrVT, Arg, Const); + SDValue Load = DAG.getLoad(PtrVT, dl, Chain, AddArg, + MachinePointerInfo(), + false, false, 0); + MemOpChains.push_back(Load.getValue(1)); + RegsToPass.push_back(std::make_pair(j, Load)); + } + offset = ARM::R4 - CCInfo.getFirstByValReg(); + CCInfo.clearFirstByValReg(); + } + + unsigned LocMemOffset = VA.getLocMemOffset(); + SDValue StkPtrOff = DAG.getIntPtrConstant(LocMemOffset); + SDValue Dst = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, + StkPtrOff); + SDValue SrcOffset = DAG.getIntPtrConstant(4*offset); + SDValue Src = DAG.getNode(ISD::ADD, dl, getPointerTy(), Arg, SrcOffset); + SDValue SizeNode = DAG.getConstant(Flags.getByValSize() - 4*offset, + MVT::i32); + MemOpChains.push_back(DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, + Flags.getByValAlign(), + /*isVolatile=*/false, + /*AlwaysInline=*/false, + MachinePointerInfo(0), + MachinePointerInfo(0))); + } else if (!IsSibCall) { assert(VA.isMemLoc()); @@ -1332,7 +1357,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // than necessary, because it means that each store effectively depends // on every argument instead of just those arguments it would clobber. - // Do not flag preceeding copytoreg stuff together with the following stuff. + // Do not flag preceding copytoreg stuff together with the following stuff. InFlag = SDValue(); for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, @@ -1492,6 +1517,35 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, dl, DAG, InVals); } +/// HandleByVal - Every parameter *after* a byval parameter is passed +/// on the stack. Remember the next parameter register to allocate, +/// and then confiscate the rest of the parameter registers to insure +/// this. +void +llvm::ARMTargetLowering::HandleByVal(CCState *State, unsigned &size) const { + unsigned reg = State->AllocateReg(GPRArgRegs, 4); + assert((State->getCallOrPrologue() == Prologue || + State->getCallOrPrologue() == Call) && + "unhandled ParmContext"); + if ((!State->isFirstByValRegValid()) && + (ARM::R0 <= reg) && (reg <= ARM::R3)) { + State->setFirstByValReg(reg); + // At a call site, a byval parameter that is split between + // registers and memory needs its size truncated here. In a + // function prologue, such byval parameters are reassembled in + // memory, and are not truncated. + if (State->getCallOrPrologue() == Call) { + unsigned excess = 4 * (ARM::R4 - reg); + assert(size >= excess && "expected larger existing stack allocation"); + size -= excess; + } + } + // Confiscate any remaining parameter registers to preclude their + // assignment to subsequent parameters. + while (State->AllocateReg(GPRArgRegs, 4)) + ; +} + /// MatchingStackOffset - Return true if the given stack call argument is /// already available in the same position (relatively) of the caller's /// incoming argument stack. @@ -1813,6 +1867,16 @@ bool ARMTargetLowering::isUsedByReturnOnly(SDNode *N) const { return HasRet; } +bool ARMTargetLowering::mayBeEmittedAsTailCall(CallInst *CI) const { + if (!EnableARMTailCalls) + return false; + + if (!CI->isTailCall()) + return false; + + return !Subtarget->isThumb1Only(); +} + // ConstantPool, JumpTable, GlobalAddress, and ExternalSymbol are lowered as // their target counterpart wrapped in the ARMISD::Wrapper node. Suppose N is // one of the above mentioned nodes. It has to be wrapped because otherwise @@ -2096,7 +2160,7 @@ ARMTargetLowering::LowerEH_SJLJ_DISPATCHSETUP(SDValue Op, SelectionDAG &DAG) const { DebugLoc dl = Op.getDebugLoc(); return DAG.getNode(ARMISD::EH_SJLJ_DISPATCHSETUP, dl, MVT::Other, - Op.getOperand(0), Op.getOperand(1)); + Op.getOperand(0)); } SDValue @@ -2151,6 +2215,13 @@ ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG, } return Result; } + case Intrinsic::arm_neon_vmulls: + case Intrinsic::arm_neon_vmullu: { + unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls) + ? ARMISD::VMULLs : ARMISD::VMULLu; + return DAG.getNode(NewOpc, Op.getDebugLoc(), Op.getValueType(), + Op.getOperand(1), Op.getOperand(2)); + } } } @@ -2257,6 +2328,88 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA, return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2); } +void +ARMTargetLowering::computeRegArea(CCState &CCInfo, MachineFunction &MF, + unsigned &VARegSize, unsigned &VARegSaveSize) + const { + unsigned NumGPRs; + if (CCInfo.isFirstByValRegValid()) + NumGPRs = ARM::R4 - CCInfo.getFirstByValReg(); + else { + unsigned int firstUnalloced; + firstUnalloced = CCInfo.getFirstUnallocated(GPRArgRegs, + sizeof(GPRArgRegs) / + sizeof(GPRArgRegs[0])); + NumGPRs = (firstUnalloced <= 3) ? (4 - firstUnalloced) : 0; + } + + unsigned Align = MF.getTarget().getFrameLowering()->getStackAlignment(); + VARegSize = NumGPRs * 4; + VARegSaveSize = (VARegSize + Align - 1) & ~(Align - 1); +} + +// The remaining GPRs hold either the beginning of variable-argument +// data, or the beginning of an aggregate passed by value (usuall +// byval). Either way, we allocate stack slots adjacent to the data +// provided by our caller, and store the unallocated registers there. +// If this is a variadic function, the va_list pointer will begin with +// these values; otherwise, this reassembles a (byval) structure that +// was split between registers and memory. +void +ARMTargetLowering::VarArgStyleRegisters(CCState &CCInfo, SelectionDAG &DAG, + DebugLoc dl, SDValue &Chain, + unsigned ArgOffset) const { + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned firstRegToSaveIndex; + if (CCInfo.isFirstByValRegValid()) + firstRegToSaveIndex = CCInfo.getFirstByValReg() - ARM::R0; + else { + firstRegToSaveIndex = CCInfo.getFirstUnallocated + (GPRArgRegs, sizeof(GPRArgRegs) / sizeof(GPRArgRegs[0])); + } + + unsigned VARegSize, VARegSaveSize; + computeRegArea(CCInfo, MF, VARegSize, VARegSaveSize); + if (VARegSaveSize) { + // If this function is vararg, store any remaining integer argument regs + // to their spots on the stack so that they may be loaded by deferencing + // the result of va_next. + AFI->setVarArgsRegSaveSize(VARegSaveSize); + AFI->setVarArgsFrameIndex(MFI->CreateFixedObject(VARegSaveSize, + ArgOffset + VARegSaveSize + - VARegSize, + false)); + SDValue FIN = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(), + getPointerTy()); + + SmallVector MemOps; + for (; firstRegToSaveIndex < 4; ++firstRegToSaveIndex) { + TargetRegisterClass *RC; + if (AFI->isThumb1OnlyFunction()) + RC = ARM::tGPRRegisterClass; + else + RC = ARM::GPRRegisterClass; + + unsigned VReg = MF.addLiveIn(GPRArgRegs[firstRegToSaveIndex], RC); + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); + SDValue Store = + DAG.getStore(Val.getValue(1), dl, Val, FIN, + MachinePointerInfo::getFixedStack(AFI->getVarArgsFrameIndex()), + false, false, 0); + MemOps.push_back(Store); + FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN, + DAG.getConstant(4, getPointerTy())); + } + if (!MemOps.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOps[0], MemOps.size()); + } else + // This will point to the next argument passed via stack. + AFI->setVarArgsFrameIndex(MFI->CreateFixedObject(4, ArgOffset, true)); +} + SDValue ARMTargetLowering::LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, @@ -2265,7 +2418,6 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl &InVals) const { - MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -2275,12 +2427,15 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, SmallVector ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); + CCInfo.setCallOrPrologue(Prologue); CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForNode(CallConv, /* Return*/ false, isVarArg)); SmallVector ArgValues; + int lastInsIndex = -1; + SDValue ArgValue; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -2288,7 +2443,6 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, if (VA.isRegLoc()) { EVT RegVT = VA.getLocVT(); - SDValue ArgValue; if (VA.needsCustom()) { // f64 and vector types are split up into multiple registers or // combinations of registers and stack slots. @@ -2364,67 +2518,45 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, assert(VA.isMemLoc()); assert(VA.getValVT() != MVT::i64 && "i64 should already be lowered"); - unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; - int FI = MFI->CreateFixedObject(ArgSize, VA.getLocMemOffset(), true); + int index = ArgLocs[i].getValNo(); - // Create load nodes to retrieve arguments from the stack. - SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); - InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, - MachinePointerInfo::getFixedStack(FI), - false, false, 0)); + // Some Ins[] entries become multiple ArgLoc[] entries. + // Process them only once. + if (index != lastInsIndex) + { + ISD::ArgFlagsTy Flags = Ins[index].Flags; + // FIXME: For now, all byval parameter objects are marked mutable. + // This can be changed with more analysis. + // In case of tail call optimization mark all arguments mutable. + // Since they could be overwritten by lowering of arguments in case of + // a tail call. + if (Flags.isByVal()) { + unsigned VARegSize, VARegSaveSize; + computeRegArea(CCInfo, MF, VARegSize, VARegSaveSize); + VarArgStyleRegisters(CCInfo, DAG, dl, Chain, 0); + unsigned Bytes = Flags.getByValSize() - VARegSize; + if (Bytes == 0) Bytes = 1; // Don't create zero-sized stack objects. + int FI = MFI->CreateFixedObject(Bytes, + VA.getLocMemOffset(), false); + InVals.push_back(DAG.getFrameIndex(FI, getPointerTy())); + } else { + int FI = MFI->CreateFixedObject(VA.getLocVT().getSizeInBits()/8, + VA.getLocMemOffset(), true); + + // Create load nodes to retrieve arguments from the stack. + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), + false, false, 0)); + } + lastInsIndex = index; + } } } // varargs - if (isVarArg) { - static const unsigned GPRArgRegs[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3 - }; - - unsigned NumGPRs = CCInfo.getFirstUnallocated - (GPRArgRegs, sizeof(GPRArgRegs) / sizeof(GPRArgRegs[0])); - - unsigned Align = MF.getTarget().getFrameLowering()->getStackAlignment(); - unsigned VARegSize = (4 - NumGPRs) * 4; - unsigned VARegSaveSize = (VARegSize + Align - 1) & ~(Align - 1); - unsigned ArgOffset = CCInfo.getNextStackOffset(); - if (VARegSaveSize) { - // If this function is vararg, store any remaining integer argument regs - // to their spots on the stack so that they may be loaded by deferencing - // the result of va_next. - AFI->setVarArgsRegSaveSize(VARegSaveSize); - AFI->setVarArgsFrameIndex( - MFI->CreateFixedObject(VARegSaveSize, - ArgOffset + VARegSaveSize - VARegSize, - false)); - SDValue FIN = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(), - getPointerTy()); - - SmallVector MemOps; - for (; NumGPRs < 4; ++NumGPRs) { - TargetRegisterClass *RC; - if (AFI->isThumb1OnlyFunction()) - RC = ARM::tGPRRegisterClass; - else - RC = ARM::GPRRegisterClass; - - unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC); - SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); - SDValue Store = - DAG.getStore(Val.getValue(1), dl, Val, FIN, - MachinePointerInfo::getFixedStack(AFI->getVarArgsFrameIndex()), - false, false, 0); - MemOps.push_back(Store); - FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN, - DAG.getConstant(4, getPointerTy())); - } - if (!MemOps.empty()) - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - &MemOps[0], MemOps.size()); - } else - // This will point to the next argument passed via stack. - AFI->setVarArgsFrameIndex(MFI->CreateFixedObject(4, ArgOffset, true)); - } + if (isVarArg) + VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.getNextStackOffset()); return Chain; } @@ -2517,6 +2649,27 @@ ARMTargetLowering::getVFPCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG, return DAG.getNode(ARMISD::FMSTAT, dl, MVT::Glue, Cmp); } +/// duplicateCmp - Glue values can have only one use, so this function +/// duplicates a comparison node. +SDValue +ARMTargetLowering::duplicateCmp(SDValue Cmp, SelectionDAG &DAG) const { + unsigned Opc = Cmp.getOpcode(); + DebugLoc DL = Cmp.getDebugLoc(); + if (Opc == ARMISD::CMP || Opc == ARMISD::CMPZ) + return DAG.getNode(Opc, DL, MVT::Glue, Cmp.getOperand(0),Cmp.getOperand(1)); + + assert(Opc == ARMISD::FMSTAT && "unexpected comparison operation"); + Cmp = Cmp.getOperand(0); + Opc = Cmp.getOpcode(); + if (Opc == ARMISD::CMPFP) + Cmp = DAG.getNode(Opc, DL, MVT::Glue, Cmp.getOperand(0),Cmp.getOperand(1)); + else { + assert(Opc == ARMISD::CMPFPw0 && "unexpected operand of FMSTAT"); + Cmp = DAG.getNode(Opc, DL, MVT::Glue, Cmp.getOperand(0)); + } + return DAG.getNode(ARMISD::FMSTAT, DL, MVT::Glue, Cmp); +} + SDValue ARMTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { SDValue Cond = Op.getOperand(0); SDValue SelectTrue = Op.getOperand(1); @@ -2552,7 +2705,7 @@ SDValue ARMTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { EVT VT = Cond.getValueType(); SDValue ARMcc = Cond.getOperand(2); SDValue CCR = Cond.getOperand(3); - SDValue Cmp = Cond.getOperand(4); + SDValue Cmp = duplicateCmp(Cond.getOperand(4), DAG); return DAG.getNode(ARMISD::CMOV, dl, VT, True, False, ARMcc, CCR, Cmp); } } @@ -2681,8 +2834,8 @@ ARMTargetLowering::OptimizeVFPBrcond(SDValue Op, SelectionDAG &DAG) const { // If one of the operand is zero, it's safe to ignore the NaN case since // we only care about equality comparisons. (SeenZero || (DAG.isKnownNeverNaN(LHS) && DAG.isKnownNeverNaN(RHS)))) { - // If unsafe fp math optimization is enabled and there are no othter uses of - // the CMP operands, and the condition code is EQ oe NE, we can optimize it + // If unsafe fp math optimization is enabled and there are no other uses of + // the CMP operands, and the condition code is EQ or NE, we can optimize it // to an integer comparison. if (CC == ISD::SETOEQ) CC = ISD::SETEQ; @@ -2811,8 +2964,39 @@ static SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) { return DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op); } +static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + + EVT OperandVT = Op.getOperand(0).getValueType(); + assert(OperandVT == MVT::v4i16 && "Invalid type for custom lowering!"); + if (VT != MVT::v4f32) + return DAG.UnrollVectorOp(Op.getNode()); + + unsigned CastOpc; + unsigned Opc; + switch (Op.getOpcode()) { + default: + assert(0 && "Invalid opcode!"); + case ISD::SINT_TO_FP: + CastOpc = ISD::SIGN_EXTEND; + Opc = ISD::SINT_TO_FP; + break; + case ISD::UINT_TO_FP: + CastOpc = ISD::ZERO_EXTEND; + Opc = ISD::UINT_TO_FP; + break; + } + + Op = DAG.getNode(CastOpc, dl, MVT::v4i32, Op.getOperand(0)); + return DAG.getNode(Opc, dl, VT, Op); +} + static SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) { EVT VT = Op.getValueType(); + if (VT.isVector()) + return LowerVectorINT_TO_FP(Op, DAG); + DebugLoc dl = Op.getDebugLoc(); unsigned Opc; @@ -2860,7 +3044,10 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { Tmp1 = DAG.getNode(ARMISD::VSHL, dl, OpVT, DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1), DAG.getConstant(32, MVT::i32)); - } + } else if (VT == MVT::f32) + Tmp1 = DAG.getNode(ARMISD::VSHRu, dl, MVT::v1i64, + DAG.getNode(ISD::BITCAST, dl, MVT::v1i64, Tmp1), + DAG.getConstant(32, MVT::i32)); Tmp0 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp0); Tmp1 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1); @@ -2869,11 +3056,11 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { AllOnes = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v8i8, AllOnes); SDValue MaskNot = DAG.getNode(ISD::XOR, dl, OpVT, Mask, DAG.getNode(ISD::BITCAST, dl, OpVT, AllOnes)); - + SDValue Res = DAG.getNode(ISD::OR, dl, OpVT, DAG.getNode(ISD::AND, dl, OpVT, Tmp1, Mask), DAG.getNode(ISD::AND, dl, OpVT, Tmp0, MaskNot)); - if (SrcVT == MVT::f32) { + if (VT == MVT::f32) { Res = DAG.getNode(ISD::BITCAST, dl, MVT::v2f32, Res); Res = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f32, Res, DAG.getConstant(0, MVT::i32)); @@ -3508,6 +3695,13 @@ static bool isVREVMask(const SmallVectorImpl &M, EVT VT, return true; } +static bool isVTBLMask(const SmallVectorImpl &M, EVT VT) { + // We can handle <8 x i8> vector shuffles. If the index in the mask is out of + // range, then 0 is placed into the resulting vector. So pretty much any mask + // of 8 elements can work here. + return VT == MVT::v8i8 && M.size() == 8; +} + static bool isVTRNMask(const SmallVectorImpl &M, EVT VT, unsigned &WhichResult) { unsigned EltSz = VT.getVectorElementType().getSizeInBits(); @@ -3947,6 +4141,7 @@ ARMTargetLowering::isShuffleMaskLegal(const SmallVectorImpl &M, isVREVMask(M, VT, 32) || isVREVMask(M, VT, 16) || isVEXTMask(M, VT, ReverseVEXT, Imm) || + isVTBLMask(M, VT) || isVTRNMask(M, VT, WhichResult) || isVUZPMask(M, VT, WhichResult) || isVZIPMask(M, VT, WhichResult) || @@ -4024,6 +4219,29 @@ static SDValue GeneratePerfectShuffle(unsigned PFEntry, SDValue LHS, } } +static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, + SmallVectorImpl &ShuffleMask, + SelectionDAG &DAG) { + // Check to see if we can use the VTBL instruction. + SDValue V1 = Op.getOperand(0); + SDValue V2 = Op.getOperand(1); + DebugLoc DL = Op.getDebugLoc(); + + SmallVector VTBLMask; + for (SmallVectorImpl::iterator + I = ShuffleMask.begin(), E = ShuffleMask.end(); I != E; ++I) + VTBLMask.push_back(DAG.getConstant(*I, MVT::i32)); + + if (V2.getNode()->getOpcode() == ISD::UNDEF) + return DAG.getNode(ARMISD::VTBL1, DL, MVT::v8i8, V1, + DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v8i8, + &VTBLMask[0], 8)); + + return DAG.getNode(ARMISD::VTBL2, DL, MVT::v8i8, V1, V2, + DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v8i8, + &VTBLMask[0], 8)); +} + static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { SDValue V1 = Op.getOperand(0); SDValue V2 = Op.getOperand(1); @@ -4141,6 +4359,12 @@ static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { return DAG.getNode(ISD::BITCAST, dl, VT, Val); } + if (VT == MVT::v8i8) { + SDValue NewOp = LowerVECTOR_SHUFFLEv8i8(Op, ShuffleMask, DAG); + if (NewOp.getNode()) + return NewOp; + } + return SDValue(); } @@ -4290,6 +4514,28 @@ static SDValue SkipExtension(SDNode *N, SelectionDAG &DAG) { MVT::getVectorVT(TruncVT, NumElts), Ops.data(), NumElts); } +static bool isAddSubSExt(SDNode *N, SelectionDAG &DAG) { + unsigned Opcode = N->getOpcode(); + if (Opcode == ISD::ADD || Opcode == ISD::SUB) { + SDNode *N0 = N->getOperand(0).getNode(); + SDNode *N1 = N->getOperand(1).getNode(); + return N0->hasOneUse() && N1->hasOneUse() && + isSignExtended(N0, DAG) && isSignExtended(N1, DAG); + } + return false; +} + +static bool isAddSubZExt(SDNode *N, SelectionDAG &DAG) { + unsigned Opcode = N->getOpcode(); + if (Opcode == ISD::ADD || Opcode == ISD::SUB) { + SDNode *N0 = N->getOperand(0).getNode(); + SDNode *N1 = N->getOperand(1).getNode(); + return N0->hasOneUse() && N1->hasOneUse() && + isZeroExtended(N0, DAG) && isZeroExtended(N1, DAG); + } + return false; +} + static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) { // Multiplications are only custom-lowered for 128-bit vectors so that // VMULL can be detected. Otherwise v2i64 multiplications are not legal. @@ -4298,29 +4544,73 @@ static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) { SDNode *N0 = Op.getOperand(0).getNode(); SDNode *N1 = Op.getOperand(1).getNode(); unsigned NewOpc = 0; - if (isSignExtended(N0, DAG) && isSignExtended(N1, DAG)) + bool isMLA = false; + bool isN0SExt = isSignExtended(N0, DAG); + bool isN1SExt = isSignExtended(N1, DAG); + if (isN0SExt && isN1SExt) NewOpc = ARMISD::VMULLs; - else if (isZeroExtended(N0, DAG) && isZeroExtended(N1, DAG)) - NewOpc = ARMISD::VMULLu; - else if (VT == MVT::v2i64) - // Fall through to expand this. It is not legal. - return SDValue(); - else - // Other vector multiplications are legal. - return Op; + else { + bool isN0ZExt = isZeroExtended(N0, DAG); + bool isN1ZExt = isZeroExtended(N1, DAG); + if (isN0ZExt && isN1ZExt) + NewOpc = ARMISD::VMULLu; + else if (isN1SExt || isN1ZExt) { + // Look for (s/zext A + s/zext B) * (s/zext C). We want to turn these + // into (s/zext A * s/zext C) + (s/zext B * s/zext C) + if (isN1SExt && isAddSubSExt(N0, DAG)) { + NewOpc = ARMISD::VMULLs; + isMLA = true; + } else if (isN1ZExt && isAddSubZExt(N0, DAG)) { + NewOpc = ARMISD::VMULLu; + isMLA = true; + } else if (isN0ZExt && isAddSubZExt(N1, DAG)) { + std::swap(N0, N1); + NewOpc = ARMISD::VMULLu; + isMLA = true; + } + } + + if (!NewOpc) { + if (VT == MVT::v2i64) + // Fall through to expand this. It is not legal. + return SDValue(); + else + // Other vector multiplications are legal. + return Op; + } + } // Legalize to a VMULL instruction. DebugLoc DL = Op.getDebugLoc(); - SDValue Op0 = SkipExtension(N0, DAG); + SDValue Op0; SDValue Op1 = SkipExtension(N1, DAG); + if (!isMLA) { + Op0 = SkipExtension(N0, DAG); + assert(Op0.getValueType().is64BitVector() && + Op1.getValueType().is64BitVector() && + "unexpected types for extended operands to VMULL"); + return DAG.getNode(NewOpc, DL, VT, Op0, Op1); + } - assert(Op0.getValueType().is64BitVector() && - Op1.getValueType().is64BitVector() && - "unexpected types for extended operands to VMULL"); - return DAG.getNode(NewOpc, DL, VT, Op0, Op1); + // Optimizing (zext A + zext B) * C, to (VMULL A, C) + (VMULL B, C) during + // isel lowering to take advantage of no-stall back to back vmul + vmla. + // vmull q0, d4, d6 + // vmlal q0, d5, d6 + // is faster than + // vaddl q0, d4, d5 + // vmovl q1, d6 + // vmul q0, q0, q1 + SDValue N00 = SkipExtension(N0->getOperand(0).getNode(), DAG); + SDValue N01 = SkipExtension(N0->getOperand(1).getNode(), DAG); + EVT Op1VT = Op1.getValueType(); + return DAG.getNode(N0->getOpcode(), DL, VT, + DAG.getNode(NewOpc, DL, VT, + DAG.getNode(ISD::BITCAST, DL, Op1VT, N00), Op1), + DAG.getNode(NewOpc, DL, VT, + DAG.getNode(ISD::BITCAST, DL, Op1VT, N01), Op1)); } -static SDValue +static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, DebugLoc dl, SelectionDAG &DAG) { // Convert to float // float4 xf = vcvt_f32_s32(vmovl_s16(a.lo)); @@ -4331,7 +4621,7 @@ LowerSDIV_v4i8(SDValue X, SDValue Y, DebugLoc dl, SelectionDAG &DAG) { Y = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, Y); // Get reciprocal estimate. // float4 recip = vrecpeq_f32(yf); - Y = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + Y = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, DAG.getConstant(Intrinsic::arm_neon_vrecpe, MVT::i32), Y); // Because char has a smaller range than uchar, we can actually get away // without any newton steps. This requires that we use a weird bias @@ -4349,7 +4639,7 @@ LowerSDIV_v4i8(SDValue X, SDValue Y, DebugLoc dl, SelectionDAG &DAG) { return X; } -static SDValue +static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, DebugLoc dl, SelectionDAG &DAG) { SDValue N2; // Convert to float. @@ -4359,13 +4649,13 @@ LowerSDIV_v4i16(SDValue N0, SDValue N1, DebugLoc dl, SelectionDAG &DAG) { N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v4i32, N1); N0 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, N0); N1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, N1); - + // Use reciprocal estimate and one refinement step. // float4 recip = vrecpeq_f32(yf); // recip *= vrecpsq_f32(yf, recip); - N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, DAG.getConstant(Intrinsic::arm_neon_vrecpe, MVT::i32), N1); - N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, DAG.getConstant(Intrinsic::arm_neon_vrecps, MVT::i32), N1, N2); N2 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N1, N2); @@ -4395,15 +4685,15 @@ static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG) { SDValue N0 = Op.getOperand(0); SDValue N1 = Op.getOperand(1); SDValue N2, N3; - + if (VT == MVT::v8i8) { N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v8i16, N0); N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v8i16, N1); - + N2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, DAG.getIntPtrConstant(4)); N3 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, - DAG.getIntPtrConstant(4)); + DAG.getIntPtrConstant(4)); N0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, DAG.getIntPtrConstant(0)); N1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, @@ -4414,7 +4704,7 @@ static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG) { N0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v8i16, N0, N2); N0 = LowerCONCAT_VECTORS(N0, DAG); - + N0 = DAG.getNode(ISD::TRUNCATE, dl, MVT::v8i8, N0); return N0; } @@ -4430,32 +4720,32 @@ static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG) { SDValue N0 = Op.getOperand(0); SDValue N1 = Op.getOperand(1); SDValue N2, N3; - + if (VT == MVT::v8i8) { N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::v8i16, N0); N1 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::v8i16, N1); - + N2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, DAG.getIntPtrConstant(4)); N3 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, - DAG.getIntPtrConstant(4)); + DAG.getIntPtrConstant(4)); N0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, DAG.getIntPtrConstant(0)); N1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, DAG.getIntPtrConstant(0)); - + N0 = LowerSDIV_v4i16(N0, N1, dl, DAG); // v4i16 N2 = LowerSDIV_v4i16(N2, N3, dl, DAG); // v4i16 - + N0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v8i16, N0, N2); N0 = LowerCONCAT_VECTORS(N0, DAG); - - N0 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v8i8, + + N0 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v8i8, DAG.getConstant(Intrinsic::arm_neon_vqmovnsu, MVT::i32), N0); return N0; } - + // v4i16 sdiv ... Convert to float. // float4 yf = vcvt_f32_s32(vmovl_u16(y)); // float4 xf = vcvt_f32_s32(vmovl_u16(x)); @@ -4468,13 +4758,13 @@ static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG) { // float4 recip = vrecpeq_f32(yf); // recip *= vrecpsq_f32(yf, recip); // recip *= vrecpsq_f32(yf, recip); - N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, DAG.getConstant(Intrinsic::arm_neon_vrecpe, MVT::i32), N1); - N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, DAG.getConstant(Intrinsic::arm_neon_vrecps, MVT::i32), N1, N2); N2 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N1, N2); - N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, DAG.getConstant(Intrinsic::arm_neon_vrecps, MVT::i32), N1, N2); N2 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N1, N2); @@ -4503,7 +4793,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::GlobalAddress: return Subtarget->isTargetDarwin() ? LowerGlobalAddressDarwin(Op, DAG) : LowerGlobalAddressELF(Op, DAG); - case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); + case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::SELECT: return LowerSELECT(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); case ISD::BR_CC: return LowerBR_CC(Op, DAG); @@ -4524,7 +4814,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::EH_SJLJ_DISPATCHSETUP: return LowerEH_SJLJ_DISPATCHSETUP(Op, DAG); case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG, Subtarget); - case ISD::BITCAST: return ExpandBITCAST(Op.getNode(), DAG); + case ISD::BITCAST: return ExpandBITCAST(Op.getNode(), DAG); case ISD::SHL: case ISD::SRL: case ISD::SRA: return LowerShift(Op.getNode(), DAG, Subtarget); @@ -4754,6 +5044,109 @@ ARMTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, return BB; } +MachineBasicBlock * +ARMTargetLowering::EmitAtomicBinaryMinMax(MachineInstr *MI, + MachineBasicBlock *BB, + unsigned Size, + bool signExtend, + ARMCC::CondCodes Cond) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction *MF = BB->getParent(); + MachineFunction::iterator It = BB; + ++It; + + unsigned dest = MI->getOperand(0).getReg(); + unsigned ptr = MI->getOperand(1).getReg(); + unsigned incr = MI->getOperand(2).getReg(); + unsigned oldval = dest; + DebugLoc dl = MI->getDebugLoc(); + + bool isThumb2 = Subtarget->isThumb2(); + unsigned ldrOpc, strOpc, extendOpc; + switch (Size) { + default: llvm_unreachable("unsupported size for AtomicCmpSwap!"); + case 1: + ldrOpc = isThumb2 ? ARM::t2LDREXB : ARM::LDREXB; + strOpc = isThumb2 ? ARM::t2STREXB : ARM::STREXB; + extendOpc = isThumb2 ? ARM::t2SXTBr : ARM::SXTBr; + break; + case 2: + ldrOpc = isThumb2 ? ARM::t2LDREXH : ARM::LDREXH; + strOpc = isThumb2 ? ARM::t2STREXH : ARM::STREXH; + extendOpc = isThumb2 ? ARM::t2SXTHr : ARM::SXTHr; + break; + case 4: + ldrOpc = isThumb2 ? ARM::t2LDREX : ARM::LDREX; + strOpc = isThumb2 ? ARM::t2STREX : ARM::STREX; + extendOpc = 0; + break; + } + + MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MF->insert(It, loopMBB); + MF->insert(It, exitMBB); + + // Transfer the remainder of BB and its successor edges to exitMBB. + exitMBB->splice(exitMBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + exitMBB->transferSuccessorsAndUpdatePHIs(BB); + + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + unsigned scratch = RegInfo.createVirtualRegister(ARM::GPRRegisterClass); + unsigned scratch2 = RegInfo.createVirtualRegister(ARM::GPRRegisterClass); + + // thisMBB: + // ... + // fallthrough --> loopMBB + BB->addSuccessor(loopMBB); + + // loopMBB: + // ldrex dest, ptr + // (sign extend dest, if required) + // cmp dest, incr + // cmov.cond scratch2, dest, incr + // strex scratch, scratch2, ptr + // cmp scratch, #0 + // bne- loopMBB + // fallthrough --> exitMBB + BB = loopMBB; + AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr)); + + // Sign extend the value, if necessary. + if (signExtend && extendOpc) { + oldval = RegInfo.createVirtualRegister(ARM::GPRRegisterClass); + AddDefaultPred(BuildMI(BB, dl, TII->get(extendOpc), oldval).addReg(dest)); + } + + // Build compare and cmov instructions. + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr)) + .addReg(oldval).addReg(incr)); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2MOVCCr : ARM::MOVCCr), scratch2) + .addReg(oldval).addReg(incr).addImm(Cond).addReg(ARM::CPSR); + + AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2) + .addReg(ptr)); + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) + .addReg(scratch).addImm(0)); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(loopMBB).addImm(ARMCC::NE).addReg(ARM::CPSR); + + BB->addSuccessor(loopMBB); + BB->addSuccessor(exitMBB); + + // exitMBB: + // ... + BB = exitMBB; + + MI->eraseFromParent(); // The instruction is gone now. + + return BB; +} + static MachineBasicBlock *OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ) { for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), @@ -4763,6 +5156,72 @@ MachineBasicBlock *OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ) { llvm_unreachable("Expecting a BB with two successors!"); } +// FIXME: This opcode table should obviously be expressed in the target +// description. We probably just need a "machine opcode" value in the pseudo +// instruction. But the ideal solution maybe to simply remove the "S" version +// of the opcode altogether. +struct AddSubFlagsOpcodePair { + unsigned PseudoOpc; + unsigned MachineOpc; +}; + +static AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[] = { + {ARM::ADCSri, ARM::ADCri}, + {ARM::ADCSrr, ARM::ADCrr}, + {ARM::ADCSrs, ARM::ADCrs}, + {ARM::SBCSri, ARM::SBCri}, + {ARM::SBCSrr, ARM::SBCrr}, + {ARM::SBCSrs, ARM::SBCrs}, + {ARM::RSBSri, ARM::RSBri}, + {ARM::RSBSrr, ARM::RSBrr}, + {ARM::RSBSrs, ARM::RSBrs}, + {ARM::RSCSri, ARM::RSCri}, + {ARM::RSCSrs, ARM::RSCrs}, + {ARM::t2ADCSri, ARM::t2ADCri}, + {ARM::t2ADCSrr, ARM::t2ADCrr}, + {ARM::t2ADCSrs, ARM::t2ADCrs}, + {ARM::t2SBCSri, ARM::t2SBCri}, + {ARM::t2SBCSrr, ARM::t2SBCrr}, + {ARM::t2SBCSrs, ARM::t2SBCrs}, + {ARM::t2RSBSri, ARM::t2RSBri}, + {ARM::t2RSBSrs, ARM::t2RSBrs}, +}; + +// Convert and Add or Subtract with Carry and Flags to a generic opcode with +// CPSR operand. e.g. ADCS (...) -> ADC (... CPSR). +// +// FIXME: Somewhere we should assert that CPSR is in the correct +// position to be recognized by the target descrition as the 'S' bit. +bool ARMTargetLowering::RemapAddSubWithFlags(MachineInstr *MI, + MachineBasicBlock *BB) const { + unsigned OldOpc = MI->getOpcode(); + unsigned NewOpc = 0; + + // This is only called for instructions that need remapping, so iterating over + // the tiny opcode table is not costly. + static const int NPairs = + sizeof(AddSubFlagsOpcodeMap) / sizeof(AddSubFlagsOpcodePair); + for (AddSubFlagsOpcodePair *Pair = &AddSubFlagsOpcodeMap[0], + *End = &AddSubFlagsOpcodeMap[NPairs]; Pair != End; ++Pair) { + if (OldOpc == Pair->PseudoOpc) { + NewOpc = Pair->MachineOpc; + break; + } + } + if (!NewOpc) + return false; + + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + MachineInstrBuilder MIB = BuildMI(*BB, MI, dl, TII->get(NewOpc)); + for (unsigned i = 0; i < MI->getNumOperands(); ++i) + MIB.addOperand(MI->getOperand(i)); + AddDefaultPred(MIB); + MIB.addReg(ARM::CPSR, RegState::Define); // S bit + MI->eraseFromParent(); + return true; +} + MachineBasicBlock * ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB) const { @@ -4770,10 +5229,13 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, DebugLoc dl = MI->getDebugLoc(); bool isThumb2 = Subtarget->isThumb2(); switch (MI->getOpcode()) { - default: + default: { + if (RemapAddSubWithFlags(MI, BB)) + return BB; + MI->dump(); llvm_unreachable("Unexpected instr type to insert"); - + } case ARM::ATOMIC_LOAD_ADD_I8: return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr); case ARM::ATOMIC_LOAD_ADD_I16: @@ -4816,6 +5278,34 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case ARM::ATOMIC_LOAD_SUB_I32: return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2SUBrr : ARM::SUBrr); + case ARM::ATOMIC_LOAD_MIN_I8: + return EmitAtomicBinaryMinMax(MI, BB, 1, true, ARMCC::LT); + case ARM::ATOMIC_LOAD_MIN_I16: + return EmitAtomicBinaryMinMax(MI, BB, 2, true, ARMCC::LT); + case ARM::ATOMIC_LOAD_MIN_I32: + return EmitAtomicBinaryMinMax(MI, BB, 4, true, ARMCC::LT); + + case ARM::ATOMIC_LOAD_MAX_I8: + return EmitAtomicBinaryMinMax(MI, BB, 1, true, ARMCC::GT); + case ARM::ATOMIC_LOAD_MAX_I16: + return EmitAtomicBinaryMinMax(MI, BB, 2, true, ARMCC::GT); + case ARM::ATOMIC_LOAD_MAX_I32: + return EmitAtomicBinaryMinMax(MI, BB, 4, true, ARMCC::GT); + + case ARM::ATOMIC_LOAD_UMIN_I8: + return EmitAtomicBinaryMinMax(MI, BB, 1, false, ARMCC::LO); + case ARM::ATOMIC_LOAD_UMIN_I16: + return EmitAtomicBinaryMinMax(MI, BB, 2, false, ARMCC::LO); + case ARM::ATOMIC_LOAD_UMIN_I32: + return EmitAtomicBinaryMinMax(MI, BB, 4, false, ARMCC::LO); + + case ARM::ATOMIC_LOAD_UMAX_I8: + return EmitAtomicBinaryMinMax(MI, BB, 1, false, ARMCC::HI); + case ARM::ATOMIC_LOAD_UMAX_I16: + return EmitAtomicBinaryMinMax(MI, BB, 2, false, ARMCC::HI); + case ARM::ATOMIC_LOAD_UMAX_I32: + return EmitAtomicBinaryMinMax(MI, BB, 4, false, ARMCC::HI); + case ARM::ATOMIC_SWAP_I8: return EmitAtomicBinary(MI, BB, 1, 0); case ARM::ATOMIC_SWAP_I16: return EmitAtomicBinary(MI, BB, 2, 0); case ARM::ATOMIC_SWAP_I32: return EmitAtomicBinary(MI, BB, 4, 0); @@ -5034,6 +5524,42 @@ static SDValue PerformSUBCombine(SDNode *N, return SDValue(); } +/// PerformVMULCombine +/// Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the +/// special multiplier accumulator forwarding. +/// vmul d3, d0, d2 +/// vmla d3, d1, d2 +/// is faster than +/// vadd d3, d0, d1 +/// vmul d3, d3, d2 +static SDValue PerformVMULCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { + if (!Subtarget->hasVMLxForwarding()) + return SDValue(); + + SelectionDAG &DAG = DCI.DAG; + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + unsigned Opcode = N0.getOpcode(); + if (Opcode != ISD::ADD && Opcode != ISD::SUB && + Opcode != ISD::FADD && Opcode != ISD::FSUB) { + Opcode = N0.getOpcode(); + if (Opcode != ISD::ADD && Opcode != ISD::SUB && + Opcode != ISD::FADD && Opcode != ISD::FSUB) + return SDValue(); + std::swap(N0, N1); + } + + EVT VT = N->getValueType(0); + DebugLoc DL = N->getDebugLoc(); + SDValue N00 = N0->getOperand(0); + SDValue N01 = N0->getOperand(1); + return DAG.getNode(Opcode, DL, VT, + DAG.getNode(ISD::MUL, DL, VT, N00, N1), + DAG.getNode(ISD::MUL, DL, VT, N01, N1)); +} + static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget) { @@ -5046,6 +5572,8 @@ static SDValue PerformMULCombine(SDNode *N, return SDValue(); EVT VT = N->getValueType(0); + if (VT.is64BitVector() || VT.is128BitVector()) + return PerformVMULCombine(N, DCI, Subtarget); if (VT != MVT::i32) return SDValue(); @@ -5088,12 +5616,16 @@ static SDValue PerformMULCombine(SDNode *N, static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) { + // Attempt to use immediate-form VBIC BuildVectorSDNode *BVN = dyn_cast(N->getOperand(1)); DebugLoc dl = N->getDebugLoc(); EVT VT = N->getValueType(0); SelectionDAG &DAG = DCI.DAG; + if(!DAG.getTargetLoweringInfo().isTypeLegal(VT)) + return SDValue(); + APInt SplatBits, SplatUndef; unsigned SplatBitSize; bool HasAnyUndefs; @@ -5127,6 +5659,9 @@ static SDValue PerformORCombine(SDNode *N, EVT VT = N->getValueType(0); SelectionDAG &DAG = DCI.DAG; + if(!DAG.getTargetLoweringInfo().isTypeLegal(VT)) + return SDValue(); + APInt SplatBits, SplatUndef; unsigned SplatBitSize; bool HasAnyUndefs; @@ -5147,6 +5682,37 @@ static SDValue PerformORCombine(SDNode *N, } } + SDValue N0 = N->getOperand(0); + if (N0.getOpcode() != ISD::AND) + return SDValue(); + SDValue N1 = N->getOperand(1); + + // (or (and B, A), (and C, ~A)) => (VBSL A, B, C) when A is a constant. + if (Subtarget->hasNEON() && N1.getOpcode() == ISD::AND && VT.isVector() && + DAG.getTargetLoweringInfo().isTypeLegal(VT)) { + APInt SplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + + BuildVectorSDNode *BVN0 = dyn_cast(N0->getOperand(1)); + APInt SplatBits0; + if (BVN0 && BVN0->isConstantSplat(SplatBits0, SplatUndef, SplatBitSize, + HasAnyUndefs) && !HasAnyUndefs) { + BuildVectorSDNode *BVN1 = dyn_cast(N1->getOperand(1)); + APInt SplatBits1; + if (BVN1 && BVN1->isConstantSplat(SplatBits1, SplatUndef, SplatBitSize, + HasAnyUndefs) && !HasAnyUndefs && + SplatBits0 == ~SplatBits1) { + // Canonicalize the vector type to make instruction selection simpler. + EVT CanonicalVT = VT.is128BitVector() ? MVT::v4i32 : MVT::v2i32; + SDValue Result = DAG.getNode(ARMISD::VBSL, dl, CanonicalVT, + N0->getOperand(1), N0->getOperand(0), + N1->getOperand(0)); + return DAG.getNode(ISD::BITCAST, dl, VT, Result); + } + } + } + // Try to use the ARM/Thumb2 BFI (bitfield insert) instruction when // reasonable. @@ -5154,19 +5720,16 @@ static SDValue PerformORCombine(SDNode *N, if (Subtarget->isThumb1Only() || !Subtarget->hasV6T2Ops()) return SDValue(); - SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); DebugLoc DL = N->getDebugLoc(); // 1) or (and A, mask), val => ARMbfi A, val, mask // iff (val & mask) == val // // 2) or (and A, mask), (and B, mask2) => ARMbfi A, (lsr B, amt), mask // 2a) iff isBitFieldInvertedMask(mask) && isBitFieldInvertedMask(~mask2) - // && CountPopulation_32(mask) == CountPopulation_32(~mask2) + // && mask == ~mask2 // 2b) iff isBitFieldInvertedMask(~mask) && isBitFieldInvertedMask(mask2) - // && CountPopulation_32(mask) == CountPopulation_32(~mask2) + // && ~mask == mask2 // (i.e., copy a bitfield value into another bitfield of the same width) - if (N0.getOpcode() != ISD::AND) - return SDValue(); if (VT != MVT::i32) return SDValue(); @@ -5209,26 +5772,26 @@ static SDValue PerformORCombine(SDNode *N, return SDValue(); unsigned Mask2 = N11C->getZExtValue(); + // Mask and ~Mask2 (or reverse) must be equivalent for the BFI pattern + // as is to match. if (ARM::isBitFieldInvertedMask(Mask) && - ARM::isBitFieldInvertedMask(~Mask2) && - (CountPopulation_32(Mask) == CountPopulation_32(~Mask2))) { + (Mask == ~Mask2)) { // The pack halfword instruction works better for masks that fit it, // so use that when it's available. if (Subtarget->hasT2ExtractPack() && (Mask == 0xffff || Mask == 0xffff0000)) return SDValue(); // 2a - unsigned lsb = CountTrailingZeros_32(Mask2); + unsigned amt = CountTrailingZeros_32(Mask2); Res = DAG.getNode(ISD::SRL, DL, VT, N1.getOperand(0), - DAG.getConstant(lsb, MVT::i32)); + DAG.getConstant(amt, MVT::i32)); Res = DAG.getNode(ARMISD::BFI, DL, VT, N00, Res, DAG.getConstant(Mask, MVT::i32)); // Do not add new nodes to DAG combiner worklist. DCI.CombineTo(N, Res, false); return SDValue(); } else if (ARM::isBitFieldInvertedMask(~Mask) && - ARM::isBitFieldInvertedMask(Mask2) && - (CountPopulation_32(~Mask) == CountPopulation_32(Mask2))) { + (~Mask == Mask2)) { // The pack halfword instruction works better for masks that fit it, // so use that when it's available. if (Subtarget->hasT2ExtractPack() && @@ -5239,7 +5802,7 @@ static SDValue PerformORCombine(SDNode *N, Res = DAG.getNode(ISD::SRL, DL, VT, N00, DAG.getConstant(lsb, MVT::i32)); Res = DAG.getNode(ARMISD::BFI, DL, VT, N1.getOperand(0), Res, - DAG.getConstant(Mask2, MVT::i32)); + DAG.getConstant(Mask2, MVT::i32)); // Do not add new nodes to DAG combiner worklist. DCI.CombineTo(N, Res, false); return SDValue(); @@ -5294,6 +5857,37 @@ static SDValue PerformVMOVRRDCombine(SDNode *N, SDValue InDouble = N->getOperand(0); if (InDouble.getOpcode() == ARMISD::VMOVDRR) return DCI.CombineTo(N, InDouble.getOperand(0), InDouble.getOperand(1)); + + // vmovrrd(load f64) -> (load i32), (load i32) + SDNode *InNode = InDouble.getNode(); + if (ISD::isNormalLoad(InNode) && InNode->hasOneUse() && + InNode->getValueType(0) == MVT::f64 && + InNode->getOperand(1).getOpcode() == ISD::FrameIndex && + !cast(InNode)->isVolatile()) { + // TODO: Should this be done for non-FrameIndex operands? + LoadSDNode *LD = cast(InNode); + + SelectionDAG &DAG = DCI.DAG; + DebugLoc DL = LD->getDebugLoc(); + SDValue BasePtr = LD->getBasePtr(); + SDValue NewLD1 = DAG.getLoad(MVT::i32, DL, LD->getChain(), BasePtr, + LD->getPointerInfo(), LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); + + SDValue OffsetPtr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr, + DAG.getConstant(4, MVT::i32)); + SDValue NewLD2 = DAG.getLoad(MVT::i32, DL, NewLD1.getValue(1), OffsetPtr, + LD->getPointerInfo(), LD->isVolatile(), + LD->isNonTemporal(), + std::min(4U, LD->getAlignment() / 2)); + + DAG.ReplaceAllUsesOfValueWith(SDValue(LD, 1), NewLD2.getValue(1)); + SDValue Result = DCI.CombineTo(N, NewLD1, NewLD2); + DCI.RemoveFromWorklist(LD); + DAG.DeleteNode(LD); + return Result; + } + return SDValue(); } @@ -5323,8 +5917,28 @@ static SDValue PerformSTORECombine(SDNode *N, // Otherwise, the i64 value will be legalized to a pair of i32 values. StoreSDNode *St = cast(N); SDValue StVal = St->getValue(); - if (!ISD::isNormalStore(St) || St->isVolatile() || - StVal.getValueType() != MVT::i64 || + if (!ISD::isNormalStore(St) || St->isVolatile()) + return SDValue(); + + if (StVal.getNode()->getOpcode() == ARMISD::VMOVDRR && + StVal.getNode()->hasOneUse() && !St->isVolatile()) { + SelectionDAG &DAG = DCI.DAG; + DebugLoc DL = St->getDebugLoc(); + SDValue BasePtr = St->getBasePtr(); + SDValue NewST1 = DAG.getStore(St->getChain(), DL, + StVal.getNode()->getOperand(0), BasePtr, + St->getPointerInfo(), St->isVolatile(), + St->isNonTemporal(), St->getAlignment()); + + SDValue OffsetPtr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr, + DAG.getConstant(4, MVT::i32)); + return DAG.getStore(NewST1.getValue(0), DL, StVal.getNode()->getOperand(1), + OffsetPtr, St->getPointerInfo(), St->isVolatile(), + St->isNonTemporal(), + std::min(4U, St->getAlignment() / 2)); + } + + if (StVal.getValueType() != MVT::i64 || StVal.getNode()->getOpcode() != ISD::EXTRACT_VECTOR_ELT) return SDValue(); @@ -5553,7 +6167,7 @@ static SDValue CombineBaseUpdate(SDNode *N, EVT VecTy; if (isLoad) VecTy = N->getValueType(0); - else + else VecTy = N->getOperand(AddrOpIdx+1).getValueType(); unsigned NumBytes = NumVecs * VecTy.getSizeInBits() / 8; if (isLaneOp) @@ -5603,7 +6217,7 @@ static SDValue CombineBaseUpdate(SDNode *N, DCI.CombineTo(User, SDValue(UpdN.getNode(), NumResultVecs)); break; - } + } return SDValue(); } diff --git a/contrib/llvm/lib/Target/ARM/ARMISelLowering.h b/contrib/llvm/lib/Target/ARM/ARMISelLowering.h index dc400c485ec6..a2e626062ac6 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelLowering.h +++ b/contrib/llvm/lib/Target/ARM/ARMISelLowering.h @@ -57,7 +57,6 @@ namespace llvm { CMPFPw0, // ARM VFP compare against zero instruction, sets FPSCR. FMSTAT, // ARM fmstat instruction. CMOV, // ARM conditional move instructions. - CNEG, // ARM conditional negate instructions. BCC_i64, @@ -89,7 +88,7 @@ namespace llvm { MEMBARRIER_MCR, // Memory barrier (MCR) PRELOAD, // Preload - + VCEQ, // Vector compare equal. VCEQZ, // Vector compare equal to zero. VCGE, // Vector compare greater than or equal. @@ -154,6 +153,8 @@ namespace llvm { VZIP, // zip (interleave) VUZP, // unzip (deinterleave) VTRN, // transpose + VTBL1, // 1-register shuffle with mask + VTBL2, // 2-register shuffle with mask // Vector multiply long: VMULLs, // ...signed @@ -172,12 +173,15 @@ namespace llvm { // Bit-field insert BFI, - + // Vector OR with immediate VORRIMM, // Vector AND with NOT of immediate VBICIMM, + // Vector bitwise select + VBSL, + // Vector load N-element structure to all lanes: VLD2DUP = ISD::FIRST_TARGET_MEMORY_OPCODE, VLD3DUP, @@ -330,9 +334,6 @@ namespace llvm { Sched::Preference getSchedulingPreference(SDNode *N) const; - unsigned getRegPressureLimit(const TargetRegisterClass *RC, - MachineFunction &MF) const; - bool isShuffleMaskLegal(const SmallVectorImpl &M, EVT VT) const; bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; @@ -407,7 +408,7 @@ namespace llvm { SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG) const; SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, + SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST) const; SDValue ReconstructShuffle(SDValue Op, SelectionDAG &DAG) const; @@ -425,6 +426,13 @@ namespace llvm { DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl &InVals) const; + void VarArgStyleRegisters(CCState &CCInfo, SelectionDAG &DAG, + DebugLoc dl, SDValue &Chain, unsigned ArgOffset) + const; + + void computeRegArea(CCState &CCInfo, MachineFunction &MF, + unsigned &VARegSize, unsigned &VARegSaveSize) const; + virtual SDValue LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, @@ -435,6 +443,9 @@ namespace llvm { DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl &InVals) const; + /// HandleByVal - Target-specific cleanup for ByVal support. + virtual void HandleByVal(CCState *, unsigned &) const; + /// IsEligibleForTailCallOptimization - Check whether the call is eligible /// for tail call optimization. Targets which want to do tail call /// optimization should implement this function. @@ -456,10 +467,13 @@ namespace llvm { virtual bool isUsedByReturnOnly(SDNode *N) const; + virtual bool mayBeEmittedAsTailCall(CallInst *CI) const; + SDValue getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &ARMcc, SelectionDAG &DAG, DebugLoc dl) const; SDValue getVFPCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG, DebugLoc dl) const; + SDValue duplicateCmp(SDValue Cmp, SelectionDAG &DAG) const; SDValue OptimizeVFPBrcond(SDValue Op, SelectionDAG &DAG) const; @@ -470,16 +484,22 @@ namespace llvm { MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode) const; + MachineBasicBlock * EmitAtomicBinaryMinMax(MachineInstr *MI, + MachineBasicBlock *BB, + unsigned Size, + bool signExtend, + ARMCC::CondCodes Cond) const; + bool RemapAddSubWithFlags(MachineInstr *MI, MachineBasicBlock *BB) const; }; - + enum NEONModImmType { VMOVModImm, VMVNModImm, OtherModImm }; - - + + namespace ARM { FastISel *createFastISel(FunctionLoweringInfo &funcInfo); } diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td b/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td index 359ac45cee1d..f5fb98ece4af 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -206,19 +206,30 @@ def setend_op : Operand { let PrintMethod = "printSetendOperand"; } -def cps_opt : Operand { - let PrintMethod = "printCPSOptionOperand"; -} - def msr_mask : Operand { let PrintMethod = "printMSRMaskOperand"; let ParserMatchClass = MSRMaskOperand; } -// A8.6.117, A8.6.118. Different instructions are generated for #0 and #-0. -// The neg_zero operand translates -0 to -1, -1 to -2, ..., etc. -def neg_zero : Operand { - let PrintMethod = "printNegZeroOperand"; +// Shift Right Immediate - A shift right immediate is encoded differently from +// other shift immediates. The imm6 field is encoded like so: +// +// Offset Encoding +// 8 imm6<5:3> = '001', 8 - is encoded in imm6<2:0> +// 16 imm6<5:4> = '01', 16 - is encoded in imm6<3:0> +// 32 imm6<5> = '1', 32 - is encoded in imm6<4:0> +// 64 64 - is encoded in imm6<5:0> +def shr_imm8 : Operand { + let EncoderMethod = "getShiftRight8Imm"; +} +def shr_imm16 : Operand { + let EncoderMethod = "getShiftRight16Imm"; +} +def shr_imm32 : Operand { + let EncoderMethod = "getShiftRight32Imm"; +} +def shr_imm64 : Operand { + let EncoderMethod = "getShiftRight64Imm"; } //===----------------------------------------------------------------------===// @@ -279,6 +290,7 @@ class PseudoInst pattern> let OutOperandList = oops; let InOperandList = iops; let Pattern = pattern; + let isCodeGenOnly = 1; } // PseudoInst that's ARM-mode only. @@ -422,11 +434,11 @@ class AIstrex opcod, dag oops, dag iops, InstrItinClass itin, opc, asm, "", pattern> { bits<4> Rd; bits<4> Rt; - bits<4> Rn; + bits<4> addr; let Inst{27-23} = 0b00011; let Inst{22-21} = opcod; let Inst{20} = 0; - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{15-12} = Rd; let Inst{11-4} = 0b11111001; let Inst{3-0} = Rt; @@ -513,6 +525,24 @@ class AI2stridx pattern> + : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr, + pattern> { + // AM2 store w/ two operands: (GPR, am2offset) + // {17-14} Rn + // {13} 1 == Rm, 0 == imm12 + // {12} isAdd + // {11-0} imm12/Rm + bits<18> addr; + let Inst{25} = addr{13}; + let Inst{23} = addr{12}; + let Inst{19-16} = addr{17-14}; + let Inst{11-0} = addr{11-0}; +} // addrmode3 instructions class AI3ld op, bit op20, dag oops, dag iops, Format f, @@ -547,6 +577,34 @@ class AI3ldstidx op, bit op20, bit isLd, bit isPre, dag oops, dag iops, let Inst{15-12} = Rt; // Rt let Inst{7-4} = op; } + +// FIXME: Merge with the above class when addrmode2 gets used for LDR, LDRB +// but for now use this class for LDRSBT, LDRHT, LDSHT. +class AI3ldstidxT op, bit op20, bit isLd, bit isPre, dag oops, dag iops, + IndexMode im, Format f, InstrItinClass itin, string opc, + string asm, string cstr, list pattern> + : I { + // {13} 1 == imm8, 0 == Rm + // {12-9} Rn + // {8} isAdd + // {7-4} imm7_4/zero + // {3-0} imm3_0/Rm + bits<14> addr; + bits<4> Rt; + let Inst{27-25} = 0b000; + let Inst{24} = isPre; // P bit + let Inst{23} = addr{8}; // U bit + let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm + let Inst{20} = op20; // L bit + let Inst{19-16} = addr{12-9}; // Rn + let Inst{15-12} = Rt; // Rt + let Inst{11-8} = addr{7-4}; // imm7_4/zero + let Inst{7-4} = op; + let Inst{3-0} = addr{3-0}; // imm3_0/Rm + let AsmMatchConverter = "CvtLdWriteBackRegAddrMode3"; +} + class AI3stridx op, bit isByte, bit isPre, dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list pattern> @@ -619,12 +677,25 @@ class AI3sthpo pattern> : I { + // {13} 1 == imm8, 0 == Rm + // {12-9} Rn + // {8} isAdd + // {7-4} imm7_4/zero + // {3-0} imm3_0/Rm + bits<14> addr; + bits<4> Rt; + let Inst{3-0} = addr{3-0}; // imm3_0/Rm let Inst{4} = 1; let Inst{5} = 1; // H bit let Inst{6} = 0; // S bit let Inst{7} = 1; + let Inst{11-8} = addr{7-4}; // imm7_4/zero + let Inst{15-12} = Rt; // Rt + let Inst{19-16} = addr{12-9}; // Rn let Inst{20} = 0; // L bit let Inst{21} = 0; // W bit + let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm + let Inst{23} = addr{8}; // U bit let Inst{24} = 0; // P bit let Inst{27-25} = 0b000; } @@ -1670,7 +1741,8 @@ class N2VImm op11_8, bit op7, bit op6, bit op4, } // NEON 3 vector register format. -class N3V op21_20, bits<4> op11_8, bit op6, bit op4, + +class N3VCommon op21_20, bits<4> op11_8, bit op6, bit op4, dag oops, dag iops, Format f, InstrItinClass itin, string opc, string dt, string asm, string cstr, list pattern> : NDataI { @@ -1680,6 +1752,13 @@ class N3V op21_20, bits<4> op11_8, bit op6, bit op4, let Inst{11-8} = op11_8; let Inst{6} = op6; let Inst{4} = op4; +} + +class N3V op21_20, bits<4> op11_8, bit op6, bit op4, + dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : N3VCommon { // Instruction operands. bits<5> Vd; @@ -1694,6 +1773,47 @@ class N3V op21_20, bits<4> op11_8, bit op6, bit op4, let Inst{5} = Vm{4}; } +class N3VLane32 op21_20, bits<4> op11_8, bit op6, bit op4, + dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : N3VCommon { + + // Instruction operands. + bits<5> Vd; + bits<5> Vn; + bits<5> Vm; + bit lane; + + let Inst{15-12} = Vd{3-0}; + let Inst{22} = Vd{4}; + let Inst{19-16} = Vn{3-0}; + let Inst{7} = Vn{4}; + let Inst{3-0} = Vm{3-0}; + let Inst{5} = lane; +} + +class N3VLane16 op21_20, bits<4> op11_8, bit op6, bit op4, + dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : N3VCommon { + + // Instruction operands. + bits<5> Vd; + bits<5> Vn; + bits<5> Vm; + bits<2> lane; + + let Inst{15-12} = Vd{3-0}; + let Inst{22} = Vd{4}; + let Inst{19-16} = Vn{3-0}; + let Inst{7} = Vn{4}; + let Inst{2-0} = Vm{2-0}; + let Inst{5} = lane{1}; + let Inst{3} = lane{0}; +} + // Same as N3V except it doesn't have a data type suffix. class N3VX op21_20, bits<4> op11_8, bit op6, bit op4, @@ -1730,6 +1850,8 @@ class NVLaneOp opcod1, bits<4> opcod2, bits<2> opcod3, let Inst{11-8} = opcod2; let Inst{6-5} = opcod3; let Inst{4} = 1; + // A8.6.303, A8.6.328, A8.6.329 + let Inst{3-0} = 0b0000; let OutOperandList = oops; let InOperandList = !con(iops, (ins pred:$p)); diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td index 6e3fe2e039f5..209c1a3fd96a 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -58,7 +58,7 @@ def SDT_ARMEH_SJLJ_Setjmp : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisInt<2>]>; def SDT_ARMEH_SJLJ_Longjmp: SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisInt<1>]>; -def SDT_ARMEH_SJLJ_DispatchSetup: SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; +def SDT_ARMEH_SJLJ_DispatchSetup: SDTypeProfile<0, 0, []>; def SDT_ARMMEMBARRIER : SDTypeProfile<0, 1, [SDTCisInt<0>]>; @@ -93,8 +93,6 @@ def ARMretflag : SDNode<"ARMISD::RET_FLAG", SDTNone, def ARMcmov : SDNode<"ARMISD::CMOV", SDT_ARMCMov, [SDNPInGlue]>; -def ARMcneg : SDNode<"ARMISD::CNEG", SDT_ARMCMov, - [SDNPInGlue]>; def ARMbrcond : SDNode<"ARMISD::BRCOND", SDT_ARMBrcond, [SDNPHasChain, SDNPInGlue, SDNPOutGlue]>; @@ -205,13 +203,13 @@ def so_imm_not_XFORM : SDNodeXForm; /// imm1_15 predicate - True if the 32-bit immediate is in the range [1,15]. -def imm1_15 : PatLeaf<(i32 imm), [{ - return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 16; +def imm1_15 : ImmLeaf= 1 && (int32_t)Imm < 16; }]>; /// imm16_31 predicate - True if the 32-bit immediate is in the range [16,31]. -def imm16_31 : PatLeaf<(i32 imm), [{ - return (int32_t)N->getZExtValue() >= 16 && (int32_t)N->getZExtValue() < 32; +def imm16_31 : ImmLeaf= 16 && (int32_t)Imm < 32; }]>; def so_imm_neg : @@ -241,8 +239,8 @@ def lo16AllZero : PatLeaf<(i32 imm), [{ /// imm0_65535 predicate - True if the 32-bit immediate is in the range /// [0.65535]. -def imm0_65535 : PatLeaf<(i32 imm), [{ - return (uint32_t)N->getZExtValue() < 65536; +def imm0_65535 : ImmLeaf= 0 && Imm < 65536; }]>; class BinOpFrag : PatFrag<(ops node:$LHS, node:$RHS), res>; @@ -377,17 +375,23 @@ def neon_vcvt_imm32 : Operand { } // rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24. -def rot_imm : Operand, PatLeaf<(i32 imm), [{ - int32_t v = (int32_t)N->getZExtValue(); +def rot_imm : Operand, ImmLeaf { let EncoderMethod = "getRotImmOpValue"; } +def ShifterAsmOperand : AsmOperandClass { + let Name = "Shifter"; + let SuperClasses = []; +} + // shift_imm: An integer that encodes a shift amount and the type of shift // (currently either asr or lsl) using the same encoding used for the // immediates in so_reg operands. def shift_imm : Operand { let PrintMethod = "printShiftImmOperand"; + let ParserMatchClass = ShifterAsmOperand; } // shifter_operand operands: so_reg and so_imm. @@ -396,19 +400,21 @@ def so_reg : Operand, // reg reg imm [shl,srl,sra,rotr]> { let EncoderMethod = "getSORegOpValue"; let PrintMethod = "printSORegOperand"; - let MIOperandInfo = (ops GPR, GPR, i32imm); + let MIOperandInfo = (ops GPR, GPR, shift_imm); } def shift_so_reg : Operand, // reg reg imm ComplexPattern { let EncoderMethod = "getSORegOpValue"; let PrintMethod = "printSORegOperand"; - let MIOperandInfo = (ops GPR, GPR, i32imm); + let MIOperandInfo = (ops GPR, GPR, shift_imm); } // so_imm - Match a 32-bit shifter_operand immediate operand, which is an // 8-bit immediate rotated by an arbitrary number of bits. -def so_imm : Operand, PatLeaf<(imm), [{ return Pred_so_imm(N); }]> { +def so_imm : Operand, ImmLeaf { let EncoderMethod = "getSOImmOpValue"; let PrintMethod = "printSOImmOperand"; } @@ -429,13 +435,13 @@ def arm_i32imm : PatLeaf<(imm), [{ }]>; /// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31]. -def imm0_31 : Operand, PatLeaf<(imm), [{ - return (int32_t)N->getZExtValue() < 32; +def imm0_31 : Operand, ImmLeaf= 0 && Imm < 32; }]>; /// imm0_31_m1 - Matches and prints like imm0_31, but encodes as 'value - 1'. -def imm0_31_m1 : Operand, PatLeaf<(imm), [{ - return (int32_t)N->getZExtValue() < 32; +def imm0_31_m1 : Operand, ImmLeaf= 0 && Imm < 32; }]> { let EncoderMethod = "getImmMinusOneOpValue"; } @@ -458,19 +464,30 @@ def bf_inv_mask_imm : Operand, } /// lsb_pos_imm - position of the lsb bit, used by BFI4p and t2BFI4p -def lsb_pos_imm : Operand, PatLeaf<(imm), [{ - return isInt<5>(N->getSExtValue()); +def lsb_pos_imm : Operand, ImmLeaf(Imm); }]>; /// width_imm - number of bits to be copied, used by BFI4p and t2BFI4p -def width_imm : Operand, PatLeaf<(imm), [{ - return N->getSExtValue() > 0 && N->getSExtValue() <= 32; +def width_imm : Operand, ImmLeaf 0 && Imm <= 32; }] > { let EncoderMethod = "getMsbOpValue"; } // Define ARM specific addressing modes. +def MemMode2AsmOperand : AsmOperandClass { + let Name = "MemMode2"; + let SuperClasses = []; + let ParserMethod = "tryParseMemMode2Operand"; +} + +def MemMode3AsmOperand : AsmOperandClass { + let Name = "MemMode3"; + let SuperClasses = []; + let ParserMethod = "tryParseMemMode3Operand"; +} // addrmode_imm12 := reg +/- imm12 // @@ -501,6 +518,7 @@ def addrmode2 : Operand, ComplexPattern { let EncoderMethod = "getAddrMode2OpValue"; let PrintMethod = "printAddrMode2Operand"; + let ParserMatchClass = MemMode2AsmOperand; let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); } @@ -519,6 +537,7 @@ def addrmode3 : Operand, ComplexPattern { let EncoderMethod = "getAddrMode3OpValue"; let PrintMethod = "printAddrMode3Operand"; + let ParserMatchClass = MemMode3AsmOperand; let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); } @@ -586,6 +605,21 @@ def addrmodepc : Operand, let MIOperandInfo = (ops GPR, i32imm); } +def MemMode7AsmOperand : AsmOperandClass { + let Name = "MemMode7"; + let SuperClasses = []; +} + +// addrmode7 := reg +// Used by load/store exclusive instructions. Useful to enable right assembly +// parsing and printing. Not used for any codegen matching. +// +def addrmode7 : Operand { + let PrintMethod = "printAddrMode7Operand"; + let MIOperandInfo = (ops GPR); + let ParserMatchClass = MemMode7AsmOperand; +} + def nohash_imm : Operand { let PrintMethod = "printNoHashImmediate"; } @@ -902,52 +936,23 @@ multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, let Inst{19-16} = Rn; } } -// Carry setting variants -let isCodeGenOnly = 1, Defs = [CPSR] in { -multiclass AI1_adde_sube_s_irs opcod, string opc, PatFrag opnode, - bit Commutable = 0> { - def Sri : AXI1, - Requires<[IsARM]> { - bits<4> Rd; - bits<4> Rn; - bits<12> imm; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; - let Inst{11-0} = imm; - let Inst{20} = 1; - let Inst{25} = 1; - } - def Srr : AXI1, - Requires<[IsARM]> { - bits<4> Rd; - bits<4> Rn; - bits<4> Rm; - let Inst{11-4} = 0b00000000; - let isCommutable = Commutable; - let Inst{3-0} = Rm; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; - let Inst{20} = 1; - let Inst{25} = 0; - } - def Srs : AXI1, - Requires<[IsARM]> { - bits<4> Rd; - bits<4> Rn; - bits<12> shift; - let Inst{11-0} = shift; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; - let Inst{20} = 1; - let Inst{25} = 0; - } } + +// Carry setting variants +// NOTE: CPSR def omitted because it will be handled by the custom inserter. +let usesCustomInserter = 1 in { +multiclass AI1_adde_sube_s_irs { + def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), + Size4Bytes, IIC_iALUi, + [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>; + def rr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + Size4Bytes, IIC_iALUr, + [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> { + let isCommutable = Commutable; + } + def rs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), + Size4Bytes, IIC_iALUsr, + [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>; } } @@ -972,6 +977,7 @@ multiclass AI_ldr1 { bits<4> Rt; bits<17> shift; + let shift{4} = 0; // Inst{4} = 0 let Inst{23} = shift{12}; // U (add = ('U' == 1)) let Inst{19-16} = shift{16-13}; // Rn let Inst{15-12} = Rt; @@ -1001,6 +1007,7 @@ multiclass AI_str1 { bits<4> Rt; bits<17> shift; + let shift{4} = 0; // Inst{4} = 0 let Inst{23} = shift{12}; // U (add = ('U' == 1)) let Inst{19-16} = shift{16-13}; // Rn let Inst{15-12} = Rt; @@ -1249,7 +1256,7 @@ let neverHasSideEffects = 1, isReMaterializable = 1 in // The 'adr' mnemonic encodes differently if the label is before or after // the instruction. The {24-21} opcode bits are set by the fixup, as we don't // know until then which form of the instruction will be used. -def ADR : AI1<0, (outs GPR:$Rd), (ins adrlabel:$label), +def ADR : AI1<{0,?,?,0}, (outs GPR:$Rd), (ins adrlabel:$label), MiscFrm, IIC_iALUi, "adr", "\t$Rd, #$label", []> { bits<4> Rd; bits<12> label; @@ -1311,6 +1318,9 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { // before calls from potentially appearing dead. let isCall = 1, // On non-Darwin platforms R9 is callee-saved. + // FIXME: Do we really need a non-predicated version? If so, it should + // at least be a pseudo instruction expanding to the predicated version + // at MC lowering time. Defs = [R0, R1, R2, R3, R12, LR, D0, D1, D2, D3, D4, D5, D6, D7, D16, D17, D18, D19, D20, D21, D22, D23, @@ -1340,7 +1350,16 @@ let isCall = 1, Requires<[IsARM, HasV5T, IsNotDarwin]> { bits<4> func; let Inst{31-4} = 0b1110000100101111111111110011; - let Inst{3-0} = func; + let Inst{3-0} = func; + } + + def BLX_pred : AI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm, + IIC_Br, "blx", "\t$func", + [(ARMcall_pred GPR:$func)]>, + Requires<[IsARM, HasV5T, IsNotDarwin]> { + bits<4> func; + let Inst{27-4} = 0b000100101111111111110011; + let Inst{3-0} = func; } // ARMv4T @@ -1364,30 +1383,25 @@ let isCall = 1, D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR], Uses = [R7, SP] in { - def BLr9 : ABXI<0b1011, (outs), (ins bltarget:$func, variable_ops), - IIC_Br, "bl\t$func", - [(ARMcall tglobaladdr:$func)]>, Requires<[IsARM, IsDarwin]> { - let Inst{31-28} = 0b1110; - bits<24> func; - let Inst{23-0} = func; - } + def BLr9 : ARMPseudoInst<(outs), (ins bltarget:$func, variable_ops), + Size4Bytes, IIC_Br, + [(ARMcall tglobaladdr:$func)]>, Requires<[IsARM, IsDarwin]>; - def BLr9_pred : ABI<0b1011, (outs), (ins bltarget:$func, variable_ops), - IIC_Br, "bl", "\t$func", + def BLr9_pred : ARMPseudoInst<(outs), + (ins bltarget:$func, pred:$p, variable_ops), + Size4Bytes, IIC_Br, [(ARMcall_pred tglobaladdr:$func)]>, - Requires<[IsARM, IsDarwin]> { - bits<24> func; - let Inst{23-0} = func; - } + Requires<[IsARM, IsDarwin]>; // ARMv5T and above - def BLXr9 : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm, - IIC_Br, "blx\t$func", - [(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T, IsDarwin]> { - bits<4> func; - let Inst{31-4} = 0b1110000100101111111111110011; - let Inst{3-0} = func; - } + def BLXr9 : ARMPseudoInst<(outs), (ins GPR:$func, variable_ops), + Size4Bytes, IIC_Br, + [(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T, IsDarwin]>; + + def BLXr9_pred: ARMPseudoInst<(outs), (ins GPR:$func, pred:$p, variable_ops), + Size4Bytes, IIC_Br, + [(ARMcall_pred GPR:$func)]>, + Requires<[IsARM, HasV5T, IsDarwin]>; // ARMv4T // Note: Restrict $func to the tGPR regclass to prevent it being in LR. @@ -1403,11 +1417,7 @@ let isCall = 1, // Tail calls. -// FIXME: These should probably be xformed into the non-TC versions of the -// instructions as part of MC lowering. -// FIXME: These seem to be used for both Thumb and ARM instruction selection. -// Thumb should have its own version since the instruction is actually -// different, even though the mnemonic is the same. +// FIXME: The Thumb versions of these should live in ARMInstrThumb.td let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { // Darwin versions. let Defs = [R0, R1, R2, R3, R9, R12, @@ -1421,21 +1431,21 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops), IIC_Br, []>, Requires<[IsDarwin]>; - def TAILJMPd : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), - IIC_Br, "b\t$dst @ TAILCALL", + def TAILJMPd : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops), + Size4Bytes, IIC_Br, []>, Requires<[IsARM, IsDarwin]>; - def TAILJMPdt: ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), - IIC_Br, "b.w\t$dst @ TAILCALL", + def tTAILJMPd: tPseudoInst<(outs), (ins brtarget:$dst, variable_ops), + Size4Bytes, IIC_Br, []>, Requires<[IsThumb, IsDarwin]>; - def TAILJMPr : AXI<(outs), (ins tcGPR:$dst, variable_ops), - BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL", - []>, Requires<[IsDarwin]> { - bits<4> dst; - let Inst{31-4} = 0b1110000100101111111111110001; - let Inst{3-0} = dst; - } + def TAILJMPr : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops), + Size4Bytes, IIC_Br, + []>, Requires<[IsARM, IsDarwin]>; + + def tTAILJMPr : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops), + Size4Bytes, IIC_Br, + []>, Requires<[IsThumb, IsDarwin]>; } // Non-Darwin versions (the difference is R9). @@ -1450,34 +1460,31 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { def TCRETURNriND : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops), IIC_Br, []>, Requires<[IsNotDarwin]>; - def TAILJMPdND : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), - IIC_Br, "b\t$dst @ TAILCALL", + def TAILJMPdND : ARMPseudoInst<(outs), (ins brtarget:$dst, variable_ops), + Size4Bytes, IIC_Br, []>, Requires<[IsARM, IsNotDarwin]>; - def TAILJMPdNDt : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), - IIC_Br, "b.w\t$dst @ TAILCALL", + def tTAILJMPdND : tPseudoInst<(outs), (ins brtarget:$dst, variable_ops), + Size4Bytes, IIC_Br, []>, Requires<[IsThumb, IsNotDarwin]>; - def TAILJMPrND : AXI<(outs), (ins tcGPR:$dst, variable_ops), - BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL", - []>, Requires<[IsNotDarwin]> { - bits<4> dst; - let Inst{31-4} = 0b1110000100101111111111110001; - let Inst{3-0} = dst; - } + def TAILJMPrND : ARMPseudoInst<(outs), (ins tcGPR:$dst, variable_ops), + Size4Bytes, IIC_Br, + []>, Requires<[IsARM, IsNotDarwin]>; + def tTAILJMPrND : tPseudoInst<(outs), (ins tcGPR:$dst, variable_ops), + Size4Bytes, IIC_Br, + []>, Requires<[IsThumb, IsNotDarwin]>; } } let isBranch = 1, isTerminator = 1 in { - // B is "predicable" since it can be xformed into a Bcc. + // B is "predicable" since it's just a Bcc with an 'always' condition. let isBarrier = 1 in { let isPredicable = 1 in - def B : ABXI<0b1010, (outs), (ins brtarget:$target), IIC_Br, - "b\t$target", [(br bb:$target)]> { - bits<24> target; - let Inst{31-28} = 0b1110; - let Inst{23-0} = target; - } + // FIXME: We shouldn't need this pseudo at all. Just using Bcc directly + // should be sufficient. + def B : ARMPseudoInst<(outs), (ins brtarget:$target), Size4Bytes, IIC_Br, + [(br bb:$target)]>; let isNotDuplicable = 1, isIndirectBranch = 1 in { def BR_JTr : ARMPseudoInst<(outs), @@ -1509,6 +1516,16 @@ let isBranch = 1, isTerminator = 1 in { } } +// BLX (immediate) -- for disassembly only +def BLXi : AXI<(outs), (ins br_target:$target), BrMiscFrm, NoItinerary, + "blx\t$target", [/* pattern left blank */]>, + Requires<[IsARM, HasV5T]> { + let Inst{31-25} = 0b1111101; + bits<25> target; + let Inst{23-0} = target{24-1}; + let Inst{24} = target{0}; +} + // Branch and Exchange Jazelle -- for disassembly only def BXJ : ABI<0b0001, (outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func", [/* For disassembly only; pattern left blank */]> { @@ -1533,6 +1550,7 @@ def SVC : ABI<0b1111, (outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", let Inst{23-0} = svc; } } +def : MnemonicAlias<"swi", "svc">; // Store Return State is a system instruction -- for disassembly only let isCodeGenOnly = 1 in { // FIXME: This should not use submode! @@ -1541,6 +1559,8 @@ def SRSW : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, i32imm:$mode), [/* For disassembly only; pattern left blank */]> { let Inst{31-28} = 0b1111; let Inst{22-20} = 0b110; // W = 1 + let Inst{19-8} = 0xd05; + let Inst{7-5} = 0b000; } def SRS : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, i32imm:$mode), @@ -1548,6 +1568,8 @@ def SRS : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, i32imm:$mode), [/* For disassembly only; pattern left blank */]> { let Inst{31-28} = 0b1111; let Inst{22-20} = 0b100; // W = 0 + let Inst{19-8} = 0xd05; + let Inst{7-5} = 0b000; } // Return From Exception is a system instruction -- for disassembly only @@ -1556,6 +1578,7 @@ def RFEW : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base), [/* For disassembly only; pattern left blank */]> { let Inst{31-28} = 0b1111; let Inst{22-20} = 0b011; // W = 1 + let Inst{15-0} = 0x0a00; } def RFE : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base), @@ -1563,6 +1586,7 @@ def RFE : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base), [/* For disassembly only; pattern left blank */]> { let Inst{31-28} = 0b1111; let Inst{22-20} = 0b001; // W = 0 + let Inst{15-0} = 0x0a00; } } // isCodeGenOnly = 1 @@ -1610,15 +1634,11 @@ def LDRSB : AI3ld<0b1101, 1, (outs GPR:$Rt), (ins addrmode3:$addr), LdMiscFrm, IIC_iLoad_bh_r, "ldrsb", "\t$Rt, $addr", [(set GPR:$Rt, (sextloadi8 addrmode3:$addr))]>; -let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1, - isCodeGenOnly = 1 in { // $dst2 doesn't exist in asmstring? -// FIXME: $dst2 isn't in the asm string as it's implied by $Rd (dst2 = Rd+1) -// how to represent that such that tblgen is happy and we don't -// mark this codegen only? +let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in { // Load doubleword def LDRD : AI3ld<0b1101, 0, (outs GPR:$Rd, GPR:$dst2), (ins addrmode3:$addr), LdMiscFrm, - IIC_iLoad_d_r, "ldrd", "\t$Rd, $addr", + IIC_iLoad_d_r, "ldrd", "\t$Rd, $dst2, $addr", []>, Requires<[IsARM, HasV5TE]>; } @@ -1636,6 +1656,7 @@ multiclass AI2_ldridx { let Inst{23} = addr{12}; let Inst{19-16} = addr{17-14}; let Inst{11-0} = addr{11-0}; + let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2"; } def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), (ins GPR:$Rn, am2offset:$offset), @@ -1688,40 +1709,80 @@ let mayLoad = 1, neverHasSideEffects = 1 in { defm LDRH : AI3_ldridx<0b1011, 1, "ldrh", IIC_iLoad_bh_ru>; defm LDRSH : AI3_ldridx<0b1111, 1, "ldrsh", IIC_iLoad_bh_ru>; defm LDRSB : AI3_ldridx<0b1101, 1, "ldrsb", IIC_iLoad_bh_ru>; -let hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in -defm LDRD : AI3_ldridx<0b1101, 0, "ldrd", IIC_iLoad_d_ru>; +let hasExtraDefRegAllocReq = 1 in { +def LDRD_PRE : AI3ldstidx<0b1101, 0, 1, 1, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb), + (ins addrmode3:$addr), IndexModePre, + LdMiscFrm, IIC_iLoad_d_ru, + "ldrd", "\t$Rt, $Rt2, $addr!", + "$addr.base = $Rn_wb", []> { + bits<14> addr; + let Inst{23} = addr{8}; // U bit + let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm + let Inst{19-16} = addr{12-9}; // Rn + let Inst{11-8} = addr{7-4}; // imm7_4/zero + let Inst{3-0} = addr{3-0}; // imm3_0/Rm +} +def LDRD_POST: AI3ldstidx<0b1101, 0, 1, 0, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb), + (ins GPR:$Rn, am3offset:$offset), IndexModePost, + LdMiscFrm, IIC_iLoad_d_ru, + "ldrd", "\t$Rt, $Rt2, [$Rn], $offset", + "$Rn = $Rn_wb", []> { + bits<10> offset; + bits<4> Rn; + let Inst{23} = offset{8}; // U bit + let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm + let Inst{19-16} = Rn; + let Inst{11-8} = offset{7-4}; // imm7_4/zero + let Inst{3-0} = offset{3-0}; // imm3_0/Rm +} +} // hasExtraDefRegAllocReq = 1 } // mayLoad = 1, neverHasSideEffects = 1 // LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only. let mayLoad = 1, neverHasSideEffects = 1 in { -def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, am2offset:$offset), IndexModeNone, - LdFrm, IIC_iLoad_ru, - "ldrt", "\t$dst, [$base], $offset", "$base = $base_wb", []> { +def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb), + (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru, + "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> { + // {17-14} Rn + // {13} 1 == Rm, 0 == imm12 + // {12} isAdd + // {11-0} imm12/Rm + bits<18> addr; + let Inst{25} = addr{13}; + let Inst{23} = addr{12}; + let Inst{21} = 1; // overwrite + let Inst{19-16} = addr{17-14}; + let Inst{11-0} = addr{11-0}; + let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2"; +} +def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb), + (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_bh_ru, + "ldrbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> { + // {17-14} Rn + // {13} 1 == Rm, 0 == imm12 + // {12} isAdd + // {11-0} imm12/Rm + bits<18> addr; + let Inst{25} = addr{13}; + let Inst{23} = addr{12}; + let Inst{21} = 1; // overwrite + let Inst{19-16} = addr{17-14}; + let Inst{11-0} = addr{11-0}; + let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2"; +} +def LDRSBT : AI3ldstidxT<0b1101, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb), + (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, + "ldrsbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> { let Inst{21} = 1; // overwrite } -def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, am2offset:$offset), IndexModeNone, - LdFrm, IIC_iLoad_bh_ru, - "ldrbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> { +def LDRHT : AI3ldstidxT<0b1011, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb), + (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, + "ldrht", "\t$Rt, $addr", "$addr.base = $base_wb", []> { let Inst{21} = 1; // overwrite } -def LDRSBT : AI3ldstidx<0b1101, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, am3offset:$offset), IndexModePost, - LdMiscFrm, IIC_iLoad_bh_ru, - "ldrsbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> { - let Inst{21} = 1; // overwrite -} -def LDRHT : AI3ldstidx<0b1011, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, am3offset:$offset), IndexModePost, - LdMiscFrm, IIC_iLoad_bh_ru, - "ldrht", "\t$dst, [$base], $offset", "$base = $base_wb", []> { - let Inst{21} = 1; // overwrite -} -def LDRSHT : AI3ldstidx<0b1111, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb), - (ins GPR:$base, am3offset:$offset), IndexModePost, - LdMiscFrm, IIC_iLoad_bh_ru, - "ldrsht", "\t$dst, [$base], $offset", "$base = $base_wb", []> { +def LDRSHT : AI3ldstidxT<0b1111, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb), + (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, + "ldrsht", "\t$Rt, $addr", "$addr.base = $base_wb", []> { let Inst{21} = 1; // overwrite } } @@ -1734,55 +1795,61 @@ def STRH : AI3str<0b1011, (outs), (ins GPR:$Rt, addrmode3:$addr), StMiscFrm, [(truncstorei16 GPR:$Rt, addrmode3:$addr)]>; // Store doubleword -let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1, - isCodeGenOnly = 1 in // $src2 doesn't exist in asm string -def STRD : AI3str<0b1111, (outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr), +let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in +def STRD : AI3str<0b1111, (outs), (ins GPR:$Rt, GPR:$src2, addrmode3:$addr), StMiscFrm, IIC_iStore_d_r, - "strd", "\t$src1, $addr", []>, Requires<[IsARM, HasV5TE]>; + "strd", "\t$Rt, $src2, $addr", []>, Requires<[IsARM, HasV5TE]>; // Indexed stores def STR_PRE : AI2stridx<0, 1, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), IndexModePre, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb", + "str", "\t$Rt, [$Rn, $offset]!", + "$Rn = $Rn_wb,@earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (pre_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; def STR_POST : AI2stridx<0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), IndexModePost, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + "str", "\t$Rt, [$Rn], $offset", + "$Rn = $Rn_wb,@earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (post_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; def STRB_PRE : AI2stridx<1, 1, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), IndexModePre, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb", + "strb", "\t$Rt, [$Rn, $offset]!", + "$Rn = $Rn_wb,@earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; def STRB_POST: AI2stridx<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), IndexModePost, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + "strb", "\t$Rt, [$Rn], $offset", + "$Rn = $Rn_wb,@earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; def STRH_PRE : AI3stridx<0b1011, 0, 1, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am3offset:$offset), IndexModePre, StMiscFrm, IIC_iStore_ru, - "strh", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb", + "strh", "\t$Rt, [$Rn, $offset]!", + "$Rn = $Rn_wb,@earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (pre_truncsti16 GPR:$Rt, GPR:$Rn, am3offset:$offset))]>; def STRH_POST: AI3stridx<0b1011, 0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am3offset:$offset), IndexModePost, StMiscFrm, IIC_iStore_bh_ru, - "strh", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + "strh", "\t$Rt, [$Rn], $offset", + "$Rn = $Rn_wb,@earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (post_truncsti16 GPR:$Rt, GPR:$Rn, am3offset:$offset))]>; // For disassembly only +let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in { def STRD_PRE : AI3stdpr<(outs GPR:$base_wb), (ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset), StMiscFrm, IIC_iStore_d_ru, @@ -1795,31 +1862,32 @@ def STRD_POST: AI3stdpo<(outs GPR:$base_wb), StMiscFrm, IIC_iStore_d_ru, "strd", "\t$src1, $src2, [$base], $offset", "$base = $base_wb", []>; +} // mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 // STRT, STRBT, and STRHT are for disassembly only. -def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn,am2offset:$offset), - IndexModeNone, StFrm, IIC_iStore_ru, - "strt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", - [/* For disassembly only; pattern left blank */]> { - let Inst{21} = 1; // overwrite -} - -def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), - IndexModeNone, StFrm, IIC_iStore_bh_ru, - "strbt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", +def STRT : AI2stridxT<0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr), + IndexModePost, StFrm, IIC_iStore_ru, + "strt", "\t$Rt, $addr", "$addr.base = $Rn_wb", [/* For disassembly only; pattern left blank */]> { let Inst{21} = 1; // overwrite + let AsmMatchConverter = "CvtStWriteBackRegAddrMode2"; } -def STRHT: AI3sthpo<(outs GPR:$base_wb), - (ins GPR:$src, GPR:$base,am3offset:$offset), +def STRBT : AI2stridxT<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr), + IndexModePost, StFrm, IIC_iStore_bh_ru, + "strbt", "\t$Rt, $addr", "$addr.base = $Rn_wb", + [/* For disassembly only; pattern left blank */]> { + let Inst{21} = 1; // overwrite + let AsmMatchConverter = "CvtStWriteBackRegAddrMode2"; +} + +def STRHT: AI3sthpo<(outs GPR:$base_wb), (ins GPR:$Rt, addrmode3:$addr), StMiscFrm, IIC_iStore_bh_ru, - "strht", "\t$src, [$base], $offset", "$base = $base_wb", + "strht", "\t$Rt, $addr", "$addr.base = $base_wb", [/* For disassembly only; pattern left blank */]> { let Inst{21} = 1; // overwrite + let AsmMatchConverter = "CvtStWriteBackRegAddrMode3"; } //===----------------------------------------------------------------------===// @@ -1892,7 +1960,7 @@ multiclass arm_ldst_mult; // FIXME: Should pc be an implicit operand like PICADD, etc? let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in -// FIXME: Should be a pseudo-instruction. -def LDMIA_RET : AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, - reglist:$regs, variable_ops), - IndexModeUpd, LdStMulFrm, IIC_iLoad_mBr, - "ldmia${p}\t$Rn!, $regs", - "$Rn = $wb", []> { - let Inst{24-23} = 0b01; // Increment After - let Inst{21} = 1; // Writeback - let Inst{20} = 1; // Load -} +def LDMIA_RET : ARMPseudoInst<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, + reglist:$regs, variable_ops), + Size4Bytes, IIC_iLoad_mBr, []>, + RegConstraint<"$Rn = $wb">; //===----------------------------------------------------------------------===// // Move Instructions. @@ -1933,6 +1995,7 @@ def MOVr : AsI1<0b1101, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMOVr, bits<4> Rd; bits<4> Rm; + let Inst{19-16} = 0b0000; let Inst{11-4} = 0b00000000; let Inst{25} = 0; let Inst{3-0} = Rm; @@ -1959,6 +2022,7 @@ def MOVs : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg:$src), bits<4> Rd; bits<12> src; let Inst{15-12} = Rd; + let Inst{19-16} = 0b0000; let Inst{11-0} = src; let Inst{25} = 0; } @@ -2145,10 +2209,12 @@ defm SBC : AI1_adde_sube_irs<0b0110, "sbc", BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>; // ADC and SUBC with 's' bit set. -defm ADCS : AI1_adde_sube_s_irs<0b0101, "adcs", - BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; -defm SBCS : AI1_adde_sube_s_irs<0b0110, "sbcs", - BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>; +let usesCustomInserter = 1 in { +defm ADCS : AI1_adde_sube_s_irs< + BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; +defm SBCS : AI1_adde_sube_s_irs< + BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>; +} def RSBri : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm, IIC_iALUi, "rsb", "\t$Rd, $Rn, $imm", @@ -2190,31 +2256,17 @@ def RSBrs : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), } // RSB with 's' bit set. -let isCodeGenOnly = 1, Defs = [CPSR] in { -def RSBSri : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm, - IIC_iALUi, "rsbs", "\t$Rd, $Rn, $imm", - [(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]> { - bits<4> Rd; - bits<4> Rn; - bits<12> imm; - let Inst{25} = 1; - let Inst{20} = 1; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; - let Inst{11-0} = imm; -} -def RSBSrs : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - DPSoRegFrm, IIC_iALUsr, "rsbs", "\t$Rd, $Rn, $shift", - [(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]> { - bits<4> Rd; - bits<4> Rn; - bits<12> shift; - let Inst{25} = 0; - let Inst{20} = 1; - let Inst{11-0} = shift; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; -} +// NOTE: CPSR def omitted because it will be handled by the custom inserter. +let usesCustomInserter = 1 in { +def RSBSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), + Size4Bytes, IIC_iALUi, + [(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]>; +def RSBSrr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + Size4Bytes, IIC_iALUr, + [/* For disassembly only; pattern left blank */]>; +def RSBSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), + Size4Bytes, IIC_iALUsr, + [(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]>; } let Uses = [CPSR] in { @@ -2258,34 +2310,14 @@ def RSCrs : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), } } -// FIXME: Allow these to be predicated. -let isCodeGenOnly = 1, Defs = [CPSR], Uses = [CPSR] in { -def RSCSri : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), - DPFrm, IIC_iALUi, "rscs\t$Rd, $Rn, $imm", - [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>, - Requires<[IsARM]> { - bits<4> Rd; - bits<4> Rn; - bits<12> imm; - let Inst{25} = 1; - let Inst{20} = 1; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; - let Inst{11-0} = imm; -} -def RSCSrs : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - DPSoRegFrm, IIC_iALUsr, "rscs\t$Rd, $Rn, $shift", - [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>, - Requires<[IsARM]> { - bits<4> Rd; - bits<4> Rn; - bits<12> shift; - let Inst{25} = 0; - let Inst{20} = 1; - let Inst{11-0} = shift; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; -} +// NOTE: CPSR def omitted because it will be handled by the custom inserter. +let usesCustomInserter = 1, Uses = [CPSR] in { +def RSCSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), + Size4Bytes, IIC_iALUi, + [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>; +def RSCSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), + Size4Bytes, IIC_iALUsr, + [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>; } // (sub X, imm) gets canonicalized to (add X, -imm). Match this form. @@ -2300,8 +2332,10 @@ def : ARMPat<(addc GPR:$src, so_imm_neg:$imm), // The with-carry-in form matches bitwise not instead of the negation. // Effectively, the inverse interpretation of the carry flag already accounts // for part of the negation. -def : ARMPat<(adde GPR:$src, so_imm_not:$imm), +def : ARMPat<(adde_dead_carry GPR:$src, so_imm_not:$imm), (SBCri GPR:$src, so_imm_not:$imm)>; +def : ARMPat<(adde_live_carry GPR:$src, so_imm_not:$imm), + (SBCSri GPR:$src, so_imm_not:$imm)>; // Note: These are implemented in C++ code, because they have to generate // ADD/SUBrs instructions, which use a complex pattern that a xform function @@ -2617,14 +2651,16 @@ def MULv5: ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, def MUL : AsMul1I32<0b0000000, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm", [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>, - Requires<[IsARM, HasV6]>; + Requires<[IsARM, HasV6]> { + let Inst{15-12} = 0b0000; +} } let Constraints = "@earlyclobber $Rd" in def MLAv5: ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s), - Size4Bytes, IIC_iMAC32, - [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>, + Size4Bytes, IIC_iMAC32, + [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>, Requires<[IsARM, NoV6]> { bits<4> Ra; let Inst{15-12} = Ra; @@ -2657,7 +2693,7 @@ let neverHasSideEffects = 1 in { let isCommutable = 1 in { let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in { def SMULLv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), Size4Bytes, IIC_iMUL64, []>, Requires<[IsARM, NoV6]>; @@ -2681,15 +2717,15 @@ def UMULL : AsMul1I64<0b0000100, (outs GPR:$RdLo, GPR:$RdHi), // Multiply + accumulate let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in { def SMLALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), Size4Bytes, IIC_iMAC64, []>, Requires<[IsARM, NoV6]>; def UMLALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), Size4Bytes, IIC_iMAC64, []>, Requires<[IsARM, NoV6]>; def UMAALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), Size4Bytes, IIC_iMAC64, []>, Requires<[IsARM, NoV6]>; @@ -2970,17 +3006,25 @@ def REVSH : AMiscA1I<0b01101111, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm), IIC_iUNAr, "revsh", "\t$Rd, $Rm", [(set GPR:$Rd, (sext_inreg - (or (srl (and GPR:$Rm, 0xFF00), (i32 8)), + (or (srl GPR:$Rm, (i32 8)), (shl GPR:$Rm, (i32 8))), i16))]>, Requires<[IsARM, HasV6]>; +def : ARMV6Pat<(sext_inreg (or (srl (and GPR:$Rm, 0xFF00), (i32 8)), + (shl GPR:$Rm, (i32 8))), i16), + (REVSH GPR:$Rm)>; + +// Need the AddedComplexity or else MOVs + REV would be chosen. +let AddedComplexity = 5 in +def : ARMV6Pat<(sra (bswap GPR:$Rm), (i32 16)), (REVSH GPR:$Rm)>; + def lsl_shift_imm : SDNodeXFormgetZExtValue()); return CurDAG->getTargetConstant(Sh, MVT::i32); }]>; -def lsl_amt : PatLeaf<(i32 imm), [{ - return (N->getZExtValue() < 32); +def lsl_amt : ImmLeaf 0 && Imm < 32; }], lsl_shift_imm>; def PKHBT : APKHI<0b01101000, 0, (outs GPR:$Rd), @@ -3002,8 +3046,8 @@ def asr_shift_imm : SDNodeXFormgetTargetConstant(Sh, MVT::i32); }]>; -def asr_amt : PatLeaf<(i32 imm), [{ - return (N->getZExtValue() <= 32); +def asr_amt : ImmLeaf 0 && Imm <= 32; }], asr_shift_imm>; // Note: Shifts of 1-15 bits will be transformed to srl instead of sra and @@ -3119,88 +3163,43 @@ def BCCZi64 : PseudoInst<(outs), // Conditional moves // FIXME: should be able to write a pattern for ARMcmov, but can't use // a two-value operand where a dag node expects two operands. :( -// FIXME: These should all be pseudo-instructions that get expanded to -// the normal MOV instructions. That would fix the dependency on -// special casing them in tblgen. let neverHasSideEffects = 1 in { -def MOVCCr : AI1<0b1101, (outs GPR:$Rd), (ins GPR:$false, GPR:$Rm), DPFrm, - IIC_iCMOVr, "mov", "\t$Rd, $Rm", - [/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $Rd">, UnaryDP { - bits<4> Rd; - bits<4> Rm; - let Inst{25} = 0; - let Inst{20} = 0; - let Inst{15-12} = Rd; - let Inst{11-4} = 0b00000000; - let Inst{3-0} = Rm; -} - -def MOVCCs : AI1<0b1101, (outs GPR:$Rd), - (ins GPR:$false, so_reg:$shift), DPSoRegFrm, IIC_iCMOVsr, - "mov", "\t$Rd, $shift", - [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg:$shift, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $Rd">, UnaryDP { - bits<4> Rd; - bits<12> shift; - let Inst{25} = 0; - let Inst{20} = 0; - let Inst{19-16} = 0; - let Inst{15-12} = Rd; - let Inst{11-0} = shift; -} +def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, GPR:$Rm, pred:$p), + Size4Bytes, IIC_iCMOVr, + [/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $Rd">; +def MOVCCs : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$false, so_reg:$shift, pred:$p), + Size4Bytes, IIC_iCMOVsr, + [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg:$shift, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $Rd">; let isMoveImm = 1 in -def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm_hilo16:$imm), - DPFrm, IIC_iMOVi, - "movw", "\t$Rd, $imm", - []>, - RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>, - UnaryDP { - bits<4> Rd; - bits<16> imm; - let Inst{25} = 1; - let Inst{20} = 0; - let Inst{19-16} = imm{15-12}; - let Inst{15-12} = Rd; - let Inst{11-0} = imm{11-0}; -} +def MOVCCi16 : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$false, i32imm_hilo16:$imm, pred:$p), + Size4Bytes, IIC_iMOVi, + []>, + RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>; let isMoveImm = 1 in -def MOVCCi : AI1<0b1101, (outs GPR:$Rd), - (ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi, - "mov", "\t$Rd, $imm", +def MOVCCi : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$false, so_imm:$imm, pred:$p), + Size4Bytes, IIC_iCMOVi, [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm:$imm, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $Rd">, UnaryDP { - bits<4> Rd; - bits<12> imm; - let Inst{25} = 1; - let Inst{20} = 0; - let Inst{19-16} = 0b0000; - let Inst{15-12} = Rd; - let Inst{11-0} = imm; -} + RegConstraint<"$false = $Rd">; // Two instruction predicate mov immediate. let isMoveImm = 1 in -def MOVCCi32imm : PseudoInst<(outs GPR:$Rd), - (ins GPR:$false, i32imm:$src, pred:$p), - IIC_iCMOVix2, []>, RegConstraint<"$false = $Rd">; +def MOVCCi32imm : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$false, i32imm:$src, pred:$p), + Size8Bytes, IIC_iCMOVix2, []>, RegConstraint<"$false = $Rd">; let isMoveImm = 1 in -def MVNCCi : AI1<0b1111, (outs GPR:$Rd), - (ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi, - "mvn", "\t$Rd, $imm", +def MVNCCi : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$false, so_imm:$imm, pred:$p), + Size4Bytes, IIC_iCMOVi, [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm_not:$imm, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $Rd">, UnaryDP { - bits<4> Rd; - bits<12> imm; - let Inst{25} = 1; - let Inst{20} = 0; - let Inst{19-16} = 0b0000; - let Inst{15-12} = Rd; - let Inst{11-0} = imm; -} + RegConstraint<"$false = $Rd">; } // neverHasSideEffects //===----------------------------------------------------------------------===// @@ -3221,13 +3220,6 @@ def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, let Inst{31-4} = 0xf57ff05; let Inst{3-0} = opt; } - -def DMB_MCR : AInoP<(outs), (ins GPR:$zero), MiscFrm, NoItinerary, - "mcr", "\tp15, 0, $zero, c7, c10, 5", - [(ARMMemBarrierMCR GPR:$zero)]>, - Requires<[IsARM, HasV6]> { - // FIXME: add encoding -} } def DSB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, @@ -3266,6 +3258,18 @@ let usesCustomInserter = 1 in { def ATOMIC_LOAD_NAND_I8 : PseudoInst< (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, [(set GPR:$dst, (atomic_load_nand_8 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_MIN_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_min_8 GPR:$ptr, GPR:$val))]>; + def ATOMIC_LOAD_MAX_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_max_8 GPR:$ptr, GPR:$val))]>; + def ATOMIC_LOAD_UMIN_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_min_8 GPR:$ptr, GPR:$val))]>; + def ATOMIC_LOAD_UMAX_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_max_8 GPR:$ptr, GPR:$val))]>; def ATOMIC_LOAD_ADD_I16 : PseudoInst< (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, [(set GPR:$dst, (atomic_load_add_16 GPR:$ptr, GPR:$incr))]>; @@ -3284,6 +3288,18 @@ let usesCustomInserter = 1 in { def ATOMIC_LOAD_NAND_I16 : PseudoInst< (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, [(set GPR:$dst, (atomic_load_nand_16 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_MIN_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_min_16 GPR:$ptr, GPR:$val))]>; + def ATOMIC_LOAD_MAX_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_max_16 GPR:$ptr, GPR:$val))]>; + def ATOMIC_LOAD_UMIN_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_min_16 GPR:$ptr, GPR:$val))]>; + def ATOMIC_LOAD_UMAX_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_max_16 GPR:$ptr, GPR:$val))]>; def ATOMIC_LOAD_ADD_I32 : PseudoInst< (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, [(set GPR:$dst, (atomic_load_add_32 GPR:$ptr, GPR:$incr))]>; @@ -3302,6 +3318,18 @@ let usesCustomInserter = 1 in { def ATOMIC_LOAD_NAND_I32 : PseudoInst< (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, [(set GPR:$dst, (atomic_load_nand_32 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_MIN_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_min_32 GPR:$ptr, GPR:$val))]>; + def ATOMIC_LOAD_MAX_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_max_32 GPR:$ptr, GPR:$val))]>; + def ATOMIC_LOAD_UMIN_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_min_32 GPR:$ptr, GPR:$val))]>; + def ATOMIC_LOAD_UMAX_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$val), NoItinerary, + [(set GPR:$dst, (atomic_load_max_32 GPR:$ptr, GPR:$val))]>; def ATOMIC_SWAP_I8 : PseudoInst< (outs GPR:$dst), (ins GPR:$ptr, GPR:$new), NoItinerary, @@ -3326,39 +3354,26 @@ let usesCustomInserter = 1 in { } let mayLoad = 1 in { -def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary, - "ldrexb", "\t$Rt, [$Rn]", - []>; -def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary, - "ldrexh", "\t$Rt, [$Rn]", - []>; -def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary, - "ldrex", "\t$Rt, [$Rn]", - []>; -def LDREXD : AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2), (ins GPR:$Rn), - NoItinerary, - "ldrexd", "\t$Rt, $Rt2, [$Rn]", - []>; +def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary, + "ldrexb", "\t$Rt, $addr", []>; +def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary, + "ldrexh", "\t$Rt, $addr", []>; +def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary, + "ldrex", "\t$Rt, $addr", []>; +def LDREXD : AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2), (ins addrmode7:$addr), + NoItinerary, "ldrexd", "\t$Rt, $Rt2, $addr", []>; } let mayStore = 1, Constraints = "@earlyclobber $Rd" in { -def STREXB : AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$src, GPR:$Rn), - NoItinerary, - "strexb", "\t$Rd, $src, [$Rn]", - []>; -def STREXH : AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn), - NoItinerary, - "strexh", "\t$Rd, $Rt, [$Rn]", - []>; -def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn), - NoItinerary, - "strex", "\t$Rd, $Rt, [$Rn]", - []>; +def STREXB : AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr), + NoItinerary, "strexb", "\t$Rd, $Rt, $addr", []>; +def STREXH : AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr), + NoItinerary, "strexh", "\t$Rd, $Rt, $addr", []>; +def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr), + NoItinerary, "strex", "\t$Rd, $Rt, $addr", []>; def STREXD : AIstrex<0b01, (outs GPR:$Rd), - (ins GPR:$Rt, GPR:$Rt2, GPR:$Rn), - NoItinerary, - "strexd", "\t$Rd, $Rt, $Rt2, [$Rn]", - []>; + (ins GPR:$Rt, GPR:$Rt2, addrmode7:$addr), + NoItinerary, "strexd", "\t$Rd, $Rt, $Rt2, $addr", []>; } // Clear-Exclusive is for disassembly only. @@ -3376,12 +3391,330 @@ def SWPB : AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swpb", [/* For disassembly only; pattern left blank */]>; } +//===----------------------------------------------------------------------===// +// Coprocessor Instructions. +// + +def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), + NoItinerary, "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + bits<4> opc1; + bits<4> CRn; + bits<4> CRd; + bits<4> cop; + bits<3> opc2; + bits<4> CRm; + + let Inst{3-0} = CRm; + let Inst{4} = 0; + let Inst{7-5} = opc2; + let Inst{11-8} = cop; + let Inst{15-12} = CRd; + let Inst{19-16} = CRn; + let Inst{23-20} = opc1; +} + +def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), + NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + bits<4> opc1; + bits<4> CRn; + bits<4> CRd; + bits<4> cop; + bits<3> opc2; + bits<4> CRm; + + let Inst{3-0} = CRm; + let Inst{4} = 0; + let Inst{7-5} = opc2; + let Inst{11-8} = cop; + let Inst{15-12} = CRd; + let Inst{19-16} = CRn; + let Inst{23-20} = opc1; +} + +class ACI + : InoP { + let Inst{27-25} = 0b110; +} + +multiclass LdStCop op31_28, bit load, dag ops, string opc, string cond>{ + + def _OFFSET : ACI<(outs), + !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), + !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def _PRE : ACI<(outs), + !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), + !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr!", IndexModePre> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 1; // W = 1 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def _POST : ACI<(outs), + !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), + !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr", IndexModePost> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{21} = 1; // W = 1 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def _OPTION : ACI<(outs), + !con((ins nohash_imm:$cop,nohash_imm:$CRd,GPR:$base, nohash_imm:$option), + ops), + !strconcat(opc, cond), "\tp$cop, cr$CRd, [$base], \\{$option\\}"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{23} = 1; // U = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def L_OFFSET : ACI<(outs), + !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), + !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } + + def L_PRE : ACI<(outs), + !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), + !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr!", + IndexModePre> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 1; // W = 1 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } + + def L_POST : ACI<(outs), + !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), + !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr", + IndexModePost> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{21} = 1; // W = 1 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } + + def L_OPTION : ACI<(outs), + !con((ins nohash_imm:$cop, nohash_imm:$CRd,GPR:$base,nohash_imm:$option), + ops), + !strconcat(!strconcat(opc, "l"), cond), + "\tp$cop, cr$CRd, [$base], \\{$option\\}"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{23} = 1; // U = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } +} + +defm LDC : LdStCop<{?,?,?,?}, 1, (ins pred:$p), "ldc", "${p}">; +defm LDC2 : LdStCop<0b1111, 1, (ins), "ldc2", "">; +defm STC : LdStCop<{?,?,?,?}, 0, (ins pred:$p), "stc", "${p}">; +defm STC2 : LdStCop<0b1111, 0, (ins), "stc2", "">; + +//===----------------------------------------------------------------------===// +// Move between coprocessor and ARM core register -- for disassembly only +// + +class MovRCopro + : ABI<0b1110, oops, iops, NoItinerary, opc, + "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{20} = direction; + let Inst{4} = 1; + + bits<4> Rt; + bits<4> cop; + bits<3> opc1; + bits<3> opc2; + bits<4> CRm; + bits<4> CRn; + + let Inst{15-12} = Rt; + let Inst{11-8} = cop; + let Inst{23-21} = opc1; + let Inst{7-5} = opc2; + let Inst{3-0} = CRm; + let Inst{19-16} = CRn; +} + +def MCR : MovRCopro<"mcr", 0 /* from ARM core register to coprocessor */, + (outs), (ins p_imm:$cop, i32imm:$opc1, + GPR:$Rt, c_imm:$CRn, c_imm:$CRm, + i32imm:$opc2)>; +def MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */, + (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, + c_imm:$CRn, c_imm:$CRm, i32imm:$opc2)>; + +class MovRCopro2 + : ABXI<0b1110, oops, iops, NoItinerary, + !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{20} = direction; + let Inst{4} = 1; + + bits<4> Rt; + bits<4> cop; + bits<3> opc1; + bits<3> opc2; + bits<4> CRm; + bits<4> CRn; + + let Inst{15-12} = Rt; + let Inst{11-8} = cop; + let Inst{23-21} = opc1; + let Inst{7-5} = opc2; + let Inst{3-0} = CRm; + let Inst{19-16} = CRn; +} + +def MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */, + (outs), (ins p_imm:$cop, i32imm:$opc1, + GPR:$Rt, c_imm:$CRn, c_imm:$CRm, + i32imm:$opc2)>; +def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */, + (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, + c_imm:$CRn, c_imm:$CRm, + i32imm:$opc2)>; + +class MovRRCopro + : ABI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, + GPR:$Rt, GPR:$Rt2, c_imm:$CRm), + NoItinerary, opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-21} = 0b010; + let Inst{20} = direction; + + bits<4> Rt; + bits<4> Rt2; + bits<4> cop; + bits<4> opc1; + bits<4> CRm; + + let Inst{15-12} = Rt; + let Inst{19-16} = Rt2; + let Inst{11-8} = cop; + let Inst{7-4} = opc1; + let Inst{3-0} = CRm; +} + +def MCRR : MovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */>; +def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>; + +class MovRRCopro2 + : ABXI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, + GPR:$Rt, GPR:$Rt2, c_imm:$CRm), + NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{23-21} = 0b010; + let Inst{20} = direction; + + bits<4> Rt; + bits<4> Rt2; + bits<4> cop; + bits<4> opc1; + bits<4> CRm; + + let Inst{15-12} = Rt; + let Inst{19-16} = Rt2; + let Inst{11-8} = cop; + let Inst{7-4} = opc1; + let Inst{3-0} = CRm; +} + +def MCRR2 : MovRRCopro2<"mcrr2", 0 /* from ARM core register to coprocessor */>; +def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>; + +//===----------------------------------------------------------------------===// +// Move between special register and ARM core register -- for disassembly only +// + +// Move to ARM core register from Special Register +def MRS : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, cpsr", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + let Inst{23-16} = 0b00001111; + let Inst{15-12} = Rd; + let Inst{7-4} = 0b0000; +} + +def MRSsys : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary,"mrs","\t$Rd, spsr", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + let Inst{23-16} = 0b01001111; + let Inst{15-12} = Rd; + let Inst{7-4} = 0b0000; +} + +// Move from ARM core register to Special Register +// +// No need to have both system and application versions, the encodings are the +// same and the assembly parser has no way to distinguish between them. The mask +// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains +// the mask with the fields to be accessed in the special register. +def MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary, + "msr", "\t$mask, $Rn", + [/* For disassembly only; pattern left blank */]> { + bits<5> mask; + bits<4> Rn; + + let Inst{23} = 0; + let Inst{22} = mask{4}; // R bit + let Inst{21-20} = 0b10; + let Inst{19-16} = mask{3-0}; + let Inst{15-12} = 0b1111; + let Inst{11-4} = 0b00000000; + let Inst{3-0} = Rn; +} + +def MSRi : ABI<0b0011, (outs), (ins msr_mask:$mask, so_imm:$a), NoItinerary, + "msr", "\t$mask, $a", + [/* For disassembly only; pattern left blank */]> { + bits<5> mask; + bits<12> a; + + let Inst{23} = 0; + let Inst{22} = mask{4}; // R bit + let Inst{21-20} = 0b10; + let Inst{19-16} = mask{3-0}; + let Inst{15-12} = 0b1111; + let Inst{11-0} = a; +} + //===----------------------------------------------------------------------===// // TLS Instructions // // __aeabi_read_tp preserves the registers r1-r3. -// This is a pseudo inst so that we can get the encoding right, +// This is a pseudo inst so that we can get the encoding right, // complete with fixup for the aeabi_read_tp function. let isCall = 1, Defs = [R0, R12, LR, CPSR], Uses = [SP] in { @@ -3397,7 +3730,7 @@ let isCall = 1, // here, and we're using the stack frame for the containing function to // save/restore registers, we can't keep anything live in regs across // the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon -// when we get here from a longjmp(). We force everthing out of registers +// when we get here from a longjmp(). We force everything out of registers // except for our own input by listing the relevant registers in Defs. By // doing so, we also cause the prologue/epilogue code to actively preserve // all of the callee-saved resgisters, which is exactly what we want. @@ -3440,8 +3773,8 @@ def Int_eh_sjlj_longjmp : PseudoInst<(outs), (ins GPR:$src, GPR:$scratch), // that need the instruction size). let isBarrier = 1, hasSideEffects = 1 in def Int_eh_sjlj_dispatchsetup : - PseudoInst<(outs), (ins GPR:$src), NoItinerary, - [(ARMeh_sjlj_dispatchsetup GPR:$src)]>, + PseudoInst<(outs), (ins), NoItinerary, + [(ARMeh_sjlj_dispatchsetup)]>, Requires<[IsDarwin]>; //===----------------------------------------------------------------------===// @@ -3583,6 +3916,12 @@ def : ARMV5TEPat<(add GPR:$acc, (sra (mul GPR:$a, sext_16_node:$b), (i32 16))), (SMLAWB GPR:$a, GPR:$b, GPR:$acc)>; + +// Pre-v7 uses MCR for synchronization barriers. +def : ARMPat<(ARMMemBarrierMCR GPR:$zero), (MCR 15, 0, GPR:$zero, 7, 10, 5)>, + Requires<[IsARM, HasV6]>; + + //===----------------------------------------------------------------------===// // Thumb Support // @@ -3607,305 +3946,3 @@ include "ARMInstrVFP.td" include "ARMInstrNEON.td" -//===----------------------------------------------------------------------===// -// Coprocessor Instructions. For disassembly only. -// - -def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), - NoItinerary, "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", - [/* For disassembly only; pattern left blank */]> { - bits<4> opc1; - bits<4> CRn; - bits<4> CRd; - bits<4> cop; - bits<3> opc2; - bits<4> CRm; - - let Inst{3-0} = CRm; - let Inst{4} = 0; - let Inst{7-5} = opc2; - let Inst{11-8} = cop; - let Inst{15-12} = CRd; - let Inst{19-16} = CRn; - let Inst{23-20} = opc1; -} - -def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), - NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-28} = 0b1111; - bits<4> opc1; - bits<4> CRn; - bits<4> CRd; - bits<4> cop; - bits<3> opc2; - bits<4> CRm; - - let Inst{3-0} = CRm; - let Inst{4} = 0; - let Inst{7-5} = opc2; - let Inst{11-8} = cop; - let Inst{15-12} = CRd; - let Inst{19-16} = CRn; - let Inst{23-20} = opc1; -} - -class ACI - : I { - let Inst{27-25} = 0b110; -} - -multiclass LdStCop op31_28, bit load, string opc> { - - def _OFFSET : ACI<(outs), - (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), - opc, "\tp$cop, cr$CRd, $addr"> { - let Inst{31-28} = op31_28; - let Inst{24} = 1; // P = 1 - let Inst{21} = 0; // W = 0 - let Inst{22} = 0; // D = 0 - let Inst{20} = load; - } - - def _PRE : ACI<(outs), - (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), - opc, "\tp$cop, cr$CRd, $addr!"> { - let Inst{31-28} = op31_28; - let Inst{24} = 1; // P = 1 - let Inst{21} = 1; // W = 1 - let Inst{22} = 0; // D = 0 - let Inst{20} = load; - } - - def _POST : ACI<(outs), - (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset), - opc, "\tp$cop, cr$CRd, [$base], $offset"> { - let Inst{31-28} = op31_28; - let Inst{24} = 0; // P = 0 - let Inst{21} = 1; // W = 1 - let Inst{22} = 0; // D = 0 - let Inst{20} = load; - } - - def _OPTION : ACI<(outs), - (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, i32imm:$option), - opc, "\tp$cop, cr$CRd, [$base], $option"> { - let Inst{31-28} = op31_28; - let Inst{24} = 0; // P = 0 - let Inst{23} = 1; // U = 1 - let Inst{21} = 0; // W = 0 - let Inst{22} = 0; // D = 0 - let Inst{20} = load; - } - - def L_OFFSET : ACI<(outs), - (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), - !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr"> { - let Inst{31-28} = op31_28; - let Inst{24} = 1; // P = 1 - let Inst{21} = 0; // W = 0 - let Inst{22} = 1; // D = 1 - let Inst{20} = load; - } - - def L_PRE : ACI<(outs), - (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), - !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!"> { - let Inst{31-28} = op31_28; - let Inst{24} = 1; // P = 1 - let Inst{21} = 1; // W = 1 - let Inst{22} = 1; // D = 1 - let Inst{20} = load; - } - - def L_POST : ACI<(outs), - (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset), - !strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $offset"> { - let Inst{31-28} = op31_28; - let Inst{24} = 0; // P = 0 - let Inst{21} = 1; // W = 1 - let Inst{22} = 1; // D = 1 - let Inst{20} = load; - } - - def L_OPTION : ACI<(outs), - (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, nohash_imm:$option), - !strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $option"> { - let Inst{31-28} = op31_28; - let Inst{24} = 0; // P = 0 - let Inst{23} = 1; // U = 1 - let Inst{21} = 0; // W = 0 - let Inst{22} = 1; // D = 1 - let Inst{20} = load; - } -} - -defm LDC : LdStCop<{?,?,?,?}, 1, "ldc">; -defm LDC2 : LdStCop<0b1111, 1, "ldc2">; -defm STC : LdStCop<{?,?,?,?}, 0, "stc">; -defm STC2 : LdStCop<0b1111, 0, "stc2">; - -//===----------------------------------------------------------------------===// -// Move between coprocessor and ARM core register -- for disassembly only -// - -class MovRCopro - : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, - GPR:$Rt, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), - NoItinerary, opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2", - [/* For disassembly only; pattern left blank */]> { - let Inst{20} = direction; - let Inst{4} = 1; - - bits<4> Rt; - bits<4> cop; - bits<3> opc1; - bits<3> opc2; - bits<4> CRm; - bits<4> CRn; - - let Inst{15-12} = Rt; - let Inst{11-8} = cop; - let Inst{23-21} = opc1; - let Inst{7-5} = opc2; - let Inst{3-0} = CRm; - let Inst{19-16} = CRn; -} - -def MCR : MovRCopro<"mcr", 0 /* from ARM core register to coprocessor */>; -def MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */>; - -class MovRCopro2 - : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, - GPR:$Rt, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), - NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), - [/* For disassembly only; pattern left blank */]> { - let Inst{31-28} = 0b1111; - let Inst{20} = direction; - let Inst{4} = 1; - - bits<4> Rt; - bits<4> cop; - bits<3> opc1; - bits<3> opc2; - bits<4> CRm; - bits<4> CRn; - - let Inst{15-12} = Rt; - let Inst{11-8} = cop; - let Inst{23-21} = opc1; - let Inst{7-5} = opc2; - let Inst{3-0} = CRm; - let Inst{19-16} = CRn; -} - -def MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */>; -def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */>; - -class MovRRCopro - : ABI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, - GPR:$Rt, GPR:$Rt2, c_imm:$CRm), - NoItinerary, opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", - [/* For disassembly only; pattern left blank */]> { - let Inst{23-21} = 0b010; - let Inst{20} = direction; - - bits<4> Rt; - bits<4> Rt2; - bits<4> cop; - bits<4> opc1; - bits<4> CRm; - - let Inst{15-12} = Rt; - let Inst{19-16} = Rt2; - let Inst{11-8} = cop; - let Inst{7-4} = opc1; - let Inst{3-0} = CRm; -} - -def MCRR : MovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */>; -def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>; - -class MovRRCopro2 - : ABXI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, - GPR:$Rt, GPR:$Rt2, c_imm:$CRm), - NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), - [/* For disassembly only; pattern left blank */]> { - let Inst{31-28} = 0b1111; - let Inst{23-21} = 0b010; - let Inst{20} = direction; - - bits<4> Rt; - bits<4> Rt2; - bits<4> cop; - bits<4> opc1; - bits<4> CRm; - - let Inst{15-12} = Rt; - let Inst{19-16} = Rt2; - let Inst{11-8} = cop; - let Inst{7-4} = opc1; - let Inst{3-0} = CRm; -} - -def MCRR2 : MovRRCopro2<"mcrr2", 0 /* from ARM core register to coprocessor */>; -def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>; - -//===----------------------------------------------------------------------===// -// Move between special register and ARM core register -- for disassembly only -// - -// Move to ARM core register from Special Register -def MRS : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, cpsr", - [/* For disassembly only; pattern left blank */]> { - bits<4> Rd; - let Inst{23-16} = 0b00001111; - let Inst{15-12} = Rd; - let Inst{7-4} = 0b0000; -} - -def MRSsys : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary,"mrs","\t$Rd, spsr", - [/* For disassembly only; pattern left blank */]> { - bits<4> Rd; - let Inst{23-16} = 0b01001111; - let Inst{15-12} = Rd; - let Inst{7-4} = 0b0000; -} - -// Move from ARM core register to Special Register -// -// No need to have both system and application versions, the encodings are the -// same and the assembly parser has no way to distinguish between them. The mask -// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains -// the mask with the fields to be accessed in the special register. -def MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary, - "msr", "\t$mask, $Rn", - [/* For disassembly only; pattern left blank */]> { - bits<5> mask; - bits<4> Rn; - - let Inst{23} = 0; - let Inst{22} = mask{4}; // R bit - let Inst{21-20} = 0b10; - let Inst{19-16} = mask{3-0}; - let Inst{15-12} = 0b1111; - let Inst{11-4} = 0b00000000; - let Inst{3-0} = Rn; -} - -def MSRi : ABI<0b0011, (outs), (ins msr_mask:$mask, so_imm:$a), NoItinerary, - "msr", "\t$mask, $a", - [/* For disassembly only; pattern left blank */]> { - bits<5> mask; - bits<12> a; - - let Inst{23} = 0; - let Inst{22} = mask{4}; // R bit - let Inst{21-20} = 0b10; - let Inst{19-16} = mask{3-0}; - let Inst{15-12} = 0b1111; - let Inst{11-0} = a; -} diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td b/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td index dc3d63e26ef5..e34d69a44d9f 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td @@ -80,6 +80,12 @@ def SDTARMVORRIMM : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>, def NEONvorrImm : SDNode<"ARMISD::VORRIMM", SDTARMVORRIMM>; def NEONvbicImm : SDNode<"ARMISD::VBICIMM", SDTARMVORRIMM>; +def NEONvbsl : SDNode<"ARMISD::VBSL", + SDTypeProfile<1, 3, [SDTCisVec<0>, + SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, + SDTCisSameAs<0, 3>]>>; + def NEONvdup : SDNode<"ARMISD::VDUP", SDTypeProfile<1, 1, [SDTCisVec<0>]>>; // VDUPLANE can produce a quad-register result from a double-register source, @@ -146,10 +152,6 @@ def VLDMQIA : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn), IIC_fpLoad_m, "", [(set QPR:$dst, (v2f64 (load GPR:$Rn)))]>; -def VLDMQDB - : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn), - IIC_fpLoad_m, "", - [(set QPR:$dst, (v2f64 (load GPR:$Rn)))]>; // Use VSTM to store a Q register as a D register pair. // This is a pseudo instruction that is expanded to VSTMD after reg alloc. @@ -157,10 +159,6 @@ def VSTMQIA : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn), IIC_fpStore_m, "", [(store (v2f64 QPR:$src), GPR:$Rn)]>; -def VSTMQDB - : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn), - IIC_fpStore_m, "", - [(store (v2f64 QPR:$src), GPR:$Rn)]>; // Classes for VLD* pseudo-instructions with multi-register operands. // These are expanded to real instructions after register allocation. @@ -1801,7 +1799,7 @@ class N3VDX op21_20, bits<4> op11_8, bit op4, class N3VDSL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> - : N3V<0, 1, op21_20, op11_8, 1, 0, + : N3VLane32<0, 1, op21_20, op11_8, 1, 0, (outs DPR:$Vd), (ins DPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", [(set (Ty DPR:$Vd), @@ -1811,7 +1809,7 @@ class N3VDSL op21_20, bits<4> op11_8, } class N3VDSL16 op21_20, bits<4> op11_8, string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> - : N3V<0, 1, op21_20, op11_8, 1, 0, + : N3VLane16<0, 1, op21_20, op11_8, 1, 0, (outs DPR:$Vd), (ins DPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), NVMulSLFrm, IIC_VMULi16D, OpcodeStr, Dt,"$Vd, $Vn, $Vm[$lane]","", [(set (Ty DPR:$Vd), @@ -1841,7 +1839,7 @@ class N3VQX op21_20, bits<4> op11_8, bit op4, class N3VQSL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, SDNode ShOp> - : N3V<1, 1, op21_20, op11_8, 1, 0, + : N3VLane32<1, 1, op21_20, op11_8, 1, 0, (outs QPR:$Vd), (ins QPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", [(set (ResTy QPR:$Vd), @@ -1852,7 +1850,7 @@ class N3VQSL op21_20, bits<4> op11_8, } class N3VQSL16 op21_20, bits<4> op11_8, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, SDNode ShOp> - : N3V<1, 1, op21_20, op11_8, 1, 0, + : N3VLane16<1, 1, op21_20, op11_8, 1, 0, (outs QPR:$Vd), (ins QPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), NVMulSLFrm, IIC_VMULi16Q, OpcodeStr, Dt,"$Vd, $Vn, $Vm[$lane]","", [(set (ResTy QPR:$Vd), @@ -1874,7 +1872,7 @@ class N3VDInt op21_20, bits<4> op11_8, bit op4, } class N3VDIntSL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty, Intrinsic IntOp> - : N3V<0, 1, op21_20, op11_8, 1, 0, + : N3VLane32<0, 1, op21_20, op11_8, 1, 0, (outs DPR:$Vd), (ins DPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", [(set (Ty DPR:$Vd), @@ -1885,7 +1883,7 @@ class N3VDIntSL op21_20, bits<4> op11_8, InstrItinClass itin, } class N3VDIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty, Intrinsic IntOp> - : N3V<0, 1, op21_20, op11_8, 1, 0, + : N3VLane16<0, 1, op21_20, op11_8, 1, 0, (outs DPR:$Vd), (ins DPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", [(set (Ty DPR:$Vd), @@ -1915,7 +1913,7 @@ class N3VQInt op21_20, bits<4> op11_8, bit op4, class N3VQIntSL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, Intrinsic IntOp> - : N3V<1, 1, op21_20, op11_8, 1, 0, + : N3VLane32<1, 1, op21_20, op11_8, 1, 0, (outs QPR:$Vd), (ins QPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", [(set (ResTy QPR:$Vd), @@ -1927,7 +1925,7 @@ class N3VQIntSL op21_20, bits<4> op11_8, InstrItinClass itin, class N3VQIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, Intrinsic IntOp> - : N3V<1, 1, op21_20, op11_8, 1, 0, + : N3VLane16<1, 1, op21_20, op11_8, 1, 0, (outs QPR:$Vd), (ins QPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", [(set (ResTy QPR:$Vd), @@ -1959,7 +1957,7 @@ class N3VDMulOp op21_20, bits<4> op11_8, bit op4, class N3VDMulOpSL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty, SDPatternOperator MulOp, SDPatternOperator ShOp> - : N3V<0, 1, op21_20, op11_8, 1, 0, + : N3VLane32<0, 1, op21_20, op11_8, 1, 0, (outs DPR:$Vd), (ins DPR:$src1, DPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, @@ -1972,7 +1970,7 @@ class N3VDMulOpSL op21_20, bits<4> op11_8, InstrItinClass itin, class N3VDMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty, SDNode MulOp, SDNode ShOp> - : N3V<0, 1, op21_20, op11_8, 1, 0, + : N3VLane16<0, 1, op21_20, op11_8, 1, 0, (outs DPR:$Vd), (ins DPR:$src1, DPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, @@ -1994,7 +1992,7 @@ class N3VQMulOp op21_20, bits<4> op11_8, bit op4, class N3VQMulOpSL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, SDPatternOperator MulOp, SDPatternOperator ShOp> - : N3V<1, 1, op21_20, op11_8, 1, 0, + : N3VLane32<1, 1, op21_20, op11_8, 1, 0, (outs QPR:$Vd), (ins QPR:$src1, QPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, @@ -2008,7 +2006,7 @@ class N3VQMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, SDNode MulOp, SDNode ShOp> - : N3V<1, 1, op21_20, op11_8, 1, 0, + : N3VLane16<1, 1, op21_20, op11_8, 1, 0, (outs QPR:$Vd), (ins QPR:$src1, QPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), NVMulSLFrm, itin, @@ -2069,7 +2067,7 @@ class N3VLMulOp op21_20, bits<4> op11_8, bit op4, class N3VLMulOpSL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType TyQ, ValueType TyD, SDNode MulOp, SDNode OpNode> - : N3V op21_20, bits<4> op11_8, class N3VLMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType TyQ, ValueType TyD, SDNode MulOp, SDNode OpNode> - : N3V op21_20, bits<4> op11_8, bit op4, class N3VLInt3SL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, Intrinsic IntOp> - : N3V op21_20, bits<4> op11_8, InstrItinClass itin, class N3VLInt3SL16 op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, Intrinsic IntOp> - : N3V op21_20, bits<4> op11_8, bit op4, class N3VLSL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType TyQ, ValueType TyD, SDNode OpNode> - : N3V op21_20, bits<4> op11_8, class N3VLSL16 op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType TyQ, ValueType TyD, SDNode OpNode> - : N3V op21_20, bits<4> op11_8, bit op4, class N3VLIntSL op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, Intrinsic IntOp> - : N3V op21_20, bits<4> op11_8, InstrItinClass itin, class N3VLIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, Intrinsic IntOp> - : N3V op24_23, bits<2> op21_20, bits<2> op19_18, // Shift by immediate, // both double- and quad-register. class N2VDSh op11_8, bit op7, bit op4, - Format f, InstrItinClass itin, string OpcodeStr, string Dt, - ValueType Ty, SDNode OpNode> + Format f, InstrItinClass itin, Operand ImmTy, + string OpcodeStr, string Dt, ValueType Ty, SDNode OpNode> : N2VImm; class N2VQSh op11_8, bit op7, bit op4, - Format f, InstrItinClass itin, string OpcodeStr, string Dt, - ValueType Ty, SDNode OpNode> + Format f, InstrItinClass itin, Operand ImmTy, + string OpcodeStr, string Dt, ValueType Ty, SDNode OpNode> : N2VImm; @@ -2315,9 +2313,9 @@ class N2VLSh op11_8, bit op7, bit op6, bit op4, // Narrow shift by immediate. class N2VNSh op11_8, bit op7, bit op6, bit op4, InstrItinClass itin, string OpcodeStr, string Dt, - ValueType ResTy, ValueType OpTy, SDNode OpNode> + ValueType ResTy, ValueType OpTy, Operand ImmTy, SDNode OpNode> : N2VImm; @@ -2325,16 +2323,18 @@ class N2VNSh op11_8, bit op7, bit op6, bit op4, // Shift right by immediate and accumulate, // both double- and quad-register. class N2VDShAdd op11_8, bit op7, bit op4, - string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + Operand ImmTy, string OpcodeStr, string Dt, + ValueType Ty, SDNode ShOp> : N2VImm; class N2VQShAdd op11_8, bit op7, bit op4, - string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + Operand ImmTy, string OpcodeStr, string Dt, + ValueType Ty, SDNode ShOp> : N2VImm; @@ -2342,15 +2342,17 @@ class N2VQShAdd op11_8, bit op7, bit op4, // Shift by immediate and insert, // both double- and quad-register. class N2VDShIns op11_8, bit op7, bit op4, - Format f, string OpcodeStr, string Dt, ValueType Ty,SDNode ShOp> + Operand ImmTy, Format f, string OpcodeStr, string Dt, + ValueType Ty,SDNode ShOp> : N2VImm; class N2VQShIns op11_8, bit op7, bit op4, - Format f, string OpcodeStr, string Dt, ValueType Ty,SDNode ShOp> + Operand ImmTy, Format f, string OpcodeStr, string Dt, + ValueType Ty,SDNode ShOp> : N2VImm; @@ -3010,40 +3012,77 @@ multiclass N2VPLInt2_QHS op24_23, bits<2> op21_20, bits<2> op17_16, // Neon 2-register vector shift by immediate, // with f of either N2RegVShLFrm or N2RegVShRFrm // element sizes of 8, 16, 32 and 64 bits: -multiclass N2VSh_QHSD op11_8, bit op4, - InstrItinClass itin, string OpcodeStr, string Dt, - SDNode OpNode, Format f> { +multiclass N2VShL_QHSD op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + SDNode OpNode> { // 64-bit vector types. - def v8i8 : N2VDSh { let Inst{21-19} = 0b001; // imm6 = 001xxx } - def v4i16 : N2VDSh { let Inst{21-20} = 0b01; // imm6 = 01xxxx } - def v2i32 : N2VDSh { let Inst{21} = 0b1; // imm6 = 1xxxxx } - def v1i64 : N2VDSh; // imm6 = xxxxxx // 128-bit vector types. - def v16i8 : N2VQSh { let Inst{21-19} = 0b001; // imm6 = 001xxx } - def v8i16 : N2VQSh { let Inst{21-20} = 0b01; // imm6 = 01xxxx } - def v4i32 : N2VQSh { let Inst{21} = 0b1; // imm6 = 1xxxxx } - def v2i64 : N2VQSh; + // imm6 = xxxxxx +} +multiclass N2VShR_QHSD op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + SDNode OpNode> { + // 64-bit vector types. + def v8i8 : N2VDSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VDSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VDSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v1i64 : N2VDSh; + // imm6 = xxxxxx + + // 128-bit vector types. + def v16i8 : N2VQSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v8i16 : N2VQSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v4i32 : N2VQSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v2i64 : N2VQSh; // imm6 = xxxxxx } @@ -3053,79 +3092,113 @@ multiclass N2VSh_QHSD op11_8, bit op4, multiclass N2VShAdd_QHSD op11_8, bit op4, string OpcodeStr, string Dt, SDNode ShOp> { // 64-bit vector types. - def v8i8 : N2VDShAdd { let Inst{21-19} = 0b001; // imm6 = 001xxx } - def v4i16 : N2VDShAdd { let Inst{21-20} = 0b01; // imm6 = 01xxxx } - def v2i32 : N2VDShAdd { let Inst{21} = 0b1; // imm6 = 1xxxxx } - def v1i64 : N2VDShAdd; // imm6 = xxxxxx // 128-bit vector types. - def v16i8 : N2VQShAdd { let Inst{21-19} = 0b001; // imm6 = 001xxx } - def v8i16 : N2VQShAdd { let Inst{21-20} = 0b01; // imm6 = 01xxxx } - def v4i32 : N2VQShAdd { let Inst{21} = 0b1; // imm6 = 1xxxxx } - def v2i64 : N2VQShAdd; // imm6 = xxxxxx } - // Neon Shift-Insert vector operations, // with f of either N2RegVShLFrm or N2RegVShRFrm // element sizes of 8, 16, 32 and 64 bits: -multiclass N2VShIns_QHSD op11_8, bit op4, - string OpcodeStr, SDNode ShOp, - Format f> { +multiclass N2VShInsL_QHSD op11_8, bit op4, + string OpcodeStr> { // 64-bit vector types. - def v8i8 : N2VDShIns { + def v8i8 : N2VDShIns { let Inst{21-19} = 0b001; // imm6 = 001xxx } - def v4i16 : N2VDShIns { + def v4i16 : N2VDShIns { let Inst{21-20} = 0b01; // imm6 = 01xxxx } - def v2i32 : N2VDShIns { + def v2i32 : N2VDShIns { let Inst{21} = 0b1; // imm6 = 1xxxxx } - def v1i64 : N2VDShIns; + def v1i64 : N2VDShIns; // imm6 = xxxxxx // 128-bit vector types. - def v16i8 : N2VQShIns { + def v16i8 : N2VQShIns { let Inst{21-19} = 0b001; // imm6 = 001xxx } - def v8i16 : N2VQShIns { + def v8i16 : N2VQShIns { let Inst{21-20} = 0b01; // imm6 = 01xxxx } - def v4i32 : N2VQShIns { + def v4i32 : N2VQShIns { let Inst{21} = 0b1; // imm6 = 1xxxxx } - def v2i64 : N2VQShIns; + def v2i64 : N2VQShIns; + // imm6 = xxxxxx +} +multiclass N2VShInsR_QHSD op11_8, bit op4, + string OpcodeStr> { + // 64-bit vector types. + def v8i8 : N2VDShIns { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VDShIns { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VDShIns { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v1i64 : N2VDShIns; + // imm6 = xxxxxx + + // 128-bit vector types. + def v16i8 : N2VQShIns { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v8i16 : N2VQShIns { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v4i32 : N2VQShIns { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v2i64 : N2VQShIns; // imm6 = xxxxxx } @@ -3153,15 +3226,18 @@ multiclass N2VNSh_HSD op11_8, bit op7, bit op6, bit op4, InstrItinClass itin, string OpcodeStr, string Dt, SDNode OpNode> { def v8i8 : N2VNSh { + OpcodeStr, !strconcat(Dt, "16"), + v8i8, v8i16, shr_imm8, OpNode> { let Inst{21-19} = 0b001; // imm6 = 001xxx } def v4i16 : N2VNSh { + OpcodeStr, !strconcat(Dt, "32"), + v4i16, v4i32, shr_imm16, OpNode> { let Inst{21-20} = 0b01; // imm6 = 01xxxx } def v2i32 : N2VNSh { + OpcodeStr, !strconcat(Dt, "64"), + v2i32, v2i64, shr_imm32, OpNode> { let Inst{21} = 0b1; // imm6 = 1xxxxx } } @@ -3697,16 +3773,21 @@ def VBSLd : N3VX<1, 0, 0b01, 0b0001, 0, 1, (outs DPR:$Vd), (ins DPR:$src1, DPR:$Vn, DPR:$Vm), N3RegFrm, IIC_VCNTiD, "vbsl", "$Vd, $Vn, $Vm", "$src1 = $Vd", - [(set DPR:$Vd, - (v2i32 (or (and DPR:$Vn, DPR:$src1), - (and DPR:$Vm, (vnotd DPR:$src1)))))]>; + [(set DPR:$Vd, (v2i32 (NEONvbsl DPR:$src1, DPR:$Vn, DPR:$Vm)))]>; + +def : Pat<(v2i32 (or (and DPR:$Vn, DPR:$Vd), + (and DPR:$Vm, (vnotd DPR:$Vd)))), + (VBSLd DPR:$Vd, DPR:$Vn, DPR:$Vm)>; + def VBSLq : N3VX<1, 0, 0b01, 0b0001, 1, 1, (outs QPR:$Vd), (ins QPR:$src1, QPR:$Vn, QPR:$Vm), N3RegFrm, IIC_VCNTiQ, "vbsl", "$Vd, $Vn, $Vm", "$src1 = $Vd", - [(set QPR:$Vd, - (v4i32 (or (and QPR:$Vn, QPR:$src1), - (and QPR:$Vm, (vnotq QPR:$src1)))))]>; + [(set QPR:$Vd, (v4i32 (NEONvbsl QPR:$src1, QPR:$Vn, QPR:$Vm)))]>; + +def : Pat<(v4i32 (or (and QPR:$Vn, QPR:$Vd), + (and QPR:$Vm, (vnotq QPR:$Vd)))), + (VBSLq QPR:$Vd, QPR:$Vn, QPR:$Vm)>; // VBIF : Vector Bitwise Insert if False // like VBSL but with: "vbif $dst, $src3, $src1", "$src2 = $dst", @@ -3917,14 +3998,13 @@ defm VSHLs : N3VInt_QHSDSh<0, 0, 0b0100, 0, N3RegVShFrm, defm VSHLu : N3VInt_QHSDSh<1, 0, 0b0100, 0, N3RegVShFrm, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ, IIC_VSHLiQ, "vshl", "u", int_arm_neon_vshiftu>; + // VSHL : Vector Shift Left (Immediate) -defm VSHLi : N2VSh_QHSD<0, 1, 0b0101, 1, IIC_VSHLiD, "vshl", "i", NEONvshl, - N2RegVShLFrm>; +defm VSHLi : N2VShL_QHSD<0, 1, 0b0101, 1, IIC_VSHLiD, "vshl", "i", NEONvshl>; + // VSHR : Vector Shift Right (Immediate) -defm VSHRs : N2VSh_QHSD<0, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "s", NEONvshrs, - N2RegVShRFrm>; -defm VSHRu : N2VSh_QHSD<1, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "u", NEONvshru, - N2RegVShRFrm>; +defm VSHRs : N2VShR_QHSD<0, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "s",NEONvshrs>; +defm VSHRu : N2VShR_QHSD<1, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "u",NEONvshru>; // VSHLL : Vector Shift Left Long defm VSHLLs : N2VLSh_QHS<0, 1, 0b1010, 0, 0, 1, "vshll", "s", NEONvshlls>; @@ -3957,10 +4037,8 @@ defm VRSHLu : N3VInt_QHSDSh<1, 0, 0b0101, 0, N3RegVShFrm, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, "vrshl", "u", int_arm_neon_vrshiftu>; // VRSHR : Vector Rounding Shift Right -defm VRSHRs : N2VSh_QHSD<0,1,0b0010,1, IIC_VSHLi4D, "vrshr", "s", NEONvrshrs, - N2RegVShRFrm>; -defm VRSHRu : N2VSh_QHSD<1,1,0b0010,1, IIC_VSHLi4D, "vrshr", "u", NEONvrshru, - N2RegVShRFrm>; +defm VRSHRs : N2VShR_QHSD<0,1,0b0010,1, IIC_VSHLi4D, "vrshr", "s",NEONvrshrs>; +defm VRSHRu : N2VShR_QHSD<1,1,0b0010,1, IIC_VSHLi4D, "vrshr", "u",NEONvrshru>; // VRSHRN : Vector Rounding Shift Right and Narrow defm VRSHRN : N2VNSh_HSD<0, 1, 0b1000, 0, 1, 1, IIC_VSHLi4D, "vrshrn", "i", @@ -3974,13 +4052,11 @@ defm VQSHLu : N3VInt_QHSDSh<1, 0, 0b0100, 1, N3RegVShFrm, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, "vqshl", "u", int_arm_neon_vqshiftu>; // VQSHL : Vector Saturating Shift Left (Immediate) -defm VQSHLsi : N2VSh_QHSD<0,1,0b0111,1, IIC_VSHLi4D, "vqshl", "s",NEONvqshls, - N2RegVShLFrm>; -defm VQSHLui : N2VSh_QHSD<1,1,0b0111,1, IIC_VSHLi4D, "vqshl", "u",NEONvqshlu, - N2RegVShLFrm>; +defm VQSHLsi : N2VShL_QHSD<0,1,0b0111,1, IIC_VSHLi4D, "vqshl", "s",NEONvqshls>; +defm VQSHLui : N2VShL_QHSD<1,1,0b0111,1, IIC_VSHLi4D, "vqshl", "u",NEONvqshlu>; + // VQSHLU : Vector Saturating Shift Left (Immediate, Unsigned) -defm VQSHLsu : N2VSh_QHSD<1,1,0b0110,1, IIC_VSHLi4D,"vqshlu","s",NEONvqshlsu, - N2RegVShLFrm>; +defm VQSHLsu : N2VShL_QHSD<1,1,0b0110,1, IIC_VSHLi4D,"vqshlu","s",NEONvqshlsu>; // VQSHRN : Vector Saturating Shift Right and Narrow defm VQSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 0, 1, IIC_VSHLi4D, "vqshrn", "s", @@ -4018,9 +4094,10 @@ defm VRSRAs : N2VShAdd_QHSD<0, 1, 0b0011, 1, "vrsra", "s", NEONvrshrs>; defm VRSRAu : N2VShAdd_QHSD<1, 1, 0b0011, 1, "vrsra", "u", NEONvrshru>; // VSLI : Vector Shift Left and Insert -defm VSLI : N2VShIns_QHSD<1, 1, 0b0101, 1, "vsli", NEONvsli, N2RegVShLFrm>; +defm VSLI : N2VShInsL_QHSD<1, 1, 0b0101, 1, "vsli">; + // VSRI : Vector Shift Right and Insert -defm VSRI : N2VShIns_QHSD<1, 1, 0b0100, 1, "vsri", NEONvsri, N2RegVShRFrm>; +defm VSRI : N2VShInsR_QHSD<1, 1, 0b0100, 1, "vsri">; // Vector Absolute and Saturating Absolute. @@ -4362,14 +4439,8 @@ def VDUP8q : VDUPQ<0b11101110, 0b00, "8", v16i8>; def VDUP16q : VDUPQ<0b11101010, 0b01, "16", v8i16>; def VDUP32q : VDUPQ<0b11101010, 0b00, "32", v4i32>; -def VDUPfd : NVDup<0b11101000, 0b1011, 0b00, (outs DPR:$V), (ins GPR:$R), - IIC_VMOVIS, "vdup", "32", "$V, $R", - [(set DPR:$V, (v2f32 (NEONvdup - (f32 (bitconvert GPR:$R)))))]>; -def VDUPfq : NVDup<0b11101010, 0b1011, 0b00, (outs QPR:$V), (ins GPR:$R), - IIC_VMOVIS, "vdup", "32", "$V, $R", - [(set QPR:$V, (v4f32 (NEONvdup - (f32 (bitconvert GPR:$R)))))]>; +def : Pat<(v2f32 (NEONvdup (f32 (bitconvert GPR:$R)))), (VDUP32d GPR:$R)>; +def : Pat<(v4f32 (NEONvdup (f32 (bitconvert GPR:$R)))), (VDUP32q GPR:$R)>; // VDUP : Vector Duplicate Lane (from scalar to all elements) @@ -4397,9 +4468,6 @@ def VDUPLN16d : VDUPLND<{?,?,1,0}, "vdup", "16", v4i16> { def VDUPLN32d : VDUPLND<{?,1,0,0}, "vdup", "32", v2i32> { let Inst{19} = lane{0}; } -def VDUPLNfd : VDUPLND<{?,1,0,0}, "vdup", "32", v2f32> { - let Inst{19} = lane{0}; -} def VDUPLN8q : VDUPLNQ<{?,?,?,1}, "vdup", "8", v16i8, v8i8> { let Inst{19-17} = lane{2-0}; } @@ -4409,9 +4477,12 @@ def VDUPLN16q : VDUPLNQ<{?,?,1,0}, "vdup", "16", v8i16, v4i16> { def VDUPLN32q : VDUPLNQ<{?,1,0,0}, "vdup", "32", v4i32, v2i32> { let Inst{19} = lane{0}; } -def VDUPLNfq : VDUPLNQ<{?,1,0,0}, "vdup", "32", v4f32, v2f32> { - let Inst{19} = lane{0}; -} + +def : Pat<(v2f32 (NEONvduplane (v2f32 DPR:$Vm), imm:$lane)), + (VDUPLN32d DPR:$Vm, imm:$lane)>; + +def : Pat<(v4f32 (NEONvduplane (v2f32 DPR:$Vm), imm:$lane)), + (VDUPLN32q DPR:$Vm, imm:$lane)>; def : Pat<(v16i8 (NEONvduplane (v16i8 QPR:$src), imm:$lane)), (v16i8 (VDUPLN8q (v8i8 (EXTRACT_SUBREG QPR:$src, @@ -4426,7 +4497,7 @@ def : Pat<(v4i32 (NEONvduplane (v4i32 QPR:$src), imm:$lane)), (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; def : Pat<(v4f32 (NEONvduplane (v4f32 QPR:$src), imm:$lane)), - (v4f32 (VDUPLNfq (v2f32 (EXTRACT_SUBREG QPR:$src, + (v4f32 (VDUPLN32q (v2f32 (EXTRACT_SUBREG QPR:$src, (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; @@ -4517,12 +4588,12 @@ class VREV64Q op19_18, string OpcodeStr, string Dt, ValueType Ty> def VREV64d8 : VREV64D<0b00, "vrev64", "8", v8i8>; def VREV64d16 : VREV64D<0b01, "vrev64", "16", v4i16>; def VREV64d32 : VREV64D<0b10, "vrev64", "32", v2i32>; -def VREV64df : VREV64D<0b10, "vrev64", "32", v2f32>; +def : Pat<(v2f32 (NEONvrev64 (v2f32 DPR:$Vm))), (VREV64d32 DPR:$Vm)>; def VREV64q8 : VREV64Q<0b00, "vrev64", "8", v16i8>; def VREV64q16 : VREV64Q<0b01, "vrev64", "16", v8i16>; def VREV64q32 : VREV64Q<0b10, "vrev64", "32", v4i32>; -def VREV64qf : VREV64Q<0b10, "vrev64", "32", v4f32>; +def : Pat<(v4f32 (NEONvrev64 (v4f32 QPR:$Vm))), (VREV64q32 QPR:$Vm)>; // VREV32 : Vector Reverse elements within 32-bit words @@ -4628,8 +4699,8 @@ def VEXTq32 : VEXTq<"vext", "32", v4i32> { let Inst{9-8} = 0b00; } def VEXTqf : VEXTq<"vext", "32", v4f32> { - let Inst{11} = index{0}; - let Inst{10-8} = 0b000; + let Inst{11-10} = index{1-0}; + let Inst{9-8} = 0b00; } // VTRN : Vector Transpose diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrThumb.td b/contrib/llvm/lib/Target/ARM/ARMInstrThumb.td index 826ef46bcdb5..8c542fe60bba 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -27,22 +27,22 @@ def imm_comp_XFORM : SDNodeXForm; /// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7]. -def imm0_7 : PatLeaf<(i32 imm), [{ - return (uint32_t)N->getZExtValue() < 8; +def imm0_7 : ImmLeaf= 0 && Imm < 8; }]>; def imm0_7_neg : PatLeaf<(i32 imm), [{ return (uint32_t)-N->getZExtValue() < 8; }], imm_neg_XFORM>; -def imm0_255 : PatLeaf<(i32 imm), [{ - return (uint32_t)N->getZExtValue() < 256; +def imm0_255 : ImmLeaf= 0 && Imm < 256; }]>; def imm0_255_comp : PatLeaf<(i32 imm), [{ return ~((uint32_t)N->getZExtValue()) < 256; }]>; -def imm8_255 : PatLeaf<(i32 imm), [{ - return (uint32_t)N->getZExtValue() >= 8 && (uint32_t)N->getZExtValue() < 256; +def imm8_255 : ImmLeaf= 8 && Imm < 256; }]>; def imm8_255_neg : PatLeaf<(i32 imm), [{ unsigned Val = -N->getZExtValue(); @@ -369,6 +369,15 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1 in { let Inst{2-0} = 0b000; } + def tBX_Rm : TI<(outs), (ins pred:$p, GPR:$Rm), IIC_Br, "bx${p}\t$Rm", + [/* for disassembly only */]>, + T1Special<{1,1,0,?}> { + // A6.2.3 & A8.6.25 + bits<4> Rm; + let Inst{6-3} = Rm; + let Inst{2-0} = 0b000; + } + // Alternative return instruction used by vararg functions. def tBX_RET_vararg : TI<(outs), (ins tGPR:$Rm), IIC_Br, "bx\t$Rm", @@ -712,6 +721,19 @@ def tLDRpci : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i, let Inst{7-0} = addr; } +// FIXME: Remove this entry when the above ldr.n workaround is fixed. +// For disassembly use only. +def tLDRpciDIS : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i, + "ldr", "\t$Rt, $addr", + [/* disassembly only */]>, + T1Encoding<{0,1,0,0,1,?}> { + // A6.2 & A8.6.59 + bits<3> Rt; + bits<8> addr; + let Inst{10-8} = Rt; + let Inst{7-0} = addr; +} + // A8.6.194 & A8.6.192 defm tSTR : thumb_st_rr_ri_enc<0b000, 0b0110, t_addrmode_rrs4, t_addrmode_is4, AddrModeT1_4, @@ -1175,10 +1197,18 @@ def tREVSH : // A8.6.136 "revsh", "\t$Rd, $Rm", [(set tGPR:$Rd, (sext_inreg - (or (srl (and tGPR:$Rm, 0xFF00), (i32 8)), + (or (srl tGPR:$Rm, (i32 8)), (shl tGPR:$Rm, (i32 8))), i16))]>, Requires<[IsThumb, IsThumb1Only, HasV6]>; +def : T1Pat<(sext_inreg (or (srl (and tGPR:$Rm, 0xFF00), (i32 8)), + (shl tGPR:$Rm, (i32 8))), i16), + (tREVSH tGPR:$Rm)>, + Requires<[IsThumb, IsThumb1Only, HasV6]>; + +def : T1Pat<(sra (bswap tGPR:$Rm), (i32 16)), (tREVSH tGPR:$Rm)>, + Requires<[IsThumb, IsThumb1Only, HasV6]>; + // Rotate right register def tROR : // A8.6.139 T1sItDPEncode<0b0111, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), @@ -1322,10 +1352,8 @@ def tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd), // Move between coprocessor and ARM core register -- for disassembly only // -class tMovRCopro - : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, - GPR:$Rt, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), - !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), +class tMovRCopro + : T1Cop { let Inst{27-24} = 0b1110; let Inst{20} = direction; @@ -1346,8 +1374,12 @@ class tMovRCopro let Inst{19-16} = CRn; } -def tMCR : tMovRCopro<"mcr", 0 /* from ARM core register to coprocessor */>; -def tMRC : tMovRCopro<"mrc", 1 /* from coprocessor to ARM core register */>; +def tMCR : tMovRCopro<"mcr", 0 /* from ARM core register to coprocessor */, + (outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn, + c_imm:$CRm, i32imm:$opc2)>; +def tMRC : tMovRCopro<"mrc", 1 /* from coprocessor to ARM core register */, + (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, + c_imm:$CRm, i32imm:$opc2)>; class tMovRRCopro : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), @@ -1420,7 +1452,7 @@ def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br, // from some other function to get here, and we're using the stack frame for the // containing function to save/restore registers, we can't keep anything live in // regs across the eh_sjlj_setjmp(), else it will almost certainly have been -// tromped upon when we get here from a longjmp(). We force everthing out of +// tromped upon when we get here from a longjmp(). We force everything out of // registers except for our own input by listing the relevant registers in // Defs. By doing so, we also cause the prologue/epilogue code to actively // preserve all of the callee-saved resgisters, which is exactly what we want. diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrThumb2.td b/contrib/llvm/lib/Target/ARM/ARMInstrThumb2.td index 0e01be59c7e8..600a12180fc5 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -44,7 +44,9 @@ def t2_so_imm_neg_XFORM : SDNodeXForm, PatLeaf<(imm), [{ return Pred_t2_so_imm(N); }]> { +def t2_so_imm : Operand, ImmLeaf { let EncoderMethod = "getT2SOImmOpValue"; } @@ -61,49 +63,15 @@ def t2_so_imm_neg : Operand, return ARM_AM::getT2SOImmVal(-((uint32_t)N->getZExtValue())) != -1; }], t2_so_imm_neg_XFORM>; -// Break t2_so_imm's up into two pieces. This handles immediates with up to 16 -// bits set in them. This uses t2_so_imm2part to match and t2_so_imm2part_[12] -// to get the first/second pieces. -def t2_so_imm2part : Operand, - PatLeaf<(imm), [{ - return ARM_AM::isT2SOImmTwoPartVal((unsigned)N->getZExtValue()); - }]> { -} - -def t2_so_imm2part_1 : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(V, MVT::i32); -}]>; - -def t2_so_imm2part_2 : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(V, MVT::i32); -}]>; - -def t2_so_neg_imm2part : Operand, PatLeaf<(imm), [{ - return ARM_AM::isT2SOImmTwoPartVal(-(int)N->getZExtValue()); - }]> { -} - -def t2_so_neg_imm2part_1 : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(V, MVT::i32); -}]>; - -def t2_so_neg_imm2part_2 : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(V, MVT::i32); -}]>; - /// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31]. -def imm1_31 : PatLeaf<(i32 imm), [{ - return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 32; +def imm1_31 : ImmLeaf= 1 && (int32_t)Imm < 32; }]>; /// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095]. def imm0_4095 : Operand, - PatLeaf<(i32 imm), [{ - return (uint32_t)N->getZExtValue() < 4096; + ImmLeaf= 0 && Imm < 4096; }]>; def imm0_4095_neg : PatLeaf<(i32 imm), [{ @@ -118,6 +86,11 @@ def imm0_255_not : PatLeaf<(i32 imm), [{ return (uint32_t)(~N->getZExtValue()) < 255; }], imm_comp_XFORM>; +def lo5AllOne : PatLeaf<(i32 imm), [{ + // Returns true if all low 5-bits are 1. + return (((uint32_t)N->getZExtValue()) & 0x1FUL) == 0x1FUL; +}]>; + // Define Thumb2 specific addressing modes. // t2addrmode_imm12 := reg + imm12 @@ -129,6 +102,12 @@ def t2addrmode_imm12 : Operand, let ParserMatchClass = MemMode5AsmOperand; } +// t2ldrlabel := imm12 +def t2ldrlabel : Operand { + let EncoderMethod = "getAddrModeImm12OpValue"; +} + + // ADR instruction labels. def t2adrlabel : Operand { let EncoderMethod = "getT2AdrLabelOpValue"; @@ -173,6 +152,15 @@ def t2addrmode_so_reg : Operand, let ParserMatchClass = MemMode5AsmOperand; } +// t2addrmode_reg := reg +// Used by load/store exclusive instructions. Useful to enable right assembly +// parsing and printing. Not used for any codegen matching. +// +def t2addrmode_reg : Operand { + let PrintMethod = "printAddrMode7Operand"; + let MIOperandInfo = (ops tGPR); + let ParserMatchClass = MemMode7AsmOperand; +} //===----------------------------------------------------------------------===// // Multiclass helpers... @@ -700,49 +688,27 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, let Inst{24-21} = opcod; } } +} // Carry setting variants -let isCodeGenOnly = 1, Defs = [CPSR] in { -multiclass T2I_adde_sube_s_irs opcod, string opc, PatFrag opnode, - bit Commutable = 0> { +// NOTE: CPSR def omitted because it will be handled by the custom inserter. +let usesCustomInserter = 1 in { +multiclass T2I_adde_sube_s_irs { // shifted imm - def ri : T2sTwoRegImm< - (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), IIC_iALUi, - opc, "\t$Rd, $Rn, $imm", - [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>, - Requires<[IsThumb2]> { - let Inst{31-27} = 0b11110; - let Inst{25} = 0; - let Inst{24-21} = opcod; - let Inst{20} = 1; // The S bit. - let Inst{15} = 0; - } + def ri : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), + Size4Bytes, IIC_iALUi, + [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>; // register - def rr : T2sThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr, - opc, ".w\t$Rd, $Rn, $Rm", - [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>, - Requires<[IsThumb2]> { + def rr : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), + Size4Bytes, IIC_iALUr, + [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]> { let isCommutable = Commutable; - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b01; - let Inst{24-21} = opcod; - let Inst{20} = 1; // The S bit. - let Inst{14-12} = 0b000; // imm3 - let Inst{7-6} = 0b00; // imm2 - let Inst{5-4} = 0b00; // type } // shifted register - def rs : T2sTwoRegShiftedReg< - (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), - IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm", - [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>, - Requires<[IsThumb2]> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b01; - let Inst{24-21} = opcod; - let Inst{20} = 1; // The S bit. - } -} + def rs : t2PseudoInst< + (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm), + Size4Bytes, IIC_iALUsi, + [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>; } } @@ -864,6 +830,7 @@ multiclass T2I_ld opcod, string opc, let Inst{15-12} = Rt; bits<17> addr; + let addr{12} = 1; // add = TRUE let Inst{19-16} = addr{16-13}; // Rn let Inst{23} = addr{12}; // U let Inst{11-0} = addr{11-0}; // imm @@ -911,7 +878,7 @@ multiclass T2I_ld opcod, string opc, } // FIXME: Is the pci variant actually needed? - def pci : T2Ipc <(outs GPR:$Rt), (ins i32imm:$addr), iii, + def pci : T2Ipc <(outs GPR:$Rt), (ins t2ldrlabel:$addr), iii, opc, ".w\t$Rt, $addr", [(set GPR:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]> { let isReMaterializable = 1; @@ -944,6 +911,7 @@ multiclass T2I_st opcod, string opc, let Inst{15-12} = Rt; bits<17> addr; + let addr{12} = 1; // add = TRUE let Inst{19-16} = addr{16-13}; // Rn let Inst{23} = addr{12}; // U let Inst{11-0} = addr{11-0}; // imm @@ -1398,7 +1366,7 @@ def t2LDRSH_POST : T2Iidxldst<1, 0b01, 1, 0, (outs GPR:$dst, GPR:$Rn), // for disassembly only. // Ref: A8.6.57 LDR (immediate, Thumb) Encoding T4 class T2IldT type, string opc, InstrItinClass ii> - : T2Ii8<(outs GPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, + : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, "\t$Rt, $addr", []> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; @@ -1440,42 +1408,48 @@ def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs), def t2STR_PRE : T2Iidxldst<0, 0b10, 0, 1, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePre, IIC_iStore_iu, - "str", "\t$Rt, [$Rn, $addr]!", "$Rn = $base_wb", + "str", "\t$Rt, [$Rn, $addr]!", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, (pre_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STR_POST : T2Iidxldst<0, 0b10, 0, 0, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iStore_iu, - "str", "\t$Rt, [$Rn], $addr", "$Rn = $base_wb", + "str", "\t$Rt, [$Rn], $addr", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, (post_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRH_PRE : T2Iidxldst<0, 0b01, 0, 1, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePre, IIC_iStore_iu, - "strh", "\t$Rt, [$Rn, $addr]!", "$Rn = $base_wb", + "strh", "\t$Rt, [$Rn, $addr]!", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, (pre_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRH_POST : T2Iidxldst<0, 0b01, 0, 0, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu, - "strh", "\t$Rt, [$Rn], $addr", "$Rn = $base_wb", + "strh", "\t$Rt, [$Rn], $addr", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, (post_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRB_PRE : T2Iidxldst<0, 0b00, 0, 1, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePre, IIC_iStore_bh_iu, - "strb", "\t$Rt, [$Rn, $addr]!", "$Rn = $base_wb", + "strb", "\t$Rt, [$Rn, $addr]!", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, (pre_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu, - "strb", "\t$Rt, [$Rn], $addr", "$Rn = $base_wb", + "strb", "\t$Rt, [$Rn], $addr", + "$Rn = $base_wb,@earlyclobber $base_wb", [(set GPR:$base_wb, (post_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; @@ -1483,7 +1457,7 @@ def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPR:$base_wb), // only. // Ref: A8.6.193 STR (immediate, Thumb) Encoding T4 class T2IstT type, string opc, InstrItinClass ii> - : T2Ii8<(outs GPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, + : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, "\t$Rt, $addr", []> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; @@ -1508,20 +1482,20 @@ def t2STRHT : T2IstT<0b01, "strht", IIC_iStore_bh_i>; // ldrd / strd pre / post variants // For disassembly only. -def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs GPR:$Rt, GPR:$Rt2), +def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2), (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru, "ldrd", "\t$Rt, $Rt2, [$base, $imm]!", []>; -def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs GPR:$Rt, GPR:$Rt2), +def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2), (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru, "ldrd", "\t$Rt, $Rt2, [$base], $imm", []>; def t2STRD_PRE : T2Ii8s4<1, 1, 0, (outs), - (ins GPR:$Rt, GPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), + (ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base, $imm]!", []>; def t2STRD_POST : T2Ii8s4<0, 1, 0, (outs), - (ins GPR:$Rt, GPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), + (ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base], $imm", []>; // T2Ipl (Preload Data/Instruction) signals the memory system of possible future @@ -1541,6 +1515,7 @@ multiclass T2Ipl write, bits<1> instr, string opc> { let Inst{15-12} = 0b1111; bits<17> addr; + let addr{12} = 1; // add = TRUE let Inst{19-16} = addr{16-13}; // Rn let Inst{23} = addr{12}; // U let Inst{11-0} = addr{11-0}; // imm12 @@ -1813,10 +1788,8 @@ defm t2ADC : T2I_adde_sube_irs<0b1010, "adc", BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>; defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc", BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>; -defm t2ADCS : T2I_adde_sube_s_irs<0b1010, "adc", - BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; -defm t2SBCS : T2I_adde_sube_s_irs<0b1011, "sbc", - BinOpFrag<(sube_live_carry node:$LHS, node:$RHS)>>; +defm t2ADCS : T2I_adde_sube_s_irs, 1>; +defm t2SBCS : T2I_adde_sube_s_irs>; // RSB defm t2RSB : T2I_rbin_irs <0b1110, "rsb", @@ -1847,9 +1820,14 @@ def : T2Pat<(addc rGPR:$src, t2_so_imm_neg:$imm), // Effectively, the inverse interpretation of the carry flag already accounts // for part of the negation. let AddedComplexity = 1 in -def : T2Pat<(adde rGPR:$src, imm0_255_not:$imm), +def : T2Pat<(adde_dead_carry rGPR:$src, imm0_255_not:$imm), + (t2SBCri rGPR:$src, imm0_255_not:$imm)>; +def : T2Pat<(adde_dead_carry rGPR:$src, t2_so_imm_not:$imm), + (t2SBCri rGPR:$src, t2_so_imm_not:$imm)>; +let AddedComplexity = 1 in +def : T2Pat<(adde_live_carry rGPR:$src, imm0_255_not:$imm), (t2SBCSri rGPR:$src, imm0_255_not:$imm)>; -def : T2Pat<(adde rGPR:$src, t2_so_imm_not:$imm), +def : T2Pat<(adde_live_carry rGPR:$src, t2_so_imm_not:$imm), (t2SBCSri rGPR:$src, t2_so_imm_not:$imm)>; // Select Bytes -- for disassembly only @@ -2052,6 +2030,10 @@ defm t2LSR : T2I_sh_ir<0b01, "lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>; defm t2ASR : T2I_sh_ir<0b10, "asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>; defm t2ROR : T2I_sh_ir<0b11, "ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>; +// (rotr x, (and y, 0x...1f)) ==> (ROR x, y) +def : Pat<(rotr rGPR:$lhs, (and rGPR:$rhs, lo5AllOne)), + (t2RORrr rGPR:$lhs, rGPR:$rhs)>; + let Uses = [CPSR] in { def t2RRX : T2sTwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iMOVsi, "rrx", "\t$Rd, $Rm", @@ -2140,10 +2122,12 @@ def t2BFC : T2BitFI<(outs rGPR:$Rd), (ins rGPR:$src, bf_inv_mask_imm:$imm), IIC_iUNAsi, "bfc", "\t$Rd, $imm", [(set rGPR:$Rd, (and rGPR:$src, bf_inv_mask_imm:$imm))]> { let Inst{31-27} = 0b11110; + let Inst{26} = 0; // should be 0. let Inst{25} = 1; let Inst{24-20} = 0b10110; let Inst{19-16} = 0b1111; // Rn let Inst{15} = 0; + let Inst{5} = 0; // should be 0. bits<10> imm; let msb{4-0} = imm{9-5}; @@ -2176,9 +2160,11 @@ let Constraints = "$src = $Rd" in { [(set rGPR:$Rd, (ARMbfi rGPR:$src, rGPR:$Rn, bf_inv_mask_imm:$imm))]> { let Inst{31-27} = 0b11110; + let Inst{26} = 0; // should be 0. let Inst{25} = 1; let Inst{24-20} = 0b10110; let Inst{15} = 0; + let Inst{5} = 0; // should be 0. bits<10> imm; let msb{4-0} = imm{9-5}; @@ -2193,9 +2179,11 @@ let Constraints = "$src = $Rd" in { IIC_iBITi, "bfi", "\t$Rd, $Rn, $lsbit, $width", []> { let Inst{31-27} = 0b11110; + let Inst{26} = 0; // should be 0. let Inst{25} = 1; let Inst{24-20} = 0b10110; let Inst{15} = 0; + let Inst{5} = 0; // should be 0. bits<5> lsbit; bits<5> width; @@ -2607,9 +2595,15 @@ def t2REVSH : T2I_misc<0b01, 0b11, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr, "revsh", ".w\t$Rd, $Rm", [(set rGPR:$Rd, (sext_inreg - (or (srl (and rGPR:$Rm, 0xFF00), (i32 8)), + (or (srl rGPR:$Rm, (i32 8)), (shl rGPR:$Rm, (i32 8))), i16))]>; +def : T2Pat<(sext_inreg (or (srl (and rGPR:$Rm, 0xFF00), (i32 8)), + (shl rGPR:$Rm, (i32 8))), i16), + (t2REVSH rGPR:$Rm)>; + +def : T2Pat<(sra (bswap rGPR:$Rm), (i32 16)), (t2REVSH rGPR:$Rm)>; + def t2PKHBT : T2ThreeReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, shift_imm:$sh), IIC_iBITsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh", @@ -2843,9 +2837,9 @@ class T2I_ldrex opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, let Inst{5-4} = opcod; let Inst{3-0} = 0b1111; - bits<4> Rn; + bits<4> addr; bits<4> Rt; - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{15-12} = Rt; } class T2I_strex opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, @@ -2859,37 +2853,37 @@ class T2I_strex opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, let Inst{5-4} = opcod; bits<4> Rd; - bits<4> Rn; + bits<4> addr; bits<4> Rt; - let Inst{11-8} = Rd; - let Inst{19-16} = Rn; + let Inst{3-0} = Rd; + let Inst{19-16} = addr; let Inst{15-12} = Rt; } let mayLoad = 1 in { -def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins rGPR:$Rn), AddrModeNone, - Size4Bytes, NoItinerary, "ldrexb", "\t$Rt, [$Rn]", +def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone, + Size4Bytes, NoItinerary, "ldrexb", "\t$Rt, $addr", "", []>; -def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins rGPR:$Rn), AddrModeNone, - Size4Bytes, NoItinerary, "ldrexh", "\t$Rt, [$Rn]", +def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone, + Size4Bytes, NoItinerary, "ldrexh", "\t$Rt, $addr", "", []>; -def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins rGPR:$Rn), AddrModeNone, +def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr), AddrModeNone, Size4Bytes, NoItinerary, - "ldrex", "\t$Rt, [$Rn]", "", + "ldrex", "\t$Rt, $addr", "", []> { let Inst{31-27} = 0b11101; let Inst{26-20} = 0b0000101; let Inst{11-8} = 0b1111; let Inst{7-0} = 0b00000000; // imm8 = 0 - bits<4> Rn; bits<4> Rt; - let Inst{19-16} = Rn; + bits<4> addr; + let Inst{19-16} = addr; let Inst{15-12} = Rt; } -def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2), (ins rGPR:$Rn), +def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2), (ins t2addrmode_reg:$addr), AddrModeNone, Size4Bytes, NoItinerary, - "ldrexd", "\t$Rt, $Rt2, [$Rn]", "", + "ldrexd", "\t$Rt, $Rt2, $addr", "", [], {?, ?, ?, ?}> { bits<4> Rt2; let Inst{11-8} = Rt2; @@ -2897,31 +2891,31 @@ def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2), (ins rGPR:$Rn), } let mayStore = 1, Constraints = "@earlyclobber $Rd" in { -def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd), (ins rGPR:$Rt, rGPR:$Rn), - AddrModeNone, Size4Bytes, NoItinerary, - "strexb", "\t$Rd, $Rt, [$Rn]", "", []>; -def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd), (ins rGPR:$Rt, rGPR:$Rn), - AddrModeNone, Size4Bytes, NoItinerary, - "strexh", "\t$Rd, $Rt, [$Rn]", "", []>; -def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, rGPR:$Rn), - AddrModeNone, Size4Bytes, NoItinerary, - "strex", "\t$Rd, $Rt, [$Rn]", "", - []> { +def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexb", "\t$Rd, $Rt, $addr", "", []>; +def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexh", "\t$Rd, $Rt, $addr", "", []>; +def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr), + AddrModeNone, Size4Bytes, NoItinerary, + "strex", "\t$Rd, $Rt, $addr", "", + []> { let Inst{31-27} = 0b11101; let Inst{26-20} = 0b0000100; let Inst{7-0} = 0b00000000; // imm8 = 0 bits<4> Rd; - bits<4> Rn; + bits<4> addr; bits<4> Rt; let Inst{11-8} = Rd; - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{15-12} = Rt; } def t2STREXD : T2I_strex<0b11, (outs rGPR:$Rd), - (ins rGPR:$Rt, rGPR:$Rt2, rGPR:$Rn), + (ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_reg:$addr), AddrModeNone, Size4Bytes, NoItinerary, - "strexd", "\t$Rd, $Rt, $Rt2, [$Rn]", "", [], + "strexd", "\t$Rd, $Rt, $Rt2, $addr", "", [], {?, ?, ?, ?}> { bits<4> Rt2; let Inst{11-8} = Rt2; @@ -2965,7 +2959,7 @@ let isCall = 1, // here, and we're using the stack frame for the containing function to // save/restore registers, we can't keep anything live in regs across // the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon -// when we get here from a longjmp(). We force everthing out of registers +// when we get here from a longjmp(). We force everything out of registers // except for our own input by listing the relevant registers in Defs. By // doing so, we also cause the prologue/epilogue code to actively preserve // all of the callee-saved resgisters, which is exactly what we want. @@ -3238,19 +3232,20 @@ class T2RFE op31_20, dag oops, dag iops, InstrItinClass itin, bits<4> Rn; let Inst{19-16} = Rn; + let Inst{15-0} = 0xc000; } def t2RFEDBW : T2RFE<0b111010000011, - (outs), (ins rGPR:$Rn), NoItinerary, "rfedb", "\t$Rn!", + (outs), (ins GPR:$Rn), NoItinerary, "rfedb", "\t$Rn!", [/* For disassembly only; pattern left blank */]>; def t2RFEDB : T2RFE<0b111010000001, - (outs), (ins rGPR:$Rn), NoItinerary, "rfeab", "\t$Rn", + (outs), (ins GPR:$Rn), NoItinerary, "rfedb", "\t$Rn", [/* For disassembly only; pattern left blank */]>; def t2RFEIAW : T2RFE<0b111010011011, - (outs), (ins rGPR:$Rn), NoItinerary, "rfeia", "\t$Rn!", + (outs), (ins GPR:$Rn), NoItinerary, "rfeia", "\t$Rn!", [/* For disassembly only; pattern left blank */]>; def t2RFEIA : T2RFE<0b111010011001, - (outs), (ins rGPR:$Rn), NoItinerary, "rfeia", "\t$Rn", + (outs), (ins GPR:$Rn), NoItinerary, "rfeia", "\t$Rn", [/* For disassembly only; pattern left blank */]>; //===----------------------------------------------------------------------===// @@ -3352,10 +3347,8 @@ def t2MSR : T2SpecialReg<0b111100111000 /* op31-20 */, 0b10 /* op15-14 */, // Move between coprocessor and ARM core register -- for disassembly only // -class t2MovRCopro - : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, - GPR:$Rt, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), - !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), +class t2MovRCopro + : T2Cop { let Inst{27-24} = 0b1110; let Inst{20} = direction; @@ -3376,8 +3369,12 @@ class t2MovRCopro let Inst{19-16} = CRn; } -def t2MCR2 : t2MovRCopro<"mcr2", 0 /* from ARM core register to coprocessor */>; -def t2MRC2 : t2MovRCopro<"mrc2", 1 /* from coprocessor to ARM core register */>; +def t2MCR2 : t2MovRCopro<"mcr2", 0 /* from ARM core register to coprocessor */, + (outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, c_imm:$CRn, + c_imm:$CRm, i32imm:$opc2)>; +def t2MRC2 : t2MovRCopro<"mrc2", 1 /* from coprocessor to ARM core register */, + (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, + c_imm:$CRm, i32imm:$opc2)>; class t2MovRRCopro : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td b/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td index 29902833f2bb..376bd9607e4b 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td @@ -101,14 +101,6 @@ multiclass vfp_ldst_mult { - let Inst{24-23} = 0b10; // Decrement Before - let Inst{21} = 0; // No writeback - let Inst{20} = L_bit; - } def DDB_UPD : AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops), IndexModeUpd, itin_upd, @@ -143,18 +135,6 @@ multiclass vfp_ldst_mult { - let Inst{24-23} = 0b10; // Decrement Before - let Inst{21} = 0; // No writeback - let Inst{20} = L_bit; - - // Some single precision VFP instructions may be executed on both NEON and - // VFP pipelines. - let D = VFPNeonDomain; - } def SDB_UPD : AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, spr_reglist:$regs, variable_ops), IndexModeUpd, itin_upd, @@ -467,6 +447,10 @@ def VMOVRS : AVConv2I<0b11100001, 0b1010, let Inst{6-5} = 0b00; let Inst{3-0} = 0b0000; + + // Some single precision VFP instructions may be executed on both NEON and VFP + // pipelines. + let D = VFPNeonDomain; } def VMOVSR : AVConv4I<0b11100000, 0b1010, @@ -484,6 +468,10 @@ def VMOVSR : AVConv4I<0b11100000, 0b1010, let Inst{6-5} = 0b00; let Inst{3-0} = 0b0000; + + // Some single precision VFP instructions may be executed on both NEON and VFP + // pipelines. + let D = VFPNeonDomain; } let neverHasSideEffects = 1 in { @@ -503,6 +491,10 @@ def VMOVRRD : AVConv3I<0b11000101, 0b1011, let Inst{19-16} = Rt2; let Inst{7-6} = 0b00; + + // Some single precision VFP instructions may be executed on both NEON and VFP + // pipelines. + let D = VFPNeonDomain; } def VMOVRRS : AVConv3I<0b11000101, 0b1010, @@ -510,6 +502,10 @@ def VMOVRRS : AVConv3I<0b11000101, 0b1010, IIC_fpMOVDI, "vmov", "\t$wb, $dst2, $src1, $src2", [/* For disassembly only; pattern left blank */]> { let Inst{7-6} = 0b00; + + // Some single precision VFP instructions may be executed on both NEON and VFP + // pipelines. + let D = VFPNeonDomain; } } // neverHasSideEffects @@ -532,6 +528,10 @@ def VMOVDRR : AVConv5I<0b11000100, 0b1011, let Inst{19-16} = Rt2; let Inst{7-6} = 0b00; + + // Some single precision VFP instructions may be executed on both NEON and VFP + // pipelines. + let D = VFPNeonDomain; } let neverHasSideEffects = 1 in @@ -540,6 +540,10 @@ def VMOVSRR : AVConv5I<0b11000100, 0b1010, IIC_fpMOVID, "vmov", "\t$dst1, $dst2, $src1, $src2", [/* For disassembly only; pattern left blank */]> { let Inst{7-6} = 0b00; + + // Some single precision VFP instructions may be executed on both NEON and VFP + // pipelines. + let D = VFPNeonDomain; } // FMRDH: SPR -> GPR @@ -972,33 +976,15 @@ def : Pat<(fsub_mlx (fmul_su SPR:$a, SPR:$b), SPR:$dstin), // let neverHasSideEffects = 1 in { -def VMOVDcc : ADuI<0b11101, 0b11, 0b0000, 0b01, 0, - (outs DPR:$Dd), (ins DPR:$Dn, DPR:$Dm), - IIC_fpUNA64, "vmov", ".f64\t$Dd, $Dm", +def VMOVDcc : ARMPseudoInst<(outs DPR:$Dd), (ins DPR:$Dn, DPR:$Dm, pred:$p), + Size4Bytes, IIC_fpUNA64, [/*(set DPR:$Dd, (ARMcmov DPR:$Dn, DPR:$Dm, imm:$cc))*/]>, RegConstraint<"$Dn = $Dd">; -def VMOVScc : ASuI<0b11101, 0b11, 0b0000, 0b01, 0, - (outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm), - IIC_fpUNA32, "vmov", ".f32\t$Sd, $Sm", +def VMOVScc : ARMPseudoInst<(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm, pred:$p), + Size4Bytes, IIC_fpUNA32, [/*(set SPR:$Sd, (ARMcmov SPR:$Sn, SPR:$Sm, imm:$cc))*/]>, RegConstraint<"$Sn = $Sd">; - -def VNEGDcc : ADuI<0b11101, 0b11, 0b0001, 0b01, 0, - (outs DPR:$Dd), (ins DPR:$Dn, DPR:$Dm), - IIC_fpUNA64, "vneg", ".f64\t$Dd, $Dm", - [/*(set DPR:$Dd, (ARMcneg DPR:$Dn, DPR:$Dm, imm:$cc))*/]>, - RegConstraint<"$Dn = $Dd">; - -def VNEGScc : ASuI<0b11101, 0b11, 0b0001, 0b01, 0, - (outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm), - IIC_fpUNA32, "vneg", ".f32\t$Sd, $Sm", - [/*(set SPR:$Sd, (ARMcneg SPR:$Sn, SPR:$Sm, imm:$cc))*/]>, - RegConstraint<"$Sn = $Sd"> { - // Some single precision VFP instructions may be executed on both NEON and - // VFP pipelines on A8. - let D = VFPNeonA8Domain; -} } // neverHasSideEffects //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/contrib/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index d9dc5cdedb30..df89fadb311b 100644 --- a/contrib/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -79,7 +79,7 @@ namespace { unsigned Position; MachineBasicBlock::iterator MBBI; bool Merged; - MemOpQueueEntry(int o, unsigned r, bool k, unsigned p, + MemOpQueueEntry(int o, unsigned r, bool k, unsigned p, MachineBasicBlock::iterator i) : Offset(o), Reg(r), isKill(k), Position(p), MBBI(i), Merged(false) {} }; @@ -174,7 +174,7 @@ static int getLoadStoreMultipleOpcode(int Opcode, ARM_AM::AMSubMode Mode) { switch (Mode) { default: llvm_unreachable("Unhandled submode!"); case ARM_AM::ia: return ARM::VLDMSIA; - case ARM_AM::db: return ARM::VLDMSDB; + case ARM_AM::db: return 0; // Only VLDMSDB_UPD exists. } break; case ARM::VSTRS: @@ -182,7 +182,7 @@ static int getLoadStoreMultipleOpcode(int Opcode, ARM_AM::AMSubMode Mode) { switch (Mode) { default: llvm_unreachable("Unhandled submode!"); case ARM_AM::ia: return ARM::VSTMSIA; - case ARM_AM::db: return ARM::VSTMSDB; + case ARM_AM::db: return 0; // Only VSTMSDB_UPD exists. } break; case ARM::VLDRD: @@ -190,7 +190,7 @@ static int getLoadStoreMultipleOpcode(int Opcode, ARM_AM::AMSubMode Mode) { switch (Mode) { default: llvm_unreachable("Unhandled submode!"); case ARM_AM::ia: return ARM::VLDMDIA; - case ARM_AM::db: return ARM::VLDMDDB; + case ARM_AM::db: return 0; // Only VLDMDDB_UPD exists. } break; case ARM::VSTRD: @@ -198,7 +198,7 @@ static int getLoadStoreMultipleOpcode(int Opcode, ARM_AM::AMSubMode Mode) { switch (Mode) { default: llvm_unreachable("Unhandled submode!"); case ARM_AM::ia: return ARM::VSTMDIA; - case ARM_AM::db: return ARM::VSTMDDB; + case ARM_AM::db: return 0; // Only VSTMDDB_UPD exists. } break; } @@ -246,13 +246,9 @@ AMSubMode getLoadStoreMultipleSubMode(int Opcode) { case ARM::t2LDMDB_UPD: case ARM::t2STMDB: case ARM::t2STMDB_UPD: - case ARM::VLDMSDB: case ARM::VLDMSDB_UPD: - case ARM::VSTMSDB: case ARM::VSTMSDB_UPD: - case ARM::VLDMDDB: case ARM::VLDMDDB_UPD: - case ARM::VSTMDDB: case ARM::VSTMDDB_UPD: return ARM_AM::db; @@ -312,6 +308,10 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB, // VLDM/VSTM do not support DB mode without also updating the base reg. Mode = ARM_AM::db; else if (Offset != 0) { + // Check if this is a supported opcode before we insert instructions to + // calculate a new base register. + if (!getLoadStoreMultipleOpcode(Opcode, Mode)) return false; + // If starting offset isn't zero, insert a MI to materialize a new base. // But only do so if it is cost effective, i.e. merging more than two // loads / stores. @@ -354,6 +354,7 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB, bool isDef = (isi32Load(Opcode) || Opcode == ARM::VLDRS || Opcode == ARM::VLDRD); Opcode = getLoadStoreMultipleOpcode(Opcode, Mode); + if (!Opcode) return false; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(Opcode)) .addReg(Base, getKillRegState(BaseKill)) .addImm(Pred).addReg(PredReg); @@ -453,6 +454,25 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned PRegNum = PMO.isUndef() ? UINT_MAX : getARMRegisterNumbering(PReg); unsigned Count = 1; + unsigned Limit = ~0U; + + // vldm / vstm limit are 32 for S variants, 16 for D variants. + + switch (Opcode) { + default: break; + case ARM::VSTRS: + Limit = 32; + break; + case ARM::VSTRD: + Limit = 16; + break; + case ARM::VLDRD: + Limit = 16; + break; + case ARM::VLDRS: + Limit = 32; + break; + } for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) { int NewOffset = MemOps[i].Offset; @@ -460,13 +480,13 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Reg = MO.getReg(); unsigned RegNum = MO.isUndef() ? UINT_MAX : getARMRegisterNumbering(Reg); - // Register numbers must be in ascending order. For VFP, the registers - // must also be consecutive and there is a limit of 16 double-word - // registers per instruction. + // Register numbers must be in ascending order. For VFP / NEON load and + // store multiples, the registers must also be consecutive and within the + // limit on the number of registers per instruction. if (Reg != ARM::SP && NewOffset == Offset + (int)Size && - ((isNotVFP && RegNum > PRegNum) - || ((Size < 8 || Count < 16) && RegNum == PRegNum+1))) { + ((isNotVFP && RegNum > PRegNum) || + ((Count < Limit) && RegNum == PRegNum+1))) { Offset += Size; PRegNum = RegNum; ++Count; @@ -567,14 +587,10 @@ static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) { case ARM::t2STMIA: case ARM::t2STMDB: case ARM::VLDMSIA: - case ARM::VLDMSDB: case ARM::VSTMSIA: - case ARM::VSTMSDB: return (MI->getNumOperands() - MI->getDesc().getNumOperands() + 1) * 4; case ARM::VLDMDIA: - case ARM::VLDMDDB: case ARM::VSTMDIA: - case ARM::VSTMDDB: return (MI->getNumOperands() - MI->getDesc().getNumOperands() + 1) * 8; } } @@ -624,7 +640,6 @@ static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, } break; case ARM::VLDMSIA: - case ARM::VLDMSDB: switch (Mode) { default: llvm_unreachable("Unhandled submode!"); case ARM_AM::ia: return ARM::VLDMSIA_UPD; @@ -632,7 +647,6 @@ static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, } break; case ARM::VLDMDIA: - case ARM::VLDMDDB: switch (Mode) { default: llvm_unreachable("Unhandled submode!"); case ARM_AM::ia: return ARM::VLDMDIA_UPD; @@ -640,7 +654,6 @@ static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, } break; case ARM::VSTMSIA: - case ARM::VSTMSDB: switch (Mode) { default: llvm_unreachable("Unhandled submode!"); case ARM_AM::ia: return ARM::VSTMSIA_UPD; @@ -648,7 +661,6 @@ static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, } break; case ARM::VSTMDIA: - case ARM::VSTMDDB: switch (Mode) { default: llvm_unreachable("Unhandled submode!"); case ARM_AM::ia: return ARM::VSTMDIA_UPD; @@ -749,7 +761,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB, MIB.addOperand(MI->getOperand(OpNum)); // Transfer memoperands. - (*MIB).setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); + MIB->setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); MBB.erase(MBBI); return true; @@ -1275,14 +1287,14 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize, CurrPred, CurrPredReg, Scratch, MemOps, Merges); - // Try folding preceeding/trailing base inc/dec into the generated + // Try folding preceding/trailing base inc/dec into the generated // LDM/STM ops. for (unsigned i = 0, e = Merges.size(); i < e; ++i) if (MergeBaseUpdateLSMultiple(MBB, Merges[i], Advance, MBBI)) ++NumMerges; NumMerges += Merges.size(); - // Try folding preceeding/trailing base inc/dec into those load/store + // Try folding preceding/trailing base inc/dec into those load/store // that were not merged to form LDM/STM ops. for (unsigned i = 0; i != NumMemOps; ++i) if (!MemOps[i].Merged) @@ -1292,7 +1304,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { // RS may be pointing to an instruction that's deleted. RS->skipTo(prior(MBBI)); } else if (NumMemOps == 1) { - // Try folding preceeding/trailing base inc/dec into the single + // Try folding preceding/trailing base inc/dec into the single // load/store. if (MergeBaseUpdateLoadStore(MBB, MemOps[0].MBBI, TII, Advance, MBBI)) { ++NumMerges; @@ -1322,7 +1334,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { } /// MergeReturnIntoLDM - If this is a exit BB, try merging the return ops -/// ("bx lr" and "mov pc, lr") into the preceeding stack restore so it +/// ("bx lr" and "mov pc, lr") into the preceding stack restore so it /// directly restore the value of LR into pc. /// ldmfd sp!, {..., lr} /// bx lr @@ -1530,15 +1542,9 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, // Then make sure the immediate offset fits. int OffImm = getMemoryOpOffset(Op0); if (isT2) { - if (OffImm < 0) { - if (OffImm < -255) - // Can't fall back to t2LDRi8 / t2STRi8. - return false; - } else { - int Limit = (1 << 8) * Scale; - if (OffImm >= Limit || (OffImm & (Scale-1))) - return false; - } + int Limit = (1 << 8) * Scale; + if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1))) + return false; Offset = OffImm; } else { ARM_AM::AddrOpc AddSub = ARM_AM::add; diff --git a/contrib/llvm/lib/Target/ARM/ARMMCAsmInfo.cpp b/contrib/llvm/lib/Target/ARM/ARMMCAsmInfo.cpp index 53edfcad9308..a3f89e92f8ec 100644 --- a/contrib/llvm/lib/Target/ARM/ARMMCAsmInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMMCAsmInfo.cpp @@ -12,8 +12,16 @@ //===----------------------------------------------------------------------===// #include "ARMMCAsmInfo.h" +#include "llvm/Support/CommandLine.h" + using namespace llvm; +cl::opt +EnableARMEHABI("arm-enable-ehabi", cl::Hidden, + cl::desc("Generate ARM EHABI tables"), + cl::init(false)); + + static const char *const arm_asm_table[] = { "{r0}", "r0", "{r1}", "r1", @@ -65,4 +73,8 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() { DwarfRequiresFrameSection = false; SupportsDebugInformation = true; + + // Exceptions handling + if (EnableARMEHABI) + ExceptionsType = ExceptionHandling::ARM; } diff --git a/contrib/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp b/contrib/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp index 6d7b48587d19..10607b17c532 100644 --- a/contrib/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -278,6 +278,15 @@ class ARMMCCodeEmitter : public MCCodeEmitter { unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups) const; + unsigned getShiftRight8Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; + unsigned getShiftRight16Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; + unsigned getShiftRight32Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; + unsigned getShiftRight64Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; + unsigned NEONThumb2DataIPostEncoder(const MCInst &MI, unsigned EncodedValue) const; unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI, @@ -1201,6 +1210,30 @@ getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, return MO.getReg(); } +unsigned ARMMCCodeEmitter:: +getShiftRight8Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const { + return 8 - MI.getOperand(Op).getImm(); +} + +unsigned ARMMCCodeEmitter:: +getShiftRight16Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const { + return 16 - MI.getOperand(Op).getImm(); +} + +unsigned ARMMCCodeEmitter:: +getShiftRight32Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const { + return 32 - MI.getOperand(Op).getImm(); +} + +unsigned ARMMCCodeEmitter:: +getShiftRight64Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const { + return 64 - MI.getOperand(Op).getImm(); +} + void ARMMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups) const { diff --git a/contrib/llvm/lib/Target/ARM/ARMMCExpr.h b/contrib/llvm/lib/Target/ARM/ARMMCExpr.h index d42f766ca91f..0a2e883deb1d 100644 --- a/contrib/llvm/lib/Target/ARM/ARMMCExpr.h +++ b/contrib/llvm/lib/Target/ARM/ARMMCExpr.h @@ -60,6 +60,9 @@ class ARMMCExpr : public MCTargetExpr { bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout) const; void AddValueSymbols(MCAssembler *) const; + const MCSection *FindAssociatedSection() const { + return getSubExpr()->FindAssociatedSection(); + } static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; diff --git a/contrib/llvm/lib/Target/ARM/ARMRegisterInfo.cpp b/contrib/llvm/lib/Target/ARM/ARMRegisterInfo.cpp index ad51bc13edf0..1cba1ba591ef 100644 --- a/contrib/llvm/lib/Target/ARM/ARMRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMRegisterInfo.cpp @@ -12,26 +12,8 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" -#include "ARMInstrInfo.h" -#include "ARMMachineFunctionInfo.h" #include "ARMRegisterInfo.h" -#include "ARMSubtarget.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineLocation.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallVector.h" using namespace llvm; ARMRegisterInfo::ARMRegisterInfo(const ARMBaseInstrInfo &tii, diff --git a/contrib/llvm/lib/Target/ARM/ARMRegisterInfo.td b/contrib/llvm/lib/Target/ARM/ARMRegisterInfo.td index 22d15b572ddd..54bf82a99e73 100644 --- a/contrib/llvm/lib/Target/ARM/ARMRegisterInfo.td +++ b/contrib/llvm/lib/Target/ARM/ARMRegisterInfo.td @@ -70,6 +70,8 @@ def R4 : ARMReg< 4, "r4">, DwarfRegNum<[4]>; def R5 : ARMReg< 5, "r5">, DwarfRegNum<[5]>; def R6 : ARMReg< 6, "r6">, DwarfRegNum<[6]>; def R7 : ARMReg< 7, "r7">, DwarfRegNum<[7]>; +// These require 32-bit instructions. +let CostPerUse = 1 in { def R8 : ARMReg< 8, "r8">, DwarfRegNum<[8]>; def R9 : ARMReg< 9, "r9">, DwarfRegNum<[9]>; def R10 : ARMReg<10, "r10">, DwarfRegNum<[10]>; @@ -78,6 +80,7 @@ def R12 : ARMReg<12, "r12">, DwarfRegNum<[12]>; def SP : ARMReg<13, "sp">, DwarfRegNum<[13]>; def LR : ARMReg<14, "lr">, DwarfRegNum<[14]>; def PC : ARMReg<15, "pc">, DwarfRegNum<[15]>; +} // Float registers def S0 : ARMFReg< 0, "s0">; def S1 : ARMFReg< 1, "s1">; @@ -99,33 +102,41 @@ def S30 : ARMFReg<30, "s30">; def S31 : ARMFReg<31, "s31">; // Aliases of the F* registers used to hold 64-bit fp values (doubles) let SubRegIndices = [ssub_0, ssub_1] in { -def D0 : ARMReg< 0, "d0", [S0, S1]>; -def D1 : ARMReg< 1, "d1", [S2, S3]>; -def D2 : ARMReg< 2, "d2", [S4, S5]>; -def D3 : ARMReg< 3, "d3", [S6, S7]>; -def D4 : ARMReg< 4, "d4", [S8, S9]>; -def D5 : ARMReg< 5, "d5", [S10, S11]>; -def D6 : ARMReg< 6, "d6", [S12, S13]>; -def D7 : ARMReg< 7, "d7", [S14, S15]>; -def D8 : ARMReg< 8, "d8", [S16, S17]>; -def D9 : ARMReg< 9, "d9", [S18, S19]>; -def D10 : ARMReg<10, "d10", [S20, S21]>; -def D11 : ARMReg<11, "d11", [S22, S23]>; -def D12 : ARMReg<12, "d12", [S24, S25]>; -def D13 : ARMReg<13, "d13", [S26, S27]>; -def D14 : ARMReg<14, "d14", [S28, S29]>; -def D15 : ARMReg<15, "d15", [S30, S31]>; +def D0 : ARMReg< 0, "d0", [S0, S1]>, DwarfRegNum<[256]>; +def D1 : ARMReg< 1, "d1", [S2, S3]>, DwarfRegNum<[257]>; +def D2 : ARMReg< 2, "d2", [S4, S5]>, DwarfRegNum<[258]>; +def D3 : ARMReg< 3, "d3", [S6, S7]>, DwarfRegNum<[259]>; +def D4 : ARMReg< 4, "d4", [S8, S9]>, DwarfRegNum<[260]>; +def D5 : ARMReg< 5, "d5", [S10, S11]>, DwarfRegNum<[261]>; +def D6 : ARMReg< 6, "d6", [S12, S13]>, DwarfRegNum<[262]>; +def D7 : ARMReg< 7, "d7", [S14, S15]>, DwarfRegNum<[263]>; +def D8 : ARMReg< 8, "d8", [S16, S17]>, DwarfRegNum<[264]>; +def D9 : ARMReg< 9, "d9", [S18, S19]>, DwarfRegNum<[265]>; +def D10 : ARMReg<10, "d10", [S20, S21]>, DwarfRegNum<[266]>; +def D11 : ARMReg<11, "d11", [S22, S23]>, DwarfRegNum<[267]>; +def D12 : ARMReg<12, "d12", [S24, S25]>, DwarfRegNum<[268]>; +def D13 : ARMReg<13, "d13", [S26, S27]>, DwarfRegNum<[269]>; +def D14 : ARMReg<14, "d14", [S28, S29]>, DwarfRegNum<[270]>; +def D15 : ARMReg<15, "d15", [S30, S31]>, DwarfRegNum<[271]>; } // VFP3 defines 16 additional double registers -def D16 : ARMFReg<16, "d16">; def D17 : ARMFReg<17, "d17">; -def D18 : ARMFReg<18, "d18">; def D19 : ARMFReg<19, "d19">; -def D20 : ARMFReg<20, "d20">; def D21 : ARMFReg<21, "d21">; -def D22 : ARMFReg<22, "d22">; def D23 : ARMFReg<23, "d23">; -def D24 : ARMFReg<24, "d24">; def D25 : ARMFReg<25, "d25">; -def D26 : ARMFReg<26, "d26">; def D27 : ARMFReg<27, "d27">; -def D28 : ARMFReg<28, "d28">; def D29 : ARMFReg<29, "d29">; -def D30 : ARMFReg<30, "d30">; def D31 : ARMFReg<31, "d31">; +def D16 : ARMFReg<16, "d16">, DwarfRegNum<[272]>; +def D17 : ARMFReg<17, "d17">, DwarfRegNum<[273]>; +def D18 : ARMFReg<18, "d18">, DwarfRegNum<[274]>; +def D19 : ARMFReg<19, "d19">, DwarfRegNum<[275]>; +def D20 : ARMFReg<20, "d20">, DwarfRegNum<[276]>; +def D21 : ARMFReg<21, "d21">, DwarfRegNum<[277]>; +def D22 : ARMFReg<22, "d22">, DwarfRegNum<[278]>; +def D23 : ARMFReg<23, "d23">, DwarfRegNum<[279]>; +def D24 : ARMFReg<24, "d24">, DwarfRegNum<[280]>; +def D25 : ARMFReg<25, "d25">, DwarfRegNum<[281]>; +def D26 : ARMFReg<26, "d26">, DwarfRegNum<[282]>; +def D27 : ARMFReg<27, "d27">, DwarfRegNum<[283]>; +def D28 : ARMFReg<28, "d28">, DwarfRegNum<[284]>; +def D29 : ARMFReg<29, "d29">, DwarfRegNum<[285]>; +def D30 : ARMFReg<30, "d30">, DwarfRegNum<[286]>; +def D31 : ARMFReg<31, "d31">, DwarfRegNum<[287]>; // Advanced SIMD (NEON) defines 16 quad-word aliases let SubRegIndices = [dsub_0, dsub_1], diff --git a/contrib/llvm/lib/Target/ARM/ARMScheduleA9.td b/contrib/llvm/lib/Target/ARM/ARMScheduleA9.td index 82c6735f1b14..49fedf63f8bc 100644 --- a/contrib/llvm/lib/Target/ARM/ARMScheduleA9.td +++ b/contrib/llvm/lib/Target/ARM/ARMScheduleA9.td @@ -656,19 +656,19 @@ def CortexA9Itineraries : ProcessorItineraries< [1, 1, 1]>, // // Single-precision to Integer Move + // + // On A9 move-from-VFP is free to issue with no stall if other VFP + // operations are in flight. I assume it still can't dual-issue though. InstrItinData, - InstrStage<1, [A9_MUX0], 0>, - InstrStage<1, [A9_DRegsVFP], 0, Required>, - InstrStage<2, [A9_DRegsN], 0, Reserved>, - InstrStage<1, [A9_NPipe]>], + InstrStage<1, [A9_MUX0], 0>], [2, 1]>, // // Double-precision to Integer Move + // + // On A9 move-from-VFP is free to issue with no stall if other VFP + // operations are in flight. I assume it still can't dual-issue though. InstrItinData, - InstrStage<1, [A9_MUX0], 0>, - InstrStage<1, [A9_DRegsVFP], 0, Required>, - InstrStage<2, [A9_DRegsN], 0, Reserved>, - InstrStage<1, [A9_NPipe]>], + InstrStage<1, [A9_MUX0], 0>], [2, 1, 1]>, // // Single-precision FP Load @@ -691,20 +691,22 @@ def CortexA9Itineraries : ProcessorItineraries< [2, 1]>, // // FP Load Multiple + // FIXME: assumes 2 doubles which requires 2 LS cycles. InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsVFP], 0, Required>, InstrStage<2, [A9_DRegsN], 0, Reserved>, InstrStage<1, [A9_NPipe], 0>, - InstrStage<1, [A9_LSUnit]>], [1, 1, 1, 1]>, + InstrStage<2, [A9_LSUnit]>], [1, 1, 1, 1]>, // // FP Load Multiple + update + // FIXME: assumes 2 doubles which requires 2 LS cycles. InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsVFP], 0, Required>, InstrStage<2, [A9_DRegsN], 0, Reserved>, InstrStage<1, [A9_NPipe], 0>, - InstrStage<1, [A9_LSUnit]>], [2, 1, 1, 1]>, + InstrStage<2, [A9_LSUnit]>], [2, 1, 1, 1]>, // // Single-precision FP Store InstrItinData, @@ -725,205 +727,206 @@ def CortexA9Itineraries : ProcessorItineraries< [1, 1]>, // // FP Store Multiple + // FIXME: assumes 2 doubles which requires 2 LS cycles. InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsVFP], 0, Required>, InstrStage<2, [A9_DRegsN], 0, Reserved>, InstrStage<1, [A9_NPipe], 0>, - InstrStage<1, [A9_LSUnit]>], [1, 1, 1, 1]>, + InstrStage<2, [A9_LSUnit]>], [1, 1, 1, 1]>, // // FP Store Multiple + update + // FIXME: assumes 2 doubles which requires 2 LS cycles. InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsVFP], 0, Required>, InstrStage<2, [A9_DRegsN], 0, Reserved>, InstrStage<1, [A9_NPipe], 0>, - InstrStage<1, [A9_LSUnit]>], [2, 1, 1, 1]>, + InstrStage<2, [A9_LSUnit]>], [2, 1, 1, 1]>, // NEON // VLD1 - // FIXME: Conservatively assume insufficent alignment. InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [2, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [1, 1]>, // VLD1x2 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [2, 2, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [1, 1, 1]>, // VLD1x3 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [2, 2, 3, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [1, 1, 2, 1]>, // VLD1x4 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [2, 2, 3, 3, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [1, 1, 2, 2, 1]>, // VLD1u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [2, 2, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [1, 2, 1]>, // VLD1x2u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [2, 2, 2, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [1, 1, 2, 1]>, // VLD1x3u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [2, 2, 3, 2, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [1, 1, 2, 2, 1]>, // VLD1x4u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [2, 2, 3, 3, 2, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [1, 1, 2, 2, 2, 1]>, // // VLD1ln InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [4, 1, 1, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [3, 1, 1, 1]>, // // VLD1lnu InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [4, 2, 1, 1, 1, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [3, 2, 1, 1, 1, 1]>, // // VLD1dup InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [3, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [2, 1]>, // // VLD1dupu InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [3, 2, 1, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [2, 2, 1, 1]>, // // VLD2 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, // Extra latency cycles since wbck is 7 cycles - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [3, 3, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [2, 2, 1]>, // // VLD2x2 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [3, 4, 3, 4, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [2, 3, 2, 3, 1]>, // // VLD2ln InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [4, 4, 1, 1, 1, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [3, 3, 1, 1, 1, 1]>, // // VLD2u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, // Extra latency cycles since wbck is 7 cycles - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [3, 3, 2, 1, 1, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [2, 2, 2, 1, 1, 1]>, // // VLD2x2u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [3, 4, 3, 4, 2, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [2, 3, 2, 3, 2, 1]>, // // VLD2lnu InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [4, 4, 2, 1, 1, 1, 1, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [3, 3, 2, 1, 1, 1, 1, 1]>, // // VLD2dup InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [3, 3, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [2, 2, 1]>, // // VLD2dupu InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<8, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], - [3, 3, 2, 1, 1]>, + InstrStage<7, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], + [2, 2, 2, 1, 1]>, // // VLD3 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<10,[A9_DRegsVFP], 0, Reserved>, - InstrStage<4, [A9_NPipe], 0>, - InstrStage<4, [A9_LSUnit]>], - [4, 4, 5, 1]>, + InstrStage<9,[A9_DRegsVFP], 0, Reserved>, + InstrStage<3, [A9_NPipe], 0>, + InstrStage<3, [A9_LSUnit]>], + [3, 3, 4, 1]>, // // VLD3ln InstrItinData, @@ -938,10 +941,10 @@ def CortexA9Itineraries : ProcessorItineraries< InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<10,[A9_DRegsVFP], 0, Reserved>, - InstrStage<4, [A9_NPipe], 0>, - InstrStage<4, [A9_LSUnit]>], - [4, 4, 5, 2, 1]>, + InstrStage<9,[A9_DRegsVFP], 0, Reserved>, + InstrStage<3, [A9_NPipe], 0>, + InstrStage<3, [A9_LSUnit]>], + [3, 3, 4, 2, 1]>, // // VLD3lnu InstrItinData, @@ -974,108 +977,108 @@ def CortexA9Itineraries : ProcessorItineraries< InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<10,[A9_DRegsVFP], 0, Reserved>, - InstrStage<4, [A9_NPipe], 0>, - InstrStage<4, [A9_LSUnit]>], - [4, 4, 5, 5, 1]>, + InstrStage<9,[A9_DRegsVFP], 0, Reserved>, + InstrStage<3, [A9_NPipe], 0>, + InstrStage<3, [A9_LSUnit]>], + [3, 3, 4, 4, 1]>, // // VLD4ln InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<11,[A9_DRegsVFP], 0, Reserved>, - InstrStage<5, [A9_NPipe], 0>, - InstrStage<5, [A9_LSUnit]>], - [5, 5, 6, 6, 1, 1, 1, 1, 2, 2]>, + InstrStage<10,[A9_DRegsVFP], 0, Reserved>, + InstrStage<4, [A9_NPipe], 0>, + InstrStage<4, [A9_LSUnit]>], + [4, 4, 5, 5, 1, 1, 1, 1, 2, 2]>, // // VLD4u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<10,[A9_DRegsVFP], 0, Reserved>, - InstrStage<4, [A9_NPipe], 0>, - InstrStage<4, [A9_LSUnit]>], - [4, 4, 5, 5, 2, 1]>, + InstrStage<9,[A9_DRegsVFP], 0, Reserved>, + InstrStage<3, [A9_NPipe], 0>, + InstrStage<3, [A9_LSUnit]>], + [3, 3, 4, 4, 2, 1]>, // // VLD4lnu InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<11,[A9_DRegsVFP], 0, Reserved>, - InstrStage<5, [A9_NPipe], 0>, - InstrStage<5, [A9_LSUnit]>], - [5, 5, 6, 6, 2, 1, 1, 1, 1, 1, 2, 2]>, + InstrStage<10,[A9_DRegsVFP], 0, Reserved>, + InstrStage<4, [A9_NPipe], 0>, + InstrStage<4, [A9_LSUnit]>], + [4, 4, 5, 5, 2, 1, 1, 1, 1, 1, 2, 2]>, // // VLD4dup InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [3, 3, 4, 4, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [2, 2, 3, 3, 1]>, // // VLD4dupu InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<9, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], - [3, 3, 4, 4, 2, 1, 1]>, + InstrStage<8, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], + [2, 2, 3, 3, 2, 1, 1]>, // // VST1 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<2, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [1, 1, 1]>, // // VST1x2 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<2, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [1, 1, 1, 1]>, // // VST1x3 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [1, 1, 1, 1, 2]>, // // VST1x4 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [1, 1, 1, 1, 2, 2]>, // // VST1u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<2, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [2, 1, 1, 1, 1]>, // // VST1x2u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<2, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [2, 1, 1, 1, 1, 1]>, // // VST1x3u @@ -1083,44 +1086,44 @@ def CortexA9Itineraries : ProcessorItineraries< InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, InstrStage<2, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [2, 1, 1, 1, 1, 1, 2]>, // // VST1x4u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [2, 1, 1, 1, 1, 1, 2, 2]>, // // VST1ln InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<2, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [1, 1, 1]>, // // VST1lnu InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [2, 1, 1, 1, 1]>, // // VST2 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<2, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [1, 1, 1, 1]>, // // VST2x2 @@ -1136,9 +1139,9 @@ def CortexA9Itineraries : ProcessorItineraries< InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<2, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [2, 1, 1, 1, 1, 1]>, // // VST2x2u @@ -1154,36 +1157,36 @@ def CortexA9Itineraries : ProcessorItineraries< InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<2, [A9_DRegsVFP], 0, Reserved>, - InstrStage<2, [A9_NPipe], 0>, - InstrStage<2, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [1, 1, 1, 1]>, // // VST2lnu InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<1, [A9_DRegsVFP], 0, Reserved>, + InstrStage<1, [A9_NPipe], 0>, + InstrStage<1, [A9_LSUnit]>], [2, 1, 1, 1, 1, 1]>, // // VST3 InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [1, 1, 1, 1, 2]>, // // VST3u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [2, 1, 1, 1, 1, 1, 2]>, // // VST3ln @@ -1208,36 +1211,36 @@ def CortexA9Itineraries : ProcessorItineraries< InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [1, 1, 1, 1, 2, 2]>, // // VST4u InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [2, 1, 1, 1, 1, 1, 2, 2]>, // // VST4ln InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [1, 1, 1, 1, 2, 2]>, // // VST4lnu InstrItinData, InstrStage<1, [A9_MUX0], 0>, InstrStage<1, [A9_DRegsN], 0, Required>, - InstrStage<3, [A9_DRegsVFP], 0, Reserved>, - InstrStage<3, [A9_NPipe], 0>, - InstrStage<3, [A9_LSUnit]>], + InstrStage<2, [A9_DRegsVFP], 0, Reserved>, + InstrStage<2, [A9_NPipe], 0>, + InstrStage<2, [A9_LSUnit]>], [2, 1, 1, 1, 1, 1, 2, 2]>, // diff --git a/contrib/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp b/contrib/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp index 2b9202bff01c..aa1e398c0e42 100644 --- a/contrib/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp @@ -35,7 +35,7 @@ ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, // This requires 4-byte alignment. if ((Align & 3) != 0) return SDValue(); - // This requires the copy size to be a constant, preferrably + // This requires the copy size to be a constant, preferably // within a subtarget-specific limit. ConstantSDNode *ConstantSize = dyn_cast(Size); if (!ConstantSize) diff --git a/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp b/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp index 1465984899c6..c6f266b07531 100644 --- a/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp @@ -38,6 +38,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, , ARMFPUType(None) , UseNEONForSinglePrecisionFP(false) , SlowFPVMLx(false) + , HasVMLxForwarding(false) , SlowFPBrcc(false) , IsThumb(isT) , ThumbMode(Thumb1) @@ -51,6 +52,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, , HasT2ExtractPack(false) , HasDataBarrier(false) , Pref32BitThumb(false) + , AvoidCPSRPartialUpdate(false) , HasMPExtension(false) , FPOnlySP(false) , AllowsUnalignedMem(false) diff --git a/contrib/llvm/lib/Target/ARM/ARMSubtarget.h b/contrib/llvm/lib/Target/ARM/ARMSubtarget.h index 76c1c3fb41b1..0271c873f191 100644 --- a/contrib/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/contrib/llvm/lib/Target/ARM/ARMSubtarget.h @@ -61,6 +61,10 @@ class ARMSubtarget : public TargetSubtarget { /// whether the FP VML[AS] instructions are slow (if so, don't use them). bool SlowFPVMLx; + /// HasVMLxForwarding - If true, NEON has special multiplier accumulator + /// forwarding to allow mul + mla being issued back to back. + bool HasVMLxForwarding; + /// SlowFPBrcc - True if floating point compare + branch is slow. bool SlowFPBrcc; @@ -106,6 +110,11 @@ class ARMSubtarget : public TargetSubtarget { /// over 16-bit ones. bool Pref32BitThumb; + /// AvoidCPSRPartialUpdate - If true, codegen would avoid using instructions + /// that partially update CPSR and add false dependency on the previous + /// CPSR setting instruction. + bool AvoidCPSRPartialUpdate; + /// HasMPExtension - True if the subtarget supports Multiprocessing /// extension (ARMv7 only). bool HasMPExtension; @@ -182,15 +191,19 @@ class ARMSubtarget : public TargetSubtarget { bool hasT2ExtractPack() const { return HasT2ExtractPack; } bool hasDataBarrier() const { return HasDataBarrier; } bool useFPVMLx() const { return !SlowFPVMLx; } + bool hasVMLxForwarding() const { return HasVMLxForwarding; } bool isFPBrccSlow() const { return SlowFPBrcc; } bool isFPOnlySP() const { return FPOnlySP; } bool prefers32BitThumb() const { return Pref32BitThumb; } + bool avoidCPSRPartialUpdate() const { return AvoidCPSRPartialUpdate; } bool hasMPExtension() const { return HasMPExtension; } bool hasFP16() const { return HasFP16; } bool hasD16() const { return HasD16; } - bool isTargetDarwin() const { return TargetTriple.getOS() == Triple::Darwin; } + const Triple &getTargetTriple() const { return TargetTriple; } + + bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } bool isTargetELF() const { return !isTargetDarwin(); } bool isAPCS_ABI() const { return TargetABI == ARM_ABI_APCS; } diff --git a/contrib/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/contrib/llvm/lib/Target/ARM/ARMTargetMachine.cpp index 0ee773b165fb..29aa4f7ad2ce 100644 --- a/contrib/llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -22,16 +22,13 @@ #include "llvm/Target/TargetRegistry.h" using namespace llvm; -static cl::optExpandMLx("expand-fp-mlx", cl::init(false), cl::Hidden); - static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { Triple TheTriple(TT); - switch (TheTriple.getOS()) { - case Triple::Darwin: + + if (TheTriple.isOSDarwin()) return new ARMMCAsmInfoDarwin(); - default: - return new ARMELFMCAsmInfo(); - } + + return new ARMELFMCAsmInfo(); } // This is duplicated code. Refactor this. @@ -41,17 +38,17 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCCodeEmitter *Emitter, bool RelaxAll, bool NoExecStack) { - switch (Triple(TT).getOS()) { - case Triple::Darwin: + Triple TheTriple(TT); + + if (TheTriple.isOSDarwin()) return createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll); - case Triple::MinGW32: - case Triple::Cygwin: - case Triple::Win32: + + if (TheTriple.isOSWindows()) { llvm_unreachable("ARM does not support Windows COFF format"); return NULL; - default: - return createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll, NoExecStack); } + + return createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll, NoExecStack); } extern "C" void LLVMInitializeARMTarget() { @@ -86,8 +83,7 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, : LLVMTargetMachine(T, TT), Subtarget(TT, FS, isThumb), JITInfo(), - InstrItins(Subtarget.getInstrItineraryData()) -{ + InstrItins(Subtarget.getInstrItineraryData()) { DefRelocModel = getRelocationModel(); } @@ -149,8 +145,7 @@ bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM, // FIXME: temporarily disabling load / store optimization pass for Thumb1. if (OptLevel != CodeGenOpt::None && !Subtarget.isThumb1Only()) PM.add(createARMLoadStoreOptimizationPass(true)); - if (ExpandMLx && - OptLevel != CodeGenOpt::None && Subtarget.hasVFP2()) + if (OptLevel != CodeGenOpt::None && Subtarget.isCortexA9()) PM.add(createMLxExpansionPass()); return true; diff --git a/contrib/llvm/lib/Target/ARM/ARMTargetObjectFile.cpp b/contrib/llvm/lib/Target/ARM/ARMTargetObjectFile.cpp index 7535da54a95f..19defa1b5196 100644 --- a/contrib/llvm/lib/Target/ARM/ARMTargetObjectFile.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMTargetObjectFile.cpp @@ -36,8 +36,9 @@ void ARMElfTargetObjectFile::Initialize(MCContext &Ctx, ELF::SHF_WRITE | ELF::SHF_ALLOC, SectionKind::getDataRel()); + LSDASection = NULL; } - + AttributesSection = getContext().getELFSection(".ARM.attributes", ELF::SHT_ARM_ATTRIBUTES, diff --git a/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 129af206e1d9..29ecc182d31f 100644 --- a/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -29,15 +29,6 @@ #include "llvm/ADT/Twine.h" using namespace llvm; -/// Shift types used for register controlled shifts in ARM memory addressing. -enum ShiftType { - Lsl, - Lsr, - Asr, - Ror, - Rrx -}; - namespace { class ARMOperand; @@ -55,8 +46,10 @@ class ARMAsmParser : public TargetAsmParser { int TryParseRegister(); virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); bool TryParseRegisterWithWriteBack(SmallVectorImpl &); + bool TryParseShiftRegister(SmallVectorImpl &); bool ParseRegisterList(SmallVectorImpl &); - bool ParseMemory(SmallVectorImpl &); + bool ParseMemory(SmallVectorImpl &, + ARMII::AddrMode AddrMode); bool ParseOperand(SmallVectorImpl &, StringRef Mnemonic); bool ParsePrefix(ARMMCExpr::VariantKind &RefKind); const MCExpr *ApplyPrefixToExpr(const MCExpr *E, @@ -65,13 +58,14 @@ class ARMAsmParser : public TargetAsmParser { bool ParseMemoryOffsetReg(bool &Negative, bool &OffsetRegShifted, - enum ShiftType &ShiftType, + enum ARM_AM::ShiftOpc &ShiftType, const MCExpr *&ShiftAmount, const MCExpr *&Offset, bool &OffsetIsReg, int &OffsetRegNum, SMLoc &E); - bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E); + bool ParseShift(enum ARM_AM::ShiftOpc &St, + const MCExpr *&ShiftAmount, SMLoc &E); bool ParseDirectiveWord(unsigned Size, SMLoc L); bool ParseDirectiveThumb(SMLoc L); bool ParseDirectiveThumbFunc(SMLoc L); @@ -102,10 +96,25 @@ class ARMAsmParser : public TargetAsmParser { SmallVectorImpl&); OperandMatchResultTy tryParseMSRMaskOperand( SmallVectorImpl&); + OperandMatchResultTy tryParseMemMode2Operand( + SmallVectorImpl&); + OperandMatchResultTy tryParseMemMode3Operand( + SmallVectorImpl&); + + // Asm Match Converter Methods + bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &); + bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &); + bool CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &); + bool CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &); public: ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) : TargetAsmParser(T), Parser(_Parser), TM(_TM) { + MCAsmParserExtension::Initialize(_Parser); // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures( &TM.getSubtarget())); @@ -136,6 +145,7 @@ class ARMOperand : public MCParsedAsmOperand { RegisterList, DPRRegisterList, SPRRegisterList, + Shifter, Token } Kind; @@ -178,13 +188,14 @@ class ARMOperand : public MCParsedAsmOperand { /// Combined record for all forms of ARM address expressions. struct { + ARMII::AddrMode AddrMode; unsigned BaseRegNum; union { unsigned RegNum; ///< Offset register num, when OffsetIsReg. const MCExpr *Value; ///< Offset value, when !OffsetIsReg. } Offset; const MCExpr *ShiftAmount; // used when OffsetRegShifted is true - enum ShiftType ShiftType; // used when OffsetRegShifted is true + enum ARM_AM::ShiftOpc ShiftType; // used when OffsetRegShifted is true unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true unsigned Preindexed : 1; unsigned Postindexed : 1; @@ -192,6 +203,11 @@ class ARMOperand : public MCParsedAsmOperand { unsigned Negative : 1; // only used when OffsetIsReg is true unsigned Writeback : 1; } Mem; + + struct { + ARM_AM::ShiftOpc ShiftTy; + unsigned RegNum; + } Shift; }; ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} @@ -234,6 +250,10 @@ class ARMOperand : public MCParsedAsmOperand { break; case ProcIFlags: IFlags = o.IFlags; + break; + case Shifter: + Shift = o.Shift; + break; } } @@ -290,7 +310,9 @@ class ARMOperand : public MCParsedAsmOperand { /// @name Memory Operand Accessors /// @{ - + ARMII::AddrMode getMemAddrMode() const { + return Mem.AddrMode; + } unsigned getMemBaseRegNum() const { return Mem.BaseRegNum; } @@ -310,7 +332,7 @@ class ARMOperand : public MCParsedAsmOperand { assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!"); return Mem.ShiftAmount; } - enum ShiftType getMemShiftType() const { + enum ARM_AM::ShiftOpc getMemShiftType() const { assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!"); return Mem.ShiftType; } @@ -334,6 +356,52 @@ class ARMOperand : public MCParsedAsmOperand { bool isToken() const { return Kind == Token; } bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; } bool isMemory() const { return Kind == Memory; } + bool isShifter() const { return Kind == Shifter; } + bool isMemMode2() const { + if (getMemAddrMode() != ARMII::AddrMode2) + return false; + + if (getMemOffsetIsReg()) + return true; + + if (getMemNegative() && + !(getMemPostindexed() || getMemPreindexed())) + return false; + + const MCConstantExpr *CE = dyn_cast(getMemOffset()); + if (!CE) return false; + int64_t Value = CE->getValue(); + + // The offset must be in the range 0-4095 (imm12). + if (Value > 4095 || Value < -4095) + return false; + + return true; + } + bool isMemMode3() const { + if (getMemAddrMode() != ARMII::AddrMode3) + return false; + + if (getMemOffsetIsReg()) { + if (getMemOffsetRegShifted()) + return false; // No shift with offset reg allowed + return true; + } + + if (getMemNegative() && + !(getMemPostindexed() || getMemPreindexed())) + return false; + + const MCConstantExpr *CE = dyn_cast(getMemOffset()); + if (!CE) return false; + int64_t Value = CE->getValue(); + + // The offset must be in the range 0-255 (imm8). + if (Value > 255 || Value < -255) + return false; + + return true; + } bool isMemMode5() const { if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() || getMemNegative()) @@ -346,6 +414,23 @@ class ARMOperand : public MCParsedAsmOperand { int64_t Value = CE->getValue(); return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020); } + bool isMemMode7() const { + if (!isMemory() || + getMemPreindexed() || + getMemPostindexed() || + getMemOffsetIsReg() || + getMemNegative() || + getMemWriteback()) + return false; + + const MCConstantExpr *CE = dyn_cast(getMemOffset()); + if (!CE) return false; + + if (CE->getValue()) + return false; + + return true; + } bool isMemModeRegThumb() const { if (!isMemory() || !getMemOffsetIsReg() || getMemWriteback()) return false; @@ -402,6 +487,12 @@ class ARMOperand : public MCParsedAsmOperand { Inst.addOperand(MCOperand::CreateReg(getReg())); } + void addShifterOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm( + ARM_AM::getSORegOpc(Shift.ShiftTy, 0))); + } + void addRegListOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); const SmallVectorImpl &RegList = getRegList(); @@ -428,6 +519,88 @@ class ARMOperand : public MCParsedAsmOperand { Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); } + void addMemMode7Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && isMemMode7() && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum())); + + const MCConstantExpr *CE = dyn_cast(getMemOffset()); + (void)CE; + assert((CE || CE->getValue() == 0) && + "No offset operand support in mode 7"); + } + + void addMemMode2Operands(MCInst &Inst, unsigned N) const { + assert(isMemMode2() && "Invalid mode or number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum())); + unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1); + + if (getMemOffsetIsReg()) { + Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum())); + + ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add; + ARM_AM::ShiftOpc ShOpc = ARM_AM::no_shift; + int64_t ShiftAmount = 0; + + if (getMemOffsetRegShifted()) { + ShOpc = getMemShiftType(); + const MCConstantExpr *CE = + dyn_cast(getMemShiftAmount()); + ShiftAmount = CE->getValue(); + } + + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(AMOpc, ShiftAmount, + ShOpc, IdxMode))); + return; + } + + // Create a operand placeholder to always yield the same number of operands. + Inst.addOperand(MCOperand::CreateReg(0)); + + // FIXME: #-0 is encoded differently than #0. Does the parser preserve + // the difference? + const MCConstantExpr *CE = dyn_cast(getMemOffset()); + assert(CE && "Non-constant mode 2 offset operand!"); + int64_t Offset = CE->getValue(); + + if (Offset >= 0) + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::add, + Offset, ARM_AM::no_shift, IdxMode))); + else + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub, + -Offset, ARM_AM::no_shift, IdxMode))); + } + + void addMemMode3Operands(MCInst &Inst, unsigned N) const { + assert(isMemMode3() && "Invalid mode or number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum())); + unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1); + + if (getMemOffsetIsReg()) { + Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum())); + + ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add; + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(AMOpc, 0, + IdxMode))); + return; + } + + // Create a operand placeholder to always yield the same number of operands. + Inst.addOperand(MCOperand::CreateReg(0)); + + // FIXME: #-0 is encoded differently than #0. Does the parser preserve + // the difference? + const MCConstantExpr *CE = dyn_cast(getMemOffset()); + assert(CE && "Non-constant mode 3 offset operand!"); + int64_t Offset = CE->getValue(); + + if (Offset >= 0) + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::add, + Offset, IdxMode))); + else + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::sub, + -Offset, IdxMode))); + } + void addMemMode5Operands(MCInst &Inst, unsigned N) const { assert(N == 2 && isMemMode5() && "Invalid number of operands!"); @@ -525,6 +698,15 @@ class ARMOperand : public MCParsedAsmOperand { return Op; } + static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy, + SMLoc S, SMLoc E) { + ARMOperand *Op = new ARMOperand(Shifter); + Op->Shift.ShiftTy = ShTy; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static ARMOperand * CreateRegList(const SmallVectorImpl > &Regs, SMLoc StartLoc, SMLoc EndLoc) { @@ -553,9 +735,10 @@ class ARMOperand : public MCParsedAsmOperand { return Op; } - static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg, - const MCExpr *Offset, int OffsetRegNum, - bool OffsetRegShifted, enum ShiftType ShiftType, + static ARMOperand *CreateMem(ARMII::AddrMode AddrMode, unsigned BaseRegNum, + bool OffsetIsReg, const MCExpr *Offset, + int OffsetRegNum, bool OffsetRegShifted, + enum ARM_AM::ShiftOpc ShiftType, const MCExpr *ShiftAmount, bool Preindexed, bool Postindexed, bool Negative, bool Writeback, SMLoc S, SMLoc E) { @@ -571,6 +754,7 @@ class ARMOperand : public MCParsedAsmOperand { "Cannot have expression offset and register offset!"); ARMOperand *Op = new ARMOperand(Memory); + Op->Mem.AddrMode = AddrMode; Op->Mem.BaseRegNum = BaseRegNum; Op->Mem.OffsetIsReg = OffsetIsReg; if (OffsetIsReg) @@ -642,7 +826,8 @@ void ARMOperand::dump(raw_ostream &OS) const { break; case Memory: OS << ""; break; + case Shifter: + OS << ""; + break; case RegisterList: case DPRRegisterList: case SPRRegisterList: { @@ -738,6 +926,42 @@ int ARMAsmParser::TryParseRegister() { return RegNum; } +/// Try to parse a register name. The token must be an Identifier when called, +/// and if it is a register name the token is eaten and the register number is +/// returned. Otherwise return -1. +/// +bool ARMAsmParser::TryParseShiftRegister( + SmallVectorImpl &Operands) { + SMLoc S = Parser.getTok().getLoc(); + const AsmToken &Tok = Parser.getTok(); + assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); + + std::string upperCase = Tok.getString().str(); + std::string lowerCase = LowercaseString(upperCase); + ARM_AM::ShiftOpc ShiftTy = StringSwitch(lowerCase) + .Case("lsl", ARM_AM::lsl) + .Case("lsr", ARM_AM::lsr) + .Case("asr", ARM_AM::asr) + .Case("ror", ARM_AM::ror) + .Case("rrx", ARM_AM::rrx) + .Default(ARM_AM::no_shift); + + if (ShiftTy == ARM_AM::no_shift) + return true; + + Parser.Lex(); // Eat shift-type operand; + int RegNum = TryParseRegister(); + if (RegNum == -1) + return Error(Parser.getTok().getLoc(), "register expected"); + + Operands.push_back(ARMOperand::CreateReg(RegNum,S, Parser.getTok().getLoc())); + Operands.push_back(ARMOperand::CreateShifter(ShiftTy, + S, Parser.getTok().getLoc())); + + return false; +} + + /// Try to parse a register name. The token must be an Identifier when called. /// If it's a register, an AsmOperand is created. Another AsmOperand is created /// if there is a "writeback". 'true' if it's not a register. @@ -1046,13 +1270,96 @@ tryParseMSRMaskOperand(SmallVectorImpl &Operands) { return MatchOperand_Success; } +/// tryParseMemMode2Operand - Try to parse memory addressing mode 2 operand. +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +tryParseMemMode2Operand(SmallVectorImpl &Operands) { + assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\""); + + if (ParseMemory(Operands, ARMII::AddrMode2)) + return MatchOperand_NoMatch; + + return MatchOperand_Success; +} + +/// tryParseMemMode3Operand - Try to parse memory addressing mode 3 operand. +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +tryParseMemMode3Operand(SmallVectorImpl &Operands) { + assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\""); + + if (ParseMemory(Operands, ARMII::AddrMode3)) + return MatchOperand_NoMatch; + + return MatchOperand_Success; +} + +/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst. +/// Needed here because the Asm Gen Matcher can't handle properly tied operands +/// when they refer multiple MIOperands inside a single one. +bool ARMAsmParser:: +CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &Operands) { + ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); + + // Create a writeback register dummy placeholder. + Inst.addOperand(MCOperand::CreateImm(0)); + + ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3); + ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); + return true; +} + +/// CvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst. +/// Needed here because the Asm Gen Matcher can't handle properly tied operands +/// when they refer multiple MIOperands inside a single one. +bool ARMAsmParser:: +CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &Operands) { + // Create a writeback register dummy placeholder. + Inst.addOperand(MCOperand::CreateImm(0)); + ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); + ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3); + ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); + return true; +} + +/// CvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst. +/// Needed here because the Asm Gen Matcher can't handle properly tied operands +/// when they refer multiple MIOperands inside a single one. +bool ARMAsmParser:: +CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &Operands) { + ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); + + // Create a writeback register dummy placeholder. + Inst.addOperand(MCOperand::CreateImm(0)); + + ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3); + ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); + return true; +} + +/// CvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst. +/// Needed here because the Asm Gen Matcher can't handle properly tied operands +/// when they refer multiple MIOperands inside a single one. +bool ARMAsmParser:: +CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &Operands) { + // Create a writeback register dummy placeholder. + Inst.addOperand(MCOperand::CreateImm(0)); + ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); + ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3); + ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); + return true; +} + /// Parse an ARM memory expression, return false if successful else return true /// or an error. The first token must be a '[' when called. /// /// TODO Only preindexing and postindexing addressing are started, unindexed /// with option, etc are still to do. bool ARMAsmParser:: -ParseMemory(SmallVectorImpl &Operands) { +ParseMemory(SmallVectorImpl &Operands, + ARMII::AddrMode AddrMode = ARMII::AddrModeNone) { SMLoc S, E; assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a Left Bracket"); @@ -1083,7 +1390,7 @@ ParseMemory(SmallVectorImpl &Operands) { ARMOperand *WBOp = 0; int OffsetRegNum = -1; bool OffsetRegShifted = false; - enum ShiftType ShiftType = Lsl; + enum ARM_AM::ShiftOpc ShiftType = ARM_AM::lsl; const MCExpr *ShiftAmount = 0; const MCExpr *Offset = 0; @@ -1106,10 +1413,17 @@ ParseMemory(SmallVectorImpl &Operands) { const AsmToken &ExclaimTok = Parser.getTok(); if (ExclaimTok.is(AsmToken::Exclaim)) { + // None of addrmode3 instruction uses "!" + if (AddrMode == ARMII::AddrMode3) + return true; + WBOp = ARMOperand::CreateToken(ExclaimTok.getString(), ExclaimTok.getLoc()); Writeback = true; Parser.Lex(); // Eat exclaim token + } else { // In addressing mode 2, pre-indexed mode always end with "!" + if (AddrMode == ARMII::AddrMode2) + Preindexed = false; } } else { // The "[Rn" we have so far was not followed by a comma. @@ -1143,13 +1457,17 @@ ParseMemory(SmallVectorImpl &Operands) { if (!OffsetIsReg) { if (!Offset) Offset = MCConstantExpr::Create(0, getContext()); + } else { + if (AddrMode == ARMII::AddrMode3 && OffsetRegShifted) { + Error(E, "shift amount not supported"); + return true; + } } - Operands.push_back(ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, - OffsetRegNum, OffsetRegShifted, - ShiftType, ShiftAmount, Preindexed, - Postindexed, Negative, Writeback, - S, E)); + Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg, + Offset, OffsetRegNum, OffsetRegShifted, + ShiftType, ShiftAmount, Preindexed, + Postindexed, Negative, Writeback, S, E)); if (WBOp) Operands.push_back(WBOp); @@ -1165,7 +1483,7 @@ ParseMemory(SmallVectorImpl &Operands) { /// we return false on success or an error otherwise. bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, bool &OffsetRegShifted, - enum ShiftType &ShiftType, + enum ARM_AM::ShiftOpc &ShiftType, const MCExpr *&ShiftAmount, const MCExpr *&Offset, bool &OffsetIsReg, @@ -1226,28 +1544,28 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, /// ( lsl | lsr | asr | ror ) , # shift_amount /// rrx /// and returns true if it parses a shift otherwise it returns false. -bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount, - SMLoc &E) { +bool ARMAsmParser::ParseShift(ARM_AM::ShiftOpc &St, + const MCExpr *&ShiftAmount, SMLoc &E) { const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) return true; StringRef ShiftName = Tok.getString(); if (ShiftName == "lsl" || ShiftName == "LSL") - St = Lsl; + St = ARM_AM::lsl; else if (ShiftName == "lsr" || ShiftName == "LSR") - St = Lsr; + St = ARM_AM::lsr; else if (ShiftName == "asr" || ShiftName == "ASR") - St = Asr; + St = ARM_AM::asr; else if (ShiftName == "ror" || ShiftName == "ROR") - St = Ror; + St = ARM_AM::ror; else if (ShiftName == "rrx" || ShiftName == "RRX") - St = Rrx; + St = ARM_AM::rrx; else return true; Parser.Lex(); // Eat shift type token. // Rrx stands alone. - if (St == Rrx) + if (St == ARM_AM::rrx) return false; // Otherwise, there must be a '#' and a shift amount. @@ -1286,6 +1604,9 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl &Operands, case AsmToken::Identifier: if (!TryParseRegisterWithWriteBack(Operands)) return false; + if (!TryParseShiftRegister(Operands)) + return false; + // Fall though for the Identifier case that is not a register or a // special name. diff --git a/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 78d73d3a272b..bdce2c4cf896 100644 --- a/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -18,6 +18,7 @@ #include "ARMDisassembler.h" #include "ARMDisassemblerCore.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/MC/EDInstInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/Target/TargetRegistry.h" @@ -94,6 +95,9 @@ static unsigned decodeARMInstruction(uint32_t &insn) { // As a result, the decoder fails to deocode USAT properly. if (slice(insn, 27, 21) == 0x37 && slice(insn, 5, 4) == 1) return ARM::USAT; + // As a result, the decoder fails to deocode UQADD16 properly. + if (slice(insn, 27, 20) == 0x66 && slice(insn, 7, 4) == 1) + return ARM::UQADD16; // Ditto for ADDSrs, which is a super-instruction for A8.6.7 & A8.6.8. // As a result, the decoder fails to decode UMULL properly. @@ -280,6 +284,24 @@ static unsigned T2Morph2LoadLiteral(unsigned Opcode) { } } +// Helper function for special case handling of PLD (literal) and friends. +// See A8.6.117 T1 & T2 and friends for why we morphed the opcode +// before returning it. +static unsigned T2Morph2PLDLiteral(unsigned Opcode) { + switch (Opcode) { + default: + return Opcode; // Return unmorphed opcode. + + case ARM::t2PLDi8: case ARM::t2PLDs: + case ARM::t2PLDWi12: case ARM::t2PLDWi8: + case ARM::t2PLDWs: + return ARM::t2PLDi12; + + case ARM::t2PLIi8: case ARM::t2PLIs: + return ARM::t2PLIi12; + } +} + /// decodeThumbSideEffect is a decorator function which can potentially twiddle /// the instruction or morph the returned opcode under Thumb2. /// @@ -330,12 +352,27 @@ static unsigned decodeThumbSideEffect(bool IsThumb2, unsigned &insn) { } // --------- Transform End Marker --------- + unsigned unmorphed = decodeThumbInstruction(insn); + // See, for example, A6.3.7 Load word: Table A6-18 Load word. // See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode // before returning it to our caller. if (op1 == 3 && slice(op2, 6, 5) == 0 && slice(op2, 0, 0) == 1 - && slice(insn, 19, 16) == 15) - return T2Morph2LoadLiteral(decodeThumbInstruction(insn)); + && slice(insn, 19, 16) == 15) { + unsigned morphed = T2Morph2LoadLiteral(unmorphed); + if (morphed != unmorphed) + return morphed; + } + + // See, for example, A8.6.117 PLD,PLDW (immediate) T1 & T2, and friends for + // why we morphed the opcode before returning it to our caller. + if (slice(insn, 31, 25) == 0x7C && slice(insn, 15, 12) == 0xF + && slice(insn, 22, 22) == 0 && slice(insn, 20, 20) == 1 + && slice(insn, 19, 16) == 15) { + unsigned morphed = T2Morph2PLDLiteral(unmorphed); + if (morphed != unmorphed) + return morphed; + } // One last check for NEON/VFP instructions. if ((op1 == 1 || op1 == 3) && slice(op2, 6, 6) == 1) @@ -375,21 +412,23 @@ bool ARMDisassembler::getInstruction(MCInst &MI, Size = 4; DEBUG({ - errs() << "Opcode=" << Opcode << " Name=" << ARMUtils::OpcodeName(Opcode) + errs() << "\nOpcode=" << Opcode << " Name=" < Builder(CreateMCBuilder(Opcode, Format)); if (!Builder) return false; + Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(), + getDisInfoBlock(), getMCContext(), + Address); + if (!Builder->Build(MI, insn)) return false; - delete Builder; - return true; } @@ -398,7 +437,7 @@ bool ThumbDisassembler::getInstruction(MCInst &MI, const MemoryObject &Region, uint64_t Address, raw_ostream &os) const { - // The Thumb instruction stream is a sequence of halhwords. + // The Thumb instruction stream is a sequence of halfwords. // This represents the first halfword as well as the machine instruction // passed to decodeThumbInstruction(). For 16-bit Thumb instruction, the top @@ -463,17 +502,19 @@ bool ThumbDisassembler::getInstruction(MCInst &MI, showBitVector(errs(), insn); }); - ARMBasicMCBuilder *Builder = CreateMCBuilder(Opcode, Format); + OwningPtr Builder(CreateMCBuilder(Opcode, Format)); if (!Builder) return false; Builder->SetSession(const_cast(&SO)); + Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(), + getDisInfoBlock(), getMCContext(), + Address); + if (!Builder->Build(MI, insn)) return false; - delete Builder; - return true; } diff --git a/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index bac68dd9ead0..642829cdab09 100644 --- a/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -17,6 +17,7 @@ #include "ARMDisassemblerCore.h" #include "ARMAddressingModes.h" +#include "ARMMCExpr.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -82,10 +83,28 @@ const char *ARMUtils::OpcodeName(unsigned Opcode) { // FIXME: Auto-gened? static unsigned getRegisterEnum(BO B, unsigned RegClassID, unsigned RawRegister) { - // For this purpose, we can treat rGPR as if it were GPR. - if (RegClassID == ARM::rGPRRegClassID) RegClassID = ARM::GPRRegClassID; + if (RegClassID == ARM::rGPRRegClassID) { + // Check for The register numbers 13 and 15 that are not permitted for many + // Thumb register specifiers. + if (RawRegister == 13 || RawRegister == 15) { + B->SetErr(-1); + return 0; + } + // For this purpose, we can treat rGPR as if it were GPR. + RegClassID = ARM::GPRRegClassID; + } // See also decodeNEONRd(), decodeNEONRn(), decodeNEONRm(). + // A7.3 register encoding + // Qd -> bit[12] == 0 + // Qn -> bit[16] == 0 + // Qm -> bit[0] == 0 + // + // If one of these bits is 1, the instruction is UNDEFINED. + if (RegClassID == ARM::QPRRegClassID && slice(RawRegister, 0, 0) == 1) { + B->SetErr(-1); + return 0; + } unsigned RegNum = RegClassID == ARM::QPRRegClassID ? RawRegister >> 1 : RawRegister; @@ -497,14 +516,66 @@ static bool DisassemblePseudo(MCInst &MI, unsigned Opcode, uint32_t insn, return false; } -// Multiply Instructions. -// MLA, MLS, SMLABB, SMLABT, SMLATB, SMLATT, SMLAWB, SMLAWT, SMMLA, SMMLS: -// Rd{19-16} Rn{3-0} Rm{11-8} Ra{15-12} +// A8.6.94 MLA +// if d == 15 || n == 15 || m == 15 || a == 15 then UNPREDICTABLE; // -// MUL, SMMUL, SMULBB, SMULBT, SMULTB, SMULTT, SMULWB, SMULWT: +// A8.6.105 MUL +// if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; +// +// A8.6.246 UMULL +// if dLo == 15 || dHi == 15 || n == 15 || m == 15 then UNPREDICTABLE; +// if dHi == dLo then UNPREDICTABLE; +static bool BadRegsMulFrm(unsigned Opcode, uint32_t insn) { + unsigned R19_16 = slice(insn, 19, 16); + unsigned R15_12 = slice(insn, 15, 12); + unsigned R11_8 = slice(insn, 11, 8); + unsigned R3_0 = slice(insn, 3, 0); + switch (Opcode) { + default: + // Did we miss an opcode? + DEBUG(errs() << "BadRegsMulFrm: unexpected opcode!"); + return false; + case ARM::MLA: case ARM::MLS: case ARM::SMLABB: case ARM::SMLABT: + case ARM::SMLATB: case ARM::SMLATT: case ARM::SMLAWB: case ARM::SMLAWT: + case ARM::SMMLA: case ARM::SMMLAR: case ARM::SMMLS: case ARM::SMMLSR: + case ARM::USADA8: + if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15) + return true; + return false; + case ARM::MUL: case ARM::SMMUL: case ARM::SMMULR: + case ARM::SMULBB: case ARM::SMULBT: case ARM::SMULTB: case ARM::SMULTT: + case ARM::SMULWB: case ARM::SMULWT: case ARM::SMUAD: case ARM::SMUADX: + // A8.6.167 SMLAD & A8.6.172 SMLSD + case ARM::SMLAD: case ARM::SMLADX: case ARM::SMLSD: case ARM::SMLSDX: + case ARM::USAD8: + if (R19_16 == 15 || R11_8 == 15 || R3_0 == 15) + return true; + return false; + case ARM::SMLAL: case ARM::SMULL: case ARM::UMAAL: case ARM::UMLAL: + case ARM::UMULL: + case ARM::SMLALBB: case ARM::SMLALBT: case ARM::SMLALTB: case ARM::SMLALTT: + case ARM::SMLALD: case ARM::SMLALDX: case ARM::SMLSLD: case ARM::SMLSLDX: + if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15) + return true; + if (R19_16 == R15_12) + return true; + return false;; + } +} + +// Multiply Instructions. +// MLA, MLS, SMLABB, SMLABT, SMLATB, SMLATT, SMLAWB, SMLAWT, SMMLA, SMMLAR, +// SMMLS, SMMLAR, SMLAD, SMLADX, SMLSD, SMLSDX, and USADA8 (for convenience): +// Rd{19-16} Rn{3-0} Rm{11-8} Ra{15-12} +// But note that register checking for {SMLAD, SMLADX, SMLSD, SMLSDX} is +// only for {d, n, m}. +// +// MUL, SMMUL, SMMULR, SMULBB, SMULBT, SMULTB, SMULTT, SMULWB, SMULWT, SMUAD, +// SMUADX, and USAD8 (for convenience): // Rd{19-16} Rn{3-0} Rm{11-8} // -// SMLAL, SMULL, UMAAL, UMLAL, UMULL, SMLALBB, SMLALBT, SMLALTB, SMLALTT: +// SMLAL, SMULL, UMAAL, UMLAL, UMULL, SMLALBB, SMLALBT, SMLALTB, SMLALTT, +// SMLALD, SMLADLX, SMLSLD, SMLSLDX: // RdLo{15-12} RdHi{19-16} Rn{3-0} Rm{11-8} // // The mapping of the multiply registers to the "regular" ARM registers, where @@ -531,6 +602,10 @@ static bool DisassembleMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, && OpInfo[2].RegClass == ARM::GPRRegClassID && "Expect three register operands"); + // Sanity check for the register encodings. + if (BadRegsMulFrm(Opcode, insn)) + return false; + // Instructions with two destination registers have RdLo{15-12} first. if (NumDefs == 2) { assert(NumOps >= 4 && OpInfo[3].RegClass == ARM::GPRRegClassID && @@ -618,18 +693,38 @@ static inline unsigned GetCopOpc(uint32_t insn) { static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - assert(NumOps >= 5 && "Num of operands >= 5 for coprocessor instr"); + assert(NumOps >= 4 && "Num of operands >= 4 for coprocessor instr"); unsigned &OpIdx = NumOpsAdded; + // A8.6.92 + // if coproc == '101x' then SEE "Advanced SIMD and VFP" + // But since the special instructions have more explicit encoding bits + // specified, if coproc == 10 or 11, we should reject it as invalid. + unsigned coproc = GetCoprocessor(insn); + if ((Opcode == ARM::MCR || Opcode == ARM::MCRR || + Opcode == ARM::MRC || Opcode == ARM::MRRC) && + (coproc == 10 || coproc == 11)) { + DEBUG(errs() << "Encoding error: coproc == 10 or 11 for MCR[R]/MR[R]C\n"); + return false; + } + bool OneCopOpc = (Opcode == ARM::MCRR || Opcode == ARM::MCRR2 || Opcode == ARM::MRRC || Opcode == ARM::MRRC2); + // CDP/CDP2 has no GPR operand; the opc1 operand is also wider (Inst{23-20}). bool NoGPR = (Opcode == ARM::CDP || Opcode == ARM::CDP2); bool LdStCop = LdStCopOpcode(Opcode); + bool RtOut = (Opcode == ARM::MRC || Opcode == ARM::MRC2); OpIdx = 0; - MI.addOperand(MCOperand::CreateImm(GetCoprocessor(insn))); + if (RtOut) { + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + decodeRd(insn)))); + ++OpIdx; + } + MI.addOperand(MCOperand::CreateImm(coproc)); + ++OpIdx; if (LdStCop) { // Unindex if P:W = 0b00 --> _OPTION variant @@ -639,26 +734,34 @@ static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn, MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)))); + OpIdx += 2; if (PW) { MI.addOperand(MCOperand::CreateReg(0)); ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; + const TargetInstrDesc &TID = ARMInsts[Opcode]; + unsigned IndexMode = + (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2, - ARM_AM::no_shift); + ARM_AM::no_shift, IndexMode); MI.addOperand(MCOperand::CreateImm(Offset)); - OpIdx = 5; + OpIdx += 2; } else { MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 0))); - OpIdx = 4; + ++OpIdx; } } else { MI.addOperand(MCOperand::CreateImm(OneCopOpc ? GetCopOpc(insn) : GetCopOpc1(insn, NoGPR))); + ++OpIdx; - MI.addOperand(NoGPR ? MCOperand::CreateImm(decodeRd(insn)) - : MCOperand::CreateReg( - getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); + if (!RtOut) { + MI.addOperand(NoGPR ? MCOperand::CreateImm(decodeRd(insn)) + : MCOperand::CreateReg( + getRegisterEnum(B, ARM::GPRRegClassID, + decodeRd(insn)))); + ++OpIdx; + } MI.addOperand(OneCopOpc ? MCOperand::CreateReg( getRegisterEnum(B, ARM::GPRRegClassID, @@ -667,7 +770,7 @@ static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn, MI.addOperand(MCOperand::CreateImm(decodeRm(insn))); - OpIdx = 5; + OpIdx += 2; if (!OneCopOpc) { MI.addOperand(MCOperand::CreateImm(GetCopOpc2(insn))); @@ -679,8 +782,8 @@ static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn, } // Branch Instructions. -// BLr9: SignExtend(Imm24:'00', 32) -// Bcc, BLr9_pred: SignExtend(Imm24:'00', 32) Pred0 Pred1 +// BL: SignExtend(Imm24:'00', 32) +// Bcc, BL_pred: SignExtend(Imm24:'00', 32) Pred0 Pred1 // SMC: ZeroExtend(imm4, 32) // SVC: ZeroExtend(Imm24, 32) // @@ -735,6 +838,11 @@ static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // MSRi take a mask, followed by one so_imm operand. The mask contains the // R Bit in bit 4, and the special register fields in bits 3-0. if (Opcode == ARM::MSRi) { + // A5.2.11 MSR (immediate), and hints & B6.1.6 MSR (immediate) + // The hints instructions have more specific encodings, so if mask == 0, + // we should reject this as an invalid instruction. + if (slice(insn, 19, 16) == 0) + return false; MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ | slice(insn, 19, 16) /* Special Reg */ )); // SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0. @@ -760,11 +868,11 @@ static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } - assert((Opcode == ARM::Bcc || Opcode == ARM::BLr9 || Opcode == ARM::BLr9_pred + assert((Opcode == ARM::Bcc || Opcode == ARM::BL || Opcode == ARM::BL_pred || Opcode == ARM::SMC || Opcode == ARM::SVC) && "Unexpected Opcode"); - assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Reg operand expected"); + assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected"); int Imm32 = 0; if (Opcode == ARM::SMC) { @@ -778,12 +886,6 @@ static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned Imm26 = slice(insn, 23, 0) << 2; //Imm32 = signextend(Imm26); Imm32 = SignExtend32<26>(Imm26); - - // When executing an ARM instruction, PC reads as the address of the current - // instruction plus 8. The assembler subtracts 8 from the difference - // between the branch instruction and the target address, disassembler has - // to add 8 to compensate. - Imm32 += 8; } MI.addOperand(MCOperand::CreateImm(Imm32)); @@ -793,7 +895,7 @@ static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn, } // Misc. Branch Instructions. -// BLXr9, BXr9 +// BLX, BLXi, BX // BX, BX_RET static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { @@ -809,8 +911,9 @@ static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR) return true; - // BLXr9 and BX take one GPR reg. - if (Opcode == ARM::BLXr9 || Opcode == ARM::BX) { + // BLX and BX take one GPR reg. + if (Opcode == ARM::BLX || Opcode == ARM::BLX_pred || + Opcode == ARM::BX) { assert(NumOps >= 1 && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && "Reg operand expected"); MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, @@ -819,6 +922,17 @@ static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } + // BLXi takes imm32 (the PC offset). + if (Opcode == ARM::BLXi) { + assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected"); + // SignExtend(imm24:H:'0', 32) where imm24 = Inst{23-0} and H = Inst{24}. + unsigned Imm26 = slice(insn, 23, 0) << 2 | slice(insn, 24, 24) << 1; + int Imm32 = SignExtend32<26>(Imm26); + MI.addOperand(MCOperand::CreateImm(Imm32)); + OpIdx = 1; + return true; + } + return false; } @@ -837,6 +951,24 @@ static inline bool getBFCInvMask(uint32_t insn, uint32_t &mask) { return true; } +// Standard data-processing instructions allow PC as a register specifier, +// but we should reject other DPFrm instructions with PC as registers. +static bool BadRegsDPFrm(unsigned Opcode, uint32_t insn) { + switch (Opcode) { + default: + // Did we miss an opcode? + if (decodeRd(insn) == 15 || decodeRn(insn) == 15 || decodeRm(insn) == 15) { + DEBUG(errs() << "DPFrm with bad reg specifier(s)\n"); + return true; + } + case ARM::ADCrr: case ARM::ADDSrr: case ARM::ADDrr: case ARM::ANDrr: + case ARM::BICrr: case ARM::CMNzrr: case ARM::CMPrr: case ARM::EORrr: + case ARM::ORRrr: case ARM::RSBrr: case ARM::RSCrr: case ARM::SBCrr: + case ARM::SUBSrr: case ARM::SUBrr: case ARM::TEQrr: case ARM::TSTrr: + return false; + } +} + // A major complication is the fact that some of the saturating add/subtract // operations have Rd Rm Rn, instead of the "normal" Rd Rn Rm. // They are QADD, QDADD, QDSUB, and QSUB. @@ -864,6 +996,10 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // Special-case handling of BFC/BFI/SBFX/UBFX. if (Opcode == ARM::BFC || Opcode == ARM::BFI) { + // A8.6.17 BFC & A8.6.18 BFI + // Sanity check Rd. + if (decodeRd(insn) == 15) + return false; MI.addOperand(MCOperand::CreateReg(0)); if (Opcode == ARM::BFI) { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, @@ -879,6 +1015,9 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } if (Opcode == ARM::SBFX || Opcode == ARM::UBFX) { + // Sanity check Rd and Rm. + if (decodeRd(insn) == 15 || decodeRm(insn) == 15) + return false; MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRm(insn)))); MI.addOperand(MCOperand::CreateImm(slice(insn, 11, 7))); @@ -915,15 +1054,21 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // Assert disabled because saturating operations, e.g., A8.6.127 QASX, are // routed here as well. // assert(getIBit(insn) == 0 && "I_Bit != '0' reg/reg form"); + if (BadRegsDPFrm(Opcode, insn)) + return false; MI.addOperand(MCOperand::CreateReg( getRegisterEnum(B, ARM::GPRRegClassID, RmRn? decodeRn(insn) : decodeRm(insn)))); ++OpIdx; } else if (Opcode == ARM::MOVi16 || Opcode == ARM::MOVTi16) { + // These two instructions don't allow d as 15. + if (decodeRd(insn) == 15) + return false; // We have an imm16 = imm4:imm12 (imm4=Inst{19:16}, imm12 = Inst{11:0}). assert(getIBit(insn) == 1 && "I_Bit != '1' reg/imm form"); unsigned Imm16 = slice(insn, 19, 16) << 12 | slice(insn, 11, 0); - MI.addOperand(MCOperand::CreateImm(Imm16)); + if (!B->tryAddingSymbolicOperand(Imm16, 4, MI)) + MI.addOperand(MCOperand::CreateImm(Imm16)); ++OpIdx; } else { // We have a reg/imm form. @@ -992,6 +1137,21 @@ static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRm(insn)))); if (Rs) { + // If Inst{7} != 0, we should reject this insn as an invalid encoding. + if (slice(insn, 7, 7)) + return false; + + // A8.6.3 ADC (register-shifted register) + // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; + // + // This also accounts for shift instructions (register) where, fortunately, + // Inst{19-16} = 0b0000. + // A8.6.89 LSL (register) + // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; + if (decodeRd(insn) == 15 || decodeRn(insn) == 15 || + decodeRm(insn) == 15 || decodeRs(insn) == 15) + return false; + // Register-controlled shifts: [Rm, Rs, shift]. MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRs(insn)))); @@ -1015,6 +1175,71 @@ static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } +static bool BadRegsLdStFrm(unsigned Opcode, uint32_t insn, bool Store, bool WBack, + bool Imm) { + const StringRef Name = ARMInsts[Opcode].Name; + unsigned Rt = decodeRd(insn); + unsigned Rn = decodeRn(insn); + unsigned Rm = decodeRm(insn); + unsigned P = getPBit(insn); + unsigned W = getWBit(insn); + + if (Store) { + // Only STR (immediate, register) allows PC as the source. + if (Name.startswith("STRB") && Rt == 15) { + DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n"); + return true; + } + if (WBack && (Rn == 15 || Rn == Rt)) { + DEBUG(errs() << "if wback && (n == 15 || n == t) then UNPREDICTABLE\n"); + return true; + } + if (!Imm && Rm == 15) { + DEBUG(errs() << "if m == 15 then UNPREDICTABLE\n"); + return true; + } + } else { + // Only LDR (immediate, register) allows PC as the destination. + if (Name.startswith("LDRB") && Rt == 15) { + DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n"); + return true; + } + if (Imm) { + // Immediate + if (Rn == 15) { + // The literal form must be in offset mode; it's an encoding error + // otherwise. + if (!(P == 1 && W == 0)) { + DEBUG(errs() << "Ld literal form with !(P == 1 && W == 0)\n"); + return true; + } + // LDRB (literal) does not allow PC as the destination. + if (Opcode != ARM::LDRi12 && Rt == 15) { + DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n"); + return true; + } + } else { + // Write back while Rn == Rt does not make sense. + if (WBack && (Rn == Rt)) { + DEBUG(errs() << "if wback && n == t then UNPREDICTABLE\n"); + return true; + } + } + } else { + // Register + if (Rm == 15) { + DEBUG(errs() << "if m == 15 then UNPREDICTABLE\n"); + return true; + } + if (WBack && (Rn == 15 || Rn == Rt)) { + DEBUG(errs() << "if wback && (n == 15 || n == t) then UNPREDICTABLE\n"); + return true; + } + } + } + return false; +} + static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) { @@ -1077,19 +1302,41 @@ static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, if (OpIdx + 1 >= NumOps) return false; - assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) && - (OpInfo[OpIdx+1].RegClass < 0) && - "Expect 1 reg operand followed by 1 imm operand"); + if (BadRegsLdStFrm(Opcode, insn, isStore, isPrePost, getIBit(insn)==0)) + return false; ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; + unsigned IndexMode = + (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; if (getIBit(insn) == 0) { - MI.addOperand(MCOperand::CreateReg(0)); + // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2). + // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already + // been populated. + if (isPrePost) { + MI.addOperand(MCOperand::CreateReg(0)); + OpIdx += 1; + } - // Disassemble the 12-bit immediate offset. unsigned Imm12 = slice(insn, 11, 0); - unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift); - MI.addOperand(MCOperand::CreateImm(Offset)); + if (Opcode == ARM::LDRBi12 || Opcode == ARM::LDRi12 || + Opcode == ARM::STRBi12 || Opcode == ARM::STRi12) { + // Disassemble the 12-bit immediate offset, which is the second operand in + // $addrmode_imm12 => (ops GPR:$base, i32imm:$offsimm). + int Offset = AddrOpcode == ARM_AM::add ? 1 * Imm12 : -1 * Imm12; + MI.addOperand(MCOperand::CreateImm(Offset)); + } else { + // Disassemble the 12-bit immediate offset, which is the second operand in + // $am2offset => (ops GPR, i32imm). + unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift, + IndexMode); + MI.addOperand(MCOperand::CreateImm(Offset)); + } + OpIdx += 1; } else { + // If Inst{25} = 1 and Inst{4} != 0, we should reject this as invalid. + if (slice(insn,4,4) == 1) + return false; + // Disassemble the offset reg (Rm), shift type, and immediate shift length. MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRm(insn)))); @@ -1101,9 +1348,9 @@ static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // A8.4.1. Possible rrx or shift amount of 32... getImmShiftSE(ShOp, ShImm); MI.addOperand(MCOperand::CreateImm( - ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp))); + ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp, IndexMode))); + OpIdx += 2; } - OpIdx += 2; return true; } @@ -1125,7 +1372,7 @@ static bool HasDualReg(unsigned Opcode) { case ARM::LDRD: case ARM::LDRD_PRE: case ARM::LDRD_POST: case ARM::STRD: case ARM::STRD_PRE: case ARM::STRD_POST: return true; - } + } } static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, @@ -1153,8 +1400,6 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, ++OpIdx; } - bool DualReg = HasDualReg(Opcode); - // Disassemble the dst/src operand. if (OpIdx >= NumOps) return false; @@ -1165,8 +1410,8 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, decodeRd(insn)))); ++OpIdx; - // Fill in LDRD and STRD's second operand. - if (DualReg) { + // Fill in LDRD and STRD's second operand Rt operand. + if (HasDualReg(Opcode)) { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRd(insn) + 1))); ++OpIdx; @@ -1188,7 +1433,7 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && "Reg operand expected"); assert((!isPrePost || (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1)) - && "Index mode or tied_to operand expected"); + && "Offset mode or tied_to operand expected"); MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)))); ++OpIdx; @@ -1204,19 +1449,22 @@ static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, "Expect 1 reg operand followed by 1 imm operand"); ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; + unsigned IndexMode = + (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; if (getAM3IBit(insn) == 1) { MI.addOperand(MCOperand::CreateReg(0)); // Disassemble the 8-bit immediate offset. unsigned Imm4H = (insn >> ARMII::ImmHiShift) & 0xF; unsigned Imm4L = insn & 0xF; - unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L); + unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L, + IndexMode); MI.addOperand(MCOperand::CreateImm(Offset)); } else { // Disassemble the offset reg (Rm). MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRm(insn)))); - unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0); + unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0, IndexMode); MI.addOperand(MCOperand::CreateImm(Offset)); } OpIdx += 2; @@ -1236,13 +1484,13 @@ static bool DisassembleStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, } // The algorithm for disassembly of LdStMulFrm is different from others because -// it explicitly populates the two predicate operands after operand 0 (the base) -// and operand 1 (the AM4 mode imm). After operand 3, we need to populate the -// reglist with each affected register encoded as an MCOperand. +// it explicitly populates the two predicate operands after the base register. +// After that, we need to populate the reglist with each affected register +// encoded as an MCOperand. static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - assert(NumOps >= 5 && "LdStMulFrm expects NumOps >= 5"); + assert(NumOps >= 4 && "LdStMulFrm expects NumOps >= 4"); NumOpsAdded = 0; unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)); @@ -1260,8 +1508,10 @@ static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, MI.addOperand(MCOperand::CreateReg(Base)); // Handling the two predicate operands before the reglist. - int64_t CondVal = insn >> ARMII::CondShift; - MI.addOperand(MCOperand::CreateImm(CondVal == 0xF ? 0xE : CondVal)); + int64_t CondVal = getCondField(insn); + if (CondVal == 0xF) + return false; + MI.addOperand(MCOperand::CreateImm(CondVal)); MI.addOperand(MCOperand::CreateReg(ARM::CPSR)); NumOpsAdded += 3; @@ -1352,6 +1602,12 @@ static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID; + // Sanity check the registers, which should not be 15. + if (decodeRd(insn) == 15 || decodeRm(insn) == 15) + return false; + if (ThreeReg && decodeRn(insn) == 15) + return false; + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRd(insn)))); ++OpIdx; @@ -1376,7 +1632,7 @@ static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, ARM_AM::ShiftOpc Opc = ARM_AM::no_shift; if (Opcode == ARM::PKHBT) Opc = ARM_AM::lsl; - else if (Opcode == ARM::PKHBT) + else if (Opcode == ARM::PKHTB) Opc = ARM_AM::asr; getImmShiftSE(Opc, ShiftAmt); MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(Opc, ShiftAmt))); @@ -1391,6 +1647,11 @@ static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { + // A8.6.183 SSAT + // if d == 15 || n == 15 then UNPREDICTABLE; + if (decodeRd(insn) == 15 || decodeRm(insn) == 15) + return false; + const TargetInstrDesc &TID = ARMInsts[Opcode]; NumOpsAdded = TID.getNumOperands() - 2; // ignore predicate operands @@ -1429,6 +1690,11 @@ static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleExtFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { + // A8.6.220 SXTAB + // if d == 15 || m == 15 then UNPREDICTABLE; + if (decodeRd(insn) == 15 || decodeRm(insn) == 15) + return false; + const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; unsigned &OpIdx = NumOpsAdded; @@ -1611,7 +1877,7 @@ static bool DisassembleVFPBinaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // A8.6.295 vcvt (floating-point <-> integer) // Int to FP: VSITOD, VSITOS, VUITOD, VUITOS // FP to Int: VTOSI[Z|R]D, VTOSI[Z|R]S, VTOUI[Z|R]D, VTOUI[Z|R]S -// +// // A8.6.297 vcvt (floating-point and fixed-point) // Dd|Sd Dd|Sd(TIED_TO) #fbits(= 16|32 - UInt(imm4:i)) static bool DisassembleVFPConv1Frm(MCInst &MI, unsigned Opcode, uint32_t insn, @@ -1800,15 +2066,14 @@ static bool DisassembleVFPLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, } // VFP Load/Store Multiple Instructions. -// This is similar to the algorithm for LDM/STM in that operand 0 (the base) and -// operand 1 (the AM4 mode imm) is followed by two predicate operands. It is -// followed by a reglist of either DPR(s) or SPR(s). +// We have an optional write back reg, the base, and two predicate operands. +// It is then followed by a reglist of either DPR(s) or SPR(s). // // VLDMD[_UPD], VLDMS[_UPD], VSTMD[_UPD], VSTMS[_UPD] static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - assert(NumOps >= 5 && "VFPLdStMulFrm expects NumOps >= 5"); + assert(NumOps >= 4 && "VFPLdStMulFrm expects NumOps >= 4"); unsigned &OpIdx = NumOpsAdded; @@ -1827,25 +2092,18 @@ static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, MI.addOperand(MCOperand::CreateReg(Base)); - // Next comes the AM4 Opcode. - ARM_AM::AMSubMode SubMode = getAMSubModeForBits(getPUBits(insn)); - // Must be either "ia" or "db" submode. - if (SubMode != ARM_AM::ia && SubMode != ARM_AM::db) { - DEBUG(errs() << "Illegal addressing mode 4 sub-mode!\n"); - return false; - } - MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM4ModeImm(SubMode))); - // Handling the two predicate operands before the reglist. - int64_t CondVal = insn >> ARMII::CondShift; - MI.addOperand(MCOperand::CreateImm(CondVal == 0xF ? 0xE : CondVal)); + int64_t CondVal = getCondField(insn); + if (CondVal == 0xF) + return false; + MI.addOperand(MCOperand::CreateImm(CondVal)); MI.addOperand(MCOperand::CreateReg(ARM::CPSR)); - OpIdx += 4; + OpIdx += 3; - bool isSPVFP = (Opcode == ARM::VLDMSIA || Opcode == ARM::VLDMSDB || + bool isSPVFP = (Opcode == ARM::VLDMSIA || Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMSDB_UPD || - Opcode == ARM::VSTMSIA || Opcode == ARM::VSTMSDB || + Opcode == ARM::VSTMSIA || Opcode == ARM::VSTMSIA_UPD || Opcode == ARM::VSTMSDB_UPD); unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID; @@ -1855,6 +2113,11 @@ static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // Fill the variadic part of reglist. unsigned char Imm8 = insn & 0xFF; unsigned Regs = isSPVFP ? Imm8 : Imm8/2; + + // Apply some sanity checks before proceeding. + if (Regs == 0 || (RegD + Regs) > 32 || (!isSPVFP && Regs > 16)) + return false; + for (unsigned i = 0; i < Regs; ++i) { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, RegD + i))); @@ -2136,7 +2399,7 @@ static unsigned decodeN3VImm(uint32_t insn) { // Correctly set VLD*/VST*'s TIED_TO GPR, as the asm printer needs it. static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool Store, bool DblSpaced, - BO B) { + unsigned alignment, BO B) { const TargetInstrDesc &TID = ARMInsts[Opcode]; const TargetOperandInfo *OpInfo = TID.OpInfo; @@ -2180,9 +2443,10 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected"); + // addrmode6 := (ops GPR:$addr, i32imm) MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, Rn))); - MI.addOperand(MCOperand::CreateImm(0)); // Alignment ignored? + MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment OpIdx += 2; if (WB) { @@ -2230,9 +2494,10 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected"); + // addrmode6 := (ops GPR:$addr, i32imm) MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, Rn))); - MI.addOperand(MCOperand::CreateImm(0)); // Alignment ignored? + MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment OpIdx += 2; if (WB) { @@ -2263,6 +2528,92 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } +// A8.6.308, A8.6.311, A8.6.314, A8.6.317. +static bool Align4OneLaneInst(unsigned elem, unsigned size, + unsigned index_align, unsigned & alignment) { + unsigned bits = 0; + switch (elem) { + default: + return false; + case 1: + // A8.6.308 + if (size == 0) + return slice(index_align, 0, 0) == 0; + else if (size == 1) { + bits = slice(index_align, 1, 0); + if (bits != 0 && bits != 1) + return false; + if (bits == 1) + alignment = 16; + return true; + } else if (size == 2) { + bits = slice(index_align, 2, 0); + if (bits != 0 && bits != 3) + return false; + if (bits == 3) + alignment = 32; + return true;; + } + return true; + case 2: + // A8.6.311 + if (size == 0) { + if (slice(index_align, 0, 0) == 1) + alignment = 16; + return true; + } if (size == 1) { + if (slice(index_align, 0, 0) == 1) + alignment = 32; + return true; + } else if (size == 2) { + if (slice(index_align, 1, 1) != 0) + return false; + if (slice(index_align, 0, 0) == 1) + alignment = 64; + return true;; + } + return true; + case 3: + // A8.6.314 + if (size == 0) { + if (slice(index_align, 0, 0) != 0) + return false; + return true; + } if (size == 1) { + if (slice(index_align, 0, 0) != 0) + return false; + return true; + return true; + } else if (size == 2) { + if (slice(index_align, 1, 0) != 0) + return false; + return true;; + } + return true; + case 4: + // A8.6.317 + if (size == 0) { + if (slice(index_align, 0, 0) == 1) + alignment = 32; + return true; + } if (size == 1) { + if (slice(index_align, 0, 0) == 1) + alignment = 64; + return true; + } else if (size == 2) { + bits = slice(index_align, 1, 0); + if (bits == 3) + return false; + if (bits == 1) + alignment = 64; + else if (bits == 2) + alignment = 128; + return true;; + } + return true; + } +} + // A7.7 // If L (Inst{21}) == 0, store instructions. // Find out about double-spaced-ness of the Opcode and pass it on to @@ -2272,11 +2623,33 @@ static bool DisassembleNLdSt(MCInst &MI, unsigned Opcode, uint32_t insn, const StringRef Name = ARMInsts[Opcode].Name; bool DblSpaced = false; + // 0 represents standard alignment, i.e., unaligned data access. + unsigned alignment = 0; + + unsigned elem = 0; // legal values: {1, 2, 3, 4} + if (Name.startswith("VST1") || Name.startswith("VLD1")) + elem = 1; + + if (Name.startswith("VST2") || Name.startswith("VLD2")) + elem = 2; + + if (Name.startswith("VST3") || Name.startswith("VLD3")) + elem = 3; + + if (Name.startswith("VST4") || Name.startswith("VLD4")) + elem = 4; if (Name.find("LN") != std::string::npos) { // To one lane instructions. // See, for example, 8.6.317 VLD4 (single 4-element structure to one lane). + // Utility function takes number of elements, size, and index_align. + if (!Align4OneLaneInst(elem, + slice(insn, 11, 10), + slice(insn, 7, 4), + alignment)) + return false; + // == 16 && Inst{5} == 1 --> DblSpaced = true if (Name.endswith("16") || Name.endswith("16_UPD")) DblSpaced = slice(insn, 5, 5) == 1; @@ -2284,30 +2657,102 @@ static bool DisassembleNLdSt(MCInst &MI, unsigned Opcode, uint32_t insn, // == 32 && Inst{6} == 1 --> DblSpaced = true if (Name.endswith("32") || Name.endswith("32_UPD")) DblSpaced = slice(insn, 6, 6) == 1; + } else if (Name.find("DUP") != std::string::npos) { + // Single element (or structure) to all lanes. + // Inst{9-8} encodes the number of element(s) in the structure, with: + // 0b00 (VLD1DUP) (for this, a bit makes sense only for data size 16 and 32. + // 0b01 (VLD2DUP) + // 0b10 (VLD3DUP) (for this, a bit must be encoded as 0) + // 0b11 (VLD4DUP) + // + // Inst{7-6} encodes the data size, with: + // 0b00 => 8, 0b01 => 16, 0b10 => 32 + // + // Inst{4} (the a bit) encodes the align action (0: standard alignment) + unsigned elem = slice(insn, 9, 8) + 1; + unsigned a = slice(insn, 4, 4); + if (elem != 3) { + // 0b11 is not a valid encoding for Inst{7-6}. + if (slice(insn, 7, 6) == 3) + return false; + unsigned data_size = 8 << slice(insn, 7, 6); + // For VLD1DUP, a bit makes sense only for data size of 16 and 32. + if (a && data_size == 8) + return false; + // Now we can calculate the alignment! + if (a) + alignment = elem * data_size; + } else { + if (a) { + // A8.6.315 VLD3 (single 3-element structure to all lanes) + // The a bit must be encoded as 0. + return false; + } + } } else { // Multiple n-element structures with type encoded as Inst{11-8}. // See, for example, A8.6.316 VLD4 (multiple 4-element structures). - // n == 2 && type == 0b1001 -> DblSpaced = true - if (Name.startswith("VST2") || Name.startswith("VLD2")) - DblSpaced = slice(insn, 11, 8) == 9; - - // n == 3 && type == 0b0101 -> DblSpaced = true - if (Name.startswith("VST3") || Name.startswith("VLD3")) - DblSpaced = slice(insn, 11, 8) == 5; - - // n == 4 && type == 0b0001 -> DblSpaced = true - if (Name.startswith("VST4") || Name.startswith("VLD4")) - DblSpaced = slice(insn, 11, 8) == 1; - + // Inst{5-4} encodes alignment. + unsigned align = slice(insn, 5, 4); + switch (align) { + default: + break; + case 1: + alignment = 64; break; + case 2: + alignment = 128; break; + case 3: + alignment = 256; break; + } + + unsigned type = slice(insn, 11, 8); + // Reject UNDEFINED instructions based on type and align. + // Plus set DblSpaced flag where appropriate. + switch (elem) { + default: + break; + case 1: + // n == 1 + // A8.6.307 & A8.6.391 + if ((type == 7 && slice(align, 1, 1) == 1) || + (type == 10 && align == 3) || + (type == 6 && slice(align, 1, 1) == 1)) + return false; + break; + case 2: + // n == 2 && type == 0b1001 -> DblSpaced = true + // A8.6.310 & A8.6.393 + if ((type == 8 || type == 9) && align == 3) + return false; + DblSpaced = (type == 9); + break; + case 3: + // n == 3 && type == 0b0101 -> DblSpaced = true + // A8.6.313 & A8.6.395 + if (slice(insn, 7, 6) == 3 || slice(align, 1, 1) == 1) + return false; + DblSpaced = (type == 5); + break; + case 4: + // n == 4 && type == 0b0001 -> DblSpaced = true + // A8.6.316 & A8.6.397 + if (slice(insn, 7, 6) == 3) + return false; + DblSpaced = (type == 1); + break; + } } return DisassembleNLdSt0(MI, Opcode, insn, NumOps, NumOpsAdded, - slice(insn, 21, 21) == 0, DblSpaced, B); + slice(insn, 21, 21) == 0, DblSpaced, alignment/8, B); } // VMOV (immediate) // Qd/Dd imm +// VBIC (immediate) +// VORR (immediate) +// Qd/Dd imm src(=Qd/Dd) static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { @@ -2334,12 +2779,20 @@ static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode, case ARM::VMOVv8i16: case ARM::VMVNv4i16: case ARM::VMVNv8i16: + case ARM::VBICiv4i16: + case ARM::VBICiv8i16: + case ARM::VORRiv4i16: + case ARM::VORRiv8i16: esize = ESize16; break; case ARM::VMOVv2i32: case ARM::VMOVv4i32: case ARM::VMVNv2i32: case ARM::VMVNv4i32: + case ARM::VBICiv2i32: + case ARM::VBICiv4i32: + case ARM::VORRiv2i32: + case ARM::VORRiv4i32: esize = ESize32; break; case ARM::VMOVv1i64: @@ -2347,7 +2800,7 @@ static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode, esize = ESize64; break; default: - assert(0 && "Unreachable code!"); + assert(0 && "Unexpected opcode!"); return false; } @@ -2356,6 +2809,16 @@ static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode, MI.addOperand(MCOperand::CreateImm(decodeN1VImm(insn, esize))); NumOpsAdded = 2; + + // VBIC/VORRiv*i* variants have an extra $src = $Vd to be filled in. + if (NumOps >= 3 && + (OpInfo[2].RegClass == ARM::DPRRegClassID || + OpInfo[2].RegClass == ARM::QPRRegClassID)) { + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass, + decodeNEONRd(insn)))); + NumOpsAdded += 1; + } + return true; } @@ -2376,7 +2839,7 @@ enum N2VFlag { // // Vector Move Long: // Qd Dm -// +// // Vector Move Narrow: // Dd Qm // @@ -2518,7 +2981,7 @@ static bool DisassembleNVectorShift(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpInfo[OpIdx].RegClass < 0 && "Imm operand expected"); // Add the imm operand. - + // VSHLL has maximum shift count as the imm, inferred from its size. unsigned Imm; switch (Opcode) { @@ -2631,7 +3094,7 @@ static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn, // N3RegFrm. if (Opcode == ARM::VMOVDneon || Opcode == ARM::VMOVQ) return true; - + // Dm = Inst{5:3-0} => NEON Rm // or // Dm is restricted to D0-D7 if size is 16, D0-D15 otherwise @@ -2770,7 +3233,7 @@ static bool DisassembleNGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, ElemSize esize = Opcode == ARM::VGETLNi32 ? ESize32 : ((Opcode == ARM::VGETLNs16 || Opcode == ARM::VGETLNu16) ? ESize16 - : ESize32); + : ESize8); // Rt = Inst{15-12} => ARM Rd MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, @@ -2852,17 +3315,6 @@ static bool DisassembleNDupFrm(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } -// A8.6.41 DMB -// A8.6.42 DSB -// A8.6.49 ISB -static inline bool MemBarrierInstr(uint32_t insn) { - unsigned op7_4 = slice(insn, 7, 4); - if (slice(insn, 31, 8) == 0xf57ff0 && (op7_4 >= 4 && op7_4 <= 6)) - return true; - - return false; -} - static inline bool PreLoadOpcode(unsigned Opcode) { switch(Opcode) { case ARM::PLDi12: case ARM::PLDrs: @@ -2878,8 +3330,8 @@ static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { // Preload Data/Instruction requires either 2 or 3 operands. - // PLDi, PLDWi, PLIi: addrmode_imm12 - // PLDr[a|m], PLDWr[a|m], PLIr[a|m]: ldst_so_reg + // PLDi12, PLDWi12, PLIi12: addrmode_imm12 + // PLDrs, PLDWrs, PLIrs: ldst_so_reg MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)))); @@ -2888,10 +3340,19 @@ static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn, || Opcode == ARM::PLIi12) { unsigned Imm12 = slice(insn, 11, 0); bool Negative = getUBit(insn) == 0; + + // A8.6.118 PLD (literal) PLDWi12 with Rn=PC is transformed to PLDi12. + if (Opcode == ARM::PLDWi12 && slice(insn, 19, 16) == 0xF) { + DEBUG(errs() << "Rn == '1111': PLDWi12 morphed to PLDi12\n"); + MI.setOpcode(ARM::PLDi12); + } + // -0 is represented specially. All other values are as normal. + int Offset = Negative ? -1 * Imm12 : Imm12; if (Imm12 == 0 && Negative) - Imm12 = INT32_MIN; - MI.addOperand(MCOperand::CreateImm(Imm12)); + Offset = INT32_MIN; + + MI.addOperand(MCOperand::CreateImm(Offset)); NumOpsAdded = 2; } else { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, @@ -2917,14 +3378,20 @@ static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - if (MemBarrierInstr(insn)) { - // DMBsy, DSBsy, and ISBsy instructions have zero operand and are taken care - // of within the generic ARMBasicMCBuilder::BuildIt() method. - // + if (Opcode == ARM::DMB || Opcode == ARM::DSB) { // Inst{3-0} encodes the memory barrier option for the variants. - MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0))); - NumOpsAdded = 1; - return true; + unsigned opt = slice(insn, 3, 0); + switch (opt) { + case ARM_MB::SY: case ARM_MB::ST: + case ARM_MB::ISH: case ARM_MB::ISHST: + case ARM_MB::NSH: case ARM_MB::NSHST: + case ARM_MB::OSH: case ARM_MB::OSHST: + MI.addOperand(MCOperand::CreateImm(opt)); + NumOpsAdded = 1; + return true; + default: + return false; + } } switch (Opcode) { @@ -2936,6 +3403,11 @@ static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, case ARM::WFI: case ARM::SEV: return true; + case ARM::SWP: + case ARM::SWPB: + // SWP, SWPB: Rd Rm Rn + // Delegate to DisassembleLdStExFrm().... + return DisassembleLdStExFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B); default: break; } @@ -2950,20 +3422,32 @@ static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // opcodes which match the same real instruction. This is needed since there's // no current handling of optional arguments. Fix here when a better handling // of optional arguments is implemented. - if (Opcode == ARM::CPS3p) { + if (Opcode == ARM::CPS3p) { // M = 1 + // Let's reject these impossible imod values by returning false: + // 1. (imod=0b01) + // + // AsmPrinter cannot handle imod=0b00, plus (imod=0b00,M=1,iflags!=0) is an + // invalid combination, so we just check for imod=0b00 here. + if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1) + return false; MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode NumOpsAdded = 3; return true; } - if (Opcode == ARM::CPS2p) { + if (Opcode == ARM::CPS2p) { // mode = 0, M = 0 + // Let's reject these impossible imod values by returning false: + // 1. (imod=0b00,M=0) + // 2. (imod=0b01) + if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1) + return false; MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags NumOpsAdded = 2; return true; } - if (Opcode == ARM::CPS1p) { + if (Opcode == ARM::CPS1p) { // imod = 0, iflags = 0, M = 1 MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode NumOpsAdded = 1; return true; @@ -3142,7 +3626,7 @@ bool ARMBasicMCBuilder::DoPredicateOperands(MCInst& MI, unsigned Opcode, return false; } - + /// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process /// the possible Predicate and SBitModifier, to build the remaining MCOperand /// constituents. @@ -3154,6 +3638,7 @@ bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode, const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; const std::string &Name = ARMInsts[Opcode].Name; unsigned Idx = MI.getNumOperands(); + uint64_t TSFlags = ARMInsts[Opcode].TSFlags; // First, we check whether this instr specifies the PredicateOperand through // a pair of TargetOperandInfos with isPredicate() property. @@ -3173,14 +3658,23 @@ bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode, // like ARM. // // A8.6.16 B - if (Name == "t2Bcc") - MI.addOperand(MCOperand::CreateImm(CondCode(slice(insn, 25, 22)))); - else if (Name == "tBcc") - MI.addOperand(MCOperand::CreateImm(CondCode(slice(insn, 11, 8)))); - else + // Check for undefined encodings. + unsigned cond; + if (Name == "t2Bcc") { + if ((cond = slice(insn, 25, 22)) >= 14) + return false; + MI.addOperand(MCOperand::CreateImm(CondCode(cond))); + } else if (Name == "tBcc") { + if ((cond = slice(insn, 11, 8)) == 14) + return false; + MI.addOperand(MCOperand::CreateImm(CondCode(cond))); + } else MI.addOperand(MCOperand::CreateImm(ARMCC::AL)); } else { // ARM instructions get their condition field from Inst{31-28}. + // We should reject Inst{31-28} = 0b1111 as invalid encoding. + if (!isNEONDomain(TSFlags) && getCondField(insn) == 0xF) + return false; MI.addOperand(MCOperand::CreateImm(CondCode(getCondField(insn)))); } } @@ -3243,3 +3737,84 @@ ARMBasicMCBuilder *llvm::CreateMCBuilder(unsigned Opcode, ARMFormat Format) { return new ARMBasicMCBuilder(Opcode, Format, ARMInsts[Opcode].getNumOperands()); } + +/// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic +/// operand in place of the immediate Value in the MCInst. The immediate +/// Value has had any PC adjustment made by the caller. If the getOpInfo() +/// function was set as part of the setupBuilderForSymbolicDisassembly() call +/// then that function is called to get any symbolic information at the +/// builder's Address for this instrution. If that returns non-zero then the +/// symbolic information it returns is used to create an MCExpr and that is +/// added as an operand to the MCInst. This function returns true if it adds +/// an operand to the MCInst and false otherwise. +bool ARMBasicMCBuilder::tryAddingSymbolicOperand(uint64_t Value, + uint64_t InstSize, + MCInst &MI) { + if (!GetOpInfo) + return false; + + struct LLVMOpInfo1 SymbolicOp; + SymbolicOp.Value = Value; + if (!GetOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp)) + return false; + + const MCExpr *Add = NULL; + if (SymbolicOp.AddSymbol.Present) { + if (SymbolicOp.AddSymbol.Name) { + StringRef Name(SymbolicOp.AddSymbol.Name); + MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name); + Add = MCSymbolRefExpr::Create(Sym, *Ctx); + } else { + Add = MCConstantExpr::Create(SymbolicOp.AddSymbol.Value, *Ctx); + } + } + + const MCExpr *Sub = NULL; + if (SymbolicOp.SubtractSymbol.Present) { + if (SymbolicOp.SubtractSymbol.Name) { + StringRef Name(SymbolicOp.SubtractSymbol.Name); + MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name); + Sub = MCSymbolRefExpr::Create(Sym, *Ctx); + } else { + Sub = MCConstantExpr::Create(SymbolicOp.SubtractSymbol.Value, *Ctx); + } + } + + const MCExpr *Off = NULL; + if (SymbolicOp.Value != 0) + Off = MCConstantExpr::Create(SymbolicOp.Value, *Ctx); + + const MCExpr *Expr; + if (Sub) { + const MCExpr *LHS; + if (Add) + LHS = MCBinaryExpr::CreateSub(Add, Sub, *Ctx); + else + LHS = MCUnaryExpr::CreateMinus(Sub, *Ctx); + if (Off != 0) + Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx); + else + Expr = LHS; + } else if (Add) { + if (Off != 0) + Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx); + else + Expr = Add; + } else { + if (Off != 0) + Expr = Off; + else + Expr = MCConstantExpr::Create(0, *Ctx); + } + + if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_HI16) + MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateUpper16(Expr, *Ctx))); + else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_LO16) + MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateLower16(Expr, *Ctx))); + else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_None) + MI.addOperand(MCOperand::CreateExpr(Expr)); + else + assert("bad SymbolicOp.VariantKind"); + + return true; +} diff --git a/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h b/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h index 9c30d332d1f2..a7ba14141c0a 100644 --- a/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h +++ b/contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h @@ -22,12 +22,17 @@ #define ARMDISASSEMBLERCORE_H #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCContext.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm-c/Disassembler.h" #include "ARMBaseInstrInfo.h" #include "ARMRegisterInfo.h" #include "ARMDisassembler.h" namespace llvm { +class MCContext; class ARMUtils { public: @@ -134,6 +139,31 @@ static inline void setSlice(unsigned &Bits, unsigned From, unsigned To, Bits |= (Val & Mask) << To; } +// Return an integer result equal to the number of bits of x that are ones. +static inline uint32_t +BitCount (uint64_t x) +{ + // c accumulates the total bits set in x + uint32_t c; + for (c = 0; x; ++c) + { + x &= x - 1; // clear the least significant bit set + } + return c; +} + +static inline bool +BitIsSet (const uint64_t value, const uint64_t bit) +{ + return (value & (1ull << bit)) != 0; +} + +static inline bool +BitIsClear (const uint64_t value, const uint64_t bit) +{ + return (value & (1ull << bit)) == 0; +} + /// Various utilities for checking the target specific flags. /// A unary data processing instruction doesn't have an Rn operand. @@ -141,6 +171,12 @@ static inline bool isUnaryDP(uint64_t TSFlags) { return (TSFlags & ARMII::UnaryDP); } +/// A NEON Domain instruction has cond field (Inst{31-28}) as 0b1111. +static inline bool isNEONDomain(uint64_t TSFlags) { + return (TSFlags & ARMII::DomainNEON) || + (TSFlags & ARMII::DomainNEONA8); +} + /// This four-bit field describes the addressing mode used. /// See also ARMBaseInstrInfo.h. static inline unsigned getAddrMode(uint64_t TSFlags) { @@ -196,7 +232,7 @@ class ARMBasicMCBuilder { public: ARMBasicMCBuilder(ARMBasicMCBuilder &B) : Opcode(B.Opcode), Format(B.Format), NumOps(B.NumOps), Disasm(B.Disasm), - SP(B.SP) { + SP(B.SP), GetOpInfo(0), DisInfo(0), Ctx(0) { Err = 0; } @@ -255,6 +291,44 @@ class ARMBasicMCBuilder { assert(SP); return slice(SP->ITState, 7, 4); } + +private: + // + // Hooks for symbolic disassembly via the public 'C' interface. + // + // The function to get the symbolic information for operands. + LLVMOpInfoCallback GetOpInfo; + // The pointer to the block of symbolic information for above call back. + void *DisInfo; + // The assembly context for creating symbols and MCExprs in place of + // immediate operands when there is symbolic information. + MCContext *Ctx; + // The address of the instruction being disassembled. + uint64_t Address; + +public: + void setupBuilderForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo, + void *disInfo, MCContext *ctx, + uint64_t address) { + GetOpInfo = getOpInfo; + DisInfo = disInfo; + Ctx = ctx; + Address = address; + } + + uint64_t getBuilderAddress() const { return Address; } + + /// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic + /// operand in place of the immediate Value in the MCInst. The immediate + /// Value has had any PC adjustment made by the caller. If the getOpInfo() + /// function was set as part of the setupBuilderForSymbolicDisassembly() call + /// then that function is called to get any symbolic information at the + /// builder's Address for this instrution. If that returns non-zero then the + /// symbolic information it returns is used to create an MCExpr and that is + /// added as an operand to the MCInst. This function returns true if it adds + /// an operand to the MCInst and false otherwise. + bool tryAddingSymbolicOperand(uint64_t Value, uint64_t InstSize, MCInst &MI); + }; } // namespace llvm diff --git a/contrib/llvm/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/contrib/llvm/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index 23372e022414..8d39982f5640 100644 --- a/contrib/llvm/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/contrib/llvm/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -108,6 +108,8 @@ static inline bool IsGPR(unsigned RegClass) { // Utilities for 32-bit Thumb instructions. +static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; } + // Extract imm4: Inst{19-16}. static inline unsigned getImm4(uint32_t insn) { return slice(insn, 19, 16); @@ -398,9 +400,17 @@ static bool DisassembleThumb1General(MCInst &MI, unsigned Opcode, uint32_t insn, assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef() && "Pure imm operand expected"); - MI.addOperand(MCOperand::CreateImm(UseRt ? getT1Imm8(insn) - : (Imm3 ? getT1Imm3(insn) - : getT1Imm5(insn)))); + unsigned Imm = 0; + if (UseRt) + Imm = getT1Imm8(insn); + else if (Imm3) + Imm = getT1Imm3(insn); + else { + Imm = getT1Imm5(insn); + ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 12, 11)); + getImmShiftSE(ShOp, Imm); + } + MI.addOperand(MCOperand::CreateImm(Imm)); } ++OpIdx; @@ -469,6 +479,7 @@ static bool DisassembleThumb1DP(MCInst &MI, unsigned Opcode, uint32_t insn, // tBX_RET: 0 operand // tBX_RET_vararg: Rm // tBLXr_r9: Rm +// tBRIND: Rm static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { @@ -476,11 +487,17 @@ static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, if (NumOps == 0) return true; - // BX/BLX has 1 reg operand: Rm. - if (NumOps == 1) { + // BX/BLX/tBRIND (indirect branch, i.e, mov pc, Rm) has 1 reg operand: Rm. + if (Opcode==ARM::tBLXr_r9 || Opcode==ARM::tBX_Rm || Opcode==ARM::tBRIND) { + if (Opcode != ARM::tBRIND) { + // Handling the two predicate operands before the reg operand. + if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps)) + return false; + NumOpsAdded += 2; + } MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, getT1Rm(insn)))); - NumOpsAdded = 1; + NumOpsAdded += 1; return true; } @@ -598,7 +615,7 @@ static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode, // A6.2.4 Load/store single data item // -// Load/Store Register (reg|imm): tRd tRn imm5 tRm +// Load/Store Register (reg|imm): tRd tRn imm5|tRm // Load Register Signed Byte|Halfword: tRd tRn tRm static bool DisassembleThumb1LdSt(unsigned opA, MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { @@ -607,11 +624,6 @@ static bool DisassembleThumb1LdSt(unsigned opA, MCInst &MI, unsigned Opcode, const TargetOperandInfo *OpInfo = TID.OpInfo; unsigned &OpIdx = NumOpsAdded; - // Table A6-5 16-bit Thumb Load/store instructions - // opA = 0b0101 for STR/LDR (register) and friends. - // Otherwise, we have STR/LDR (immediate) and friends. - bool Imm5 = (opA != 5); - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID && OpInfo[1].RegClass == ARM::tGPRRegClassID @@ -624,28 +636,28 @@ static bool DisassembleThumb1LdSt(unsigned opA, MCInst &MI, unsigned Opcode, getT1tRn(insn)))); OpIdx = 2; - // We have either { imm5, tRm } or { tRm } remaining. - // Process the imm5 first. Note that STR/LDR (register) should skip the imm5 - // offset operand for t_addrmode_s[1|2|4]. + // We have either { imm5 } or { tRm } remaining. + // Note that STR/LDR (register) should skip the imm5 offset operand for + // t_addrmode_s[1|2|4]. assert(OpIdx < NumOps && "More operands expected"); if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - - MI.addOperand(MCOperand::CreateImm(Imm5 ? getT1Imm5(insn) : 0)); + // Table A6-5 16-bit Thumb Load/store instructions + // opA = 0b0101 for STR/LDR (register) and friends. + // Otherwise, we have STR/LDR (immediate) and friends. + assert(opA != 5 && "Immediate operand expected for this opcode"); + MI.addOperand(MCOperand::CreateImm(getT1Imm5(insn))); + ++OpIdx; + } else { + // The next reg operand is tRm, the offset. + assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID + && "Thumb reg operand expected"); + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, + getT1tRm(insn)))); ++OpIdx; } - - // The next reg operand is tRm, the offset. - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID - && "Thumb reg operand expected"); - MI.addOperand(MCOperand::CreateReg( - Imm5 ? 0 - : getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRm(insn)))); - ++OpIdx; - return true; } @@ -895,6 +907,10 @@ static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode, } unsigned RegListBits = slice(insn, 7, 0); + if (BitCount(RegListBits) < 1) { + DEBUG(errs() << "if BitCount(registers) < 1 then UNPREDICTABLE\n"); + return false; + } // Fill the variadic part of reglist. for (unsigned i = 0; i < 8; ++i) @@ -945,6 +961,11 @@ static bool DisassembleThumb1CondBr(MCInst &MI, unsigned Opcode, uint32_t insn, : (int)Imm8)); // Predicate operands by ARMBasicMCBuilder::TryPredicateAndSBitModifier(). + // But note that for tBcc, if cond = '1110' then UNDEFINED. + if (Opcode == ARM::tBcc && slice(insn, 11, 8) == 14) { + DEBUG(errs() << "if cond = '1110' then UNDEFINED\n"); + return false; + } NumOpsAdded = 1; return true; @@ -965,11 +986,7 @@ static bool DisassembleThumb1Br(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned Imm11 = getT1Imm11(insn); - // When executing a Thumb instruction, PC reads as the address of the current - // instruction plus 4. The assembler subtracts 4 from the difference between - // the branch instruction and the target address, disassembler has to add 4 to - // to compensate. - MI.addOperand(MCOperand::CreateImm(SignExtend32<12>(Imm11 << 1) + 4)); + MI.addOperand(MCOperand::CreateImm(SignExtend32<12>(Imm11 << 1))); NumOpsAdded = 1; @@ -1129,8 +1146,12 @@ static bool DisassembleThumb2SRS(MCInst &MI, unsigned Opcode, uint32_t insn, // t2RFE[IA|DB]W/t2RFE[IA|DB]: Rn static bool DisassembleThumb2RFE(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); + unsigned Rn = decodeRn(insn); + if (Rn == 15) { + DEBUG(errs() << "if n == 15 then UNPREDICTABLE\n"); + return false; + } + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,ARM::GPRRegClassID,Rn))); NumOpsAdded = 1; return true; } @@ -1149,7 +1170,7 @@ static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn, Opcode == ARM::t2STMIA || Opcode == ARM::t2STMIA_UPD || Opcode == ARM::t2STMDB || Opcode == ARM::t2STMDB_UPD) && "Unexpected opcode"); - assert(NumOps >= 5 && "Thumb2 LdStMul expects NumOps >= 5"); + assert(NumOps >= 4 && "Thumb2 LdStMul expects NumOps >= 4"); NumOpsAdded = 0; @@ -1203,45 +1224,79 @@ static bool DisassembleThumb2LdStEx(MCInst &MI, unsigned Opcode, uint32_t insn, OpIdx = 0; assert(NumOps >= 2 - && OpInfo[0].RegClass == ARM::GPRRegClassID - && OpInfo[1].RegClass == ARM::GPRRegClassID + && OpInfo[0].RegClass > 0 + && OpInfo[1].RegClass > 0 && "Expect >=2 operands and first two as reg operands"); bool isStore = (ARM::t2STREX <= Opcode && Opcode <= ARM::t2STREXH); bool isSW = (Opcode == ARM::t2LDREX || Opcode == ARM::t2STREX); bool isDW = (Opcode == ARM::t2LDREXD || Opcode == ARM::t2STREXD); + unsigned Rt = decodeRd(insn); + unsigned Rt2 = decodeRs(insn); // But note that this is Rd for t2STREX. + unsigned Rd = decodeRm(insn); + unsigned Rn = decodeRn(insn); + + // Some sanity checking first. + if (isStore) { + // if d == n || d == t then UNPREDICTABLE + // if d == n || d == t || d == t2 then UNPREDICTABLE + if (isDW) { + if (Rd == Rn || Rd == Rt || Rd == Rt2) { + DEBUG(errs() << "if d == n || d == t || d == t2 then UNPREDICTABLE\n"); + return false; + } + } else { + if (isSW) { + if (Rt2 == Rn || Rt2 == Rt) { + DEBUG(errs() << "if d == n || d == t then UNPREDICTABLE\n"); + return false; + } + } else { + if (Rd == Rn || Rd == Rt) { + DEBUG(errs() << "if d == n || d == t then UNPREDICTABLE\n"); + return false; + } + } + } + } else { + // Load + // A8.6.71 LDREXD + // if t == t2 then UNPREDICTABLE + if (isDW && Rt == Rt2) { + DEBUG(errs() << "if t == t2 then UNPREDICTABLE\n"); + return false; + } + } + // Add the destination operand for store. if (isStore) { MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, ARM::GPRRegClassID, - isSW ? decodeRs(insn) : decodeRm(insn)))); + getRegisterEnum(B, OpInfo[OpIdx].RegClass, + isSW ? Rt2 : Rd))); ++OpIdx; } // Source operand for store and destination operand for load. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, + Rt))); ++OpIdx; // Thumb2 doubleword complication: with an extra source/destination operand. if (isDW) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRs(insn)))); + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass, + Rt2))); ++OpIdx; } // Finally add the pointer operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, + Rn))); ++OpIdx; return true; } -// LLVM, as of Jan-05-2010, does not output , i.e., Rs, in the asm. -// Whereas the ARM Arch. Manual does not require that t2 = t+1 like in ARM ISA. -// // t2LDRDi8: Rd Rs Rn imm8s4 (offset mode) // t2LDRDpci: Rd Rs imm8s4 (Not decoded, prefer the generic t2LDRDi8 version) // t2STRDi8: Rd Rs Rn imm8s4 (offset mode) @@ -1255,18 +1310,50 @@ static bool DisassembleThumb2LdStDual(MCInst &MI, unsigned Opcode, if (!OpInfo) return false; assert(NumOps >= 4 - && OpInfo[0].RegClass == ARM::GPRRegClassID - && OpInfo[1].RegClass == ARM::GPRRegClassID - && OpInfo[2].RegClass == ARM::GPRRegClassID + && OpInfo[0].RegClass > 0 + && OpInfo[0].RegClass == OpInfo[1].RegClass + && OpInfo[2].RegClass > 0 && OpInfo[3].RegClass < 0 && "Expect >= 4 operands and first 3 as reg operands"); + // Thumnb allows for specifying Rt and Rt2, unlike ARM (which has Rt2==Rt+1). + unsigned Rt = decodeRd(insn); + unsigned Rt2 = decodeRs(insn); + unsigned Rn = decodeRn(insn); + + // Some sanity checking first. + + // A8.6.67 LDRD (literal) has its W bit as (0). + if (Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2LDRD_PRE || Opcode == ARM::t2LDRD_POST) { + if (Rn == 15 && slice(insn, 21, 21) != 0) + return false; + } else { + // For Dual Store, PC cannot be used as the base register. + if (Rn == 15) { + DEBUG(errs() << "if n == 15 then UNPREDICTABLE\n"); + return false; + } + } + if (Rt == Rt2) { + DEBUG(errs() << "if t == t2 then UNPREDICTABLE\n"); + return false; + } + if (Opcode != ARM::t2LDRDi8 && Opcode != ARM::t2STRDi8) { + if (Rn == Rt || Rn == Rt2) { + DEBUG(errs() << "if wback && (n == t || n == t2) then UNPREDICTABLE\n"); + return false; + } + } + // Add the operands. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + unsigned RegClassPair = OpInfo[0].RegClass; + unsigned RegClassBase = OpInfo[2].RegClass; + + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair, decodeRd(insn)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair, decodeRs(insn)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassBase, decodeRn(insn)))); // Finally add (+/-)imm8*4, depending on the U bit. @@ -1394,9 +1481,12 @@ static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - if (Thumb2ShiftOpcode(Opcode)) - MI.addOperand(MCOperand::CreateImm(getShiftAmtBits(insn))); - else { + if (Thumb2ShiftOpcode(Opcode)) { + unsigned Imm = getShiftAmtBits(insn); + ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 5, 4)); + getImmShiftSE(ShOp, Imm); + MI.addOperand(MCOperand::CreateImm(Imm)); + } else { // Build the constant shift specifier operand. unsigned bits2 = getShiftTypeBits(insn); unsigned imm5 = getShiftAmtBits(insn); @@ -1421,7 +1511,8 @@ static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const TargetInstrDesc &TID = ARMInsts[Opcode]; + const TargetOperandInfo *OpInfo = TID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1448,8 +1539,15 @@ static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode, DEBUG(errs()<<"Thumb2 encoding error: d==15 for DPModImm 2-reg instr.\n"); return false; } - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID, - decodeRn(insn)))); + int Idx; + if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + // The reg operand is tied to the first reg operand. + MI.addOperand(MI.getOperand(Idx)); + } else { + // Add second reg operand. + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID, + decodeRn(insn)))); + } ++OpIdx; } @@ -1518,7 +1616,7 @@ static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn, // o t2ADDri12, t2SUBri12: Rs Rn imm12 // o t2LEApcrel (ADR): Rs imm12 // o t2BFC (BFC): Rs Ro(TIED_TO) bf_inv_mask_imm -// o t2BFI (BFI) (Currently not defined in LLVM as of Jan-07-2010) +// o t2BFI (BFI): Rs Ro(TIED_TO) Rn bf_inv_mask_imm // o t2MOVi16: Rs imm16 // o t2MOVTi16: Rs imm16 // o t2SBFX (SBFX): Rs Rn lsb width @@ -1579,9 +1677,10 @@ static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode, if (Opcode == ARM::t2ADDri12 || Opcode == ARM::t2SUBri12 || Opcode == ARM::t2LEApcrel) MI.addOperand(MCOperand::CreateImm(getIImm3Imm8(insn))); - else if (Opcode == ARM::t2MOVi16 || Opcode == ARM::t2MOVTi16) - MI.addOperand(MCOperand::CreateImm(getImm16(insn))); - else if (Opcode == ARM::t2BFC || Opcode == ARM::t2BFI) { + else if (Opcode == ARM::t2MOVi16 || Opcode == ARM::t2MOVTi16) { + if (!B->tryAddingSymbolicOperand(getImm16(insn), 4, MI)) + MI.addOperand(MCOperand::CreateImm(getImm16(insn))); + } else if (Opcode == ARM::t2BFC || Opcode == ARM::t2BFI) { uint32_t mask = 0; if (getBitfieldInvMask(insn, mask)) MI.addOperand(MCOperand::CreateImm(mask)); @@ -1625,8 +1724,7 @@ static inline bool t2MiscCtrlInstr(uint32_t insn) { // A8.6.26 // t2BXJ -> Rn // -// Miscellaneous control: t2DMBsy (and its t2DMB variants), -// t2DSBsy (and its t2DSB varianst), t2ISBsy, t2CLREX +// Miscellaneous control: // -> no operand (except pred-imm pred-ccr for CLREX, memory barrier variants) // // Hint: t2NOP, t2YIELD, t2WFE, t2WFI, t2SEV @@ -1643,6 +1741,22 @@ static bool DisassembleThumb2BrMiscCtrl(MCInst &MI, unsigned Opcode, if (NumOps == 0) return true; + if (Opcode == ARM::t2DMB || Opcode == ARM::t2DSB) { + // Inst{3-0} encodes the memory barrier option for the variants. + unsigned opt = slice(insn, 3, 0); + switch (opt) { + case ARM_MB::SY: case ARM_MB::ST: + case ARM_MB::ISH: case ARM_MB::ISHST: + case ARM_MB::NSH: case ARM_MB::NSHST: + case ARM_MB::OSH: case ARM_MB::OSHST: + MI.addOperand(MCOperand::CreateImm(opt)); + NumOpsAdded = 1; + return true; + default: + return false; + } + } + if (t2MiscCtrlInstr(insn)) return true; @@ -1719,6 +1833,17 @@ static bool DisassembleThumb2BrMiscCtrl(MCInst &MI, unsigned Opcode, return true; } + // Some instructions have predicate operands first before the immediate. + if (Opcode == ARM::tBLXi_r9 || Opcode == ARM::tBLr9) { + // Handling the two predicate operands before the imm operand. + if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) + NumOpsAdded += 2; + else { + DEBUG(errs() << "Expected predicate operands not found.\n"); + return false; + } + } + // Add the imm operand. int Offset = 0; @@ -1739,13 +1864,12 @@ static bool DisassembleThumb2BrMiscCtrl(MCInst &MI, unsigned Opcode, Offset = decodeImm32_BLX(insn); break; } - // When executing a Thumb instruction, PC reads as the address of the current - // instruction plus 4. The assembler subtracts 4 from the difference between - // the branch instruction and the target address, disassembler has to add 4 to - // to compensate. - MI.addOperand(MCOperand::CreateImm(Offset + 4)); - NumOpsAdded = 1; + if (!B->tryAddingSymbolicOperand(Offset + B->getBuilderAddress() + 4, 4, MI)) + MI.addOperand(MCOperand::CreateImm(Offset)); + + // This is an increment as some predicate operands may have been added first. + NumOpsAdded += 1; return true; } @@ -1787,7 +1911,7 @@ static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn, decodeRn(insn)))); ++OpIdx; - if (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) { + if (OpInfo[OpIdx].RegClass == ARM::rGPRRegClassID) { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRm(insn)))); } else { @@ -1795,17 +1919,17 @@ static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn, && !OpInfo[OpIdx].isOptionalDef() && "Pure imm operand expected"); int Offset = 0; - if (slice(insn, 19, 16) == 0xFF) { - bool Negative = slice(insn, 23, 23) == 0; - unsigned Imm12 = getImm12(insn); - Offset = Negative ? -1 - Imm12 : 1 * Imm12; - } else if (Opcode == ARM::t2PLDi8 || Opcode == ARM::t2PLDWi8 || - Opcode == ARM::t2PLIi8) { + if (Opcode == ARM::t2PLDi8 || Opcode == ARM::t2PLDWi8 || + Opcode == ARM::t2PLIi8) { // A8.6.117 Encoding T2: add = FALSE unsigned Imm8 = getImm8(insn); - Offset = -1 - Imm8; - } else // The i12 forms. See, for example, A8.6.117 Encoding T1. + Offset = -1 * Imm8; + } else { + // The i12 forms. See, for example, A8.6.117 Encoding T1. + // Note that currently t2PLDi12 also handles the previously named t2PLDpci + // opcode, that's why we use decodeImm12(insn) which returns +/- imm12. Offset = decodeImm12(insn); + } MI.addOperand(MCOperand::CreateImm(Offset)); } ++OpIdx; @@ -1820,6 +1944,87 @@ static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } +static bool BadRegsThumb2LdSt(unsigned Opcode, uint32_t insn, bool Load, + unsigned R0, unsigned R1, unsigned R2, bool UseRm, bool WB) { + + // Inst{22-21} encodes the data item transferred for load/store. + // For single word, it is encoded as ob10. + bool Word = (slice(insn, 22, 21) == 2); + bool Half = (slice(insn, 22, 21) == 1); + bool Byte = (slice(insn, 22, 21) == 0); + + if (UseRm && BadReg(R2)) { + DEBUG(errs() << "if BadReg(m) then UNPREDICTABLE\n"); + return true; + } + + if (Load) { + if (!Word && R0 == 13) { + DEBUG(errs() << "if t == 13 then UNPREDICTABLE\n"); + return true; + } + if (Byte) { + if (WB && R0 == 15 && slice(insn, 10, 8) == 3) { + // A8.6.78 LDRSB (immediate) Encoding T2 (errata markup 8.0) + DEBUG(errs() << "if t == 15 && PUW == '011' then UNPREDICTABLE\n"); + return true; + } + } + // A6.3.8 Load halfword, memory hints + if (Half) { + if (WB) { + if (R0 == R1) { + // A8.6.82 LDRSH (immediate) Encoding T2 + DEBUG(errs() << "if WB && n == t then UNPREDICTABLE\n"); + return true; + } + if (R0 == 15 && slice(insn, 10, 8) == 3) { + // A8.6.82 LDRSH (immediate) Encoding T2 (errata markup 8.0) + DEBUG(errs() << "if t == 15 && PUW == '011' then UNPREDICTABLE\n"); + return true; + } + } else { + if (Opcode == ARM::t2LDRHi8 || Opcode == ARM::t2LDRSHi8) { + if (R0 == 15 && slice(insn, 10, 8) == 4) { + // A8.6.82 LDRSH (immediate) Encoding T2 + DEBUG(errs() << "if Rt == '1111' and PUW == '100' then SEE" + << " \"Unallocated memory hints\"\n"); + return true; + } + } else { + if (R0 == 15) { + // A8.6.82 LDRSH (immediate) Encoding T1 + DEBUG(errs() << "if Rt == '1111' then SEE" + << " \"Unallocated memory hints\"\n"); + return true; + } + } + } + } + } else { + if (WB && R0 == R1) { + DEBUG(errs() << "if wback && n == t then UNPREDICTABLE\n"); + return true; + } + if ((WB && R0 == 15) || (!WB && R1 == 15)) { + DEBUG(errs() << "if Rn == '1111' then UNDEFINED\n"); + return true; + } + if (Word) { + if ((WB && R1 == 15) || (!WB && R0 == 15)) { + DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n"); + return true; + } + } else { + if ((WB && BadReg(R1)) || (!WB && BadReg(R0))) { + DEBUG(errs() << "if BadReg(t) then UNPREDICTABLE\n"); + return true; + } + } + } + return false; +} + // A6.3.10 Store single data item // A6.3.9 Load byte, memory hints // A6.3.8 Load halfword, memory hints @@ -1865,16 +2070,16 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode, OpIdx = 0; assert(NumOps >= 3 && - OpInfo[0].RegClass == ARM::GPRRegClassID && - OpInfo[1].RegClass == ARM::GPRRegClassID && + OpInfo[0].RegClass > 0 && + OpInfo[1].RegClass > 0 && "Expect >= 3 operands and first two as reg operands"); - bool ThreeReg = (OpInfo[2].RegClass == ARM::GPRRegClassID); + bool ThreeReg = (OpInfo[2].RegClass > 0); bool TIED_TO = ThreeReg && TID.getOperandConstraint(2, TOI::TIED_TO) != -1; bool Imm12 = !ThreeReg && slice(insn, 23, 23) == 1; // ARMInstrThumb2.td // Build the register operands, followed by the immediate. - unsigned R0, R1, R2 = 0; + unsigned R0 = 0, R1 = 0, R2 = 0; unsigned Rd = decodeRd(insn); int Imm = 0; @@ -1905,19 +2110,24 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode, Imm = decodeImm8(insn); } - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, R0))); ++OpIdx; - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, R1))); ++OpIdx; if (ThreeReg) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + // This could be an offset register or a TIED_TO register. + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass, R2))); ++OpIdx; } + if (BadRegsThumb2LdSt(Opcode, insn, Load, R0, R1, R2, ThreeReg & !TIED_TO, + TIED_TO)) + return false; + assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef() && "Pure imm operand expected"); @@ -1947,25 +2157,25 @@ static bool DisassembleThumb2DPReg(MCInst &MI, unsigned Opcode, uint32_t insn, OpIdx = 0; assert(NumOps >= 2 && - OpInfo[0].RegClass == ARM::rGPRRegClassID && - OpInfo[1].RegClass == ARM::rGPRRegClassID && + OpInfo[0].RegClass > 0 && + OpInfo[1].RegClass > 0 && "Expect >= 2 operands and first two as reg operands"); // Build the register operands, followed by the optional rotation amount. - bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::rGPRRegClassID; + bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass > 0; - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, decodeRs(insn)))); ++OpIdx; if (ThreeReg) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass, decodeRn(insn)))); ++OpIdx; } - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, decodeRm(insn)))); ++OpIdx; diff --git a/contrib/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/contrib/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 1499da00ae1c..fc2aa7526b7f 100644 --- a/contrib/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/contrib/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -29,6 +29,9 @@ StringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const { return getInstructionName(Opcode); } +StringRef ARMInstPrinter::getRegName(unsigned RegNo) const { + return getRegisterName(RegNo); +} void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { unsigned Opcode = MI->getOpcode(); @@ -133,9 +136,10 @@ static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream, unsigned Rot = ARM_AM::getSOImmValRot(V); // Print low-level immediate formation info, per - // A5.1.3: "Data-processing operands - Immediate". + // A5.2.3: Data-processing (immediate), and + // A5.2.4: Modified immediate constants in ARM instructions if (Rot) { - O << "#" << Imm << ", " << Rot; + O << "#" << Imm << ", #" << Rot; // Pretty printed version. if (CommentStream) *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n"; @@ -178,18 +182,16 @@ void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum, } } +//===--------------------------------------------------------------------===// +// Addressing Mode #2 +//===--------------------------------------------------------------------===// -void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op, - raw_ostream &O) { +void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op, + raw_ostream &O) { const MCOperand &MO1 = MI->getOperand(Op); const MCOperand &MO2 = MI->getOperand(Op+1); const MCOperand &MO3 = MI->getOperand(Op+2); - if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. - printOperand(MI, Op, O); - return; - } - O << "[" << getRegisterName(MO1.getReg()); if (!MO2.getReg()) { @@ -212,6 +214,50 @@ void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op, O << "]"; } +void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(Op); + const MCOperand &MO2 = MI->getOperand(Op+1); + const MCOperand &MO3 = MI->getOperand(Op+2); + + O << "[" << getRegisterName(MO1.getReg()) << "], "; + + if (!MO2.getReg()) { + unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm()); + O << '#' + << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) + << ImmOffs; + return; + } + + O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) + << getRegisterName(MO2.getReg()); + + if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) + O << ", " + << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) + << " #" << ShImm; +} + +void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(Op); + + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. + printOperand(MI, Op, O); + return; + } + + const MCOperand &MO3 = MI->getOperand(Op+2); + unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm()); + + if (IdxMode == ARMII::IndexModePost) { + printAM2PostIndexOp(MI, Op, O); + return; + } + printAM2PreOrOffsetIndexOp(MI, Op, O); +} + void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) { @@ -235,11 +281,35 @@ void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI, << " #" << ShImm; } -void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum, - raw_ostream &O) { - const MCOperand &MO1 = MI->getOperand(OpNum); - const MCOperand &MO2 = MI->getOperand(OpNum+1); - const MCOperand &MO3 = MI->getOperand(OpNum+2); +//===--------------------------------------------------------------------===// +// Addressing Mode #3 +//===--------------------------------------------------------------------===// + +void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(Op); + const MCOperand &MO2 = MI->getOperand(Op+1); + const MCOperand &MO3 = MI->getOperand(Op+2); + + O << "[" << getRegisterName(MO1.getReg()) << "], "; + + if (MO2.getReg()) { + O << (char)ARM_AM::getAM3Op(MO3.getImm()) + << getRegisterName(MO2.getReg()); + return; + } + + unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()); + O << '#' + << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm())) + << ImmOffs; +} + +void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(Op); + const MCOperand &MO2 = MI->getOperand(Op+1); + const MCOperand &MO3 = MI->getOperand(Op+2); O << '[' << getRegisterName(MO1.getReg()); @@ -256,6 +326,18 @@ void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum, O << ']'; } +void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op, + raw_ostream &O) { + const MCOperand &MO3 = MI->getOperand(Op+2); + unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm()); + + if (IdxMode == ARMII::IndexModePost) { + printAM3PostIndexOp(MI, Op, O); + return; + } + printAM3PreOrOffsetIndexOp(MI, Op, O); +} + void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) { @@ -314,6 +396,12 @@ void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum, O << "]"; } +void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { + const MCOperand &MO1 = MI->getOperand(OpNum); + O << "[" << getRegisterName(MO1.getReg()) << "]"; +} + void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) { @@ -414,16 +502,6 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, } } -void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum, - raw_ostream &O) { - const MCOperand &Op = MI->getOperand(OpNum); - O << '#'; - if (Op.getImm() < 0) - O << '-' << (-Op.getImm() - 1); - else - O << Op.getImm(); -} - void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) { ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); diff --git a/contrib/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/contrib/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h index 679d3135ea6d..b3ac03ab2200 100644 --- a/contrib/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h +++ b/contrib/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h @@ -17,14 +17,18 @@ #include "llvm/MC/MCInstPrinter.h" namespace llvm { - class MCOperand; + +class MCOperand; +class TargetMachine; class ARMInstPrinter : public MCInstPrinter { public: - ARMInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} + ARMInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) + : MCInstPrinter(MAI) {} virtual void printInst(const MCInst *MI, raw_ostream &O); virtual StringRef getOpcodeName(unsigned Opcode) const; + virtual StringRef getRegName(unsigned RegNo) const; static const char *getInstructionName(unsigned Opcode); @@ -38,15 +42,25 @@ class ARMInstPrinter : public MCInstPrinter { void printSOImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAM2PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum, + raw_ostream &O); void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAM3PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum, + raw_ostream &O); void printAddrMode3OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printLdStmModeOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printAddrMode5Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printAddrMode6Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printAddrMode7Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printAddrMode6OffsetOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); @@ -87,9 +101,7 @@ class ARMInstPrinter : public MCInstPrinter { void printSetendOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printCPSIMod(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printCPSIFlag(const MCInst *MI, unsigned OpNum, raw_ostream &O); - void printCPSOptionOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printMSRMaskOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); - void printNegZeroOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); diff --git a/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp b/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp index 9a27e2f47064..f6d024232eae 100644 --- a/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp +++ b/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp @@ -15,11 +15,13 @@ #define DEBUG_TYPE "mlx-expansion" #include "ARM.h" #include "ARMBaseInstrInfo.h" +#include "ARMSubtarget.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -49,15 +51,17 @@ namespace { const TargetRegisterInfo *TRI; MachineRegisterInfo *MRI; + bool isA9; unsigned MIIdx; MachineInstr* LastMIs[4]; + SmallPtrSet IgnoreStall; void clearStack(); void pushStack(MachineInstr *MI); MachineInstr *getAccDefMI(MachineInstr *MI) const; unsigned getDefReg(MachineInstr *MI) const; bool hasRAWHazard(unsigned Reg, MachineInstr *MI) const; - bool FindMLxHazard(MachineInstr *MI) const; + bool FindMLxHazard(MachineInstr *MI); void ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI, unsigned MulOpc, unsigned AddSubOpc, bool NegAcc, bool HasLane); @@ -146,7 +150,7 @@ bool MLxExpansion::hasRAWHazard(unsigned Reg, MachineInstr *MI) const { } -bool MLxExpansion::FindMLxHazard(MachineInstr *MI) const { +bool MLxExpansion::FindMLxHazard(MachineInstr *MI) { if (NumExpand >= ExpandLimit) return false; @@ -154,7 +158,7 @@ bool MLxExpansion::FindMLxHazard(MachineInstr *MI) const { return true; MachineInstr *DefMI = getAccDefMI(MI); - if (TII->isFpMLxInstruction(DefMI->getOpcode())) + if (TII->isFpMLxInstruction(DefMI->getOpcode())) { // r0 = vmla // r3 = vmla r0, r1, r2 // takes 16 - 17 cycles @@ -163,24 +167,33 @@ bool MLxExpansion::FindMLxHazard(MachineInstr *MI) const { // r4 = vmul r1, r2 // r3 = vadd r0, r4 // takes about 14 - 15 cycles even with vmul stalling for 4 cycles. + IgnoreStall.insert(DefMI); return true; + } + + if (IgnoreStall.count(MI)) + return false; // If a VMLA.F is followed by an VADD.F or VMUL.F with no RAW hazard, the // VADD.F or VMUL.F will stall 4 cycles before issue. The 4 cycle stall // preserves the in-order retirement of the instructions. // Look at the next few instructions, if *most* of them can cause hazards, // then the scheduler can't *fix* this, we'd better break up the VMLA. + unsigned Limit1 = isA9 ? 1 : 4; + unsigned Limit2 = isA9 ? 1 : 4; for (unsigned i = 1; i <= 4; ++i) { int Idx = ((int)MIIdx - i + 4) % 4; MachineInstr *NextMI = LastMIs[Idx]; if (!NextMI) continue; - if (TII->canCauseFpMLxStall(NextMI->getOpcode())) - return true; + if (TII->canCauseFpMLxStall(NextMI->getOpcode())) { + if (i <= Limit1) + return true; + } // Look for VMLx RAW hazard. - if (hasRAWHazard(getDefReg(MI), NextMI)) + if (i <= Limit2 && hasRAWHazard(getDefReg(MI), NextMI)) return true; } @@ -248,6 +261,7 @@ bool MLxExpansion::ExpandFPMLxInstructions(MachineBasicBlock &MBB) { bool Changed = false; clearStack(); + IgnoreStall.clear(); unsigned Skip = 0; MachineBasicBlock::reverse_iterator MII = MBB.rbegin(), E = MBB.rend(); @@ -299,6 +313,8 @@ bool MLxExpansion::runOnMachineFunction(MachineFunction &Fn) { TII = static_cast(Fn.getTarget().getInstrInfo()); TRI = Fn.getTarget().getRegisterInfo(); MRI = &Fn.getRegInfo(); + const ARMSubtarget *STI = &Fn.getTarget().getSubtarget(); + isA9 = STI->isCortexA9(); bool Modified = false; for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; diff --git a/contrib/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/contrib/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp index 233e16538771..dee3d278203f 100644 --- a/contrib/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/contrib/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -34,13 +34,14 @@ bool Thumb1FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const return !MF.getFrameInfo()->hasVarSizedObjects(); } -static void emitSPUpdate(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - const TargetInstrInfo &TII, DebugLoc dl, - const Thumb1RegisterInfo &MRI, - int NumBytes) { - emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII, - MRI, dl); +static void +emitSPUpdate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + const TargetInstrInfo &TII, DebugLoc dl, + const Thumb1RegisterInfo &MRI, + int NumBytes, unsigned MIFlags = MachineInstr::NoFlags) { + emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, + MRI, MIFlags); } void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { @@ -70,11 +71,13 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { int FramePtrSpillFI = 0; if (VARegSaveSize) - emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -VARegSaveSize); + emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -VARegSaveSize, + MachineInstr::FrameSetup); if (!AFI->hasStackFrame()) { if (NumBytes != 0) - emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes); + emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes, + MachineInstr::FrameSetup); return; } @@ -131,7 +134,8 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { // Adjust FP so it point to the stack slot that contains the previous FP. if (hasFP(MF)) { BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) - .addFrameIndex(FramePtrSpillFI).addImm(0); + .addFrameIndex(FramePtrSpillFI).addImm(0) + .setMIFlags(MachineInstr::FrameSetup); if (NumBytes > 7) // If offset is > 7 then sp cannot be adjusted in a single instruction, // try restoring from fp instead. @@ -140,7 +144,8 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { if (NumBytes) // Insert it after all the callee-save spills. - emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes); + emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes, + MachineInstr::FrameSetup); if (STI.isTargetELF() && hasFP(MF)) MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - @@ -156,7 +161,7 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const { // to reference locals. if (RegInfo->hasBasePointer(MF)) BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), BasePtr).addReg(ARM::SP); - + // If the frame has variable sized objects then the epilogue must restore // the sp from fp. We can assume there's an FP here since hasFP already // checks for hasVarSizedObjects. @@ -232,8 +237,8 @@ void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF, if (NumBytes) { assert(MF.getRegInfo().isPhysRegUsed(ARM::R4) && "No scratch register to restore SP from FP!"); - emitThumbRegPlusImmediate(MBB, MBBI, ARM::R4, FramePtr, -NumBytes, - TII, *RegInfo, dl); + emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, + TII, *RegInfo); BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) .addReg(ARM::R4); } else @@ -307,6 +312,7 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, MIB.addReg(Reg, getKillRegState(isKill)); } + MIB.setMIFlags(MachineInstr::FrameSetup); return true; } diff --git a/contrib/llvm/lib/Target/ARM/Thumb1FrameLowering.h b/contrib/llvm/lib/Target/ARM/Thumb1FrameLowering.h index c592e125de17..bcfc5165fad0 100644 --- a/contrib/llvm/lib/Target/ARM/Thumb1FrameLowering.h +++ b/contrib/llvm/lib/Target/ARM/Thumb1FrameLowering.h @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #ifndef __THUMB_FRAMEINFO_H_ -#define __THUMM_FRAMEINFO_H_ +#define __THUMB_FRAMEINFO_H_ #include "ARM.h" #include "ARMFrameLowering.h" diff --git a/contrib/llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp b/contrib/llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp index f62a13e3e288..33cefb6e79bb 100644 --- a/contrib/llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -31,8 +31,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -48,15 +46,29 @@ Thumb1RegisterInfo::Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, : ARMBaseRegisterInfo(tii, sti) { } +const TargetRegisterClass* +Thumb1RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) + const { + if (RC == ARM::tGPRRegisterClass || RC->hasSuperClass(ARM::tGPRRegisterClass)) + return ARM::tGPRRegisterClass; + return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC); +} + +const TargetRegisterClass * +Thumb1RegisterInfo::getPointerRegClass(unsigned Kind) const { + return ARM::tGPRRegisterClass; +} + /// emitLoadConstPool - Emits a load from constpool to materialize the /// specified immediate. -void Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - DebugLoc dl, - unsigned DestReg, unsigned SubIdx, - int Val, - ARMCC::CondCodes Pred, - unsigned PredReg) const { +void +Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, + int Val, + ARMCC::CondCodes Pred, unsigned PredReg, + unsigned MIFlags) const { MachineFunction &MF = *MBB.getParent(); MachineConstantPool *ConstantPool = MF.getConstantPool(); const Constant *C = ConstantInt::get( @@ -64,8 +76,9 @@ void Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci)) - .addReg(DestReg, getDefRegState(true), SubIdx) - .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg); + .addReg(DestReg, getDefRegState(true), SubIdx) + .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg) + .setMIFlags(MIFlags); } @@ -76,11 +89,12 @@ void Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, static void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, + DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, bool CanChangeCC, const TargetInstrInfo &TII, const ARMBaseRegisterInfo& MRI, - DebugLoc dl) { + unsigned MIFlags = MachineInstr::NoFlags) { MachineFunction &MF = *MBB.getParent(); bool isHigh = !isARMLowRegister(DestReg) || (BaseReg != 0 && !isARMLowRegister(BaseReg)); @@ -101,14 +115,15 @@ void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB, if (NumBytes <= 255 && NumBytes >= 0) AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) - .addImm(NumBytes); + .addImm(NumBytes).setMIFlags(MIFlags); else if (NumBytes < 0 && NumBytes >= -255) { AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) - .addImm(NumBytes); + .addImm(NumBytes).setMIFlags(MIFlags); AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)) - .addReg(LdReg, RegState::Kill); + .addReg(LdReg, RegState::Kill).setMIFlags(MIFlags); } else - MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes); + MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, + ARMCC::AL, 0, MIFlags); // Emit add / sub. int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr); @@ -151,10 +166,11 @@ static unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes, /// a destreg = basereg + immediate in Thumb code. void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, + DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, const TargetInstrInfo &TII, const ARMBaseRegisterInfo& MRI, - DebugLoc dl) { + unsigned MIFlags) { bool isSub = NumBytes < 0; unsigned Bytes = (unsigned)NumBytes; if (isSub) Bytes = -NumBytes; @@ -211,8 +227,9 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, if (NumMIs > Threshold) { // This will expand into too many instructions. Load the immediate from a // constpool entry. - emitThumbRegPlusImmInReg(MBB, MBBI, DestReg, BaseReg, NumBytes, true, TII, - MRI, dl); + emitThumbRegPlusImmInReg(MBB, MBBI, dl, + DestReg, BaseReg, NumBytes, true, + TII, MRI, MIFlags); return; } @@ -224,11 +241,12 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, Bytes -= ThisVal; const TargetInstrDesc &TID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); const MachineInstrBuilder MIB = - AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)); + AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg).setMIFlags(MIFlags)); AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); } else { BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) - .addReg(BaseReg, RegState::Kill); + .addReg(BaseReg, RegState::Kill) + .setMIFlags(MIFlags); } BaseReg = DestReg; } @@ -243,9 +261,10 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); if (NeedCC) MIB = AddDefaultT1CC(MIB); - MIB .addReg(DestReg).addImm(ThisVal); + MIB.addReg(DestReg).addImm(ThisVal); if (NeedPred) MIB = AddDefaultPred(MIB); + MIB.setMIFlags(MIFlags); } else { bool isKill = BaseReg != ARM::SP; @@ -255,8 +274,9 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); if (NeedPred) MIB = AddDefaultPred(MIB); - BaseReg = DestReg; + MIB.setMIFlags(MIFlags); + BaseReg = DestReg; if (Opc == ARM::tADDrSPi) { // r4 = add sp, imm // r4 = add r4, imm @@ -274,7 +294,8 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, const TargetInstrDesc &TID = TII.get(ExtraOpc); AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) .addReg(DestReg, RegState::Kill) - .addImm(((unsigned)NumBytes) & 3)); + .addImm(((unsigned)NumBytes) & 3) + .setMIFlags(MIFlags)); } } @@ -283,8 +304,8 @@ static void emitSPUpdate(MachineBasicBlock &MBB, const TargetInstrInfo &TII, DebugLoc dl, const Thumb1RegisterInfo &MRI, int NumBytes) { - emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII, - MRI, dl); + emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, + MRI); } void Thumb1RegisterInfo:: @@ -337,7 +358,7 @@ static void emitThumbConstant(MachineBasicBlock &MBB, DestReg)) .addImm(ThisVal)); if (Imm > 0) - emitThumbRegPlusImmediate(MBB, MBBI, DestReg, DestReg, Imm, TII, MRI, dl); + emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI); if (isSub) { const TargetInstrDesc &TID = TII.get(ARM::tRSB); AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TID, DestReg)) @@ -430,8 +451,8 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, // MI would expand into a large number of instructions. Don't try to // simplify the immediate. if (NumMIs > 2) { - emitThumbRegPlusImmediate(MBB, II, DestReg, FrameReg, Offset, TII, - *this, dl); + emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII, + *this); MBB.erase(II); return true; } @@ -450,8 +471,8 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, } Offset = (Offset - Mask * Scale); MachineBasicBlock::iterator NII = llvm::next(II); - emitThumbRegPlusImmediate(MBB, NII, DestReg, DestReg, Offset, TII, - *this, dl); + emitThumbRegPlusImmediate(MBB, NII, dl, DestReg, DestReg, Offset, TII, + *this); } else { // Translate r0 = add sp, -imm to // r0 = -imm (this is then translated into a series of instructons) @@ -645,15 +666,15 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, bool UseRR = false; if (Opcode == ARM::tRestore) { if (FrameReg == ARM::SP) - emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg, - Offset, false, TII, *this, dl); + emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, + Offset, false, TII, *this); else { emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); UseRR = true; } } else { - emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg, Offset, TII, - *this, dl); + emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII, + *this); } MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi)); @@ -668,15 +689,15 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, if (Opcode == ARM::tSpill) { if (FrameReg == ARM::SP) - emitThumbRegPlusImmInReg(MBB, II, VReg, FrameReg, - Offset, false, TII, *this, dl); + emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, + Offset, false, TII, *this); else { emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); UseRR = true; } } else - emitThumbRegPlusImmediate(MBB, II, VReg, FrameReg, Offset, TII, - *this, dl); + emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII, + *this); MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi)); MI.getOperand(i).ChangeToRegister(VReg, false, false, true); if (UseRR) diff --git a/contrib/llvm/lib/Target/ARM/Thumb1RegisterInfo.h b/contrib/llvm/lib/Target/ARM/Thumb1RegisterInfo.h index 8a87cc55c829..9060e59e5980 100644 --- a/contrib/llvm/lib/Target/ARM/Thumb1RegisterInfo.h +++ b/contrib/llvm/lib/Target/ARM/Thumb1RegisterInfo.h @@ -28,6 +28,11 @@ struct Thumb1RegisterInfo : public ARMBaseRegisterInfo { public: Thumb1RegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &STI); + const TargetRegisterClass* + getLargestLegalSuperClass(const TargetRegisterClass *RC) const; + + const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const; + /// emitLoadConstPool - Emits a load from constpool to materialize the /// specified immediate. void emitLoadConstPool(MachineBasicBlock &MBB, @@ -35,7 +40,8 @@ struct Thumb1RegisterInfo : public ARMBaseRegisterInfo { DebugLoc dl, unsigned DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred = ARMCC::AL, - unsigned PredReg = 0) const; + unsigned PredReg = 0, + unsigned MIFlags = MachineInstr::NoFlags) const; /// Code Generation virtual methods... void eliminateCallFramePseudoInstr(MachineFunction &MF, diff --git a/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp b/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp index 9b1073be3c8e..d169dbb7f197 100644 --- a/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -184,7 +184,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, ARMCC::CondCodes Pred, unsigned PredReg, - const ARMBaseInstrInfo &TII) { + const ARMBaseInstrInfo &TII, unsigned MIFlags) { bool isSub = NumBytes < 0; if (isSub) NumBytes = -NumBytes; @@ -198,14 +198,14 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, // Use a movw to materialize the 16-bit constant. BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg) .addImm(NumBytes) - .addImm((unsigned)Pred).addReg(PredReg); + .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags); Fits = true; } else if ((NumBytes & 0xffff) == 0) { // Use a movt to materialize the 32-bit constant. BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg) .addReg(DestReg) .addImm(NumBytes >> 16) - .addImm((unsigned)Pred).addReg(PredReg); + .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags); Fits = true; } @@ -214,12 +214,14 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg) .addReg(BaseReg, RegState::Kill) .addReg(DestReg, RegState::Kill) - .addImm((unsigned)Pred).addReg(PredReg).addReg(0); + .addImm((unsigned)Pred).addReg(PredReg).addReg(0) + .setMIFlags(MIFlags); } else { BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg) .addReg(DestReg, RegState::Kill) .addReg(BaseReg, RegState::Kill) - .addImm((unsigned)Pred).addReg(PredReg).addReg(0); + .addImm((unsigned)Pred).addReg(PredReg).addReg(0) + .setMIFlags(MIFlags); } return; } @@ -230,7 +232,8 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, unsigned Opc = 0; if (DestReg == ARM::SP && BaseReg != ARM::SP) { // mov sp, rn. Note t2MOVr cannot be used. - BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr),DestReg).addReg(BaseReg); + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr),DestReg) + .addReg(BaseReg).setMIFlags(MIFlags); BaseReg = ARM::SP; continue; } @@ -243,7 +246,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; // FIXME: Fix Thumb1 immediate encoding. BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) - .addReg(BaseReg).addImm(ThisVal/4); + .addReg(BaseReg).addImm(ThisVal/4).setMIFlags(MIFlags); NumBytes = 0; continue; } @@ -283,7 +286,7 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineInstrBuilder MIB = AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) .addReg(BaseReg, RegState::Kill) - .addImm(ThisVal)); + .addImm(ThisVal)).setMIFlags(MIFlags); if (HasCCOut) AddDefaultCC(MIB); diff --git a/contrib/llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp b/contrib/llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp index 099b8f724140..355c3bf0352c 100644 --- a/contrib/llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/Thumb2RegisterInfo.cpp @@ -13,26 +13,15 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "ARMAddressingModes.h" -#include "ARMBaseInstrInfo.h" -#include "ARMMachineFunctionInfo.h" #include "ARMSubtarget.h" #include "Thumb2InstrInfo.h" #include "Thumb2RegisterInfo.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" -#include "llvm/LLVMContext.h" #include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineLocation.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/ErrorHandling.h" using namespace llvm; Thumb2RegisterInfo::Thumb2RegisterInfo(const ARMBaseInstrInfo &tii, @@ -42,13 +31,14 @@ Thumb2RegisterInfo::Thumb2RegisterInfo(const ARMBaseInstrInfo &tii, /// emitLoadConstPool - Emits a load from constpool to materialize the /// specified immediate. -void Thumb2RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - DebugLoc dl, - unsigned DestReg, unsigned SubIdx, - int Val, - ARMCC::CondCodes Pred, - unsigned PredReg) const { +void +Thumb2RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, + int Val, + ARMCC::CondCodes Pred, unsigned PredReg, + unsigned MIFlags) const { MachineFunction &MF = *MBB.getParent(); MachineConstantPool *ConstantPool = MF.getConstantPool(); const Constant *C = ConstantInt::get( @@ -57,5 +47,6 @@ void Thumb2RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci)) .addReg(DestReg, getDefRegState(true), SubIdx) - .addConstantPoolIndex(Idx).addImm((int64_t)ARMCC::AL).addReg(0); + .addConstantPoolIndex(Idx).addImm((int64_t)ARMCC::AL).addReg(0) + .setMIFlags(MIFlags); } diff --git a/contrib/llvm/lib/Target/ARM/Thumb2RegisterInfo.h b/contrib/llvm/lib/Target/ARM/Thumb2RegisterInfo.h index b3cf2e5b0935..824378aeab4e 100644 --- a/contrib/llvm/lib/Target/ARM/Thumb2RegisterInfo.h +++ b/contrib/llvm/lib/Target/ARM/Thumb2RegisterInfo.h @@ -35,7 +35,8 @@ struct Thumb2RegisterInfo : public ARMBaseRegisterInfo { DebugLoc dl, unsigned DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred = ARMCC::AL, - unsigned PredReg = 0) const; + unsigned PredReg = 0, + unsigned MIFlags = MachineInstr::NoFlags) const; }; } diff --git a/contrib/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp b/contrib/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp index cc8f61cd72a4..ce2e9663fb74 100644 --- a/contrib/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/contrib/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -12,6 +12,7 @@ #include "ARMAddressingModes.h" #include "ARMBaseRegisterInfo.h" #include "ARMBaseInstrInfo.h" +#include "ARMSubtarget.h" #include "Thumb2InstrInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -49,82 +50,86 @@ namespace { // 1 - No cc field. // 2 - Always set CPSR. unsigned PredCC2 : 2; + unsigned PartFlag : 1; // 16-bit instruction does partial flag update unsigned Special : 1; // Needs to be dealt with specially }; static const ReduceEntry ReduceTable[] = { - // Wide, Narrow1, Narrow2, imm1,imm2, lo1, lo2, P/C, S - { ARM::t2ADCrr, 0, ARM::tADC, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0 }, - { ARM::t2ADDrr, ARM::tADDrr, ARM::tADDhirr, 0, 0, 1, 0, 0,1, 0 }, + // Wide, Narrow1, Narrow2, imm1,imm2, lo1, lo2, P/C, PF, S + { ARM::t2ADCrr, 0, ARM::tADC, 0, 0, 0, 1, 0,0, 0,0 }, + { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,0 }, + { ARM::t2ADDrr, ARM::tADDrr, ARM::tADDhirr, 0, 0, 1, 0, 0,1, 0,0 }, // Note: immediate scale is 4. - { ARM::t2ADDrSPi,ARM::tADDrSPi,0, 8, 0, 1, 0, 1,0, 1 }, - { ARM::t2ADDSri,ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 2,2, 1 }, - { ARM::t2ADDSrr,ARM::tADDrr, 0, 0, 0, 1, 0, 2,0, 1 }, - { ARM::t2ANDrr, 0, ARM::tAND, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2ASRri, ARM::tASRri, 0, 5, 0, 1, 0, 0,0, 0 }, - { ARM::t2ASRrr, 0, ARM::tASRrr, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2BICrr, 0, ARM::tBIC, 0, 0, 0, 1, 0,0, 0 }, + { ARM::t2ADDrSPi,ARM::tADDrSPi,0, 8, 0, 1, 0, 1,0, 0,1 }, + { ARM::t2ADDSri,ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 2,2, 0,1 }, + { ARM::t2ADDSrr,ARM::tADDrr, 0, 0, 0, 1, 0, 2,0, 0,1 }, + { ARM::t2ANDrr, 0, ARM::tAND, 0, 0, 0, 1, 0,0, 1,0 }, + { ARM::t2ASRri, ARM::tASRri, 0, 5, 0, 1, 0, 0,0, 1,0 }, + { ARM::t2ASRrr, 0, ARM::tASRrr, 0, 0, 0, 1, 0,0, 1,0 }, + { ARM::t2BICrr, 0, ARM::tBIC, 0, 0, 0, 1, 0,0, 1,0 }, //FIXME: Disable CMN, as CCodes are backwards from compare expectations - //{ ARM::t2CMNrr, ARM::tCMN, 0, 0, 0, 1, 0, 2,0, 0 }, - { ARM::t2CMPri, ARM::tCMPi8, 0, 8, 0, 1, 0, 2,0, 0 }, - { ARM::t2CMPrr, ARM::tCMPhir, 0, 0, 0, 0, 0, 2,0, 1 }, - { ARM::t2EORrr, 0, ARM::tEOR, 0, 0, 0, 1, 0,0, 0 }, + //{ ARM::t2CMNrr, ARM::tCMN, 0, 0, 0, 1, 0, 2,0, 0,0 }, + { ARM::t2CMPri, ARM::tCMPi8, 0, 8, 0, 1, 0, 2,0, 0,0 }, + { ARM::t2CMPrr, ARM::tCMPhir, 0, 0, 0, 0, 0, 2,0, 0,1 }, + { ARM::t2EORrr, 0, ARM::tEOR, 0, 0, 0, 1, 0,0, 1,0 }, // FIXME: adr.n immediate offset must be multiple of 4. - //{ ARM::t2LEApcrelJT,ARM::tLEApcrelJT, 0, 0, 0, 1, 0, 1,0, 0 }, - { ARM::t2LSLri, ARM::tLSLri, 0, 5, 0, 1, 0, 0,0, 0 }, - { ARM::t2LSLrr, 0, ARM::tLSLrr, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2LSRri, ARM::tLSRri, 0, 5, 0, 1, 0, 0,0, 0 }, - { ARM::t2LSRrr, 0, ARM::tLSRrr, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2MOVi, ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 0 }, - { ARM::t2MOVi16,ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 1 }, + //{ ARM::t2LEApcrelJT,ARM::tLEApcrelJT, 0, 0, 0, 1, 0, 1,0, 0,0 }, + { ARM::t2LSLri, ARM::tLSLri, 0, 5, 0, 1, 0, 0,0, 1,0 }, + { ARM::t2LSLrr, 0, ARM::tLSLrr, 0, 0, 0, 1, 0,0, 1,0 }, + { ARM::t2LSRri, ARM::tLSRri, 0, 5, 0, 1, 0, 0,0, 1,0 }, + { ARM::t2LSRrr, 0, ARM::tLSRrr, 0, 0, 0, 1, 0,0, 1,0 }, + // FIXME: tMOVi8 and tMVN also partially update CPSR but they are less + // likely to cause issue in the loop. As a size / performance workaround, + // they are not marked as such. + { ARM::t2MOVi, ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 0,0 }, + { ARM::t2MOVi16,ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 0,1 }, // FIXME: Do we need the 16-bit 'S' variant? - { ARM::t2MOVr,ARM::tMOVgpr2gpr,0, 0, 0, 0, 0, 1,0, 0 }, - { ARM::t2MOVCCr,0, ARM::tMOVCCr, 0, 0, 0, 0, 0,1, 0 }, - { ARM::t2MOVCCi,0, ARM::tMOVCCi, 0, 8, 0, 1, 0,1, 0 }, - { ARM::t2MUL, 0, ARM::tMUL, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2MVNr, ARM::tMVN, 0, 0, 0, 1, 0, 0,0, 0 }, - { ARM::t2ORRrr, 0, ARM::tORR, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2REV, ARM::tREV, 0, 0, 0, 1, 0, 1,0, 0 }, - { ARM::t2REV16, ARM::tREV16, 0, 0, 0, 1, 0, 1,0, 0 }, - { ARM::t2REVSH, ARM::tREVSH, 0, 0, 0, 1, 0, 1,0, 0 }, - { ARM::t2RORrr, 0, ARM::tROR, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2RSBri, ARM::tRSB, 0, 0, 0, 1, 0, 0,0, 1 }, - { ARM::t2RSBSri,ARM::tRSB, 0, 0, 0, 1, 0, 2,0, 1 }, - { ARM::t2SBCrr, 0, ARM::tSBC, 0, 0, 0, 1, 0,0, 0 }, - { ARM::t2SUBri, ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 0,0, 0 }, - { ARM::t2SUBrr, ARM::tSUBrr, 0, 0, 0, 1, 0, 0,0, 0 }, - { ARM::t2SUBSri,ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 2,2, 0 }, - { ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0 }, - { ARM::t2SXTBr, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0 }, - { ARM::t2SXTHr, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0 }, - { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0 }, - { ARM::t2UXTBr, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0 }, - { ARM::t2UXTHr, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0 }, + { ARM::t2MOVr,ARM::tMOVgpr2gpr,0, 0, 0, 0, 0, 1,0, 0,0 }, + { ARM::t2MOVCCr,0, ARM::tMOVCCr, 0, 0, 0, 0, 0,1, 0,0 }, + { ARM::t2MOVCCi,0, ARM::tMOVCCi, 0, 8, 0, 1, 0,1, 0,0 }, + { ARM::t2MUL, 0, ARM::tMUL, 0, 0, 0, 1, 0,0, 1,0 }, + { ARM::t2MVNr, ARM::tMVN, 0, 0, 0, 1, 0, 0,0, 0,0 }, + { ARM::t2ORRrr, 0, ARM::tORR, 0, 0, 0, 1, 0,0, 1,0 }, + { ARM::t2REV, ARM::tREV, 0, 0, 0, 1, 0, 1,0, 0,0 }, + { ARM::t2REV16, ARM::tREV16, 0, 0, 0, 1, 0, 1,0, 0,0 }, + { ARM::t2REVSH, ARM::tREVSH, 0, 0, 0, 1, 0, 1,0, 0,0 }, + { ARM::t2RORrr, 0, ARM::tROR, 0, 0, 0, 1, 0,0, 1,0 }, + { ARM::t2RSBri, ARM::tRSB, 0, 0, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2RSBSri,ARM::tRSB, 0, 0, 0, 1, 0, 2,0, 0,1 }, + { ARM::t2SBCrr, 0, ARM::tSBC, 0, 0, 0, 1, 0,0, 0,0 }, + { ARM::t2SUBri, ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 0,0, 0,0 }, + { ARM::t2SUBrr, ARM::tSUBrr, 0, 0, 0, 1, 0, 0,0, 0,0 }, + { ARM::t2SUBSri,ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 2,2, 0,0 }, + { ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0,0 }, + { ARM::t2SXTBr, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0,0 }, + { ARM::t2SXTHr, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0,0 }, + { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0,0 }, + { ARM::t2UXTBr, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0,0 }, + { ARM::t2UXTHr, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0,0 }, // FIXME: Clean this up after splitting each Thumb load / store opcode // into multiple ones. - { ARM::t2LDRi12,ARM::tLDRi, ARM::tLDRspi, 5, 8, 1, 0, 0,0, 1 }, - { ARM::t2LDRs, ARM::tLDRr, 0, 0, 0, 1, 0, 0,0, 1 }, - { ARM::t2LDRBi12,ARM::tLDRBi, 0, 5, 0, 1, 0, 0,0, 1 }, - { ARM::t2LDRBs, ARM::tLDRBr, 0, 0, 0, 1, 0, 0,0, 1 }, - { ARM::t2LDRHi12,ARM::tLDRHi, 0, 5, 0, 1, 0, 0,0, 1 }, - { ARM::t2LDRHs, ARM::tLDRHr, 0, 0, 0, 1, 0, 0,0, 1 }, - { ARM::t2LDRSBs,ARM::tLDRSB, 0, 0, 0, 1, 0, 0,0, 1 }, - { ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 1 }, - { ARM::t2STRi12,ARM::tSTRi, ARM::tSTRspi, 5, 8, 1, 0, 0,0, 1 }, - { ARM::t2STRs, ARM::tSTRr, 0, 0, 0, 1, 0, 0,0, 1 }, - { ARM::t2STRBi12,ARM::tSTRBi, 0, 5, 0, 1, 0, 0,0, 1 }, - { ARM::t2STRBs, ARM::tSTRBr, 0, 0, 0, 1, 0, 0,0, 1 }, - { ARM::t2STRHi12,ARM::tSTRHi, 0, 5, 0, 1, 0, 0,0, 1 }, - { ARM::t2STRHs, ARM::tSTRHr, 0, 0, 0, 1, 0, 0,0, 1 }, + { ARM::t2LDRi12,ARM::tLDRi, ARM::tLDRspi, 5, 8, 1, 0, 0,0, 0,1 }, + { ARM::t2LDRs, ARM::tLDRr, 0, 0, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2LDRBi12,ARM::tLDRBi, 0, 5, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2LDRBs, ARM::tLDRBr, 0, 0, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2LDRHi12,ARM::tLDRHi, 0, 5, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2LDRHs, ARM::tLDRHr, 0, 0, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2LDRSBs,ARM::tLDRSB, 0, 0, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2STRi12,ARM::tSTRi, ARM::tSTRspi, 5, 8, 1, 0, 0,0, 0,1 }, + { ARM::t2STRs, ARM::tSTRr, 0, 0, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2STRBi12,ARM::tSTRBi, 0, 5, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2STRBs, ARM::tSTRBr, 0, 0, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2STRHi12,ARM::tSTRHi, 0, 5, 0, 1, 0, 0,0, 0,1 }, + { ARM::t2STRHs, ARM::tSTRHr, 0, 0, 0, 1, 0, 0,0, 0,1 }, - { ARM::t2LDMIA, ARM::tLDMIA, 0, 0, 0, 1, 1, 1,1, 1 }, - { ARM::t2LDMIA_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 1 }, - { ARM::t2LDMIA_UPD,ARM::tLDMIA_UPD,ARM::tPOP,0, 0, 1, 1, 1,1, 1 }, + { ARM::t2LDMIA, ARM::tLDMIA, 0, 0, 0, 1, 1, 1,1, 0,1 }, + { ARM::t2LDMIA_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 0,1 }, + { ARM::t2LDMIA_UPD,ARM::tLDMIA_UPD,ARM::tPOP,0, 0, 1, 1, 1,1, 0,1 }, // ARM::t2STM (with no basereg writeback) has no Thumb1 equivalent - { ARM::t2STMIA_UPD,ARM::tSTMIA_UPD, 0, 0, 0, 1, 1, 1,1, 1 }, - { ARM::t2STMDB_UPD, 0, ARM::tPUSH, 0, 0, 1, 1, 1,1, 1 }, + { ARM::t2STMIA_UPD,ARM::tSTMIA_UPD, 0, 0, 0, 1, 1, 1,1, 0,1 }, + { ARM::t2STMDB_UPD, 0, ARM::tPUSH, 0, 0, 1, 1, 1,1, 0,1 }, }; class Thumb2SizeReduce : public MachineFunctionPass { @@ -133,6 +138,7 @@ namespace { Thumb2SizeReduce(); const Thumb2InstrInfo *TII; + const ARMSubtarget *STI; virtual bool runOnMachineFunction(MachineFunction &MF); @@ -144,6 +150,8 @@ namespace { /// ReduceOpcodeMap - Maps wide opcode to index of entry in ReduceTable. DenseMap ReduceOpcodeMap; + bool canAddPseudoFlagDep(MachineInstr *Def, MachineInstr *Use); + bool VerifyPredAndCC(MachineInstr *MI, const ReduceEntry &Entry, bool is2Addr, ARMCC::CondCodes Pred, bool LiveCPSR, bool &HasCC, bool &CCDead); @@ -152,19 +160,20 @@ namespace { const ReduceEntry &Entry); bool ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, - const ReduceEntry &Entry, bool LiveCPSR); + const ReduceEntry &Entry, bool LiveCPSR, + MachineInstr *CPSRDef); /// ReduceTo2Addr - Reduce a 32-bit instruction to a 16-bit two-address /// instruction. bool ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, const ReduceEntry &Entry, - bool LiveCPSR); + bool LiveCPSR, MachineInstr *CPSRDef); /// ReduceToNarrow - Reduce a 32-bit instruction to a 16-bit /// non-two-address instruction. bool ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, const ReduceEntry &Entry, - bool LiveCPSR); + bool LiveCPSR, MachineInstr *CPSRDef); /// ReduceMBB - Reduce width of instructions in the specified basic block. bool ReduceMBB(MachineBasicBlock &MBB); @@ -187,6 +196,52 @@ static bool HasImplicitCPSRDef(const TargetInstrDesc &TID) { return false; } +/// canAddPseudoFlagDep - For A9 (and other out-of-order) implementations, +/// the 's' 16-bit instruction partially update CPSR. Abort the +/// transformation to avoid adding false dependency on last CPSR setting +/// instruction which hurts the ability for out-of-order execution engine +/// to do register renaming magic. +/// This function checks if there is a read-of-write dependency between the +/// last instruction that defines the CPSR and the current instruction. If there +/// is, then there is no harm done since the instruction cannot be retired +/// before the CPSR setting instruction anyway. +/// Note, we are not doing full dependency analysis here for the sake of compile +/// time. We're not looking for cases like: +/// r0 = muls ... +/// r1 = add.w r0, ... +/// ... +/// = mul.w r1 +/// In this case it would have been ok to narrow the mul.w to muls since there +/// are indirect RAW dependency between the muls and the mul.w +bool +Thumb2SizeReduce::canAddPseudoFlagDep(MachineInstr *Def, MachineInstr *Use) { + if (!Def || !STI->avoidCPSRPartialUpdate()) + return false; + + SmallSet Defs; + for (unsigned i = 0, e = Def->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = Def->getOperand(i); + if (!MO.isReg() || MO.isUndef() || MO.isUse()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0 || Reg == ARM::CPSR) + continue; + Defs.insert(Reg); + } + + for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = Use->getOperand(i); + if (!MO.isReg() || MO.isUndef() || MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + if (Defs.count(Reg)) + return false; + } + + // No read-after-write dependency. The narrowing will add false dependency. + return true; +} + bool Thumb2SizeReduce::VerifyPredAndCC(MachineInstr *MI, const ReduceEntry &Entry, bool is2Addr, ARMCC::CondCodes Pred, @@ -410,7 +465,10 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, MIB.addOperand(MI->getOperand(OpNum)); // Transfer memoperands. - (*MIB).setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); + MIB->setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); + + // Transfer MI flags. + MIB.setMIFlags(MI->getFlags()); DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB); @@ -422,7 +480,7 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, bool Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, const ReduceEntry &Entry, - bool LiveCPSR) { + bool LiveCPSR, MachineInstr *CPSRDef) { if (Entry.LowRegs1 && !VerifyLowRegs(MI)) return false; @@ -440,12 +498,12 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, switch (Opc) { default: break; case ARM::t2ADDSri: { - if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR)) + if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, CPSRDef)) return true; // fallthrough } case ARM::t2ADDSrr: - return ReduceToNarrow(MBB, MI, Entry, LiveCPSR); + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); } } break; @@ -453,13 +511,13 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, case ARM::t2RSBri: case ARM::t2RSBSri: if (MI->getOperand(2).getImm() == 0) - return ReduceToNarrow(MBB, MI, Entry, LiveCPSR); + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); break; case ARM::t2MOVi16: // Can convert only 'pure' immediate operands, not immediates obtained as // globals' addresses. if (MI->getOperand(1).isImm()) - return ReduceToNarrow(MBB, MI, Entry, LiveCPSR); + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); break; case ARM::t2CMPrr: { // Try to reduce to the lo-reg only version first. Why there are two @@ -468,17 +526,17 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, // are prioritized, but the table assumes a unique entry for each // source insn opcode. So for now, we hack a local entry record to use. static const ReduceEntry NarrowEntry = - { ARM::t2CMPrr,ARM::tCMPr, 0, 0, 0, 1, 1,2, 0, 1 }; - if (ReduceToNarrow(MBB, MI, NarrowEntry, LiveCPSR)) + { ARM::t2CMPrr,ARM::tCMPr, 0, 0, 0, 1, 1,2, 0, 0,1 }; + if (ReduceToNarrow(MBB, MI, NarrowEntry, LiveCPSR, CPSRDef)) return true; - return ReduceToNarrow(MBB, MI, Entry, LiveCPSR); + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); } case ARM::t2ADDrSPi: { static const ReduceEntry NarrowEntry = - { ARM::t2ADDrSPi,ARM::tADDspi, 0, 7, 0, 1, 0, 1, 0, 1 }; + { ARM::t2ADDrSPi,ARM::tADDspi, 0, 7, 0, 1, 0, 1, 0, 0,1 }; if (MI->getOperand(0).getReg() == ARM::SP) - return ReduceToNarrow(MBB, MI, NarrowEntry, LiveCPSR); - return ReduceToNarrow(MBB, MI, Entry, LiveCPSR); + return ReduceToNarrow(MBB, MI, NarrowEntry, LiveCPSR, CPSRDef); + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef); } } return false; @@ -487,7 +545,7 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI, bool Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, const ReduceEntry &Entry, - bool LiveCPSR) { + bool LiveCPSR, MachineInstr *CPSRDef) { if (ReduceLimit2Addr != -1 && ((int)Num2Addrs >= ReduceLimit2Addr)) return false; @@ -542,6 +600,12 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, if (!VerifyPredAndCC(MI, Entry, true, Pred, LiveCPSR, HasCC, CCDead)) return false; + // Avoid adding a false dependency on partial flag update by some 16-bit + // instructions which has the 's' bit set. + if (Entry.PartFlag && NewTID.hasOptionalDef() && HasCC && + canAddPseudoFlagDep(CPSRDef, MI)) + return false; + // Add the 16-bit instruction. DebugLoc dl = MI->getDebugLoc(); MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID); @@ -563,6 +627,9 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, MIB.addOperand(MI->getOperand(i)); } + // Transfer MI flags. + MIB.setMIFlags(MI->getFlags()); + DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB); MBB.erase(MI); @@ -573,7 +640,7 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI, bool Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, const ReduceEntry &Entry, - bool LiveCPSR) { + bool LiveCPSR, MachineInstr *CPSRDef) { if (ReduceLimit != -1 && ((int)NumNarrows >= ReduceLimit)) return false; @@ -626,6 +693,12 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, if (!VerifyPredAndCC(MI, Entry, false, Pred, LiveCPSR, HasCC, CCDead)) return false; + // Avoid adding a false dependency on partial flag update by some 16-bit + // instructions which has the 's' bit set. + if (Entry.PartFlag && NewTID.hasOptionalDef() && HasCC && + canAddPseudoFlagDep(CPSRDef, MI)) + return false; + // Add the 16-bit instruction. DebugLoc dl = MI->getDebugLoc(); MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID); @@ -663,6 +736,9 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, if (!TID.isPredicable() && NewTID.isPredicable()) AddDefaultPred(MIB); + // Transfer MI flags. + MIB.setMIFlags(MI->getFlags()); + DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB); MBB.erase(MI); @@ -670,7 +746,7 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI, return true; } -static bool UpdateCPSRDef(MachineInstr &MI, bool LiveCPSR) { +static bool UpdateCPSRDef(MachineInstr &MI, bool LiveCPSR, bool &DefCPSR) { bool HasDef = false; for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI.getOperand(i); @@ -678,6 +754,8 @@ static bool UpdateCPSRDef(MachineInstr &MI, bool LiveCPSR) { continue; if (MO.getReg() != ARM::CPSR) continue; + + DefCPSR = true; if (!MO.isDead()) HasDef = true; } @@ -707,6 +785,7 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) { // Yes, CPSR could be livein. bool LiveCPSR = MBB.isLiveIn(ARM::CPSR); + MachineInstr *CPSRDef = 0; MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end(); MachineBasicBlock::iterator NextMII; @@ -722,7 +801,7 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) { const ReduceEntry &Entry = ReduceTable[OPI->second]; // Ignore "special" cases for now. if (Entry.Special) { - if (ReduceSpecial(MBB, MI, Entry, LiveCPSR)) { + if (ReduceSpecial(MBB, MI, Entry, LiveCPSR, CPSRDef)) { Modified = true; MachineBasicBlock::iterator I = prior(NextMII); MI = &*I; @@ -731,7 +810,8 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) { } // Try to transform to a 16-bit two-address instruction. - if (Entry.NarrowOpc2 && ReduceTo2Addr(MBB, MI, Entry, LiveCPSR)) { + if (Entry.NarrowOpc2 && + ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, CPSRDef)) { Modified = true; MachineBasicBlock::iterator I = prior(NextMII); MI = &*I; @@ -739,7 +819,8 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) { } // Try to transform to a 16-bit non-two-address instruction. - if (Entry.NarrowOpc1 && ReduceToNarrow(MBB, MI, Entry, LiveCPSR)) { + if (Entry.NarrowOpc1 && + ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef)) { Modified = true; MachineBasicBlock::iterator I = prior(NextMII); MI = &*I; @@ -747,7 +828,14 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) { } ProcessNext: - LiveCPSR = UpdateCPSRDef(*MI, LiveCPSR); + bool DefCPSR = false; + LiveCPSR = UpdateCPSRDef(*MI, LiveCPSR, DefCPSR); + if (MI->getDesc().isCall()) + // Calls don't really set CPSR. + CPSRDef = 0; + else if (DefCPSR) + // This is the last CPSR defining instruction. + CPSRDef = MI; } return Modified; @@ -756,6 +844,7 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) { bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) { const TargetMachine &TM = MF.getTarget(); TII = static_cast(TM.getInstrInfo()); + STI = &TM.getSubtarget(); bool Modified = false; for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) diff --git a/contrib/llvm/lib/Target/Alpha/Alpha.td b/contrib/llvm/lib/Target/Alpha/Alpha.td index 4508eda897d2..ae79c2e4b70e 100644 --- a/contrib/llvm/lib/Target/Alpha/Alpha.td +++ b/contrib/llvm/lib/Target/Alpha/Alpha.td @@ -21,7 +21,7 @@ include "llvm/Target/Target.td" //===----------------------------------------------------------------------===// def FeatureCIX : SubtargetFeature<"cix", "HasCT", "true", - "Enable CIX extentions">; + "Enable CIX extensions">; //===----------------------------------------------------------------------===// // Register File Description diff --git a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp index c4f43ab9e4e7..ee404f06fc43 100644 --- a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp @@ -296,7 +296,7 @@ AlphaTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Build a sequence of copy-to-reg nodes chained together with token chain and // flag operands which copy the outgoing args into registers. The InFlag in - // necessary since all emited instructions must be stuck together. + // necessary since all emitted instructions must be stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, diff --git a/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.td b/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.td index 099d7157ca2b..b20171224e29 100644 --- a/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.td +++ b/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.td @@ -1030,7 +1030,7 @@ def : Pat<(brcond (setune F8RC:$RA, immFPZ), bb:$DISP), //WMB Mfc 18.4400 Write memory barrier //MF_FPCR F-P 17.025 Move from FPCR //MT_FPCR F-P 17.024 Move to FPCR -//There are in the Multimedia extentions, so let's not use them yet +//There are in the Multimedia extensions, so let's not use them yet //def MAXSB8 : OForm<0x1C, 0x3E, "MAXSB8 $RA,$RB,$RC">; //Vector signed byte maximum //def MAXSW4 : OForm< 0x1C, 0x3F, "MAXSW4 $RA,$RB,$RC">; //Vector signed word maximum //def MAXUB8 : OForm<0x1C, 0x3C, "MAXUB8 $RA,$RB,$RC">; //Vector unsigned byte maximum diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp index 7c80eec3ba63..1e1f8c9dc256 100644 --- a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp @@ -345,7 +345,7 @@ BlackfinTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. - // The InFlag in necessary since all emited instructions must be + // The InFlag in necessary since all emitted instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { diff --git a/contrib/llvm/lib/Target/CBackend/CBackend.cpp b/contrib/llvm/lib/Target/CBackend/CBackend.cpp index 6c555a3e9d1f..358d1b35b66c 100644 --- a/contrib/llvm/lib/Target/CBackend/CBackend.cpp +++ b/contrib/llvm/lib/Target/CBackend/CBackend.cpp @@ -2440,24 +2440,6 @@ void CWriter::visitReturnInst(ReturnInst &I) { return; } - if (I.getNumOperands() > 1) { - Out << " {\n"; - Out << " "; - printType(Out, I.getParent()->getParent()->getReturnType()); - Out << " llvm_cbe_mrv_temp = {\n"; - for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { - Out << " "; - writeOperand(I.getOperand(i)); - if (i != e - 1) - Out << ","; - Out << "\n"; - } - Out << " };\n"; - Out << " return llvm_cbe_mrv_temp;\n"; - Out << " }\n"; - return; - } - Out << " return"; if (I.getNumOperands()) { Out << ' '; diff --git a/contrib/llvm/lib/Target/CellSPU/SPU64InstrInfo.td b/contrib/llvm/lib/Target/CellSPU/SPU64InstrInfo.td index 5ef5716bd8cf..f340edfb0f86 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPU64InstrInfo.td +++ b/contrib/llvm/lib/Target/CellSPU/SPU64InstrInfo.td @@ -24,7 +24,7 @@ // 5. The code sequences for r64 and v2i64 are probably overly conservative, // compared to the code that gcc produces. // -// M00$E B!tes Kan be Pretty N@sTi!!!!! (appologies to Monty!) +// M00$E B!tes Kan be Pretty N@sTi!!!!! (apologies to Monty!) //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ // selb instruction definition for i64. Note that the selection mask is diff --git a/contrib/llvm/lib/Target/CellSPU/SPUAsmPrinter.cpp b/contrib/llvm/lib/Target/CellSPU/SPUAsmPrinter.cpp index 40404614b703..fd96694b32fe 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPUAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/CellSPU/SPUAsmPrinter.cpp @@ -182,6 +182,10 @@ namespace { printOp(MI->getOperand(OpNo), O); } + void printHBROperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + printOp(MI->getOperand(OpNo), O); + } + void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { // Used to generate a ".-", but it turns out that the assembler // really wants the target. @@ -279,6 +283,9 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { } O << *Mang->getSymbol(MO.getGlobal()); return; + case MachineOperand::MO_MCSymbol: + O << *(MO.getMCSymbol()); + return; default: O << ""; return; diff --git a/contrib/llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp b/contrib/llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp index d2261562e721..9351ffdc0b7f 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/CellSPU/SPUISelDAGToDAG.cpp @@ -321,12 +321,17 @@ SPUDAGToDAGISel::SelectAFormAddr(SDNode *Op, SDValue N, SDValue &Base, // These match the addr256k operand type: EVT OffsVT = MVT::i16; SDValue Zero = CurDAG->getTargetConstant(0, OffsVT); + int64_t val; switch (N.getOpcode()) { case ISD::Constant: + val = dyn_cast(N.getNode())->getSExtValue(); + Base = CurDAG->getTargetConstant( val , MVT::i32); + Index = Zero; + return true; break; case ISD::ConstantPool: case ISD::GlobalAddress: - report_fatal_error("SPU SelectAFormAddr: Constant/Pool/Global not lowered."); + report_fatal_error("SPU SelectAFormAddr: Pool/Global not lowered."); /*NOTREACHED*/ case ISD::TargetConstant: diff --git a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp index 743a4d7a0f78..8668da3ca2f8 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp +++ b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp @@ -705,7 +705,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) { offset )); - // Shift the low similarily + // Shift the low similarly // TODO: add SPUISD::SHL_BYTES low = DAG.getNode(SPUISD::SHL_BYTES, dl, MVT::i128, low, offset ); diff --git a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h index dd48d7bafaef..cf883e25ed72 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h +++ b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h @@ -183,14 +183,6 @@ namespace llvm { virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty) const; - - /// After allocating this many registers, the allocator should feel - /// register pressure. The value is a somewhat random guess, based on the - /// number of non callee saved registers in the C calling convention. - virtual unsigned getRegPressureLimit( const TargetRegisterClass *RC, - MachineFunction &MF) const{ - return 50; - } }; } diff --git a/contrib/llvm/lib/Target/CellSPU/SPUInstrFormats.td b/contrib/llvm/lib/Target/CellSPU/SPUInstrFormats.td index 21bc275209c6..bdbe2552dcdd 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPUInstrFormats.td +++ b/contrib/llvm/lib/Target/CellSPU/SPUInstrFormats.td @@ -296,3 +296,25 @@ class Pseudo pattern> let Pattern = pattern; let Inst{31-0} = 0; } + +//===----------------------------------------------------------------------===// +// Branch hint formats +//===----------------------------------------------------------------------===// +// For hbrr and hbra +class HBI16Form opcode, dag IOL, string asmstr> + : Instruction { + field bits<32> Inst; + bits<16>i16; + bits<9>RO; + + let Namespace = "SPU"; + let InOperandList = IOL; + let OutOperandList = (outs); //no output + let AsmString = asmstr; + let Itinerary = BranchHints; + + let Inst{0-6} = opcode; + let Inst{7-8} = RO{8-7}; + let Inst{9-24} = i16; + let Inst{25-31} = RO{6-0}; +} diff --git a/contrib/llvm/lib/Target/CellSPU/SPUInstrInfo.cpp b/contrib/llvm/lib/Target/CellSPU/SPUInstrInfo.cpp index f9e6c72ef310..080434d66789 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPUInstrInfo.cpp +++ b/contrib/llvm/lib/Target/CellSPU/SPUInstrInfo.cpp @@ -21,6 +21,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/MC/MCContext.h" using namespace llvm; @@ -281,9 +282,20 @@ SPUInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, return true; } +// search MBB for branch hint labels and branch hit ops +static void removeHBR( MachineBasicBlock &MBB) { + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I){ + if (I->getOpcode() == SPU::HBRA || + I->getOpcode() == SPU::HBR_LABEL){ + I=MBB.erase(I); + } + } +} + unsigned SPUInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { MachineBasicBlock::iterator I = MBB.end(); + removeHBR(MBB); if (I == MBB.begin()) return 0; --I; @@ -314,6 +326,23 @@ SPUInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { return 2; } +/** Find the optimal position for a hint branch instruction in a basic block. + * This should take into account: + * -the branch hint delays + * -congestion of the memory bus + * -dual-issue scheduling (i.e. avoid insertion of nops) + * Current implementation is rather simplistic. + */ +static MachineBasicBlock::iterator findHBRPosition(MachineBasicBlock &MBB) +{ + MachineBasicBlock::iterator J = MBB.end(); + for( int i=0; i<8; i++) { + if( J == MBB.begin() ) return J; + J--; + } + return J; +} + unsigned SPUInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, @@ -324,32 +353,61 @@ SPUInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, assert((Cond.size() == 2 || Cond.size() == 0) && "SPU branch conditions have two components!"); + MachineInstrBuilder MIB; + //TODO: make a more accurate algorithm. + bool haveHBR = MBB.size()>8; + + removeHBR(MBB); + MCSymbol *branchLabel = MBB.getParent()->getContext().CreateTempSymbol(); + // Add a label just before the branch + if (haveHBR) + MIB = BuildMI(&MBB, DL, get(SPU::HBR_LABEL)).addSym(branchLabel); + // One-way branch. if (FBB == 0) { if (Cond.empty()) { // Unconditional branch - MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(SPU::BR)); + MIB = BuildMI(&MBB, DL, get(SPU::BR)); MIB.addMBB(TBB); DEBUG(errs() << "Inserted one-way uncond branch: "); DEBUG((*MIB).dump()); + + // basic blocks have just one branch so it is safe to add the hint a its + if (haveHBR) { + MIB = BuildMI( MBB, findHBRPosition(MBB), DL, get(SPU::HBRA)); + MIB.addSym(branchLabel); + MIB.addMBB(TBB); + } } else { // Conditional branch - MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); + MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); MIB.addReg(Cond[1].getReg()).addMBB(TBB); + if (haveHBR) { + MIB = BuildMI(MBB, findHBRPosition(MBB), DL, get(SPU::HBRA)); + MIB.addSym(branchLabel); + MIB.addMBB(TBB); + } + DEBUG(errs() << "Inserted one-way cond branch: "); DEBUG((*MIB).dump()); } return 1; } else { - MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); + MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); MachineInstrBuilder MIB2 = BuildMI(&MBB, DL, get(SPU::BR)); // Two-way Conditional Branch. MIB.addReg(Cond[1].getReg()).addMBB(TBB); MIB2.addMBB(FBB); + if (haveHBR) { + MIB = BuildMI( MBB, findHBRPosition(MBB), DL, get(SPU::HBRA)); + MIB.addSym(branchLabel); + MIB.addMBB(FBB); + } + DEBUG(errs() << "Inserted conditional branch: "); DEBUG((*MIB).dump()); DEBUG(errs() << "part 2: "); diff --git a/contrib/llvm/lib/Target/CellSPU/SPUInstrInfo.td b/contrib/llvm/lib/Target/CellSPU/SPUInstrInfo.td index 25f6fd000b8b..e103c9b6a5af 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPUInstrInfo.td +++ b/contrib/llvm/lib/Target/CellSPU/SPUInstrInfo.td @@ -28,6 +28,8 @@ let hasCtrlDep = 1, Defs = [R1], Uses = [R1] in { def ADJCALLSTACKUP : Pseudo<(outs), (ins u16imm_i32:$amt), "${:comment} ADJCALLSTACKUP", [(callseq_end timm:$amt)]>; + def HBR_LABEL : Pseudo<(outs), (ins hbrtarget:$targ), + "$targ:\t${:comment}branch hint target",[ ]>; } //===----------------------------------------------------------------------===// @@ -2013,9 +2015,9 @@ class SHLHInst pattern>: RotShiftVec, pattern>; class SHLHVecInst: - SHLHInst<(outs VECREG:$rT), (ins VECREG:$rA, R16C:$rB), + SHLHInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB), [(set (vectype VECREG:$rT), - (SPUvec_shl (vectype VECREG:$rA), R16C:$rB))]>; + (SPUvec_shl (vectype VECREG:$rA), (vectype VECREG:$rB)))]>; multiclass ShiftLeftHalfword { @@ -2063,9 +2065,9 @@ class SHLInst pattern>: multiclass ShiftLeftWord { def v4i32: - SHLInst<(outs VECREG:$rT), (ins VECREG:$rA, R16C:$rB), + SHLInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB), [(set (v4i32 VECREG:$rT), - (SPUvec_shl (v4i32 VECREG:$rA), R16C:$rB))]>; + (SPUvec_shl (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)))]>; def r32: SHLInst<(outs R32C:$rT), (ins R32C:$rA, R32C:$rB), [(set R32C:$rT, (shl R32C:$rA, R32C:$rB))]>; @@ -2511,19 +2513,11 @@ class ROTHMInst pattern>: RotShiftVec, pattern>; def ROTHMv8i16: - ROTHMInst<(outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB), + ROTHMInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB), [/* see patterns below - $rB must be negated */]>; -def : Pat<(SPUvec_srl (v8i16 VECREG:$rA), R32C:$rB), - (ROTHMv8i16 VECREG:$rA, (SFIr32 R32C:$rB, 0))>; - -def : Pat<(SPUvec_srl (v8i16 VECREG:$rA), R16C:$rB), - (ROTHMv8i16 VECREG:$rA, - (SFIr32 (XSHWr16 R16C:$rB), 0))>; - -def : Pat<(SPUvec_srl (v8i16 VECREG:$rA), R8C:$rB), - (ROTHMv8i16 VECREG:$rA, - (SFIr32 (XSHWr16 (XSBHr8 R8C:$rB) ), 0))>; +def : Pat<(SPUvec_srl (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)), + (ROTHMv8i16 VECREG:$rA, (SFHIvec VECREG:$rB, 0))>; // ROTHM r16 form: Rotate 16-bit quantity to right, zero fill at the left // Note: This instruction doesn't match a pattern because rB must be negated @@ -2584,19 +2578,11 @@ class ROTMInst pattern>: RotShiftVec, pattern>; def ROTMv4i32: - ROTMInst<(outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB), + ROTMInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB), [/* see patterns below - $rB must be negated */]>; -def : Pat<(SPUvec_srl (v4i32 VECREG:$rA), R32C:$rB), - (ROTMv4i32 VECREG:$rA, (SFIr32 R32C:$rB, 0))>; - -def : Pat<(SPUvec_srl (v4i32 VECREG:$rA), R16C:$rB), - (ROTMv4i32 VECREG:$rA, - (SFIr32 (XSHWr16 R16C:$rB), 0))>; - -def : Pat<(SPUvec_srl (v4i32 VECREG:$rA), R8C:$rB), - (ROTMv4i32 VECREG:$rA, - (SFIr32 (XSHWr16 (XSBHr8 R8C:$rB)), 0))>; +def : Pat<(SPUvec_srl (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)), + (ROTMv4i32 VECREG:$rA, (SFIvec VECREG:$rB, 0))>; def ROTMr32: ROTMInst<(outs R32C:$rT), (ins R32C:$rA, R32C:$rB), @@ -2802,20 +2788,12 @@ defm ROTQMBII: RotateMaskQuadByBitsImm; //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ def ROTMAHv8i16: - RRForm<0b01111010000, (outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB), + RRForm<0b01111010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB), "rotmah\t$rT, $rA, $rB", RotShiftVec, [/* see patterns below - $rB must be negated */]>; -def : Pat<(SPUvec_sra (v8i16 VECREG:$rA), R32C:$rB), - (ROTMAHv8i16 VECREG:$rA, (SFIr32 R32C:$rB, 0))>; - -def : Pat<(SPUvec_sra (v8i16 VECREG:$rA), R16C:$rB), - (ROTMAHv8i16 VECREG:$rA, - (SFIr32 (XSHWr16 R16C:$rB), 0))>; - -def : Pat<(SPUvec_sra (v8i16 VECREG:$rA), R8C:$rB), - (ROTMAHv8i16 VECREG:$rA, - (SFIr32 (XSHWr16 (XSBHr8 R8C:$rB)), 0))>; +def : Pat<(SPUvec_sra (v8i16 VECREG:$rA), (v8i16 VECREG:$rB)), + (ROTMAHv8i16 VECREG:$rA, (SFHIvec VECREG:$rB, 0))>; def ROTMAHr16: RRForm<0b01111010000, (outs R16C:$rT), (ins R16C:$rA, R32C:$rB), @@ -2857,20 +2835,12 @@ def : Pat<(sra R16C:$rA, (i8 imm:$val)), (ROTMAHIr16 R16C:$rA, (TO_IMM32 uimm7:$val))>; def ROTMAv4i32: - RRForm<0b01011010000, (outs VECREG:$rT), (ins VECREG:$rA, R32C:$rB), + RRForm<0b01011010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB), "rotma\t$rT, $rA, $rB", RotShiftVec, [/* see patterns below - $rB must be negated */]>; -def : Pat<(SPUvec_sra (v4i32 VECREG:$rA), R32C:$rB), - (ROTMAv4i32 VECREG:$rA, (SFIr32 R32C:$rB, 0))>; - -def : Pat<(SPUvec_sra (v4i32 VECREG:$rA), R16C:$rB), - (ROTMAv4i32 VECREG:$rA, - (SFIr32 (XSHWr16 R16C:$rB), 0))>; - -def : Pat<(SPUvec_sra (v4i32 VECREG:$rA), R8C:$rB), - (ROTMAv4i32 VECREG:$rA, - (SFIr32 (XSHWr16 (XSBHr8 R8C:$rB)), 0))>; +def : Pat<(SPUvec_sra (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)), + (ROTMAv4i32 VECREG:$rA, (SFIvec (v4i32 VECREG:$rB), 0))>; def ROTMAr32: RRForm<0b01011010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB), @@ -4208,8 +4178,8 @@ def : Pat<(fabs (v4f32 VECREG:$rA)), //===----------------------------------------------------------------------===// // Hint for branch instructions: //===----------------------------------------------------------------------===// - -/* def HBR : SPUInstr<(outs), (ins), "hbr\t" */ +def HBRA : + HBI16Form<0b0001001,(ins hbrtarget:$brinst, brtarget:$btarg), "hbra\t$brinst, $btarg">; //===----------------------------------------------------------------------===// // Execution, Load NOP (execute NOPs belong in even pipeline, load NOPs belong diff --git a/contrib/llvm/lib/Target/CellSPU/SPURegisterInfo.h b/contrib/llvm/lib/Target/CellSPU/SPURegisterInfo.h index 641da0480a8d..1708c5983722 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPURegisterInfo.h +++ b/contrib/llvm/lib/Target/CellSPU/SPURegisterInfo.h @@ -46,6 +46,14 @@ namespace llvm { virtual const TargetRegisterClass * getPointerRegClass(unsigned Kind = 0) const; + /// After allocating this many registers, the allocator should feel + /// register pressure. The value is a somewhat random guess, based on the + /// number of non callee saved registers in the C calling convention. + virtual unsigned getRegPressureLimit( const TargetRegisterClass *RC, + MachineFunction &MF) const{ + return 50; + } + //! Return the array of callee-saved registers virtual const unsigned* getCalleeSavedRegs(const MachineFunction *MF) const; diff --git a/contrib/llvm/lib/Target/CppBackend/CPPBackend.cpp b/contrib/llvm/lib/Target/CppBackend/CPPBackend.cpp index 71d6049c8a1b..797cfd597e60 100644 --- a/contrib/llvm/lib/Target/CppBackend/CPPBackend.cpp +++ b/contrib/llvm/lib/Target/CppBackend/CPPBackend.cpp @@ -1348,12 +1348,10 @@ void CppWriter::printInstruction(const Instruction *I, const PHINode* phi = cast(I); Out << "PHINode* " << iName << " = PHINode::Create(" - << getCppName(phi->getType()) << ", \""; + << getCppName(phi->getType()) << ", " + << phi->getNumIncomingValues() << ", \""; printEscapedString(phi->getName()); Out << "\", " << bbname << ");"; - nl(Out) << iName << "->reserveOperandSpace(" - << phi->getNumIncomingValues() - << ");"; nl(Out); for (unsigned i = 0; i < phi->getNumOperands(); i+=2) { Out << iName << "->addIncoming(" diff --git a/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp b/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp index 3379ac216972..060a87b7c616 100644 --- a/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp +++ b/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp @@ -57,18 +57,26 @@ static unsigned mblazeBinary2Opcode[] = { }; static unsigned getRD(uint32_t insn) { + if (!MBlazeRegisterInfo::isRegister((insn>>21)&0x1F)) + return UNSUPPORTED; return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>21)&0x1F); } static unsigned getRA(uint32_t insn) { + if (!MBlazeRegisterInfo::getRegisterFromNumbering((insn>>16)&0x1F)) + return UNSUPPORTED; return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>16)&0x1F); } static unsigned getRB(uint32_t insn) { + if (!MBlazeRegisterInfo::getRegisterFromNumbering((insn>>11)&0x1F)) + return UNSUPPORTED; return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>11)&0x1F); } static int64_t getRS(uint32_t insn) { + if (!MBlazeRegisterInfo::isSpecialRegister(insn&0x3FFF)) + return UNSUPPORTED; return MBlazeRegisterInfo::getSpecialRegisterFromNumbering(insn&0x3FFF); } @@ -489,13 +497,14 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr, raw_ostream &vStream) const { // The machine instruction. uint32_t insn; + uint64_t read; uint8_t bytes[4]; - // We always consume 4 bytes of data - size = 4; + // By default we consume 1 byte on failure + size = 1; // We want to read exactly 4 bytes of data. - if (region.readBytes(address, 4, (uint8_t*)bytes, NULL) == -1) + if (region.readBytes(address, 4, (uint8_t*)bytes, &read) == -1 || read < 4) return false; // Encoded as a big-endian 32-bit word in the stream. @@ -509,44 +518,63 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr, instr.setOpcode(opcode); + unsigned RD = getRD(insn); + unsigned RA = getRA(insn); + unsigned RB = getRB(insn); + unsigned RS = getRS(insn); + uint64_t tsFlags = MBlazeInsts[opcode].TSFlags; switch ((tsFlags & MBlazeII::FormMask)) { - default: llvm_unreachable("unknown instruction encoding"); + default: + return false; case MBlazeII::FRRRR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRB(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RB)); + instr.addOperand(MCOperand::CreateReg(RA)); break; case MBlazeII::FRRR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RA)); + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FRI: switch (opcode) { - default: llvm_unreachable("unknown instruction encoding"); + default: + return false; case MBlaze::MFS: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(insn&0x3FFF)); break; case MBlaze::MTS: + if (RA == UNSUPPORTED) + return false; instr.addOperand(MCOperand::CreateImm(insn&0x3FFF)); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + instr.addOperand(MCOperand::CreateReg(RA)); break; case MBlaze::MSRSET: case MBlaze::MSRCLR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(insn&0x7FFF)); break; } break; case MBlazeII::FRRI: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RA)); switch (opcode) { default: instr.addOperand(MCOperand::CreateImm(getIMM(insn))); @@ -560,27 +588,37 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr, break; case MBlazeII::FCRR: - instr.addOperand(MCOperand::CreateReg(getRA(insn))); - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RA == UNSUPPORTED || RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RA)); + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FCRI: - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RA)); instr.addOperand(MCOperand::CreateImm(getIMM(insn))); break; case MBlazeII::FRCR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RD == UNSUPPORTED || RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FRCI: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(getIMM(insn))); break; case MBlazeII::FCCR: - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FCCI: @@ -588,33 +626,45 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr, break; case MBlazeII::FRRCI: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RA)); instr.addOperand(MCOperand::CreateImm(getSHT(insn))); break; case MBlazeII::FRRC: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RA)); break; case MBlazeII::FRCX: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(getFSL(insn))); break; case MBlazeII::FRCS: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRS(insn))); + if (RD == UNSUPPORTED || RS == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RS)); break; case MBlazeII::FCRCS: - instr.addOperand(MCOperand::CreateReg(getRS(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RS == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RS)); + instr.addOperand(MCOperand::CreateReg(RA)); break; case MBlazeII::FCRCX: - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RA)); instr.addOperand(MCOperand::CreateImm(getFSL(insn))); break; @@ -623,16 +673,23 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr, break; case MBlazeII::FCR: - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FRIR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(getIMM(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + instr.addOperand(MCOperand::CreateReg(RA)); break; } + // We always consume 4 bytes of data on success + size = 4; + return true; } diff --git a/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h b/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h index bebc6c83d544..13c4b49f981c 100644 --- a/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h +++ b/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h @@ -18,11 +18,12 @@ namespace llvm { class MCOperand; + class TargetMachine; class MBlazeInstPrinter : public MCInstPrinter { public: - MBlazeInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) { - } + MBlazeInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) + : MCInstPrinter(MAI) {} virtual void printInst(const MCInst *MI, raw_ostream &O); diff --git a/contrib/llvm/lib/Target/MBlaze/MBlaze.td b/contrib/llvm/lib/Target/MBlaze/MBlaze.td index 1fa1e4dd5776..1245658d29ba 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlaze.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlaze.td @@ -31,49 +31,28 @@ def MBlazeInstrInfo : InstrInfo; // Microblaze Subtarget features // //===----------------------------------------------------------------------===// -def FeaturePipe3 : SubtargetFeature<"pipe3", "HasPipe3", "true", - "Implements 3-stage pipeline">; def FeatureBarrel : SubtargetFeature<"barrel", "HasBarrel", "true", "Implements barrel shifter">; def FeatureDiv : SubtargetFeature<"div", "HasDiv", "true", "Implements hardware divider">; def FeatureMul : SubtargetFeature<"mul", "HasMul", "true", "Implements hardware multiplier">; -def FeatureFSL : SubtargetFeature<"fsl", "HasFSL", "true", - "Implements FSL instructions">; -def FeatureEFSL : SubtargetFeature<"efsl", "HasEFSL", "true", - "Implements extended FSL instructions">; -def FeatureMSRSet : SubtargetFeature<"msrset", "HasMSRSet", "true", - "Implements MSR register set and clear">; -def FeatureException : SubtargetFeature<"exception", "HasException", "true", - "Implements hardware exception support">; def FeaturePatCmp : SubtargetFeature<"patcmp", "HasPatCmp", "true", "Implements pattern compare instruction">; def FeatureFPU : SubtargetFeature<"fpu", "HasFPU", "true", "Implements floating point unit">; -def FeatureESR : SubtargetFeature<"esr", "HasESR", "true", - "Implements ESR and EAR registers">; -def FeaturePVR : SubtargetFeature<"pvr", "HasPVR", "true", - "Implements processor version register">; def FeatureMul64 : SubtargetFeature<"mul64", "HasMul64", "true", "Implements multiplier with 64-bit result">; def FeatureSqrt : SubtargetFeature<"sqrt", "HasSqrt", "true", "Implements sqrt and floating point convert">; -def FeatureMMU : SubtargetFeature<"mmu", "HasMMU", "true", - "Implements memory management unit">; //===----------------------------------------------------------------------===// // MBlaze processors supported. //===----------------------------------------------------------------------===// -class Proc Features> - : Processor; - -def : Proc<"v400", []>; -def : Proc<"v500", []>; -def : Proc<"v600", []>; -def : Proc<"v700", []>; -def : Proc<"v710", []>; +def : Processor<"mblaze", MBlazeGenericItineraries, []>; +def : Processor<"mblaze3", MBlazePipe3Itineraries, []>; +def : Processor<"mblaze5", MBlazePipe5Itineraries, []>; //===----------------------------------------------------------------------===// // Instruction Descriptions diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeAsmBackend.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeAsmBackend.cpp index a4b21afa599e..08f14c365957 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeAsmBackend.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeAsmBackend.cpp @@ -150,14 +150,13 @@ void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, TargetAsmBackend *llvm::createMBlazeAsmBackend(const Target &T, const std::string &TT) { - switch (Triple(TT).getOS()) { - case Triple::Darwin: + Triple TheTriple(TT); + + if (TheTriple.isOSDarwin()) assert(0 && "Mac not supported on MBlaze"); - case Triple::MinGW32: - case Triple::Cygwin: - case Triple::Win32: + + if (TheTriple.isOSWindows()) assert(0 && "Windows not supported on MBlaze"); - default: - return new ELFMBlazeAsmBackend(T, Triple(TT).getOS()); - } + + return new ELFMBlazeAsmBackend(T, TheTriple.getOS()); } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeAsmPrinter.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeAsmPrinter.cpp index 0016df569b93..0f0f60e69f08 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeAsmPrinter.cpp @@ -319,10 +319,11 @@ isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { } static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T, + TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new MBlazeInstPrinter(MAI); + return new MBlazeInstPrinter(TM, MAI); return 0; } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp index 4399ee280098..973e96844e81 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp @@ -77,7 +77,7 @@ static bool hasImmInstruction(MachineBasicBlock::iterator &candidate) { // We must assume that unknown immediate values require more than // 16-bits to represent. - if (mop.isGlobal() || mop.isSymbol()) + if (mop.isGlobal() || mop.isSymbol() || mop.isJTI() || mop.isCPI()) return true; // FIXME: we could probably check to see if the FP value happens diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp index f39826b1cf17..21a59884a6b8 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -274,7 +274,7 @@ MBlazeTargetLowering::EmitCustomShift(MachineInstr *MI, F->insert(It, loop); F->insert(It, finish); - // Update machine-CFG edges by transfering adding all successors and + // Update machine-CFG edges by transferring adding all successors and // remaining instructions from the current block to the new block which // will contain the Phi node for the select. finish->splice(finish->begin(), MBB, @@ -456,7 +456,7 @@ MBlazeTargetLowering::EmitCustomAtomic(MachineInstr *MI, F->insert(It, start); F->insert(It, exit); - // Update machine-CFG edges by transfering adding all successors and + // Update machine-CFG edges by transferring adding all successors and // remaining instructions from the current block to the new block which // will contain the Phi node for the select. exit->splice(exit->begin(), MBB, llvm::next(MachineBasicBlock::iterator(MI)), @@ -778,7 +778,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. - // The InFlag in necessary since all emited instructions must be + // The InFlag in necessary since all emitted instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { @@ -1103,7 +1103,7 @@ MBlazeTargetLowering::getSingleConstraintMatchWeight( switch (*constraint) { default: weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); - break; + break; case 'd': case 'y': if (type->isIntegerTy()) diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFPU.td b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFPU.td index 094de5c0c1a8..4acdcfdd772c 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFPU.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFPU.td @@ -21,22 +21,22 @@ class LoadFM op, string instr_asm, PatFrag OpNode> : TA; + [(set (f32 GPR:$dst), (OpNode xaddr:$addr))], IIC_MEMl>; class LoadFMI op, string instr_asm, PatFrag OpNode> : TB; + [(set (f32 GPR:$dst), (OpNode iaddr:$addr))], IIC_MEMl>; class StoreFM op, string instr_asm, PatFrag OpNode> : TA; + [(OpNode (f32 GPR:$dst), xaddr:$addr)], IIC_MEMs>; class StoreFMI op, string instr_asm, PatFrag OpNode> : TB; + [(OpNode (f32 GPR:$dst), iaddr:$addr)], IIC_MEMs>; class ArithF op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : @@ -56,15 +56,10 @@ class ArithFR op, bits<11> flags, string instr_asm, SDNode OpNode, !strconcat(instr_asm, " $dst, $c, $b"), [(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], itin>; -class LogicF op, string instr_asm> : - TB; - class LogicFI op, string instr_asm> : TB; + [], IIC_ALU>; let rb=0 in { class ArithF2 op, bits<11> flags, string instr_asm, @@ -95,10 +90,10 @@ let rb=0 in { //===----------------------------------------------------------------------===// let Predicates=[HasFPU] in { def FORI : LogicFI<0x28, "ori ">; - def FADD : ArithF<0x16, 0x000, "fadd ", fadd, IIAlu>; - def FRSUB : ArithFR<0x16, 0x080, "frsub ", fsub, IIAlu>; - def FMUL : ArithF<0x16, 0x100, "fmul ", fmul, IIAlu>; - def FDIV : ArithF<0x16, 0x180, "fdiv ", fdiv, IIAlu>; + def FADD : ArithF<0x16, 0x000, "fadd ", fadd, IIC_FPU>; + def FRSUB : ArithFR<0x16, 0x080, "frsub ", fsub, IIC_FPU>; + def FMUL : ArithF<0x16, 0x100, "fmul ", fmul, IIC_FPU>; + def FDIV : ArithF<0x16, 0x180, "fdiv ", fdiv, IIC_FPUd>; } let Predicates=[HasFPU], isCodeGenOnly=1 in { @@ -110,19 +105,19 @@ let Predicates=[HasFPU], isCodeGenOnly=1 in { } let Predicates=[HasFPU,HasSqrt] in { - def FLT : ArithIF<0x16, 0x280, "flt ", IIAlu>; - def FINT : ArithFI<0x16, 0x300, "fint ", IIAlu>; - def FSQRT : ArithF2<0x16, 0x380, "fsqrt ", IIAlu>; + def FLT : ArithIF<0x16, 0x280, "flt ", IIC_FPUf>; + def FINT : ArithFI<0x16, 0x300, "fint ", IIC_FPUi>; + def FSQRT : ArithF2<0x16, 0x380, "fsqrt ", IIC_FPUs>; } let isAsCheapAsAMove = 1 in { - def FCMP_UN : CmpFN<0x16, 0x200, "fcmp.un", IIAlu>; - def FCMP_LT : CmpFN<0x16, 0x210, "fcmp.lt", IIAlu>; - def FCMP_EQ : CmpFN<0x16, 0x220, "fcmp.eq", IIAlu>; - def FCMP_LE : CmpFN<0x16, 0x230, "fcmp.le", IIAlu>; - def FCMP_GT : CmpFN<0x16, 0x240, "fcmp.gt", IIAlu>; - def FCMP_NE : CmpFN<0x16, 0x250, "fcmp.ne", IIAlu>; - def FCMP_GE : CmpFN<0x16, 0x260, "fcmp.ge", IIAlu>; + def FCMP_UN : CmpFN<0x16, 0x200, "fcmp.un", IIC_FPUc>; + def FCMP_LT : CmpFN<0x16, 0x210, "fcmp.lt", IIC_FPUc>; + def FCMP_EQ : CmpFN<0x16, 0x220, "fcmp.eq", IIC_FPUc>; + def FCMP_LE : CmpFN<0x16, 0x230, "fcmp.le", IIC_FPUc>; + def FCMP_GT : CmpFN<0x16, 0x240, "fcmp.gt", IIC_FPUc>; + def FCMP_NE : CmpFN<0x16, 0x250, "fcmp.ne", IIC_FPUc>; + def FCMP_GE : CmpFN<0x16, 0x260, "fcmp.ge", IIC_FPUc>; } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFSL.td b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFSL.td index 32098452416b..3082a7e227f8 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFSL.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFSL.td @@ -13,7 +13,7 @@ class FSLGet op, bits<5> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(set GPR:$dst, (OpNode immZExt4:$b))],IIC_FSLg> { bits<5> rd; bits<4> fslno; @@ -29,7 +29,7 @@ class FSLGet op, bits<5> flags, string instr_asm, Intrinsic OpNode> : class FSLGetD op, bits<5> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(set GPR:$dst, (OpNode GPR:$b))], IIC_FSLg> { bits<5> rd; bits<5> rb; @@ -45,7 +45,7 @@ class FSLGetD op, bits<5> flags, string instr_asm, Intrinsic OpNode> : class FSLPut op, bits<4> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(OpNode GPR:$v, immZExt4:$b)], IIC_FSLp> { bits<5> ra; bits<4> fslno; @@ -61,7 +61,7 @@ class FSLPut op, bits<4> flags, string instr_asm, Intrinsic OpNode> : class FSLPutD op, bits<4> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(OpNode GPR:$v, GPR:$b)], IIC_FSLp> { bits<5> ra; bits<5> rb; @@ -77,7 +77,7 @@ class FSLPutD op, bits<4> flags, string instr_asm, Intrinsic OpNode> : class FSLPutT op, bits<4> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(OpNode immZExt4:$b)], IIC_FSLp> { bits<4> fslno; @@ -92,7 +92,7 @@ class FSLPutT op, bits<4> flags, string instr_asm, Intrinsic OpNode> : class FSLPutTD op, bits<4> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(OpNode GPR:$b)], IIC_FSLp> { bits<5> rb; diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFormats.td b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFormats.td index d62574d0edee..54f605f989a3 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFormats.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFormats.td @@ -81,7 +81,7 @@ class MBlazeInst op, Format form, dag outs, dag ins, string asmstr, // Pseudo instruction class //===----------------------------------------------------------------------===// class MBlazePseudo pattern>: - MBlazeInst<0x0, FPseudo, outs, ins, asmstr, pattern, IIPseudo>; + MBlazeInst<0x0, FPseudo, outs, ins, asmstr, pattern, IIC_Pseudo>; //===----------------------------------------------------------------------===// // Type A instruction class in MBlaze : <|opcode|rd|ra|rb|flags|> diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.cpp index b353dcdef05b..794ebedf1e6a 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.cpp @@ -17,6 +17,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScoreboardHazardRecognizer.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "MBlazeGenInstrInfo.inc" diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.h b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.h index b7300c14080d..b717da8e2bec 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.h @@ -261,7 +261,6 @@ class MBlazeInstrInfo : public TargetInstrInfoImpl { virtual bool ReverseBranchCondition(SmallVectorImpl &Cond) const; - virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.td b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.td index 7b8f70a30434..896e8eae1637 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.td @@ -47,22 +47,22 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MBCallSeqEnd, //===----------------------------------------------------------------------===// // MBlaze Instruction Predicate Definitions. //===----------------------------------------------------------------------===// -def HasPipe3 : Predicate<"Subtarget.hasPipe3()">; +// def HasPipe3 : Predicate<"Subtarget.hasPipe3()">; def HasBarrel : Predicate<"Subtarget.hasBarrel()">; -def NoBarrel : Predicate<"!Subtarget.hasBarrel()">; +// def NoBarrel : Predicate<"!Subtarget.hasBarrel()">; def HasDiv : Predicate<"Subtarget.hasDiv()">; def HasMul : Predicate<"Subtarget.hasMul()">; -def HasFSL : Predicate<"Subtarget.hasFSL()">; -def HasEFSL : Predicate<"Subtarget.hasEFSL()">; -def HasMSRSet : Predicate<"Subtarget.hasMSRSet()">; -def HasException : Predicate<"Subtarget.hasException()">; +// def HasFSL : Predicate<"Subtarget.hasFSL()">; +// def HasEFSL : Predicate<"Subtarget.hasEFSL()">; +// def HasMSRSet : Predicate<"Subtarget.hasMSRSet()">; +// def HasException : Predicate<"Subtarget.hasException()">; def HasPatCmp : Predicate<"Subtarget.hasPatCmp()">; def HasFPU : Predicate<"Subtarget.hasFPU()">; -def HasESR : Predicate<"Subtarget.hasESR()">; -def HasPVR : Predicate<"Subtarget.hasPVR()">; +// def HasESR : Predicate<"Subtarget.hasESR()">; +// def HasPVR : Predicate<"Subtarget.hasPVR()">; def HasMul64 : Predicate<"Subtarget.hasMul64()">; def HasSqrt : Predicate<"Subtarget.hasSqrt()">; -def HasMMU : Predicate<"Subtarget.hasMMU()">; +// def HasMMU : Predicate<"Subtarget.hasMMU()">; //===----------------------------------------------------------------------===// // MBlaze Operand, Complex Patterns and Transformations Definitions. @@ -170,18 +170,18 @@ class ArithI op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : TB; + [(set GPR:$dst, (OpNode GPR:$b, imm_type:$c))], IIC_ALU>; class ArithI32 op, string instr_asm,Operand Od, PatLeaf imm_type> : TB; + [], IIC_ALU>; class ShiftI op, bits<2> flags, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : SHT; + [(set GPR:$dst, (OpNode GPR:$b, imm_type:$c))], IIC_SHT>; class ArithR op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : @@ -193,7 +193,7 @@ class ArithRI op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : TBR; + [(set GPR:$dst, (OpNode imm_type:$b, GPR:$c))], IIC_ALU>; class ArithN op, bits<11> flags, string instr_asm, InstrItinClass itin> : @@ -204,7 +204,7 @@ class ArithN op, bits<11> flags, string instr_asm, class ArithNI op, string instr_asm,Operand Od, PatLeaf imm_type> : TB; + [], IIC_ALU>; class ArithRN op, bits<11> flags, string instr_asm, InstrItinClass itin> : @@ -215,7 +215,7 @@ class ArithRN op, bits<11> flags, string instr_asm, class ArithRNI op, string instr_asm,Operand Od, PatLeaf imm_type> : TBR; + [], IIC_ALU>; //===----------------------------------------------------------------------===// // Misc Arithmetic Instructions @@ -224,23 +224,23 @@ class ArithRNI op, string instr_asm,Operand Od, PatLeaf imm_type> : class Logic op, bits<11> flags, string instr_asm, SDNode OpNode> : TA; + [(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], IIC_ALU>; class LogicI op, string instr_asm, SDNode OpNode> : TB; + IIC_ALU>; class LogicI32 op, string instr_asm> : TB; + [], IIC_ALU>; class PatCmp op, bits<11> flags, string instr_asm> : TA; + [], IIC_ALU>; //===----------------------------------------------------------------------===// // Memory Access Instructions @@ -248,22 +248,22 @@ class PatCmp op, bits<11> flags, string instr_asm> : class LoadM op, bits<11> flags, string instr_asm> : TA; + [], IIC_MEMl>; class LoadMI op, string instr_asm, PatFrag OpNode> : TB; + [(set (i32 GPR:$dst), (OpNode iaddr:$addr))], IIC_MEMl>; class StoreM op, bits<11> flags, string instr_asm> : TA; + [], IIC_MEMs>; class StoreMI op, string instr_asm, PatFrag OpNode> : TB; + [(OpNode (i32 GPR:$dst), iaddr:$addr)], IIC_MEMs>; //===----------------------------------------------------------------------===// // Branch Instructions @@ -271,7 +271,7 @@ class StoreMI op, string instr_asm, PatFrag OpNode> : class Branch op, bits<5> br, bits<11> flags, string instr_asm> : TA { + [], IIC_BR> { let rd = 0x0; let ra = br; let Form = FCCR; @@ -280,7 +280,7 @@ class Branch op, bits<5> br, bits<11> flags, string instr_asm> : class BranchI op, bits<5> br, string instr_asm> : TB { + [], IIC_BR> { let rd = 0; let ra = br; let Form = FCCI; @@ -292,7 +292,7 @@ class BranchI op, bits<5> br, string instr_asm> : class BranchL op, bits<5> br, bits<11> flags, string instr_asm> : TA { + [], IIC_BRl> { let ra = br; let Form = FRCR; } @@ -300,7 +300,7 @@ class BranchL op, bits<5> br, bits<11> flags, string instr_asm> : class BranchLI op, bits<5> br, string instr_asm> : TB { + [], IIC_BRl> { let ra = br; let Form = FRCI; } @@ -312,7 +312,7 @@ class BranchC op, bits<5> br, bits<11> flags, string instr_asm> : TA { + [], IIC_BRc> { let rd = br; let Form = FCRR; } @@ -320,7 +320,7 @@ class BranchC op, bits<5> br, bits<11> flags, string instr_asm> : class BranchCI op, bits<5> br, string instr_asm> : TB { + [], IIC_BRc> { let rd = br; let Form = FCRI; } @@ -330,71 +330,74 @@ class BranchCI op, bits<5> br, string instr_asm> : //===----------------------------------------------------------------------===// let isCommutable = 1, isAsCheapAsAMove = 1 in { - def ADDK : Arith<0x04, 0x000, "addk ", add, IIAlu>; + def ADDK : Arith<0x04, 0x000, "addk ", add, IIC_ALU>; def AND : Logic<0x21, 0x000, "and ", and>; def OR : Logic<0x20, 0x000, "or ", or>; def XOR : Logic<0x22, 0x000, "xor ", xor>; - def PCMPBF : PatCmp<0x20, 0x400, "pcmpbf ">; - def PCMPEQ : PatCmp<0x22, 0x400, "pcmpeq ">; - def PCMPNE : PatCmp<0x23, 0x400, "pcmpne ">; + + let Predicates=[HasPatCmp] in { + def PCMPBF : PatCmp<0x20, 0x400, "pcmpbf ">; + def PCMPEQ : PatCmp<0x22, 0x400, "pcmpeq ">; + def PCMPNE : PatCmp<0x23, 0x400, "pcmpne ">; + } let Defs = [CARRY] in { - def ADD : Arith<0x00, 0x000, "add ", addc, IIAlu>; + def ADD : Arith<0x00, 0x000, "add ", addc, IIC_ALU>; let Uses = [CARRY] in { - def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>; + def ADDC : Arith<0x02, 0x000, "addc ", adde, IIC_ALU>; } } let Uses = [CARRY] in { - def ADDKC : ArithN<0x06, 0x000, "addkc ", IIAlu>; + def ADDKC : ArithN<0x06, 0x000, "addkc ", IIC_ALU>; } } let isAsCheapAsAMove = 1 in { - def ANDN : ArithN<0x23, 0x000, "andn ", IIAlu>; - def CMP : ArithN<0x05, 0x001, "cmp ", IIAlu>; - def CMPU : ArithN<0x05, 0x003, "cmpu ", IIAlu>; - def RSUBK : ArithR<0x05, 0x000, "rsubk ", sub, IIAlu>; + def ANDN : ArithN<0x23, 0x000, "andn ", IIC_ALU>; + def CMP : ArithN<0x05, 0x001, "cmp ", IIC_ALU>; + def CMPU : ArithN<0x05, 0x003, "cmpu ", IIC_ALU>; + def RSUBK : ArithR<0x05, 0x000, "rsubk ", sub, IIC_ALU>; let Defs = [CARRY] in { - def RSUB : ArithR<0x01, 0x000, "rsub ", subc, IIAlu>; + def RSUB : ArithR<0x01, 0x000, "rsub ", subc, IIC_ALU>; let Uses = [CARRY] in { - def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>; + def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIC_ALU>; } } let Uses = [CARRY] in { - def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIAlu>; + def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIC_ALU>; } } let isCommutable = 1, Predicates=[HasMul] in { - def MUL : Arith<0x10, 0x000, "mul ", mul, IIAlu>; + def MUL : Arith<0x10, 0x000, "mul ", mul, IIC_ALUm>; } let isCommutable = 1, Predicates=[HasMul,HasMul64] in { - def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIAlu>; - def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIAlu>; + def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIC_ALUm>; + def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIC_ALUm>; } let Predicates=[HasMul,HasMul64] in { - def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIAlu>; + def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIC_ALUm>; } let Predicates=[HasBarrel] in { - def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIAlu>; - def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIAlu>; - def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIAlu>; + def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIC_SHT>; + def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIC_SHT>; + def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIC_SHT>; def BSRLI : ShiftI<0x19, 0x0, "bsrli ", srl, uimm5, immZExt5>; def BSRAI : ShiftI<0x19, 0x1, "bsrai ", sra, uimm5, immZExt5>; def BSLLI : ShiftI<0x19, 0x2, "bslli ", shl, uimm5, immZExt5>; } let Predicates=[HasDiv] in { - def IDIV : ArithR<0x12, 0x000, "idiv ", sdiv, IIAlu>; - def IDIVU : ArithR<0x12, 0x002, "idivu ", udiv, IIAlu>; + def IDIV : ArithR<0x12, 0x000, "idiv ", sdiv, IIC_ALUd>; + def IDIVU : ArithR<0x12, 0x002, "idivu ", udiv, IIC_ALUd>; } //===----------------------------------------------------------------------===// @@ -552,7 +555,7 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, def RTSD : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rtsd $target, $imm", [], - IIBranch>; + IIC_BR>; } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, @@ -560,7 +563,7 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, def RTID : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rtid $target, $imm", [], - IIBranch>; + IIC_BR>; } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, @@ -568,7 +571,7 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, def RTBD : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rtbd $target, $imm", [], - IIBranch>; + IIC_BR>; } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, @@ -576,7 +579,7 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, def RTED : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rted $target, $imm", [], - IIBranch>; + IIC_BR>; } //===----------------------------------------------------------------------===// @@ -584,7 +587,7 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, //===----------------------------------------------------------------------===// let neverHasSideEffects = 1 in { - def NOP : MBlazeInst< 0x20, FC, (outs), (ins), "nop ", [], IIAlu>; + def NOP : MBlazeInst< 0x20, FC, (outs), (ins), "nop ", [], IIC_ALU>; } let usesCustomInserter = 1 in { @@ -611,17 +614,17 @@ let usesCustomInserter = 1 in { let rb = 0 in { def SEXT16 : TA<0x24, 0x061, (outs GPR:$dst), (ins GPR:$src), - "sext16 $dst, $src", [], IIAlu>; + "sext16 $dst, $src", [], IIC_ALU>; def SEXT8 : TA<0x24, 0x060, (outs GPR:$dst), (ins GPR:$src), - "sext8 $dst, $src", [], IIAlu>; + "sext8 $dst, $src", [], IIC_ALU>; let Defs = [CARRY] in { def SRL : TA<0x24, 0x041, (outs GPR:$dst), (ins GPR:$src), - "srl $dst, $src", [], IIAlu>; + "srl $dst, $src", [], IIC_ALU>; def SRA : TA<0x24, 0x001, (outs GPR:$dst), (ins GPR:$src), - "sra $dst, $src", [], IIAlu>; + "sra $dst, $src", [], IIC_ALU>; let Uses = [CARRY] in { def SRC : TA<0x24, 0x021, (outs GPR:$dst), (ins GPR:$src), - "src $dst, $src", [], IIAlu>; + "src $dst, $src", [], IIC_ALU>; } } } @@ -637,36 +640,36 @@ let isCodeGenOnly=1 in { //===----------------------------------------------------------------------===// let Form=FRCS in { def MFS : SPC<0x25, 0x2, (outs GPR:$dst), (ins SPR:$src), - "mfs $dst, $src", [], IIAlu>; + "mfs $dst, $src", [], IIC_ALU>; } let Form=FCRCS in { def MTS : SPC<0x25, 0x3, (outs SPR:$dst), (ins GPR:$src), - "mts $dst, $src", [], IIAlu>; + "mts $dst, $src", [], IIC_ALU>; } def MSRSET : MSR<0x25, 0x20, (outs GPR:$dst), (ins uimm15:$set), - "msrset $dst, $set", [], IIAlu>; + "msrset $dst, $set", [], IIC_ALU>; def MSRCLR : MSR<0x25, 0x22, (outs GPR:$dst), (ins uimm15:$clr), - "msrclr $dst, $clr", [], IIAlu>; + "msrclr $dst, $clr", [], IIC_ALU>; let rd=0x0, Form=FCRR in { def WDC : TA<0x24, 0x64, (outs), (ins GPR:$a, GPR:$b), - "wdc $a, $b", [], IIAlu>; + "wdc $a, $b", [], IIC_WDC>; def WDCF : TA<0x24, 0x74, (outs), (ins GPR:$a, GPR:$b), - "wdc.flush $a, $b", [], IIAlu>; + "wdc.flush $a, $b", [], IIC_WDC>; def WDCC : TA<0x24, 0x66, (outs), (ins GPR:$a, GPR:$b), - "wdc.clear $a, $b", [], IIAlu>; + "wdc.clear $a, $b", [], IIC_WDC>; def WIC : TA<0x24, 0x68, (outs), (ins GPR:$a, GPR:$b), - "wic $a, $b", [], IIAlu>; + "wic $a, $b", [], IIC_WDC>; } def BRK : BranchL<0x26, 0x0C, 0x000, "brk ">; def BRKI : BranchLI<0x2E, 0x0C, "brki ">; def IMM : MBlazeInst<0x2C, FCCI, (outs), (ins simm16:$imm), - "imm $imm", [], IIAlu>; + "imm $imm", [], IIC_ALU>; //===----------------------------------------------------------------------===// // Pseudo instructions for atomic operations @@ -848,11 +851,6 @@ def : Pat<(MBWrapper tconstpool:$in), (ORI (i32 R0), tconstpool:$in)>; // Misc instructions def : Pat<(and (i32 GPR:$lh), (not (i32 GPR:$rh))),(ANDN GPR:$lh, GPR:$rh)>; -// Arithmetic with immediates -def : Pat<(add (i32 GPR:$in), imm:$imm),(ADDIK GPR:$in, imm:$imm)>; -def : Pat<(or (i32 GPR:$in), imm:$imm),(ORI GPR:$in, imm:$imm)>; -def : Pat<(xor (i32 GPR:$in), imm:$imm),(XORI GPR:$in, imm:$imm)>; - // Convert any extend loads into zero extend loads def : Pat<(extloadi8 iaddr:$src), (i32 (LBUI iaddr:$src))>; def : Pat<(extloadi16 iaddr:$src), (i32 (LHUI iaddr:$src))>; diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.cpp index fa9140d7922f..ed8511df5ee8 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -181,6 +181,26 @@ unsigned MBlazeRegisterInfo::getSpecialRegisterFromNumbering(unsigned Reg) { return 0; // Not reached } +bool MBlazeRegisterInfo::isRegister(unsigned Reg) { + return Reg <= 31; +} + +bool MBlazeRegisterInfo::isSpecialRegister(unsigned Reg) { + switch (Reg) { + case 0x0000 : case 0x0001 : case 0x0003 : case 0x0005 : + case 0x0007 : case 0x000B : case 0x000D : case 0x1000 : + case 0x1001 : case 0x1002 : case 0x1003 : case 0x1004 : + case 0x2000 : case 0x2001 : case 0x2002 : case 0x2003 : + case 0x2004 : case 0x2005 : case 0x2006 : case 0x2007 : + case 0x2008 : case 0x2009 : case 0x200A : case 0x200B : + return true; + + default: + return false; + } + return false; // Not reached +} + unsigned MBlazeRegisterInfo::getPICCallReg() { return MBlaze::R20; } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.h b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.h index 839536d4e7b5..69ec5aa48914 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.h @@ -45,6 +45,8 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { static unsigned getRegisterNumbering(unsigned RegEnum); static unsigned getRegisterFromNumbering(unsigned RegEnum); static unsigned getSpecialRegisterFromNumbering(unsigned RegEnum); + static bool isRegister(unsigned RegEnum); + static bool isSpecialRegister(unsigned RegEnum); /// Get PIC indirect call register static unsigned getPICCallReg(); diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.td b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.td index fbefb22e9f25..1a695a74bca0 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.td @@ -85,18 +85,19 @@ let Namespace = "MBlaze" in { def RTLBX : MBlazeSPRReg<0x1002, "rtlbx">, DwarfRegNum<[41]>; def RTLBLO : MBlazeSPRReg<0x1003, "rtlblo">, DwarfRegNum<[42]>; def RTLBHI : MBlazeSPRReg<0x1004, "rtlbhi">, DwarfRegNum<[43]>; - def RPVR0 : MBlazeSPRReg<0x2000, "rpvr0">, DwarfRegNum<[44]>; - def RPVR1 : MBlazeSPRReg<0x2001, "rpvr1">, DwarfRegNum<[45]>; - def RPVR2 : MBlazeSPRReg<0x2002, "rpvr2">, DwarfRegNum<[46]>; - def RPVR3 : MBlazeSPRReg<0x2003, "rpvr3">, DwarfRegNum<[47]>; - def RPVR4 : MBlazeSPRReg<0x2004, "rpvr4">, DwarfRegNum<[48]>; - def RPVR5 : MBlazeSPRReg<0x2005, "rpvr5">, DwarfRegNum<[49]>; - def RPVR6 : MBlazeSPRReg<0x2006, "rpvr6">, DwarfRegNum<[50]>; - def RPVR7 : MBlazeSPRReg<0x2007, "rpvr7">, DwarfRegNum<[51]>; - def RPVR8 : MBlazeSPRReg<0x2008, "rpvr8">, DwarfRegNum<[52]>; - def RPVR9 : MBlazeSPRReg<0x2009, "rpvr9">, DwarfRegNum<[53]>; - def RPVR10 : MBlazeSPRReg<0x200A, "rpvr10">, DwarfRegNum<[54]>; - def RPVR11 : MBlazeSPRReg<0x200B, "rpvr11">, DwarfRegNum<[55]>; + def RTLBSX : MBlazeSPRReg<0x1004, "rtlbsx">, DwarfRegNum<[44]>; + def RPVR0 : MBlazeSPRReg<0x2000, "rpvr0">, DwarfRegNum<[45]>; + def RPVR1 : MBlazeSPRReg<0x2001, "rpvr1">, DwarfRegNum<[46]>; + def RPVR2 : MBlazeSPRReg<0x2002, "rpvr2">, DwarfRegNum<[47]>; + def RPVR3 : MBlazeSPRReg<0x2003, "rpvr3">, DwarfRegNum<[48]>; + def RPVR4 : MBlazeSPRReg<0x2004, "rpvr4">, DwarfRegNum<[49]>; + def RPVR5 : MBlazeSPRReg<0x2005, "rpvr5">, DwarfRegNum<[50]>; + def RPVR6 : MBlazeSPRReg<0x2006, "rpvr6">, DwarfRegNum<[51]>; + def RPVR7 : MBlazeSPRReg<0x2007, "rpvr7">, DwarfRegNum<[52]>; + def RPVR8 : MBlazeSPRReg<0x2008, "rpvr8">, DwarfRegNum<[53]>; + def RPVR9 : MBlazeSPRReg<0x2009, "rpvr9">, DwarfRegNum<[54]>; + def RPVR10 : MBlazeSPRReg<0x200A, "rpvr10">, DwarfRegNum<[55]>; + def RPVR11 : MBlazeSPRReg<0x200B, "rpvr11">, DwarfRegNum<[56]>; // The carry bit. In the Microblaze this is really bit 29 of the // MSR register but this is the only bit of that register that we diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule.td b/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule.td index ac4d98c9240e..4662f25ceb12 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule.td @@ -8,57 +8,48 @@ //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// -// Functional units across MBlaze chips sets. Based on GCC/MBlaze backend files. +// MBlaze functional units. //===----------------------------------------------------------------------===// -def ALU : FuncUnit; -def IMULDIV : FuncUnit; +def IF : FuncUnit; +def ID : FuncUnit; +def EX : FuncUnit; +def MA : FuncUnit; +def WB : FuncUnit; //===----------------------------------------------------------------------===// // Instruction Itinerary classes used for MBlaze //===----------------------------------------------------------------------===// -def IIAlu : InstrItinClass; -def IILoad : InstrItinClass; -def IIStore : InstrItinClass; -def IIXfer : InstrItinClass; -def IIBranch : InstrItinClass; -def IIHiLo : InstrItinClass; -def IIImul : InstrItinClass; -def IIIdiv : InstrItinClass; -def IIFcvt : InstrItinClass; -def IIFmove : InstrItinClass; -def IIFcmp : InstrItinClass; -def IIFadd : InstrItinClass; -def IIFmulSingle : InstrItinClass; -def IIFmulDouble : InstrItinClass; -def IIFdivSingle : InstrItinClass; -def IIFdivDouble : InstrItinClass; -def IIFsqrtSingle : InstrItinClass; -def IIFsqrtDouble : InstrItinClass; -def IIFrecipFsqrtStep : InstrItinClass; -def IIPseudo : InstrItinClass; +def IIC_ALU : InstrItinClass; +def IIC_ALUm : InstrItinClass; +def IIC_ALUd : InstrItinClass; +def IIC_SHT : InstrItinClass; +def IIC_FSLg : InstrItinClass; +def IIC_FSLp : InstrItinClass; +def IIC_MEMs : InstrItinClass; +def IIC_MEMl : InstrItinClass; +def IIC_FPU : InstrItinClass; +def IIC_FPUd : InstrItinClass; +def IIC_FPUf : InstrItinClass; +def IIC_FPUi : InstrItinClass; +def IIC_FPUs : InstrItinClass; +def IIC_FPUc : InstrItinClass; +def IIC_BR : InstrItinClass; +def IIC_BRc : InstrItinClass; +def IIC_BRl : InstrItinClass; +def IIC_WDC : InstrItinClass; +def IIC_Pseudo : InstrItinClass; //===----------------------------------------------------------------------===// -// MBlaze Generic instruction itineraries. +// MBlaze generic instruction itineraries. //===----------------------------------------------------------------------===// -def MBlazeGenericItineraries : ProcessorItineraries< - [ALU, IMULDIV], [], [ - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]> -]>; +def MBlazeGenericItineraries : ProcessorItineraries<[], [], []>; + +//===----------------------------------------------------------------------===// +// MBlaze instruction itineraries for three stage pipeline. +//===----------------------------------------------------------------------===// +include "MBlazeSchedule3.td" + +//===----------------------------------------------------------------------===// +// MBlaze instruction itineraries for five stage pipeline. +//===----------------------------------------------------------------------===// +include "MBlazeSchedule5.td" diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule3.td b/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule3.td new file mode 100644 index 000000000000..ccbf99dbd3a2 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule3.td @@ -0,0 +1,236 @@ +//===- MBlazeSchedule3.td - MBlaze Scheduling Definitions --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MBlaze instruction itineraries for the three stage pipeline. +//===----------------------------------------------------------------------===// +def MBlazePipe3Itineraries : ProcessorItineraries< + [IF,ID,EX], [], [ + + // ALU instruction with one destination register and either two register + // source operands or one register source operand and one immediate operand. + // The instruction takes one cycle to execute in each of the stages. The + // two source operands are read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_ALU, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]>], // one cycle in execute stage + [ 2 // result ready after two cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // ALU multiply instruction with one destination register and either two + // register source operands or one register source operand and one immediate + // operand. The instruction takes one cycle to execute in each of the + // pipeline stages except the execute stage, which takes three cycles. The + // two source operands are read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_ALUm, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<3,[EX]>], // three cycles in execute stage + [ 4 // result ready after four cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // ALU divide instruction with one destination register two register source + // operands. The instruction takes one cycle to execute in each the pipeline + // stages except the execute stage, which takes 34 cycles. The two + // source operands are read during the decode stage and the result is ready + // after the execute stage. + InstrItinData< IIC_ALUd, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<34,[EX]>], // 34 cycles in execute stage + [ 35 // result ready after 35 cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Shift instruction with one destination register and either two register + // source operands or one register source operand and one immediate operand. + // The instruction takes one cycle to execute in each of the pipeline stages + // except the execute stage, which takes two cycles. The two source operands + // are read during the decode stage and the result is ready after the execute + // stage. + InstrItinData< IIC_SHT, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 3 // result ready after three cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Branch instruction with one source operand register. The instruction takes + // one cycle to execute in each of the pipeline stages. The source operand is + // read during the decode stage. + InstrItinData< IIC_BR, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]>], // one cycle in execute stage + [ 1 ]>, // first operand read after one cycle + + // Conditional branch instruction with two source operand registers. The + // instruction takes one cycle to execute in each of the pipeline stages. The + // two source operands are read during the decode stage. + InstrItinData< IIC_BRc, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]>], // one cycle in execute stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Branch and link instruction with one destination register and one source + // operand register. The instruction takes one cycle to execute in each of + // the pipeline stages. The source operand is read during the decode stage + // and the destination register is ready after the execute stage. + InstrItinData< IIC_BRl, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]>], // one cycle in execute stage + [ 2 // result ready after two cycles + , 1 ]>, // first operand read after one cycle + + // Cache control instruction with two source operand registers. The + // instruction takes one cycle to execute in each of the pipeline stages + // except the memory access stage, which takes two cycles. The source + // operands are read during the decode stage. + InstrItinData< IIC_WDC, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Floating point instruction with one destination register and two source + // operand registers. The instruction takes one cycle to execute in each of + // the pipeline stages except the execute stage, which takes six cycles. The + // source operands are read during the decode stage and the results are ready + // after the execute stage. + InstrItinData< IIC_FPU, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<6,[EX]>], // six cycles in execute stage + [ 7 // result ready after seven cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Floating point divide instruction with one destination register and two + // source operand registers. The instruction takes one cycle to execute in + // each of the pipeline stages except the execute stage, which takes 30 + // cycles. The source operands are read during the decode stage and the + // results are ready after the execute stage. + InstrItinData< IIC_FPUd, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<30,[EX]>], // one cycle in execute stage + [ 31 // result ready after 31 cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Convert floating point to integer instruction with one destination + // register and one source operand register. The instruction takes one cycle + // to execute in each of the pipeline stages except the execute stage, + // which takes seven cycles. The source operands are read during the decode + // stage and the results are ready after the execute stage. + InstrItinData< IIC_FPUi, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<7,[EX]>], // seven cycles in execute stage + [ 8 // result ready after eight cycles + , 1 ]>, // first operand read after one cycle + + // Convert integer to floating point instruction with one destination + // register and one source operand register. The instruction takes one cycle + // to execute in each of the pipeline stages except the execute stage, + // which takes six cycles. The source operands are read during the decode + // stage and the results are ready after the execute stage. + InstrItinData< IIC_FPUf, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<6,[EX]>], // six cycles in execute stage + [ 7 // result ready after seven cycles + , 1 ]>, // first operand read after one cycle + + // Floating point square root instruction with one destination register and + // one source operand register. The instruction takes one cycle to execute in + // each of the pipeline stages except the execute stage, which takes 29 + // cycles. The source operands are read during the decode stage and the + // results are ready after the execute stage. + InstrItinData< IIC_FPUs, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<29,[EX]>], // 29 cycles in execute stage + [ 30 // result ready after 30 cycles + , 1 ]>, // first operand read after one cycle + + // Floating point comparison instruction with one destination register and + // two source operand registers. The instruction takes one cycle to execute + // in each of the pipeline stages except the execute stage, which takes three + // cycles. The source operands are read during the decode stage and the + // results are ready after the execute stage. + InstrItinData< IIC_FPUc, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<3,[EX]>], // three cycles in execute stage + [ 4 // result ready after four cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // FSL get instruction with one register or immediate source operand and one + // destination register. The instruction takes one cycle to execute in each + // of the pipeline stages except the execute stage, which takes two cycles. + // The one source operand is read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_FSLg, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 3 // result ready after two cycles + , 1 ]>, // first operand read after one cycle + + // FSL put instruction with either two register source operands or one + // register source operand and one immediate operand. There is no result + // produced by the instruction. The instruction takes one cycle to execute in + // each of the pipeline stages except the execute stage, which takes two + // cycles. The two source operands are read during the decode stage. + InstrItinData< IIC_FSLp, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Memory store instruction with either three register source operands or two + // register source operands and one immediate operand. There is no result + // produced by the instruction. The instruction takes one cycle to execute in + // each of the pipeline stages except the execute stage, which takes two + // cycles. All of the source operands are read during the decode stage. + InstrItinData< IIC_MEMs, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 1 // first operand read after one cycle + , 1 // second operand read after one cycle + , 1 ]>, // third operand read after one cycle + + // Memory load instruction with one destination register and either two + // register source operands or one register source operand and one immediate + // operand. The instruction takes one cycle to execute in each of the + // pipeline stages except the execute stage, which takes two cycles. All of + // the source operands are read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_MEMl, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 3 // result ready after four cycles + , 1 // second operand read after one cycle + , 1 ]> // third operand read after one cycle +]>; diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule5.td b/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule5.td new file mode 100644 index 000000000000..fa88766fdb18 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule5.td @@ -0,0 +1,267 @@ +//===- MBlazeSchedule5.td - MBlaze Scheduling Definitions --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MBlaze instruction itineraries for the five stage pipeline. +//===----------------------------------------------------------------------===// +def MBlazePipe5Itineraries : ProcessorItineraries< + [IF,ID,EX,MA,WB], [], [ + + // ALU instruction with one destination register and either two register + // source operands or one register source operand and one immediate operand. + // The instruction takes one cycle to execute in each of the stages. The + // two source operands are read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_ALU, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 2 // result ready after two cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // ALU multiply instruction with one destination register and either two + // register source operands or one register source operand and one immediate + // operand. The instruction takes one cycle to execute in each of the + // pipeline stages. The two source operands are read during the decode stage + // and the result is ready after the execute stage. + InstrItinData< IIC_ALUm, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 2 // result ready after two cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // ALU divide instruction with one destination register two register source + // operands. The instruction takes one cycle to execute in each the pipeline + // stages except the memory access stage, which takes 31 cycles. The two + // source operands are read during the decode stage and the result is ready + // after the memory access stage. + InstrItinData< IIC_ALUd, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<31,[MA]> // 31 cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 33 // result ready after 33 cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Shift instruction with one destination register and either two register + // source operands or one register source operand and one immediate operand. + // The instruction takes one cycle to execute in each of the pipeline stages. + // The two source operands are read during the decode stage and the result is + // ready after the memory access stage. + InstrItinData< IIC_SHT, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 3 // result ready after three cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Branch instruction with one source operand register. The instruction takes + // one cycle to execute in each of the pipeline stages. The source operand is + // read during the decode stage. + InstrItinData< IIC_BR, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 ]>, // first operand read after one cycle + + // Conditional branch instruction with two source operand registers. The + // instruction takes one cycle to execute in each of the pipeline stages. The + // two source operands are read during the decode stage. + InstrItinData< IIC_BRc, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Branch and link instruction with one destination register and one source + // operand register. The instruction takes one cycle to execute in each of + // the pipeline stages. The source operand is read during the decode stage + // and the destination register is ready after the writeback stage. + InstrItinData< IIC_BRl, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 4 // result ready after four cycles + , 1 ]>, // first operand read after one cycle + + // Cache control instruction with two source operand registers. The + // instruction takes one cycle to execute in each of the pipeline stages + // except the memory access stage, which takes two cycles. The source + // operands are read during the decode stage. + InstrItinData< IIC_WDC, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<2,[MA]> // two cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Floating point instruction with one destination register and two source + // operand registers. The instruction takes one cycle to execute in each of + // the pipeline stages except the memory access stage, which takes two + // cycles. The source operands are read during the decode stage and the + // results are ready after the writeback stage. + InstrItinData< IIC_FPU, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<2,[MA]> // two cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 5 // result ready after five cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Floating point divide instruction with one destination register and two + // source operand registers. The instruction takes one cycle to execute in + // each of the pipeline stages except the memory access stage, which takes 26 + // cycles. The source operands are read during the decode stage and the + // results are ready after the writeback stage. + InstrItinData< IIC_FPUd, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<26,[MA]> // 26 cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 29 // result ready after 29 cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Convert floating point to integer instruction with one destination + // register and one source operand register. The instruction takes one cycle + // to execute in each of the pipeline stages except the memory access stage, + // which takes three cycles. The source operands are read during the decode + // stage and the results are ready after the writeback stage. + InstrItinData< IIC_FPUi, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<3,[MA]> // three cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 6 // result ready after six cycles + , 1 ]>, // first operand read after one cycle + + // Convert integer to floating point instruction with one destination + // register and one source operand register. The instruction takes one cycle + // to execute in each of the pipeline stages except the memory access stage, + // which takes two cycles. The source operands are read during the decode + // stage and the results are ready after the writeback stage. + InstrItinData< IIC_FPUf, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<2,[MA]> // two cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 5 // result ready after five cycles + , 1 ]>, // first operand read after one cycle + + // Floating point square root instruction with one destination register and + // one source operand register. The instruction takes one cycle to execute in + // each of the pipeline stages except the memory access stage, which takes 25 + // cycles. The source operands are read during the decode stage and the + // results are ready after the writeback stage. + InstrItinData< IIC_FPUs, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<25,[MA]> // 25 cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 28 // result ready after 28 cycles + , 1 ]>, // first operand read after one cycle + + // Floating point comparison instruction with one destination register and + // two source operand registers. The instruction takes one cycle to execute + // in each of the pipeline stages. The source operands are read during the + // decode stage and the results are ready after the execute stage. + InstrItinData< IIC_FPUc, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 2 // result ready after two cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // FSL get instruction with one register or immediate source operand and one + // destination register. The instruction takes one cycle to execute in each + // of the pipeline stages. The one source operand is read during the decode + // stage and the result is ready after the execute stage. + InstrItinData< IIC_FSLg, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 2 // result ready after two cycles + , 1 ]>, // first operand read after one cycle + + // FSL put instruction with either two register source operands or one + // register source operand and one immediate operand. There is no result + // produced by the instruction. The instruction takes one cycle to execute in + // each of the pipeline stages. The two source operands are read during the + // decode stage. + InstrItinData< IIC_FSLp, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Memory store instruction with either three register source operands or two + // register source operands and one immediate operand. There is no result + // produced by the instruction. The instruction takes one cycle to execute in + // each of the pipeline stages. All of the source operands are read during + // the decode stage. + InstrItinData< IIC_MEMs, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 // first operand read after one cycle + , 1 // second operand read after one cycle + , 1 ]>, // third operand read after one cycle + + // Memory load instruction with one destination register and either two + // register source operands or one register source operand and one immediate + // operand. The instruction takes one cycle to execute in each of the + // pipeline stages. All of the source operands are read during the decode + // stage and the result is ready after the writeback stage. + InstrItinData< IIC_MEMl, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 4 // result ready after four cycles + , 1 // second operand read after one cycle + , 1 ]> // third operand read after one cycle +]>; diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.cpp index 344052156869..a80744a4769a 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.cpp @@ -13,19 +13,39 @@ #include "MBlazeSubtarget.h" #include "MBlaze.h" +#include "MBlazeRegisterInfo.h" #include "MBlazeGenSubtarget.inc" #include "llvm/Support/CommandLine.h" using namespace llvm; MBlazeSubtarget::MBlazeSubtarget(const std::string &TT, const std::string &FS): - HasPipe3(false), HasBarrel(false), HasDiv(false), HasMul(false), - HasFSL(false), HasEFSL(false), HasMSRSet(false), HasException(false), - HasPatCmp(false), HasFPU(false), HasESR(false), HasPVR(false), - HasMul64(false), HasSqrt(false), HasMMU(false) + HasBarrel(false), HasDiv(false), HasMul(false), HasPatCmp(false), + HasFPU(false), HasMul64(false), HasSqrt(false) { - std::string CPU = "v400"; - MBlazeArchVersion = V400; - // Parse features string. - ParseSubtargetFeatures(FS, CPU); + std::string CPU = "mblaze"; + CPU = ParseSubtargetFeatures(FS, CPU); + + // Only use instruction scheduling if the selected CPU has an instruction + // itinerary (the default CPU is the only one that doesn't). + HasItin = CPU != "mblaze"; + DEBUG(dbgs() << "CPU " << CPU << "(" << HasItin << ")\n"); + + // Compute the issue width of the MBlaze itineraries + computeIssueWidth(); } + +void MBlazeSubtarget::computeIssueWidth() { + InstrItins.IssueWidth = 1; +} + +bool MBlazeSubtarget:: +enablePostRAScheduler(CodeGenOpt::Level OptLevel, + TargetSubtarget::AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const { + Mode = TargetSubtarget::ANTIDEP_CRITICAL; + CriticalPathRCs.clear(); + CriticalPathRCs.push_back(&MBlaze::GPRRegClass); + return HasItin && OptLevel >= CodeGenOpt::Default; +} + diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.h b/contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.h index bebb3f773e03..2255b2809be2 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.h @@ -24,29 +24,14 @@ namespace llvm { class MBlazeSubtarget : public TargetSubtarget { protected: - - enum MBlazeArchEnum { - V400, V500, V600, V700, V710 - }; - - // MBlaze architecture version - MBlazeArchEnum MBlazeArchVersion; - - bool HasPipe3; bool HasBarrel; bool HasDiv; bool HasMul; - bool HasFSL; - bool HasEFSL; - bool HasMSRSet; - bool HasException; bool HasPatCmp; bool HasFPU; - bool HasESR; - bool HasPVR; bool HasMul64; bool HasSqrt; - bool HasMMU; + bool HasItin; InstrItineraryData InstrItins; @@ -61,18 +46,26 @@ class MBlazeSubtarget : public TargetSubtarget { std::string ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); + /// Compute the number of maximum number of issues per cycle for the + /// MBlaze scheduling itineraries. + void computeIssueWidth(); + + /// enablePostRAScheduler - True at 'More' optimization. + bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, + TargetSubtarget::AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const; + + /// getInstrItins - Return the instruction itineraies based on subtarget. + const InstrItineraryData &getInstrItineraryData() const { return InstrItins; } + + bool hasItin() const { return HasItin; } + bool hasPCMP() const { return HasPatCmp; } bool hasFPU() const { return HasFPU; } bool hasSqrt() const { return HasSqrt; } bool hasMul() const { return HasMul; } bool hasMul64() const { return HasMul64; } bool hasDiv() const { return HasDiv; } bool hasBarrel() const { return HasBarrel; } - - bool isV400() const { return MBlazeArchVersion == V400; } - bool isV500() const { return MBlazeArchVersion == V500; } - bool isV600() const { return MBlazeArchVersion == V600; } - bool isV700() const { return MBlazeArchVersion == V700; } - bool isV710() const { return MBlazeArchVersion == V710; } }; } // End llvm namespace diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.cpp index cd949e1998de..df34a83e33a8 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.cpp @@ -36,19 +36,18 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, bool RelaxAll, bool NoExecStack) { Triple TheTriple(TT); - switch (TheTriple.getOS()) { - case Triple::Darwin: + + if (TheTriple.isOSDarwin()) { llvm_unreachable("MBlaze does not support Darwin MACH-O format"); return NULL; - case Triple::MinGW32: - case Triple::Cygwin: - case Triple::Win32: + } + + if (TheTriple.isOSWindows()) { llvm_unreachable("MBlaze does not support Windows COFF format"); return NULL; - default: - return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, - NoExecStack); } + + return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, NoExecStack); } @@ -87,7 +86,8 @@ MBlazeTargetMachine(const Target &T, const std::string &TT, DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"), InstrInfo(*this), FrameLowering(Subtarget), - TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this) { + TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this), + InstrItins(Subtarget.getInstrItineraryData()) { if (getRelocationModel() == Reloc::Default) { setRelocationModel(Reloc::Static); } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.h b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.h index 45ad07858887..48ce37a482fc 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.h @@ -38,13 +38,18 @@ namespace llvm { MBlazeSelectionDAGInfo TSInfo; MBlazeIntrinsicInfo IntrinsicInfo; MBlazeELFWriterInfo ELFWriterInfo; + InstrItineraryData InstrItins; + public: MBlazeTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &FS); virtual const MBlazeInstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const InstrItineraryData *getInstrItineraryData() const + { return &InstrItins; } + virtual const TargetFrameLowering *getFrameLowering() const { return &FrameLowering; } diff --git a/contrib/llvm/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h b/contrib/llvm/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h index f0e1ce22841b..63860dcc7e3a 100644 --- a/contrib/llvm/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h +++ b/contrib/llvm/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h @@ -18,11 +18,12 @@ namespace llvm { class MCOperand; + class TargetMachine; class MSP430InstPrinter : public MCInstPrinter { public: - MSP430InstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) { - } + MSP430InstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) + : MCInstPrinter(MAI) {} virtual void printInst(const MCInst *MI, raw_ostream &O); diff --git a/contrib/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp b/contrib/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp index a1a7f44c19c4..5264d680d8b3 100644 --- a/contrib/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp +++ b/contrib/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp @@ -164,10 +164,11 @@ void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { } static MCInstPrinter *createMSP430MCInstPrinter(const Target &T, + TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new MSP430InstPrinter(MAI); + return new MSP430InstPrinter(TM, MAI); return 0; } diff --git a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp index a95d59c0576c..006785b1f74d 100644 --- a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -515,7 +515,7 @@ MSP430TargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, // Build a sequence of copy-to-reg nodes chained together with token chain and // flag operands which copy the outgoing args into registers. The InFlag in - // necessary since all emited instructions must be stuck together. + // necessary since all emitted instructions must be stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, diff --git a/contrib/llvm/lib/Target/Mips/Mips.h b/contrib/llvm/lib/Target/Mips/Mips.h index a9ab050d6f0d..05b4c5a070d6 100644 --- a/contrib/llvm/lib/Target/Mips/Mips.h +++ b/contrib/llvm/lib/Target/Mips/Mips.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file contains the entry points for global functions defined in +// This file contains the entry points for global functions defined in // the LLVM Mips back-end. // //===----------------------------------------------------------------------===// @@ -25,6 +25,7 @@ namespace llvm { FunctionPass *createMipsISelDag(MipsTargetMachine &TM); FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM); + FunctionPass *createMipsExpandPseudoPass(MipsTargetMachine &TM); extern Target TheMipsTarget; extern Target TheMipselTarget; diff --git a/contrib/llvm/lib/Target/Mips/Mips.td b/contrib/llvm/lib/Target/Mips/Mips.td index 3e6437b93ccf..b79016d788f0 100644 --- a/contrib/llvm/lib/Target/Mips/Mips.td +++ b/contrib/llvm/lib/Target/Mips/Mips.td @@ -59,7 +59,7 @@ def FeatureMips1 : SubtargetFeature<"mips1", "MipsArchVersion", "Mips1", def FeatureMips2 : SubtargetFeature<"mips2", "MipsArchVersion", "Mips2", "Mips2 ISA Support">; def FeatureMips32 : SubtargetFeature<"mips32", "MipsArchVersion", "Mips32", - "Mips32 ISA Support", + "Mips32 ISA Support", [FeatureCondMov, FeatureBitCount]>; def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion", "Mips32r2", "Mips32r2 ISA Support", @@ -81,7 +81,7 @@ def : Proc<"r6000", [FeatureMips2]>; def : Proc<"4ke", [FeatureMips32r2]>; -// Allegrex is a 32bit subset of r4000, both for interger and fp registers, +// Allegrex is a 32bit subset of r4000, both for integer and fp registers, // but much more similar to Mips2 than Mips3. It also contains some of // Mips32/Mips32r2 instructions and a custom vector fpu processor. def : Proc<"allegrex", [FeatureMips2, FeatureSingleFloat, FeatureEABI, diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index bd28a9bd073b..502f744e4d85 100644 --- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -30,7 +30,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" @@ -53,14 +53,14 @@ namespace { return "Mips Assembly Printer"; } - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O); void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); - void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier = 0); - void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier = 0); void printSavedRegsBitmask(raw_ostream &O); void printHex32(unsigned int Value, raw_ostream &O); @@ -77,7 +77,8 @@ namespace { } virtual void EmitFunctionBodyStart(); virtual void EmitFunctionBodyEnd(); - virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock* + MBB) const; static const char *getRegisterName(unsigned RegNo); virtual void EmitFunctionEntryLabel(); @@ -94,12 +95,12 @@ namespace { // -- Frame directive "frame Stackpointer, Stacksize, RARegister" // Describe the stack frame. // -// -- Mask directives "(f)mask bitmask, offset" +// -- Mask directives "(f)mask bitmask, offset" // Tells the assembler which registers are saved and where. -// bitmask - contain a little endian bitset indicating which registers are -// saved on function prologue (e.g. with a 0x80000000 mask, the +// bitmask - contain a little endian bitset indicating which registers are +// saved on function prologue (e.g. with a 0x80000000 mask, the // assembler knows the register 31 (RA) is saved at prologue. -// offset - the position before stack pointer subtraction indicating where +// offset - the position before stack pointer subtraction indicating where // the first saved register on prologue is located. (e.g. with a // // Consider the following function prologue: @@ -110,9 +111,9 @@ namespace { // sw $ra, 40($sp) // sw $fp, 36($sp) // -// With a 0xc0000000 mask, the assembler knows the register 31 (RA) and -// 30 (FP) are saved at prologue. As the save order on prologue is from -// left to right, RA is saved first. A -8 offset means that after the +// With a 0xc0000000 mask, the assembler knows the register 31 (RA) and +// 30 (FP) are saved at prologue. As the save order on prologue is from +// left to right, RA is saved first. A -8 offset means that after the // stack pointer subtration, the first register in the mask (RA) will be // saved at address 48-8=40. // @@ -122,7 +123,7 @@ namespace { // Mask directives //===----------------------------------------------------------------------===// -// Create a bitmask with all callee saved registers for CPU or Floating Point +// Create a bitmask with all callee saved registers for CPU or Floating Point // registers. For CPU registers consider RA, GP and FP for saving if necessary. void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { const TargetFrameLowering *TFI = TM.getFrameLowering(); @@ -168,7 +169,7 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { // Print a 32 bit hex number with all numbers. void MipsAsmPrinter::printHex32(unsigned Value, raw_ostream &O) { O << "0x"; - for (int i = 7; i >= 0; i--) + for (int i = 7; i >= 0; i--) O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); } @@ -191,9 +192,9 @@ void MipsAsmPrinter::emitFrameDirective() { } /// Emit Set directives. -const char *MipsAsmPrinter::getCurrentABIString() const { +const char *MipsAsmPrinter::getCurrentABIString() const { switch (Subtarget->getTargetABI()) { - case MipsSubtarget::O32: return "abi32"; + case MipsSubtarget::O32: return "abi32"; case MipsSubtarget::O64: return "abiO64"; case MipsSubtarget::N32: return "abiN32"; case MipsSubtarget::N64: return "abi64"; @@ -203,7 +204,7 @@ const char *MipsAsmPrinter::getCurrentABIString() const { llvm_unreachable("Unknown Mips ABI"); return NULL; -} +} void MipsAsmPrinter::EmitFunctionEntryLabel() { OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); @@ -214,7 +215,7 @@ void MipsAsmPrinter::EmitFunctionEntryLabel() { /// the first basic block in the function. void MipsAsmPrinter::EmitFunctionBodyStart() { emitFrameDirective(); - + SmallString<128> Str; raw_svector_ostream OS(Str); printSavedRegsBitmask(OS); @@ -226,7 +227,7 @@ void MipsAsmPrinter::EmitFunctionBodyStart() { void MipsAsmPrinter::EmitFunctionBodyEnd() { // There are instruction for this macros, but they must // always be at the function end, and we can't emit and - // break with BB logic. + // break with BB logic. OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); OutStreamer.EmitRawText(StringRef("\t.set\treorder")); OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); @@ -236,8 +237,8 @@ void MipsAsmPrinter::EmitFunctionBodyEnd() { /// isBlockOnlyReachableByFallthough - Return true if the basic block has /// exactly one predecessor and the control transfer mechanism between /// the predecessor and this block is a fall-through. -bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) - const { +bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* + MBB) const { // The predecessor has to be immediately before this block. const MachineBasicBlock *Pred = *MBB->pred_begin(); @@ -246,16 +247,41 @@ bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock * if (const BasicBlock *bb = Pred->getBasicBlock()) if (isa(bb->getTerminator())) return false; + + // If this is a landing pad, it isn't a fall through. If it has no preds, + // then nothing falls through to it. + if (MBB->isLandingPad() || MBB->pred_empty()) + return false; + + // If there isn't exactly one predecessor, it can't be a fall through. + MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; + ++PI2; + + if (PI2 != MBB->pred_end()) + return false; + + // The predecessor has to be immediately before this block. + if (!Pred->isLayoutSuccessor(MBB)) + return false; + + // If the block is completely empty, then it definitely does fall through. + if (Pred->empty()) + return true; - return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); + // Otherwise, check the last instruction. + // Check if the last terminator is an unconditional branch. + MachineBasicBlock::const_iterator I = Pred->end(); + while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) ; + + return !I->getDesc().isBarrier(); } // Print out an operand for an inline asm expression. -bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, +bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant,const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? - if (ExtraCode && ExtraCode[0]) + if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. printOperand(MI, OpNo, O); @@ -273,22 +299,9 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, switch(MO.getTargetFlags()) { case MipsII::MO_GPREL: O << "%gp_rel("; break; case MipsII::MO_GOT_CALL: O << "%call16("; break; - case MipsII::MO_GOT: { - const MachineOperand &LastMO = MI->getOperand(opNum-1); - bool LastMOIsGP = LastMO.getType() == MachineOperand::MO_Register - && LastMO.getReg() == Mips::GP; - if (MI->getOpcode() == Mips::LW || LastMOIsGP) - O << "%got("; - else - O << "%lo("; - break; - } - case MipsII::MO_ABS_HILO: - if (MI->getOpcode() == Mips::LUi) - O << "%hi("; - else - O << "%lo("; - break; + case MipsII::MO_GOT: O << "%got("; break; + case MipsII::MO_ABS_HI: O << "%hi("; break; + case MipsII::MO_ABS_LO: O << "%lo("; break; } switch (MO.getType()) { @@ -308,6 +321,12 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, O << *Mang->getSymbol(MO.getGlobal()); break; + case MachineOperand::MO_BlockAddress: { + MCSymbol* BA = GetBlockAddressSymbol(MO.getBlockAddress()); + O << BA->getName(); + break; + } + case MachineOperand::MO_ExternalSymbol: O << *GetExternalSymbolSymbol(MO.getSymbolName()); break; @@ -323,7 +342,7 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, if (MO.getOffset()) O << "+" << MO.getOffset(); break; - + default: llvm_unreachable(""); } @@ -336,7 +355,7 @@ void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, const MachineOperand &MO = MI->getOperand(opNum); if (MO.isImm()) O << (unsigned short int)MO.getImm(); - else + else printOperand(MI, opNum, O); } @@ -352,8 +371,8 @@ printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, return; } - // Load/Store memory operands -- imm($reg) - // If PIC target the target is loaded as the + // Load/Store memory operands -- imm($reg) + // If PIC target the target is loaded as the // pattern lw $25,%call16($28) printOperand(MI, opNum, O); O << "("; @@ -365,12 +384,12 @@ void MipsAsmPrinter:: printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier) { const MachineOperand& MO = MI->getOperand(opNum); - O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); + O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); } void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // FIXME: Use SwitchSection. - + // Tell the assembler which ABI we are using OutStreamer.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString())); @@ -383,11 +402,11 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { } // return to previous section - OutStreamer.EmitRawText(StringRef("\t.previous")); + OutStreamer.EmitRawText(StringRef("\t.previous")); } // Force static initialization. -extern "C" void LLVMInitializeMipsAsmPrinter() { +extern "C" void LLVMInitializeMipsAsmPrinter() { RegisterAsmPrinter X(TheMipsTarget); RegisterAsmPrinter Y(TheMipselTarget); } diff --git a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td b/contrib/llvm/lib/Target/Mips/MipsCallingConv.td index 8f313efaf8da..57aeb1d2793c 100644 --- a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td +++ b/contrib/llvm/lib/Target/Mips/MipsCallingConv.td @@ -1,23 +1,23 @@ //===- MipsCallingConv.td - Calling Conventions for Mips ---*- tablegen -*-===// -// +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // This describes the calling conventions for Mips architecture. //===----------------------------------------------------------------------===// /// CCIfSubtarget - Match if the current subtarget has a feature F. -class CCIfSubtarget: +class CCIfSubtarget: CCIf().", F), A>; //===----------------------------------------------------------------------===// // Mips O32 Calling Convention //===----------------------------------------------------------------------===// -// Only the return rules are defined here for O32. The rules for argument +// Only the return rules are defined here for O32. The rules for argument // passing are defined in MipsISelLowering.cpp. def RetCC_MipsO32 : CallingConv<[ // i32 are returned in registers V0, V1 @@ -41,15 +41,15 @@ def CC_MipsEABI : CallingConv<[ // Integer arguments are passed in integer registers. CCIfType<[i32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3]>>, - // Single fp arguments are passed in pairs within 32-bit mode - CCIfType<[f32], CCIfSubtarget<"isSingleFloat()", + // Single fp arguments are passed in pairs within 32-bit mode + CCIfType<[f32], CCIfSubtarget<"isSingleFloat()", CCAssignToReg<[F12, F13, F14, F15, F16, F17, F18, F19]>>>, - CCIfType<[f32], CCIfSubtarget<"isNotSingleFloat()", + CCIfType<[f32], CCIfSubtarget<"isNotSingleFloat()", CCAssignToReg<[F12, F14, F16, F18]>>>, - // The first 4 doubl fp arguments are passed in single fp registers. - CCIfType<[f64], CCIfSubtarget<"isNotSingleFloat()", + // The first 4 double fp arguments are passed in single fp registers. + CCIfType<[f64], CCIfSubtarget<"isNotSingleFloat()", CCAssignToReg<[D6, D7, D8, D9]>>>, // Integer values get stored in stack slots that are 4 bytes in diff --git a/contrib/llvm/lib/Target/Mips/MipsExpandPseudo.cpp b/contrib/llvm/lib/Target/Mips/MipsExpandPseudo.cpp new file mode 100644 index 000000000000..4423f5147980 --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MipsExpandPseudo.cpp @@ -0,0 +1,117 @@ +//===-- MipsExpandPseudo.cpp - Expand pseudo instructions ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass expands pseudo instructions into target instructions after register +// allocation but before post-RA scheduling. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mips-expand-pseudo" + +#include "Mips.h" +#include "MipsTargetMachine.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/Statistic.h" + +using namespace llvm; + +namespace { + struct MipsExpandPseudo : public MachineFunctionPass { + + TargetMachine &TM; + const TargetInstrInfo *TII; + + static char ID; + MipsExpandPseudo(TargetMachine &tm) + : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } + + virtual const char *getPassName() const { + return "Mips PseudoInstrs Expansion"; + } + + bool runOnMachineFunction(MachineFunction &F); + bool runOnMachineBasicBlock(MachineBasicBlock &MBB); + + private: + void ExpandBuildPairF64(MachineBasicBlock&, MachineBasicBlock::iterator); + void ExpandExtractElementF64(MachineBasicBlock&, + MachineBasicBlock::iterator); + }; + char MipsExpandPseudo::ID = 0; +} // end of anonymous namespace + +bool MipsExpandPseudo::runOnMachineFunction(MachineFunction& F) { + bool Changed = false; + + for (MachineFunction::iterator I = F.begin(); I != F.end(); ++I) + Changed |= runOnMachineBasicBlock(*I); + + return Changed; +} + +bool MipsExpandPseudo::runOnMachineBasicBlock(MachineBasicBlock& MBB) { + + bool Changed = false; + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) { + const TargetInstrDesc& Tid = I->getDesc(); + + switch(Tid.getOpcode()) { + default: + ++I; + continue; + case Mips::BuildPairF64: + ExpandBuildPairF64(MBB, I); + break; + case Mips::ExtractElementF64: + ExpandExtractElementF64(MBB, I); + break; + } + + // delete original instr + MBB.erase(I++); + Changed = true; + } + + return Changed; +} + +void MipsExpandPseudo::ExpandBuildPairF64(MachineBasicBlock& MBB, + MachineBasicBlock::iterator I) { + unsigned DstReg = I->getOperand(0).getReg(); + unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); + const TargetInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1); + DebugLoc dl = I->getDebugLoc(); + const unsigned* SubReg = + TM.getRegisterInfo()->getSubRegisters(DstReg); + + // mtc1 Lo, $fp + // mtc1 Hi, $fp + 1 + BuildMI(MBB, I, dl, Mtc1Tdd, *SubReg).addReg(LoReg); + BuildMI(MBB, I, dl, Mtc1Tdd, *(SubReg + 1)).addReg(HiReg); +} + +void MipsExpandPseudo::ExpandExtractElementF64(MachineBasicBlock& MBB, + MachineBasicBlock::iterator I) { + unsigned DstReg = I->getOperand(0).getReg(); + unsigned SrcReg = I->getOperand(1).getReg(); + unsigned N = I->getOperand(2).getImm(); + const TargetInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1); + DebugLoc dl = I->getDebugLoc(); + const unsigned* SubReg = TM.getRegisterInfo()->getSubRegisters(SrcReg); + + BuildMI(MBB, I, dl, Mfc1Tdd, DstReg).addReg(*(SubReg + N)); +} + +/// createMipsMipsExpandPseudoPass - Returns a pass that expands pseudo +/// instrs into real instrs +FunctionPass *llvm::createMipsExpandPseudoPass(MipsTargetMachine &tm) { + return new MipsExpandPseudo(tm); +} diff --git a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp index 87a097a5d590..21e3314a6669 100644 --- a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp @@ -203,6 +203,46 @@ void MipsFrameLowering::adjustMipsStackFrame(MachineFunction &MF) const { MipsFI->setFPUTopSavedRegOff(TopFPUSavedRegOff-StackOffset); } + +// expand pair of register and immediate if the immediate doesn't fit in the +// 16-bit offset field. +// e.g. +// if OrigImm = 0x10000, OrigReg = $sp: +// generate the following sequence of instrs: +// lui $at, hi(0x10000) +// addu $at, $sp, $at +// +// (NewReg, NewImm) = ($at, lo(Ox10000)) +// return true +static bool expandRegLargeImmPair(unsigned OrigReg, int OrigImm, + unsigned& NewReg, int& NewImm, + MachineBasicBlock& MBB, + MachineBasicBlock::iterator I) { + // OrigImm fits in the 16-bit field + if (OrigImm < 0x8000 && OrigImm >= -0x8000) { + NewReg = OrigReg; + NewImm = OrigImm; + return false; + } + + MachineFunction* MF = MBB.getParent(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + DebugLoc DL = I->getDebugLoc(); + int ImmLo = OrigImm & 0xffff; + int ImmHi = (((unsigned)OrigImm & 0xffff0000) >> 16) + + ((OrigImm & 0x8000) != 0); + + // FIXME: change this when mips goes MC". + BuildMI(MBB, I, DL, TII->get(Mips::NOAT)); + BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::AT).addImm(ImmHi); + BuildMI(MBB, I, DL, TII->get(Mips::ADDu), Mips::AT).addReg(OrigReg) + .addReg(Mips::AT); + NewReg = Mips::AT; + NewImm = ImmLo; + + return true; +} + void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -214,6 +254,9 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); + unsigned NewReg = 0; + int NewImm = 0; + bool ATUsed; // Get the right frame order for Mips. adjustMipsStackFrame(MF); @@ -236,22 +279,40 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); // Adjust stack : addi sp, sp, (-imm) + ATUsed = expandRegLargeImmPair(Mips::SP, -StackSize, NewReg, NewImm, MBB, + MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) - .addReg(Mips::SP).addImm(-StackSize); + .addReg(NewReg).addImm(NewImm); - // Save the return address only if the function isnt a leaf one. + // FIXME: change this when mips goes MC". + if (ATUsed) + BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); + + // Save the return address only if the function isn't a leaf one. // sw $ra, stack_loc($sp) if (MFI->adjustsStack()) { + ATUsed = expandRegLargeImmPair(Mips::SP, RAOffset, NewReg, NewImm, MBB, + MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::SW)) - .addReg(Mips::RA).addImm(RAOffset).addReg(Mips::SP); + .addReg(Mips::RA).addImm(NewImm).addReg(NewReg); + + // FIXME: change this when mips goes MC". + if (ATUsed) + BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); } // if framepointer enabled, save it and set it // to point to the stack pointer if (hasFP(MF)) { // sw $fp,stack_loc($sp) + ATUsed = expandRegLargeImmPair(Mips::SP, FPOffset, NewReg, NewImm, MBB, + MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::SW)) - .addReg(Mips::FP).addImm(FPOffset).addReg(Mips::SP); + .addReg(Mips::FP).addImm(NewImm).addReg(NewReg); + + // FIXME: change this when mips goes MC". + if (ATUsed) + BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); // move $fp, $sp BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP) @@ -280,6 +341,10 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF, int FPOffset = MipsFI->getFPStackOffset(); int RAOffset = MipsFI->getRAStackOffset(); + unsigned NewReg = 0; + int NewImm = 0; + bool ATUsed = false; + // if framepointer enabled, restore it and restore the // stack pointer if (hasFP(MF)) { @@ -288,21 +353,39 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF, .addReg(Mips::FP).addReg(Mips::ZERO); // lw $fp,stack_loc($sp) + ATUsed = expandRegLargeImmPair(Mips::SP, FPOffset, NewReg, NewImm, MBB, + MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::FP) - .addImm(FPOffset).addReg(Mips::SP); + .addImm(NewImm).addReg(NewReg); + + // FIXME: change this when mips goes MC". + if (ATUsed) + BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); } - // Restore the return address only if the function isnt a leaf one. + // Restore the return address only if the function isn't a leaf one. // lw $ra, stack_loc($sp) if (MFI->adjustsStack()) { + ATUsed = expandRegLargeImmPair(Mips::SP, RAOffset, NewReg, NewImm, MBB, + MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::RA) - .addImm(RAOffset).addReg(Mips::SP); + .addImm(NewImm).addReg(NewReg); + + // FIXME: change this when mips goes MC". + if (ATUsed) + BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); } // adjust stack : insert addi sp, sp, (imm) if (NumBytes) { + ATUsed = expandRegLargeImmPair(Mips::SP, NumBytes, NewReg, NewImm, MBB, + MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) - .addReg(Mips::SP).addImm(NumBytes); + .addReg(NewReg).addImm(NewImm); + + // FIXME: change this when mips goes MC". + if (ATUsed) + BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); } } diff --git a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h index a8426c1b70fd..34647df4f354 100644 --- a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h +++ b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef ALPHA_FRAMEINFO_H -#define ALPHA_FRAMEINFO_H +#ifndef MIPS_FRAMEINFO_H +#define MIPS_FRAMEINFO_H #include "Mips.h" #include "MipsSubtarget.h" diff --git a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp index 755e04df63be..0382964fe942 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -52,19 +52,19 @@ class MipsDAGToDAGISel : public SelectionDAGISel { /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can /// make the right decision when generating code for different targets. const MipsSubtarget &Subtarget; - + public: explicit MipsDAGToDAGISel(MipsTargetMachine &tm) : SelectionDAGISel(tm), TM(tm), Subtarget(tm.getSubtarget()) {} - + // Pass Name virtual const char *getPassName() const { return "MIPS DAG->DAG Pattern Instruction Selection"; - } - + } -private: + +private: // Include the pieces autogenerated from the target description. #include "MipsGenDAGISel.inc" @@ -116,12 +116,14 @@ SelectAddr(SDValue Addr, SDValue &Offset, SDValue &Base) { Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; } - + // on PIC code Load GA if (TM.getRelocationModel() == Reloc::PIC_) { - if ((Addr.getOpcode() == ISD::TargetGlobalAddress) || - (Addr.getOpcode() == ISD::TargetConstantPool) || - (Addr.getOpcode() == ISD::TargetJumpTable)){ + if ((Addr.getOpcode() == ISD::TargetGlobalAddress) || + (Addr.getOpcode() == ISD::TargetConstantPool) || + (Addr.getOpcode() == ISD::TargetJumpTable) || + (Addr.getOpcode() == ISD::TargetBlockAddress) || + (Addr.getOpcode() == ISD::TargetExternalSymbol)) { Base = CurDAG->getRegister(Mips::GP, MVT::i32); Offset = Addr; return true; @@ -130,8 +132,8 @@ SelectAddr(SDValue Addr, SDValue &Offset, SDValue &Base) { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; - } - + } + // Operand is a result from an ADD. if (Addr.getOpcode() == ISD::ADD) { if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) { @@ -158,10 +160,10 @@ SelectAddr(SDValue Addr, SDValue &Offset, SDValue &Base) { // Generate: // lui $2, %hi($CPI1_0) // lwc1 $f0, %lo($CPI1_0)($2) - if ((Addr.getOperand(0).getOpcode() == MipsISD::Hi || + if ((Addr.getOperand(0).getOpcode() == MipsISD::Hi || Addr.getOperand(0).getOpcode() == ISD::LOAD) && Addr.getOperand(1).getOpcode() == MipsISD::Lo) { - SDValue LoVal = Addr.getOperand(1); + SDValue LoVal = Addr.getOperand(1); if (dyn_cast(LoVal.getOperand(0))) { Base = Addr.getOperand(0); Offset = LoVal.getOperand(0); @@ -176,7 +178,7 @@ SelectAddr(SDValue Addr, SDValue &Offset, SDValue &Base) { } SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { - MVT::SimpleValueType NVT = + MVT::SimpleValueType NVT = N->getValueType(0).getSimpleVT().SimpleTy; if (!Subtarget.isMips1() || NVT != MVT::f64) @@ -199,14 +201,14 @@ SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { MemRefs0[0] = cast(N)->getMemOperand(); DebugLoc dl = N->getDebugLoc(); - // The second load should start after for 4 bytes. + // The second load should start after for 4 bytes. if (ConstantSDNode *C = dyn_cast(Offset0)) Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32); else if (ConstantPoolSDNode *CP = dyn_cast(Offset0)) - Offset1 = CurDAG->getTargetConstantPool(CP->getConstVal(), - MVT::i32, - CP->getAlignment(), - CP->getOffset()+4, + Offset1 = CurDAG->getTargetConstantPool(CP->getConstVal(), + MVT::i32, + CP->getAlignment(), + CP->getOffset()+4, CP->getTargetFlags()); else return NULL; @@ -220,16 +222,16 @@ SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { // Generate: // lwc $f0, X($3) // lwc $f1, X+4($3) - SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, + SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, MVT::Other, Offset0, Base, Chain); SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, NVT), 0); - SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, + SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, MVT::f64, Undef, SDValue(LD0, 0)); SDNode *LD1 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, MVT::Other, Offset1, Base, SDValue(LD0, 1)); - SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, + SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, MVT::f64, I0, SDValue(LD1, 0)); ReplaceUses(SDValue(N, 0), I1); @@ -241,7 +243,7 @@ SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) { - if (!Subtarget.isMips1() || + if (!Subtarget.isMips1() || N->getOperand(1).getValueType() != MVT::f64) return NULL; @@ -265,12 +267,12 @@ SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) { DebugLoc dl = N->getDebugLoc(); // Get the even and odd part from the f64 register - SDValue FPOdd = CurDAG->getTargetExtractSubreg(Mips::sub_fpodd, + SDValue FPOdd = CurDAG->getTargetExtractSubreg(Mips::sub_fpodd, dl, MVT::f32, N1); SDValue FPEven = CurDAG->getTargetExtractSubreg(Mips::sub_fpeven, dl, MVT::f32, N1); - // The second store should start after for 4 bytes. + // The second store should start after for 4 bytes. if (ConstantSDNode *C = dyn_cast(Offset0)) Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32); else @@ -315,26 +317,26 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { } /// - // Instruction Selection not handled by the auto-generated + // Instruction Selection not handled by the auto-generated // tablegen selection should be handled here. - /// + /// switch(Opcode) { default: break; - case ISD::SUBE: + case ISD::SUBE: case ISD::ADDE: { SDValue InFlag = Node->getOperand(2), CmpLHS; unsigned Opc = InFlag.getOpcode(); (void)Opc; - assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || - (Opc == ISD::SUBC || Opc == ISD::SUBE)) && + assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || + (Opc == ISD::SUBC || Opc == ISD::SUBE)) && "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); unsigned MOp; if (Opcode == ISD::ADDE) { CmpLHS = InFlag.getValue(0); MOp = Mips::ADDu; - } else { + } else { CmpLHS = InFlag.getOperand(0); MOp = Mips::SUBu; } @@ -346,7 +348,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { EVT VT = LHS.getValueType(); SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, dl, VT, Ops, 2); - SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, dl, VT, + SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, dl, VT, SDValue(Carry,0), RHS); return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, @@ -356,36 +358,34 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { /// Mul/Div with two results case ISD::SDIVREM: case ISD::UDIVREM: + break; case ISD::SMUL_LOHI: case ISD::UMUL_LOHI: { SDValue Op1 = Node->getOperand(0); SDValue Op2 = Node->getOperand(1); unsigned Op; - if (Opcode == ISD::UMUL_LOHI || Opcode == ISD::SMUL_LOHI) - Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); - else - Op = (Opcode == ISD::UDIVREM ? Mips::DIVu : Mips::DIV); + Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); - SDNode *MulDiv = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); + SDNode *Mul = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); - SDValue InFlag = SDValue(MulDiv, 0); - SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, + SDValue InFlag = SDValue(Mul, 0); + SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, MVT::Glue, InFlag); InFlag = SDValue(Lo,1); SDNode *Hi = CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag); - if (!SDValue(Node, 0).use_empty()) + if (!SDValue(Node, 0).use_empty()) ReplaceUses(SDValue(Node, 0), SDValue(Lo,0)); - if (!SDValue(Node, 1).use_empty()) + if (!SDValue(Node, 1).use_empty()) ReplaceUses(SDValue(Node, 1), SDValue(Hi,0)); return NULL; } /// Special Muls - case ISD::MUL: + case ISD::MUL: if (Subtarget.isMips32()) break; case ISD::MULHS: @@ -394,7 +394,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { SDValue MulOp2 = Node->getOperand(1); unsigned MulOp = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT); - SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl, + SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl, MVT::Glue, MulOp1, MulOp2); SDValue InFlag = SDValue(MulNode, 0); @@ -408,24 +408,9 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { /// Div/Rem operations case ISD::SREM: case ISD::UREM: - case ISD::SDIV: - case ISD::UDIV: { - SDValue Op1 = Node->getOperand(0); - SDValue Op2 = Node->getOperand(1); - - unsigned Op, MOp; - if (Opcode == ISD::SDIV || Opcode == ISD::UDIV) { - Op = (Opcode == ISD::SDIV ? Mips::DIV : Mips::DIVu); - MOp = Mips::MFLO; - } else { - Op = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu); - MOp = Mips::MFHI; - } - SDNode *Node = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); - - SDValue InFlag = SDValue(Node, 0); - return CurDAG->getMachineNode(MOp, dl, MVT::i32, InFlag); - } + case ISD::SDIV: + case ISD::UDIV: + break; // Get target GOT address. case ISD::GLOBAL_OFFSET_TABLE: @@ -433,15 +418,15 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { case ISD::ConstantFP: { ConstantFPSDNode *CN = dyn_cast(Node); - if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { - SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { + SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, Mips::ZERO, MVT::i32); SDValue Undef = SDValue( CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::f64), 0); SDNode *MTC = CurDAG->getMachineNode(Mips::MTC1, dl, MVT::f32, Zero); - SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, + SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, MVT::f64, Undef, SDValue(MTC, 0)); - SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, + SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, MVT::f64, I0, SDValue(MTC, 0)); ReplaceUses(SDValue(Node, 0), I1); return I1.getNode(); @@ -460,61 +445,6 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { return ResNode; // Other cases are autogenerated. break; - - /// Handle direct and indirect calls when using PIC. On PIC, when - /// GOT is smaller than about 64k (small code) the GA target is - /// loaded with only one instruction. Otherwise GA's target must - /// be loaded with 3 instructions. - case MipsISD::JmpLink: { - if (TM.getRelocationModel() == Reloc::PIC_) { - unsigned LastOpNum = Node->getNumOperands()-1; - - SDValue Chain = Node->getOperand(0); - SDValue Callee = Node->getOperand(1); - SDValue InFlag; - - // Skip the incomming flag if present - if (Node->getOperand(LastOpNum).getValueType() == MVT::Glue) - LastOpNum--; - - if ( (isa(Callee)) || - (isa(Callee)) ) - { - /// Direct call for global addresses and external symbols - SDValue GPReg = CurDAG->getRegister(Mips::GP, MVT::i32); - - // Use load to get GOT target - SDValue Ops[] = { Callee, GPReg, Chain }; - SDValue Load = SDValue(CurDAG->getMachineNode(Mips::LW, dl, MVT::i32, - MVT::Other, Ops, 3), 0); - Chain = Load.getValue(1); - - // Call target must be on T9 - Chain = CurDAG->getCopyToReg(Chain, dl, Mips::T9, Load, InFlag); - } else - /// Indirect call - Chain = CurDAG->getCopyToReg(Chain, dl, Mips::T9, Callee, InFlag); - - // Map the JmpLink operands to JALR - SDVTList NodeTys = CurDAG->getVTList(MVT::Other, MVT::Glue); - SmallVector Ops; - Ops.push_back(CurDAG->getRegister(Mips::T9, MVT::i32)); - - for (unsigned i = 2, e = LastOpNum+1; i != e; ++i) - Ops.push_back(Node->getOperand(i)); - Ops.push_back(Chain); - Ops.push_back(Chain.getValue(1)); - - // Emit Jump and Link Register - SDNode *ResNode = CurDAG->getMachineNode(Mips::JALR, dl, NodeTys, - &Ops[0], Ops.size()); - - // Replace Chain and InFlag - ReplaceUses(SDValue(Node, 0), SDValue(ResNode, 0)); - ReplaceUses(SDValue(Node, 1), SDValue(ResNode, 1)); - return ResNode; - } - } } // Select the default instruction @@ -529,7 +459,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { return ResNode; } -/// createMipsISelDag - This pass converts a legalized DAG into a +/// createMipsISelDag - This pass converts a legalized DAG into a /// MIPS-specific DAG, ready for instruction scheduling. FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) { return new MipsDAGToDAGISel(TM); diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp index 1d7a1c0ae8c7..1f1220f19203 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -41,15 +41,19 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::Lo : return "MipsISD::Lo"; case MipsISD::GPRel : return "MipsISD::GPRel"; case MipsISD::Ret : return "MipsISD::Ret"; - case MipsISD::SelectCC : return "MipsISD::SelectCC"; - case MipsISD::FPSelectCC : return "MipsISD::FPSelectCC"; case MipsISD::FPBrcond : return "MipsISD::FPBrcond"; case MipsISD::FPCmp : return "MipsISD::FPCmp"; + case MipsISD::CMovFP_T : return "MipsISD::CMovFP_T"; + case MipsISD::CMovFP_F : return "MipsISD::CMovFP_F"; case MipsISD::FPRound : return "MipsISD::FPRound"; case MipsISD::MAdd : return "MipsISD::MAdd"; case MipsISD::MAddu : return "MipsISD::MAddu"; case MipsISD::MSub : return "MipsISD::MSub"; case MipsISD::MSubu : return "MipsISD::MSubu"; + case MipsISD::DivRem : return "MipsISD::DivRem"; + case MipsISD::DivRemU : return "MipsISD::DivRemU"; + case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64"; + case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64"; default : return NULL; } } @@ -89,25 +93,22 @@ MipsTargetLowering(MipsTargetMachine &TM) // Mips Custom Operations setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::BlockAddress, MVT::i32, Custom); setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); setOperationAction(ISD::JumpTable, MVT::i32, Custom); setOperationAction(ISD::ConstantPool, MVT::i32, Custom); setOperationAction(ISD::SELECT, MVT::f32, Custom); setOperationAction(ISD::SELECT, MVT::f64, Custom); setOperationAction(ISD::SELECT, MVT::i32, Custom); - setOperationAction(ISD::SETCC, MVT::f32, Custom); - setOperationAction(ISD::SETCC, MVT::f64, Custom); setOperationAction(ISD::BRCOND, MVT::Other, Custom); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom); setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); setOperationAction(ISD::VASTART, MVT::Other, Custom); - - // We custom lower AND/OR to handle the case where the DAG contain 'ands/ors' - // with operands comming from setcc fp comparions. This is necessary since - // the result from these setcc are in a flag registers (FCR31). - setOperationAction(ISD::AND, MVT::i32, Custom); - setOperationAction(ISD::OR, MVT::i32, Custom); + setOperationAction(ISD::SDIV, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::UDIV, MVT::i32, Expand); + setOperationAction(ISD::UREM, MVT::i32, Expand); // Operations not directly supported by Mips. setOperationAction(ISD::BR_JT, MVT::Other, Expand); @@ -129,7 +130,9 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); setOperationAction(ISD::FSIN, MVT::f32, Expand); + setOperationAction(ISD::FSIN, MVT::f64, Expand); setOperationAction(ISD::FCOS, MVT::f32, Expand); + setOperationAction(ISD::FCOS, MVT::f64, Expand); setOperationAction(ISD::FPOWI, MVT::f32, Expand); setOperationAction(ISD::FPOW, MVT::f32, Expand); setOperationAction(ISD::FLOG, MVT::f32, Expand); @@ -139,6 +142,10 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); + setOperationAction(ISD::VAARG, MVT::Other, Expand); + setOperationAction(ISD::VACOPY, MVT::Other, Expand); + setOperationAction(ISD::VAEND, MVT::Other, Expand); + // Use the default for now setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); @@ -160,6 +167,9 @@ MipsTargetLowering(MipsTargetMachine &TM) setTargetDAGCombine(ISD::ADDE); setTargetDAGCombine(ISD::SUBE); + setTargetDAGCombine(ISD::SDIVREM); + setTargetDAGCombine(ISD::UDIVREM); + setTargetDAGCombine(ISD::SETCC); setStackPointerRegisterToSaveRestore(Mips::SP); computeRegisterProperties(); @@ -181,7 +191,7 @@ unsigned MipsTargetLowering::getFunctionAlignment(const Function *) const { // multHi/Lo: product of multiplication // Lo0: initial value of Lo register // Hi0: initial value of Hi register -// Return true if mattern matching was successful. +// Return true if pattern matching was successful. static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { // ADDENode's second operand must be a flag output of an ADDC node in order // for the matching to be successful. @@ -255,7 +265,7 @@ static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { // multHi/Lo: product of multiplication // Lo0: initial value of Lo register // Hi0: initial value of Hi register -// Return true if mattern matching was successful. +// Return true if pattern matching was successful. static bool SelectMsub(SDNode* SUBENode, SelectionDAG* CurDAG) { // SUBENode's second operand must be a flag output of an SUBC node in order // for the matching to be successful. @@ -346,6 +356,130 @@ static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, return SDValue(); } +static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + if (DCI.isBeforeLegalizeOps()) + return SDValue(); + + unsigned opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem : + MipsISD::DivRemU; + DebugLoc dl = N->getDebugLoc(); + + SDValue DivRem = DAG.getNode(opc, dl, MVT::Glue, + N->getOperand(0), N->getOperand(1)); + SDValue InChain = DAG.getEntryNode(); + SDValue InGlue = DivRem; + + // insert MFLO + if (N->hasAnyUseOfValue(0)) { + SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, Mips::LO, MVT::i32, + InGlue); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo); + InChain = CopyFromLo.getValue(1); + InGlue = CopyFromLo.getValue(2); + } + + // insert MFHI + if (N->hasAnyUseOfValue(1)) { + SDValue CopyFromHi = DAG.getCopyFromReg(InChain, dl, + Mips::HI, MVT::i32, InGlue); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi); + } + + return SDValue(); +} + +static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) { + switch (CC) { + default: llvm_unreachable("Unknown fp condition code!"); + case ISD::SETEQ: + case ISD::SETOEQ: return Mips::FCOND_OEQ; + case ISD::SETUNE: return Mips::FCOND_UNE; + case ISD::SETLT: + case ISD::SETOLT: return Mips::FCOND_OLT; + case ISD::SETGT: + case ISD::SETOGT: return Mips::FCOND_OGT; + case ISD::SETLE: + case ISD::SETOLE: return Mips::FCOND_OLE; + case ISD::SETGE: + case ISD::SETOGE: return Mips::FCOND_OGE; + case ISD::SETULT: return Mips::FCOND_ULT; + case ISD::SETULE: return Mips::FCOND_ULE; + case ISD::SETUGT: return Mips::FCOND_UGT; + case ISD::SETUGE: return Mips::FCOND_UGE; + case ISD::SETUO: return Mips::FCOND_UN; + case ISD::SETO: return Mips::FCOND_OR; + case ISD::SETNE: + case ISD::SETONE: return Mips::FCOND_ONE; + case ISD::SETUEQ: return Mips::FCOND_UEQ; + } +} + + +// Returns true if condition code has to be inverted. +static bool InvertFPCondCode(Mips::CondCode CC) { + if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT) + return false; + + if (CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) + return true; + + assert(false && "Illegal Condition Code"); + return false; +} + +// Creates and returns an FPCmp node from a setcc node. +// Returns Op if setcc is not a floating point comparison. +static SDValue CreateFPCmp(SelectionDAG& DAG, const SDValue& Op) { + // must be a SETCC node + if (Op.getOpcode() != ISD::SETCC) + return Op; + + SDValue LHS = Op.getOperand(0); + + if (!LHS.getValueType().isFloatingPoint()) + return Op; + + SDValue RHS = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + + // Assume the 3rd operand is a CondCodeSDNode. Add code to check the type of + // node if necessary. + ISD::CondCode CC = cast(Op.getOperand(2))->get(); + + return DAG.getNode(MipsISD::FPCmp, dl, MVT::Glue, LHS, RHS, + DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32)); +} + +// Creates and returns a CMovFPT/F node. +static SDValue CreateCMovFP(SelectionDAG& DAG, SDValue Cond, SDValue True, + SDValue False, DebugLoc DL) { + bool invert = InvertFPCondCode((Mips::CondCode) + cast(Cond.getOperand(2)) + ->getSExtValue()); + + return DAG.getNode((invert ? MipsISD::CMovFP_F : MipsISD::CMovFP_T), DL, + True.getValueType(), True, False, Cond); +} + +static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + if (DCI.isBeforeLegalizeOps()) + return SDValue(); + + SDValue Cond = CreateFPCmp(DAG, SDValue(N, 0)); + + if (Cond.getOpcode() != MipsISD::FPCmp) + return SDValue(); + + SDValue True = DAG.getConstant(1, MVT::i32); + SDValue False = DAG.getConstant(0, MVT::i32); + + return CreateCMovFP(DAG, Cond, True, False, N->getDebugLoc()); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -357,6 +491,11 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return PerformADDECombine(N, DAG, DCI, Subtarget); case ISD::SUBE: return PerformSUBECombine(N, DAG, DCI, Subtarget); + case ISD::SDIVREM: + case ISD::UDIVREM: + return PerformDivRemCombine(N, DAG, DCI, Subtarget); + case ISD::SETCC: + return PerformSETCCCombine(N, DAG, DCI, Subtarget); } return SDValue(); @@ -367,17 +506,15 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { - case ISD::AND: return LowerANDOR(Op, DAG); case ISD::BRCOND: return LowerBRCOND(Op, DAG); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); - case ISD::OR: return LowerANDOR(Op, DAG); case ISD::SELECT: return LowerSELECT(Op, DAG); - case ISD::SETCC: return LowerSETCC(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); } return SDValue(); @@ -410,122 +547,110 @@ static Mips::FPBranchCode GetFPBranchCodeFromCond(Mips::CondCode CC) { return Mips::BRANCH_INVALID; } -static unsigned FPBranchCodeToOpc(Mips::FPBranchCode BC) { - switch(BC) { - default: - llvm_unreachable("Unknown branch code"); - case Mips::BRANCH_T : return Mips::BC1T; - case Mips::BRANCH_F : return Mips::BC1F; - case Mips::BRANCH_TL : return Mips::BC1TL; - case Mips::BRANCH_FL : return Mips::BC1FL; - } -} - -static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) { - switch (CC) { - default: llvm_unreachable("Unknown fp condition code!"); - case ISD::SETEQ: - case ISD::SETOEQ: return Mips::FCOND_EQ; - case ISD::SETUNE: return Mips::FCOND_OGL; - case ISD::SETLT: - case ISD::SETOLT: return Mips::FCOND_OLT; - case ISD::SETGT: - case ISD::SETOGT: return Mips::FCOND_OGT; - case ISD::SETLE: - case ISD::SETOLE: return Mips::FCOND_OLE; - case ISD::SETGE: - case ISD::SETOGE: return Mips::FCOND_OGE; - case ISD::SETULT: return Mips::FCOND_ULT; - case ISD::SETULE: return Mips::FCOND_ULE; - case ISD::SETUGT: return Mips::FCOND_UGT; - case ISD::SETUGE: return Mips::FCOND_UGE; - case ISD::SETUO: return Mips::FCOND_UN; - case ISD::SETO: return Mips::FCOND_OR; - case ISD::SETNE: - case ISD::SETONE: return Mips::FCOND_NEQ; - case ISD::SETUEQ: return Mips::FCOND_UEQ; - } -} - MachineBasicBlock * MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB) const { + // There is no need to expand CMov instructions if target has + // conditional moves. + if (Subtarget->hasCondMov()) + return BB; + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); bool isFPCmp = false; DebugLoc dl = MI->getDebugLoc(); + unsigned Opc; switch (MI->getOpcode()) { default: assert(false && "Unexpected instr type to insert"); - case Mips::Select_FCC: - case Mips::Select_FCC_S32: - case Mips::Select_FCC_D32: - isFPCmp = true; // FALL THROUGH - case Mips::Select_CC: - case Mips::Select_CC_S32: - case Mips::Select_CC_D32: { - // To "insert" a SELECT_CC instruction, we actually have to insert the - // diamond control-flow pattern. The incoming instruction knows the - // destination vreg to set, the condition code register to branch on, the - // true/false values to select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = BB; - ++It; + case Mips::MOVT: + case Mips::MOVT_S: + case Mips::MOVT_D: + isFPCmp = true; + Opc = Mips::BC1F; + break; + case Mips::MOVF: + case Mips::MOVF_S: + case Mips::MOVF_D: + isFPCmp = true; + Opc = Mips::BC1T; + break; + case Mips::MOVZ_I: + case Mips::MOVZ_S: + case Mips::MOVZ_D: + Opc = Mips::BNE; + break; + case Mips::MOVN_I: + case Mips::MOVN_S: + case Mips::MOVN_D: + Opc = Mips::BEQ; + break; + } - // thisMBB: - // ... - // TrueVal = ... - // setcc r1, r2, r3 - // bNE r1, r0, copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, copy0MBB); - F->insert(It, sinkMBB); + // To "insert" a SELECT_CC instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; - // Transfer the remainder of BB and its successor edges to sinkMBB. - sinkMBB->splice(sinkMBB->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); - sinkMBB->transferSuccessorsAndUpdatePHIs(BB); + // thisMBB: + // ... + // TrueVal = ... + // setcc r1, r2, r3 + // bNE r1, r0, copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, copy0MBB); + F->insert(It, sinkMBB); - // Next, add the true and fallthrough blocks as its successors. - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); + // Transfer the remainder of BB and its successor edges to sinkMBB. + sinkMBB->splice(sinkMBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(BB); - // Emit the right instruction according to the type of the operands compared - if (isFPCmp) { - // Find the condiction code present in the setcc operation. - Mips::CondCode CC = (Mips::CondCode)MI->getOperand(4).getImm(); - // Get the branch opcode from the branch code. - unsigned Opc = FPBranchCodeToOpc(GetFPBranchCodeFromCond(CC)); - BuildMI(BB, dl, TII->get(Opc)).addMBB(sinkMBB); - } else - BuildMI(BB, dl, TII->get(Mips::BNE)).addReg(MI->getOperand(1).getReg()) - .addReg(Mips::ZERO).addMBB(sinkMBB); + // Next, add the true and fallthrough blocks as its successors. + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; + // Emit the right instruction according to the type of the operands compared + if (isFPCmp) + BuildMI(BB, dl, TII->get(Opc)).addMBB(sinkMBB); + else + BuildMI(BB, dl, TII->get(Opc)).addReg(MI->getOperand(2).getReg()) + .addReg(Mips::ZERO).addMBB(sinkMBB); - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - // sinkMBB: - // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] - // ... - BB = sinkMBB; + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] + // ... + BB = sinkMBB; + + if (isFPCmp) BuildMI(*BB, BB->begin(), dl, TII->get(Mips::PHI), MI->getOperand(0).getReg()) .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB) - .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB); + .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB); + else + BuildMI(*BB, BB->begin(), dl, + TII->get(Mips::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(3).getReg()).addMBB(thisMBB) + .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. - return BB; - } - } + MI->eraseFromParent(); // The pseudo instruction is gone now. + return BB; } //===----------------------------------------------------------------------===// @@ -589,27 +714,6 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const return DAG.getMergeValues(Ops, 2, dl); } -SDValue MipsTargetLowering:: -LowerANDOR(SDValue Op, SelectionDAG &DAG) const -{ - SDValue LHS = Op.getOperand(0); - SDValue RHS = Op.getOperand(1); - DebugLoc dl = Op.getDebugLoc(); - - if (LHS.getOpcode() != MipsISD::FPCmp || RHS.getOpcode() != MipsISD::FPCmp) - return Op; - - SDValue True = DAG.getConstant(1, MVT::i32); - SDValue False = DAG.getConstant(0, MVT::i32); - - SDValue LSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), - LHS, True, False, LHS.getOperand(2)); - SDValue RSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), - RHS, True, False, RHS.getOperand(2)); - - return DAG.getNode(Op.getOpcode(), dl, MVT::i32, LSEL, RSEL); -} - SDValue MipsTargetLowering:: LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { @@ -619,58 +723,32 @@ LowerBRCOND(SDValue Op, SelectionDAG &DAG) const SDValue Dest = Op.getOperand(2); DebugLoc dl = Op.getDebugLoc(); - if (Op.getOperand(1).getOpcode() != MipsISD::FPCmp) + SDValue CondRes = CreateFPCmp(DAG, Op.getOperand(1)); + + // Return if flag is not set by a floating point comparison. + if (CondRes.getOpcode() != MipsISD::FPCmp) return Op; - SDValue CondRes = Op.getOperand(1); SDValue CCNode = CondRes.getOperand(2); Mips::CondCode CC = (Mips::CondCode)cast(CCNode)->getZExtValue(); SDValue BrCode = DAG.getConstant(GetFPBranchCodeFromCond(CC), MVT::i32); return DAG.getNode(MipsISD::FPBrcond, dl, Op.getValueType(), Chain, BrCode, - Dest, CondRes); -} - -SDValue MipsTargetLowering:: -LowerSETCC(SDValue Op, SelectionDAG &DAG) const -{ - // The operands to this are the left and right operands to compare (ops #0, - // and #1) and the condition code to compare them with (op #2) as a - // CondCodeSDNode. - SDValue LHS = Op.getOperand(0); - SDValue RHS = Op.getOperand(1); - DebugLoc dl = Op.getDebugLoc(); - - ISD::CondCode CC = cast(Op.getOperand(2))->get(); - - return DAG.getNode(MipsISD::FPCmp, dl, Op.getValueType(), LHS, RHS, - DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32)); + Dest, CondRes); } SDValue MipsTargetLowering:: LowerSELECT(SDValue Op, SelectionDAG &DAG) const { - SDValue Cond = Op.getOperand(0); - SDValue True = Op.getOperand(1); - SDValue False = Op.getOperand(2); - DebugLoc dl = Op.getDebugLoc(); + SDValue Cond = CreateFPCmp(DAG, Op.getOperand(0)); - // if the incomming condition comes from a integer compare, the select - // operation must be SelectCC or a conditional move if the subtarget - // supports it. - if (Cond.getOpcode() != MipsISD::FPCmp) { - if (Subtarget->hasCondMov() && !True.getValueType().isFloatingPoint()) - return Op; - return DAG.getNode(MipsISD::SelectCC, dl, True.getValueType(), - Cond, True, False); - } + // Return if flag is not set by a floating point comparison. + if (Cond.getOpcode() != MipsISD::FPCmp) + return Op; - // if the incomming condition comes from fpcmp, the select - // operation must use FPSelectCC. - SDValue CCNode = Cond.getOperand(2); - return DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(), - Cond, True, False, CCNode); + return CreateCMovFP(DAG, Cond, Op.getOperand(1), Op.getOperand(2), + Op.getDebugLoc()); } SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, @@ -693,12 +771,13 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, return DAG.getNode(ISD::ADD, dl, MVT::i32, GOT, GPRelNode); } // %hi/%lo relocation - SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, - MipsII::MO_ABS_HILO); - SDValue HiPart = DAG.getNode(MipsISD::Hi, dl, VTs, &GA, 1); - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, GA); + SDValue GAHi = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + MipsII::MO_ABS_HI); + SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + MipsII::MO_ABS_LO); + SDValue HiPart = DAG.getNode(MipsISD::Hi, dl, VTs, &GAHi, 1); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, GALo); return DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); - } else { SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, MipsII::MO_GOT); @@ -707,9 +786,12 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, false, false, 0); // On functions and global targets not internal linked only // a load from got/GP is necessary for PIC to work. - if (!GV->hasLocalLinkage() || isa(GV)) + if (!GV->hasInternalLinkage() && + (!GV->hasLocalLinkage() || isa(GV))) return ResNode; - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, GA); + SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + MipsII::MO_ABS_LO); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, GALo); return DAG.getNode(ISD::ADD, dl, MVT::i32, ResNode, Lo); } @@ -717,6 +799,34 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, return SDValue(0,0); } +SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op, + SelectionDAG &DAG) const { + const BlockAddress *BA = cast(Op)->getBlockAddress(); + // FIXME there isn't actually debug info here + DebugLoc dl = Op.getDebugLoc(); + + if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { + // %hi/%lo relocation + SDValue BAHi = DAG.getBlockAddress(BA, MVT::i32, true, + MipsII::MO_ABS_HI); + SDValue BALo = DAG.getBlockAddress(BA, MVT::i32, true, + MipsII::MO_ABS_LO); + SDValue Hi = DAG.getNode(MipsISD::Hi, dl, MVT::i32, BAHi); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALo); + return DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo); + } + + SDValue BAGOTOffset = DAG.getBlockAddress(BA, MVT::i32, true, + MipsII::MO_GOT); + SDValue BALOOffset = DAG.getBlockAddress(BA, MVT::i32, true, + MipsII::MO_ABS_LO); + SDValue Load = DAG.getLoad(MVT::i32, dl, + DAG.getEntryNode(), BAGOTOffset, + MachinePointerInfo(), false, false, 0); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALOOffset); + return DAG.getNode(ISD::ADD, dl, MVT::i32, Load, Lo); +} + SDValue MipsTargetLowering:: LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { @@ -732,7 +842,7 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG) const // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; - unsigned char OpFlag = IsPIC ? MipsII::MO_GOT : MipsII::MO_ABS_HILO; + unsigned char OpFlag = IsPIC ? MipsII::MO_GOT : MipsII::MO_ABS_HI; EVT PtrVT = Op.getValueType(); JumpTableSDNode *JT = cast(Op); @@ -747,7 +857,9 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG) const MachinePointerInfo(), false, false, 0); - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, JTI); + SDValue JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, + MipsII::MO_ABS_LO); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, JTILo); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); return ResNode; @@ -764,7 +876,7 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const // gp_rel relocation // FIXME: we should reference the constant pool using small data sections, - // but the asm printer currently doens't support this feature without + // but the asm printer currently doesn't support this feature without // hacking it. This feature should come soon so we can uncomment the // stuff below. //if (IsInSmallSection(C->getType())) { @@ -773,18 +885,22 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const // ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { - SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), - N->getOffset(), MipsII::MO_ABS_HILO); - SDValue HiPart = DAG.getNode(MipsISD::Hi, dl, MVT::i32, CP); - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CP); + SDValue CPHi = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), + N->getOffset(), MipsII::MO_ABS_HI); + SDValue CPLo = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), + N->getOffset(), MipsII::MO_ABS_LO); + SDValue HiPart = DAG.getNode(MipsISD::Hi, dl, MVT::i32, CPHi); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CPLo); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); } else { SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), - N->getOffset(), MipsII::MO_GOT); + N->getOffset(), MipsII::MO_GOT); SDValue Load = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), CP, MachinePointerInfo::getConstantPool(), false, false, 0); - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CP); + SDValue CPLo = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), + N->getOffset(), MipsII::MO_ABS_LO); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CPLo); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, Load, Lo); } @@ -937,46 +1053,28 @@ static bool CC_MipsO32_VarArgs(unsigned ValNo, MVT ValVT, LocInfo = CCValAssign::AExt; } + unsigned Reg; + if (ValVT == MVT::i32 || ValVT == MVT::f32) { - if (unsigned Reg = State.AllocateReg(IntRegs, IntRegsSize)) { - State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, MVT::i32, LocInfo)); - return false; - } - unsigned Off = State.AllocateStack(4, 4); - State.addLoc(CCValAssign::getMem(ValNo, ValVT, Off, LocVT, LocInfo)); - return false; - } + Reg = State.AllocateReg(IntRegs, IntRegsSize); + LocVT = MVT::i32; + } else if (ValVT == MVT::f64) { + Reg = State.AllocateReg(IntRegs, IntRegsSize); + if (Reg == Mips::A1 || Reg == Mips::A3) + Reg = State.AllocateReg(IntRegs, IntRegsSize); + State.AllocateReg(IntRegs, IntRegsSize); + LocVT = MVT::i32; + } else + llvm_unreachable("Cannot handle this ValVT."); - unsigned UnallocIntReg = State.getFirstUnallocated(IntRegs, IntRegsSize); - if (ValVT == MVT::f64) { - if (IntRegs[UnallocIntReg] == (unsigned (Mips::A1))) { - // A1 can't be used anymore, because 64 bit arguments - // must be aligned when copied back to the caller stack - State.AllocateReg(IntRegs, IntRegsSize); - UnallocIntReg++; - } + if (!Reg) { + unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; + unsigned Offset = State.AllocateStack(SizeInBytes, SizeInBytes); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + } else + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - if (IntRegs[UnallocIntReg] == (unsigned (Mips::A0)) || - IntRegs[UnallocIntReg] == (unsigned (Mips::A2))) { - unsigned Reg = State.AllocateReg(IntRegs, IntRegsSize); - State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, MVT::i32, LocInfo)); - // Shadow the next register so it can be used - // later to get the other 32bit part. - State.AllocateReg(IntRegs, IntRegsSize); - return false; - } - - // Register is shadowed to preserve alignment, and the - // argument goes to a stack location. - if (UnallocIntReg != IntRegsSize) - State.AllocateReg(IntRegs, IntRegsSize); - - unsigned Off = State.AllocateStack(8, 8); - State.addLoc(CCValAssign::getMem(ValNo, ValVT, Off, LocVT, LocInfo)); - return false; - } - - return true; // CC didn't match + return false; // CC must always match } //===----------------------------------------------------------------------===// @@ -1043,11 +1141,12 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, if (VA.getValVT() == MVT::f32 && VA.getLocVT() == MVT::i32) Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); if (VA.getValVT() == MVT::f64 && VA.getLocVT() == MVT::i32) { - Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i64, Arg); - SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Arg, - DAG.getConstant(0, getPointerTy())); - SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Arg, - DAG.getConstant(1, getPointerTy())); + SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32, + Arg, DAG.getConstant(0, MVT::i32)); + SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32, + Arg, DAG.getConstant(1, MVT::i32)); + if (!Subtarget->isLittle()) + std::swap(Lo, Hi); RegsToPass.push_back(std::make_pair(VA.getLocReg(), Lo)); RegsToPass.push_back(std::make_pair(VA.getLocReg()+1, Hi)); continue; @@ -1100,7 +1199,7 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. - // The InFlag in necessary since all emited instructions must be + // The InFlag in necessary since all emitted instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { @@ -1113,12 +1212,52 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. unsigned char OpFlag = IsPIC ? MipsII::MO_GOT_CALL : MipsII::MO_NO_FLAG; - if (GlobalAddressSDNode *G = dyn_cast(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, - getPointerTy(), 0, OpFlag); - else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) + bool LoadSymAddr = false; + SDValue CalleeLo; + + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + if (IsPIC && G->getGlobal()->hasInternalLinkage()) { + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, + getPointerTy(), 0,MipsII:: MO_GOT); + CalleeLo = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), + 0, MipsII::MO_ABS_LO); + } else { + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, + getPointerTy(), 0, OpFlag); + } + + LoadSymAddr = true; + } + else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(), OpFlag); + LoadSymAddr = true; + } + + // Create nodes that load address of callee and copy it to T9 + if (IsPIC) { + if (LoadSymAddr) { + // Load callee address + SDValue LoadValue = DAG.getLoad(MVT::i32, dl, Chain, Callee, + MachinePointerInfo::getGOT(), + false, false, 0); + + // Use GOT+LO if callee has internal linkage. + if (CalleeLo.getNode()) { + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CalleeLo); + Callee = DAG.getNode(ISD::ADD, dl, MVT::i32, LoadValue, Lo); + } else + Callee = LoadValue; + + // Use chain output from LoadValue + Chain = LoadValue.getValue(1); + } + + // copy to T9 + Chain = DAG.getCopyToReg(Chain, dl, Mips::T9, Callee, SDValue(0, 0)); + InFlag = Chain.getValue(1); + Callee = DAG.getRegister(Mips::T9, MVT::i32); + } // MipsJmpLink = #chain, #target_address, #opt_in_flags... // = Chain, Callee, Reg#1, Reg#2, ... @@ -1143,7 +1282,7 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Create a stack location to hold GP when PIC is used. This stack // location is used on function prologue to save GP and also after all - // emited CALL's to restore GP. + // emitted CALL's to restore GP. if (IsPIC) { // Function can have an arbitrary number of calls, so // hold the LastArgStackLoc with the biggest offset. @@ -1218,18 +1357,18 @@ MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, /// and generate load operations for arguments places on the stack. SDValue MipsTargetLowering::LowerFormalArguments(SDValue Chain, - CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl - &Ins, - DebugLoc dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) + CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl + &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo(); - unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF); MipsFI->setVarArgsFrameIndex(0); // Used with vargs to acumulate store chains. @@ -1249,9 +1388,9 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, else CCInfo.AnalyzeFormalArguments(Ins, CC_Mips); - SDValue StackPtr; - unsigned FirstStackArgLoc = (Subtarget->isABI_EABI() ? 0 : 16); + unsigned LastStackArgEndOffset = 0; + EVT LastRegArgValVT; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -1260,6 +1399,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, if (VA.isRegLoc()) { EVT RegVT = VA.getLocVT(); ArgRegEnd = VA.getLocReg(); + LastRegArgValVT = VA.getValVT(); TargetRegisterClass *RC = 0; if (RegVT == MVT::i32) @@ -1300,8 +1440,10 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg()+1, RC); SDValue ArgValue2 = DAG.getCopyFromReg(Chain, dl, Reg2, RegVT); - SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, ArgValue2, ArgValue); - ArgValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Pair); + if (!Subtarget->isLittle()) + std::swap(ArgValue, ArgValue2); + ArgValue = DAG.getNode(MipsISD::BuildPairF64, dl, MVT::f64, + ArgValue, ArgValue2); } } @@ -1321,10 +1463,10 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // used instead of a direct negative address (which is recorded to // be used on emitPrologue) to avoid mis-calc of the first stack // offset on PEI::calculateFrameObjectOffsets. - // Arguments are always 32-bit. - unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; + unsigned ArgSize = VA.getValVT().getSizeInBits()/8; + LastStackArgEndOffset = FirstStackArgLoc + VA.getLocMemOffset() + ArgSize; int FI = MFI->CreateFixedObject(ArgSize, 0, true); - MipsFI->recordLoadArgsFI(FI, -(ArgSize+ + MipsFI->recordLoadArgsFI(FI, -(4 + (FirstStackArgLoc + VA.getLocMemOffset()))); // Create load nodes to retrieve arguments from the stack @@ -1351,29 +1493,52 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // To meet ABI, when VARARGS are passed on registers, the registers // must have their values written to the caller stack frame. If the last // argument was placed in the stack, there's no need to save any register. - if ((isVarArg) && (Subtarget->isABI_O32() && ArgRegEnd)) { - if (StackPtr.getNode() == 0) - StackPtr = DAG.getRegister(StackReg, getPointerTy()); + if (isVarArg && Subtarget->isABI_O32()) { + if (ArgRegEnd) { + // Last named formal argument is passed in register. - // The last register argument that must be saved is Mips::A3 - TargetRegisterClass *RC = Mips::CPURegsRegisterClass; - unsigned StackLoc = ArgLocs.size()-1; + // The last register argument that must be saved is Mips::A3 + TargetRegisterClass *RC = Mips::CPURegsRegisterClass; + if (LastRegArgValVT == MVT::f64) + ArgRegEnd++; - for (++ArgRegEnd; ArgRegEnd <= Mips::A3; ++ArgRegEnd, ++StackLoc) { - unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegEnd, RC); - SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, MVT::i32); + if (ArgRegEnd < Mips::A3) { + // Both the last named formal argument and the first variable + // argument are passed in registers. + for (++ArgRegEnd; ArgRegEnd <= Mips::A3; ++ArgRegEnd) { + unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegEnd, RC); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, MVT::i32); - int FI = MFI->CreateFixedObject(4, 0, true); - MipsFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4))); - SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); - OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, - MachinePointerInfo(), - false, false, 0)); + int FI = MFI->CreateFixedObject(4, 0, true); + MipsFI->recordStoreVarArgsFI(FI, -(4+(ArgRegEnd-Mips::A0)*4)); + SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); + OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, + MachinePointerInfo(), + false, false, 0)); - // Record the frame index of the first variable argument - // which is a value necessary to VASTART. - if (!MipsFI->getVarArgsFrameIndex()) + // Record the frame index of the first variable argument + // which is a value necessary to VASTART. + if (!MipsFI->getVarArgsFrameIndex()) { + MFI->setObjectAlignment(FI, 4); + MipsFI->setVarArgsFrameIndex(FI); + } + } + } else { + // Last named formal argument is in register Mips::A3, and the first + // variable argument is on stack. Record the frame index of the first + // variable argument. + int FI = MFI->CreateFixedObject(4, 0, true); + MFI->setObjectAlignment(FI, 4); + MipsFI->recordStoreVarArgsFI(FI, -20); MipsFI->setVarArgsFrameIndex(FI); + } + } else { + // Last named formal argument and all the variable arguments are passed + // on stack. Record the frame index of the first variable argument. + int FI = MFI->CreateFixedObject(4, 0, true); + MFI->setObjectAlignment(FI, 4); + MipsFI->recordStoreVarArgsFI(FI, -(4+LastStackArgEndOffset)); + MipsFI->setVarArgsFrameIndex(FI); } } diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h b/contrib/llvm/lib/Target/Mips/MipsISelLowering.h index 9d6b9f3daf87..e4d0c3d24f9c 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.h @@ -31,45 +31,50 @@ namespace llvm { // Get the Higher 16 bits from a 32-bit immediate // No relation with Mips Hi register - Hi, + Hi, // Get the Lower 16 bits from a 32-bit immediate // No relation with Mips Lo register - Lo, + Lo, // Handle gp_rel (small data/bss sections) relocation. GPRel, - // Select CC Pseudo Instruction - SelectCC, - - // Floating Point Select CC Pseudo Instruction - FPSelectCC, - // Floating Point Branch Conditional FPBrcond, // Floating Point Compare FPCmp, + // Floating Point Conditional Moves + CMovFP_T, + CMovFP_F, + // Floating Point Rounding FPRound, - // Return + // Return Ret, // MAdd/Sub nodes MAdd, MAddu, MSub, - MSubu + MSubu, + + // DivRem(u) + DivRem, + DivRemU, + + BuildPairF64, + ExtractElementF64 }; } //===--------------------------------------------------------------------===// // TargetLowering Implementation //===--------------------------------------------------------------------===// - + class MipsTargetLowering : public TargetLowering { public: explicit MipsTargetLowering(MipsTargetMachine &TM); @@ -77,7 +82,7 @@ namespace llvm { /// LowerOperation - Provide custom lowering hooks for some operations. virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; - /// getTargetNodeName - This method returns the name of a target specific + /// getTargetNodeName - This method returns the name of a target specific // DAG node. virtual const char *getTargetNodeName(unsigned Opcode) const; @@ -87,7 +92,7 @@ namespace llvm { /// getFunctionAlignment - Return the Log2 alignment of this function. virtual unsigned getFunctionAlignment(const Function *F) const; - virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; private: // Subtarget Info const MipsSubtarget *Subtarget; @@ -101,16 +106,15 @@ namespace llvm { SmallVectorImpl &InVals) const; // Lower Operand specifics - SDValue LowerANDOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const; SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; virtual SDValue @@ -149,7 +153,7 @@ namespace llvm { ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; - std::pair + std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td index 977e0dfa145a..a86c5c7e8b83 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td @@ -24,19 +24,28 @@ //===----------------------------------------------------------------------===// // Floating Point Compare and Branch -def SDT_MipsFPBrcond : SDTypeProfile<0, 3, [SDTCisSameAs<0, 2>, SDTCisInt<0>, - SDTCisVT<1, OtherVT>]>; -def SDT_MipsFPCmp : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, - SDTCisSameAs<1, 2>, SDTCisFP<1>, - SDTCisInt<3>]>; -def SDT_MipsFPSelectCC : SDTypeProfile<1, 4, [SDTCisInt<1>, SDTCisInt<4>, - SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>]>; +def SDT_MipsFPBrcond : SDTypeProfile<0, 2, [SDTCisInt<0>, + SDTCisVT<1, OtherVT>]>; +def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>, + SDTCisInt<2>]>; +def SDT_MipsCMovFP : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, + SDTCisSameAs<1, 2>]>; +def SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, + SDTCisVT<1, i32>, + SDTCisSameAs<1, 2>]>; +def SDT_MipsExtractElementF64 : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, + SDTCisVT<1, f64>, + SDTCisVT<0, i32>]>; +def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>; +def MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP, [SDNPInGlue]>; +def MipsCMovFP_F : SDNode<"MipsISD::CMovFP_F", SDT_MipsCMovFP, [SDNPInGlue]>; def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInGlue]>; -def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond, - [SDNPHasChain]>; -def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp>; -def MipsFPSelectCC : SDNode<"MipsISD::FPSelectCC", SDT_MipsFPSelectCC>; +def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond, + [SDNPHasChain, SDNPOptInGlue]>; +def MipsBuildPairF64 : SDNode<"MipsISD::BuildPairF64", SDT_MipsBuildPairF64>; +def MipsExtractElementF64 : SDNode<"MipsISD::ExtractElementF64", + SDT_MipsExtractElementF64>; // Operand for printing out a condition code. let PrintMethod = "printFCCOperand" in @@ -54,7 +63,7 @@ def IsNotMipsI : Predicate<"!Subtarget.isMips1()">; //===----------------------------------------------------------------------===// // Instruction Class Templates // -// A set of multiclasses is used to address the register usage. +// A set of multiclasses is used to address the register usage. // // S32 - single precision in 16 32bit even fp registers // single precision in 32 32bit fp registers in SingleOnly mode @@ -65,7 +74,7 @@ def IsNotMipsI : Predicate<"!Subtarget.isMips1()">; // Only S32 and D32 are supported right now. //===----------------------------------------------------------------------===// -multiclass FFR1_1 funct, string asmstr> +multiclass FFR1_1 funct, string asmstr> { def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs), !strconcat(asmstr, ".s $fd, $fs"), []>; @@ -74,31 +83,31 @@ multiclass FFR1_1 funct, string asmstr> !strconcat(asmstr, ".d $fd, $fs"), []>, Requires<[In32BitMode]>; } -multiclass FFR1_2 funct, string asmstr, SDNode FOp> +multiclass FFR1_2 funct, string asmstr, SDNode FOp> { def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs), - !strconcat(asmstr, ".s $fd, $fs"), + !strconcat(asmstr, ".s $fd, $fs"), [(set FGR32:$fd, (FOp FGR32:$fs))]>; def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs), - !strconcat(asmstr, ".d $fd, $fs"), + !strconcat(asmstr, ".d $fd, $fs"), [(set AFGR64:$fd, (FOp AFGR64:$fs))]>, Requires<[In32BitMode]>; } -class FFR1_3 funct, bits<5> fmt, RegisterClass RcSrc, - RegisterClass RcDst, string asmstr>: - FFR<0x11, funct, fmt, (outs RcSrc:$fd), (ins RcDst:$fs), - !strconcat(asmstr, " $fd, $fs"), []>; +class FFR1_3 funct, bits<5> fmt, RegisterClass RcSrc, + RegisterClass RcDst, string asmstr>: + FFR<0x11, funct, fmt, (outs RcSrc:$fd), (ins RcDst:$fs), + !strconcat(asmstr, " $fd, $fs"), []>; multiclass FFR1_4 funct, string asmstr, SDNode FOp> { - def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), - (ins FGR32:$fs, FGR32:$ft), + def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), + (ins FGR32:$fs, FGR32:$ft), !strconcat(asmstr, ".s $fd, $fs, $ft"), [(set FGR32:$fd, (FOp FGR32:$fs, FGR32:$ft))]>; - def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), - (ins AFGR64:$fs, AFGR64:$ft), + def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), + (ins AFGR64:$fs, AFGR64:$ft), !strconcat(asmstr, ".d $fd, $fs, $ft"), [(set AFGR64:$fd, (FOp AFGR64:$fs, AFGR64:$ft))]>, Requires<[In32BitMode]>; @@ -115,8 +124,8 @@ let ft = 0 in { defm TRUNC_W : FFR1_1<0b001101, "trunc.w">; defm CVTW : FFR1_1<0b100100, "cvt.w">; - defm FABS : FFR1_2<0b000101, "abs", fabs>; - defm FNEG : FFR1_2<0b000111, "neg", fneg>; + defm FABS : FFR1_2<0b000101, "abs", fabs>; + defm FNEG : FFR1_2<0b000111, "neg", fneg>; defm FSQRT : FFR1_2<0b000100, "sqrt", fsqrt>; /// Convert to Single Precison @@ -140,23 +149,23 @@ let ft = 0 in { def TRUNC_LD : FFR1_3<0b001001, 0x1, AFGR64, AFGR64, "trunc.l">; /// Convert to long signed integer - def CVTL_S : FFR1_3<0b100101, 0x0, FGR32, FGR32, "cvt.l">; - def CVTL_D : FFR1_3<0b100101, 0x1, AFGR64, AFGR64, "cvt.l">; + def CVTL_S : FFR1_3<0b100101, 0x0, FGR32, FGR32, "cvt.l">; + def CVTL_D : FFR1_3<0b100101, 0x1, AFGR64, AFGR64, "cvt.l">; + + /// Convert to Double Precison + def CVTD_S32 : FFR1_3<0b100001, 0x0, AFGR64, FGR32, "cvt.d.s">; + def CVTD_W32 : FFR1_3<0b100001, 0x2, AFGR64, FGR32, "cvt.d.w">; + def CVTD_L32 : FFR1_3<0b100001, 0x3, AFGR64, AFGR64, "cvt.d.l">; - /// Convert to Double Precison - def CVTD_S32 : FFR1_3<0b100001, 0x0, AFGR64, FGR32, "cvt.d.s">; - def CVTD_W32 : FFR1_3<0b100001, 0x2, AFGR64, FGR32, "cvt.d.w">; - def CVTD_L32 : FFR1_3<0b100001, 0x3, AFGR64, AFGR64, "cvt.d.l">; - /// Convert to Single Precison def CVTS_D32 : FFR1_3<0b100000, 0x1, FGR32, AFGR64, "cvt.s.d">; - def CVTS_L32 : FFR1_3<0b100000, 0x3, FGR32, AFGR64, "cvt.s.l">; + def CVTS_L32 : FFR1_3<0b100000, 0x3, FGR32, AFGR64, "cvt.s.l">; } } // The odd-numbered registers are only referenced when doing loads, // stores, and moves between floating-point and integer registers. -// When defining instructions, we reference all 32-bit registers, +// When defining instructions, we reference all 32-bit registers, // regardless of register aliasing. let fd = 0 in { /// Move Control Registers From/To CPU Registers @@ -165,7 +174,7 @@ let fd = 0 in { def CTC1 : FFR<0x11, 0x0, 0x6, (outs CCR:$rt), (ins CPURegs:$fs), "ctc1 $fs, $rt", []>; - + def MFC1 : FFR<0x11, 0x00, 0x00, (outs CPURegs:$rt), (ins FGR32:$fs), "mfc1 $rt, $fs", []>; @@ -180,18 +189,18 @@ def FMOV_D32 : FFR<0x11, 0b000110, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs), /// Floating Point Memory Instructions let Predicates = [IsNotSingleFloat, IsNotMipsI] in { - def LDC1 : FFI<0b110101, (outs AFGR64:$ft), (ins mem:$addr), + def LDC1 : FFI<0b110101, (outs AFGR64:$ft), (ins mem:$addr), "ldc1 $ft, $addr", [(set AFGR64:$ft, (load addr:$addr))]>; - def SDC1 : FFI<0b111101, (outs), (ins AFGR64:$ft, mem:$addr), + def SDC1 : FFI<0b111101, (outs), (ins AFGR64:$ft, mem:$addr), "sdc1 $ft, $addr", [(store AFGR64:$ft, addr:$addr)]>; } -// LWC1 and SWC1 can always be emited with odd registers. +// LWC1 and SWC1 can always be emitted with odd registers. def LWC1 : FFI<0b110001, (outs FGR32:$ft), (ins mem:$addr), "lwc1 $ft, $addr", - [(set FGR32:$ft, (load addr:$addr))]>; + [(set FGR32:$ft, (load addr:$addr))]>; def SWC1 : FFI<0b111001, (outs), (ins FGR32:$ft, mem:$addr), "swc1 $ft, $addr", - [(store FGR32:$ft, addr:$addr)]>; + [(store FGR32:$ft, addr:$addr)]>; /// Floating-point Aritmetic defm FADD : FFR1_4<0x10, "add", fadd>; @@ -202,7 +211,7 @@ defm FSUB : FFR1_4<0x01, "sub", fsub>; //===----------------------------------------------------------------------===// // Floating Point Branch Codes //===----------------------------------------------------------------------===// -// Mips branch codes. These correspond to condcode in MipsInstrInfo.h. +// Mips branch codes. These correspond to condcode in MipsInstrInfo.h. // They must be kept in synch. def MIPS_BRANCH_F : PatLeaf<(i32 0)>; def MIPS_BRANCH_T : PatLeaf<(i32 1)>; @@ -210,11 +219,11 @@ def MIPS_BRANCH_FL : PatLeaf<(i32 2)>; def MIPS_BRANCH_TL : PatLeaf<(i32 3)>; /// Floating Point Branch of False/True (Likely) -let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in { - class FBRANCH : FFI<0x11, (outs), +let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in + class FBRANCH : FFI<0x11, (outs), (ins brtarget:$dst), !strconcat(asmstr, " $dst"), - [(MipsFPBrcond op, bb:$dst, FCR31)]>; -} + [(MipsFPBrcond op, bb:$dst)]>; + def BC1F : FBRANCH; def BC1T : FBRANCH; def BC1FL : FBRANCH; @@ -223,11 +232,11 @@ def BC1TL : FBRANCH; //===----------------------------------------------------------------------===// // Floating Point Flag Conditions //===----------------------------------------------------------------------===// -// Mips condition codes. They must correspond to condcode in MipsInstrInfo.h. +// Mips condition codes. They must correspond to condcode in MipsInstrInfo.h. // They must be kept in synch. def MIPS_FCOND_F : PatLeaf<(i32 0)>; def MIPS_FCOND_UN : PatLeaf<(i32 1)>; -def MIPS_FCOND_EQ : PatLeaf<(i32 2)>; +def MIPS_FCOND_OEQ : PatLeaf<(i32 2)>; def MIPS_FCOND_UEQ : PatLeaf<(i32 3)>; def MIPS_FCOND_OLT : PatLeaf<(i32 4)>; def MIPS_FCOND_ULT : PatLeaf<(i32 5)>; @@ -245,44 +254,90 @@ def MIPS_FCOND_NGT : PatLeaf<(i32 15)>; /// Floating Point Compare let hasDelaySlot = 1, Defs=[FCR31] in { def FCMP_S32 : FCC<0x0, (outs), (ins FGR32:$fs, FGR32:$ft, condcode:$cc), - "c.$cc.s $fs, $ft", - [(set FCR31, (MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc))]>; - + "c.$cc.s $fs, $ft", + [(MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc)]>; + def FCMP_D32 : FCC<0x1, (outs), (ins AFGR64:$fs, AFGR64:$ft, condcode:$cc), - "c.$cc.d $fs, $ft", - [(set FCR31, (MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc))]>, - Requires<[In32BitMode]>; + "c.$cc.d $fs, $ft", + [(MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc)]>, + Requires<[In32BitMode]>; +} + + +// Conditional moves: +// These instructions are expanded in +// MipsISelLowering::EmitInstrWithCustomInserter if target does not have +// conditional move instructions. +// flag:int, data:float +let usesCustomInserter = 1, Constraints = "$F = $dst" in +class CondMovIntFP fmt, bits<6> func, + string instr_asm> : + FFR<0x11, func, fmt, (outs RC:$dst), (ins RC:$T, CPURegs:$cond, RC:$F), + !strconcat(instr_asm, "\t$dst, $T, $cond"), []>; + +def MOVZ_S : CondMovIntFP; +def MOVN_S : CondMovIntFP; + +let Predicates = [In32BitMode] in { + def MOVZ_D : CondMovIntFP; + def MOVN_D : CondMovIntFP; +} + +defm : MovzPats; +defm : MovnPats; + +let Predicates = [In32BitMode] in { + defm : MovzPats; + defm : MovnPats; +} + +let usesCustomInserter = 1, Uses = [FCR31], Constraints = "$F = $dst" in { +// flag:float, data:int +class CondMovFPInt tf, string instr_asm> : + FCMOV; + +// flag:float, data:float +class CondMovFPFP fmt, bits<1> tf, + string instr_asm> : + FFCMOV; +} + +def MOVT : CondMovFPInt; +def MOVF : CondMovFPInt; +def MOVT_S : CondMovFPFP; +def MOVF_S : CondMovFPFP; + +let Predicates = [In32BitMode] in { + def MOVT_D : CondMovFPFP; + def MOVF_D : CondMovFPFP; } //===----------------------------------------------------------------------===// // Floating Point Pseudo-Instructions //===----------------------------------------------------------------------===// +def MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src), + "# MOVCCRToCCR", []>; -// For some explanation, see Select_CC at MipsInstrInfo.td. We also embedd a -// condiciton code to enable easy handling by the Custom Inserter. -let usesCustomInserter = 1, Uses=[FCR31] in { - class PseudoFPSelCC : - MipsPseudo<(outs RC:$dst), - (ins CPURegs:$CmpRes, RC:$T, RC:$F, condcode:$cc), asmstr, - [(set RC:$dst, (MipsFPSelectCC CPURegs:$CmpRes, RC:$T, RC:$F, - imm:$cc))]>; -} +// This pseudo instr gets expanded into 2 mtc1 instrs after register +// allocation. +def BuildPairF64 : + MipsPseudo<(outs AFGR64:$dst), + (ins CPURegs:$lo, CPURegs:$hi), "", + [(set AFGR64:$dst, (MipsBuildPairF64 CPURegs:$lo, CPURegs:$hi))]>; -// The values to be selected are fp but the condition test is with integers. -def Select_CC_S32 : PseudoSelCC; -def Select_CC_D32 : PseudoSelCC, - Requires<[In32BitMode]>; - -// The values to be selected are int but the condition test is done with fp. -def Select_FCC : PseudoFPSelCC; - -// The values to be selected and the condition test is done with fp. -def Select_FCC_S32 : PseudoFPSelCC; -def Select_FCC_D32 : PseudoFPSelCC, - Requires<[In32BitMode]>; - -def MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src), - "# MOVCCRToCCR", []>; +// This pseudo instr gets expanded into 2 mfc1 instrs after register +// allocation. +// if n is 0, lower part of src is extracted. +// if n is 1, higher part of src is extracted. +def ExtractElementF64 : + MipsPseudo<(outs CPURegs:$dst), + (ins AFGR64:$src, i32imm:$n), "", + [(set CPURegs:$dst, + (MipsExtractElementF64 AFGR64:$src, imm:$n))]>; //===----------------------------------------------------------------------===// // Floating Point Patterns @@ -306,7 +361,7 @@ def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S32 FGR32:$src))>; def : Pat<(i32 (bitconvert FGR32:$src)), (MFC1 FGR32:$src)>; def : Pat<(f32 (bitconvert CPURegs:$src)), (MTC1 CPURegs:$src)>; -let Predicates = [In32BitMode] in { +let Predicates = [In32BitMode] in { def : Pat<(f32 (fround AFGR64:$src)), (CVTS_D32 AFGR64:$src)>; def : Pat<(f64 (fextend FGR32:$src)), (CVTD_S32 FGR32:$src)>; } diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td b/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td index 98ae2fa7da45..9dfcdfbdb255 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td @@ -22,8 +22,8 @@ //===----------------------------------------------------------------------===// // Generic Mips Format -class MipsInst pattern, - InstrItinClass itin>: Instruction +class MipsInst pattern, + InstrItinClass itin>: Instruction { field bits<32> Inst; @@ -32,8 +32,8 @@ class MipsInst pattern, bits<6> opcode; // Top 5 bits are the 'opcode' field - let Inst{31-26} = opcode; - + let Inst{31-26} = opcode; + dag OutOperandList = outs; dag InOperandList = ins; @@ -52,7 +52,7 @@ class MipsPseudo pattern>: class FR op, bits<6> _funct, dag outs, dag ins, string asmstr, list pattern, InstrItinClass itin>: - MipsInst + MipsInst { bits<5> rd; bits<5> rs; @@ -64,7 +64,7 @@ class FR op, bits<6> _funct, dag outs, dag ins, string asmstr, let funct = _funct; let Inst{25-21} = rs; - let Inst{20-16} = rt; + let Inst{20-16} = rt; let Inst{15-11} = rd; let Inst{10-6} = shamt; let Inst{5-0} = funct; @@ -75,7 +75,7 @@ class FR op, bits<6> _funct, dag outs, dag ins, string asmstr, //===----------------------------------------------------------------------===// class FI op, dag outs, dag ins, string asmstr, list pattern, - InstrItinClass itin>: MipsInst + InstrItinClass itin>: MipsInst { bits<5> rt; bits<5> rs; @@ -84,7 +84,7 @@ class FI op, dag outs, dag ins, string asmstr, list pattern, let opcode = op; let Inst{25-21} = rs; - let Inst{20-16} = rt; + let Inst{20-16} = rt; let Inst{15-0} = imm16; } @@ -93,12 +93,12 @@ class FI op, dag outs, dag ins, string asmstr, list pattern, //===----------------------------------------------------------------------===// class FJ op, dag outs, dag ins, string asmstr, list pattern, - InstrItinClass itin>: MipsInst + InstrItinClass itin>: MipsInst { bits<26> addr; let opcode = op; - + let Inst{25-0} = addr; } @@ -119,9 +119,9 @@ class FJ op, dag outs, dag ins, string asmstr, list pattern, // Format FR instruction class in Mips : <|opcode|fmt|ft|fs|fd|funct|> //===----------------------------------------------------------------------===// -class FFR op, bits<6> _funct, bits<5> _fmt, dag outs, dag ins, - string asmstr, list pattern> : - MipsInst +class FFR op, bits<6> _funct, bits<5> _fmt, dag outs, dag ins, + string asmstr, list pattern> : + MipsInst { bits<5> fd; bits<5> fs; @@ -134,7 +134,7 @@ class FFR op, bits<6> _funct, bits<5> _fmt, dag outs, dag ins, let fmt = _fmt; let Inst{25-21} = fmt; - let Inst{20-16} = ft; + let Inst{20-16} = ft; let Inst{15-11} = fs; let Inst{10-6} = fd; let Inst{5-0} = funct; @@ -144,8 +144,8 @@ class FFR op, bits<6> _funct, bits<5> _fmt, dag outs, dag ins, // Format FI instruction class in Mips : <|opcode|base|ft|immediate|> //===----------------------------------------------------------------------===// -class FFI op, dag outs, dag ins, string asmstr, list pattern>: - MipsInst +class FFI op, dag outs, dag ins, string asmstr, list pattern>: + MipsInst { bits<5> ft; bits<5> base; @@ -154,7 +154,7 @@ class FFI op, dag outs, dag ins, string asmstr, list pattern>: let opcode = op; let Inst{25-21} = base; - let Inst{20-16} = ft; + let Inst{20-16} = ft; let Inst{15-0} = imm16; } @@ -162,8 +162,8 @@ class FFI op, dag outs, dag ins, string asmstr, list pattern>: // Compare instruction class in Mips : <|010001|fmt|ft|fs|0000011|condcode|> //===----------------------------------------------------------------------===// -class FCC _fmt, dag outs, dag ins, string asmstr, list pattern> : - MipsInst +class FCC _fmt, dag outs, dag ins, string asmstr, list pattern> : + MipsInst { bits<5> fs; bits<5> ft; @@ -174,9 +174,54 @@ class FCC _fmt, dag outs, dag ins, string asmstr, list pattern> : let fmt = _fmt; let Inst{25-21} = fmt; - let Inst{20-16} = ft; + let Inst{20-16} = ft; let Inst{15-11} = fs; let Inst{10-6} = 0; let Inst{5-4} = 0b11; let Inst{3-0} = cc; } + + +class FCMOV _tf, dag outs, dag ins, string asmstr, + list pattern> : + MipsInst +{ + bits<5> rd; + bits<5> rs; + bits<3> N; + bits<1> tf; + + let opcode = 0; + let tf = _tf; + + let Inst{25-21} = rs; + let Inst{20-18} = N; + let Inst{17} = 0; + let Inst{16} = tf; + let Inst{15-11} = rd; + let Inst{10-6} = 0; + let Inst{5-0} = 1; +} + +class FFCMOV _fmt, bits<1> _tf, dag outs, dag ins, string asmstr, + list pattern> : + MipsInst +{ + bits<5> fd; + bits<5> fs; + bits<3> N; + bits<5> fmt; + bits<1> tf; + + let opcode = 17; + let fmt = _fmt; + let tf = _tf; + + let Inst{25-21} = fmt; + let Inst{20-18} = N; + let Inst{17} = 0; + let Inst{16} = tf; + let Inst{15-11} = fs; + let Inst{10-6} = fd; + let Inst{5-0} = 17; +} \ No newline at end of file diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp index aaf307b1ce3f..be044fa1f3b3 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp @@ -36,7 +36,7 @@ static bool isZeroImm(const MachineOperand &op) { /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than loading from the stack slot. unsigned MipsInstrInfo:: -isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const +isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const { if ((MI->getOpcode() == Mips::LW) || (MI->getOpcode() == Mips::LWC1) || (MI->getOpcode() == Mips::LDC1)) { @@ -57,7 +57,7 @@ isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than storing to the stack slot. unsigned MipsInstrInfo:: -isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const +isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const { if ((MI->getOpcode() == Mips::SW) || (MI->getOpcode() == Mips::SWC1) || (MI->getOpcode() == Mips::SDC1)) { @@ -74,7 +74,7 @@ isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const /// insertNoop - If data hazard condition is found insert the target nop /// instruction. void MipsInstrInfo:: -insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const +insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { DebugLoc DL; BuildMI(MBB, MI, DL, get(Mips::NOP)); @@ -136,7 +136,7 @@ copyPhysReg(MachineBasicBlock &MBB, .addReg(SrcReg, getKillRegState(KillSrc)); return; } - + if (Mips::AFGR64RegClass.contains(DestReg, SrcReg)) { BuildMI(MBB, I, DL, get(Mips::FMOV_D32), DestReg) .addReg(SrcReg, getKillRegState(KillSrc)); @@ -153,13 +153,13 @@ copyPhysReg(MachineBasicBlock &MBB, void MipsInstrInfo:: storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned SrcReg, bool isKill, int FI, + unsigned SrcReg, bool isKill, int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); - if (RC == Mips::CPURegsRegisterClass) + if (RC == Mips::CPURegsRegisterClass) BuildMI(MBB, I, DL, get(Mips::SW)).addReg(SrcReg, getKillRegState(isKill)) .addImm(0).addFrameIndex(FI); else if (RC == Mips::FGR32RegisterClass) @@ -171,7 +171,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, .addReg(SrcReg, getKillRegState(isKill)) .addImm(0).addFrameIndex(FI); } else { - const TargetRegisterInfo *TRI = + const TargetRegisterInfo *TRI = MBB.getParent()->getTarget().getRegisterInfo(); const unsigned *SubSet = TRI->getSubRegisters(SrcReg); BuildMI(MBB, I, DL, get(Mips::SWC1)) @@ -189,12 +189,12 @@ void MipsInstrInfo:: loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg, int FI, const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const + const TargetRegisterInfo *TRI) const { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); - if (RC == Mips::CPURegsRegisterClass) + if (RC == Mips::CPURegsRegisterClass) BuildMI(MBB, I, DL, get(Mips::LW), DestReg).addImm(0).addFrameIndex(FI); else if (RC == Mips::FGR32RegisterClass) BuildMI(MBB, I, DL, get(Mips::LWC1), DestReg).addImm(0).addFrameIndex(FI); @@ -202,7 +202,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, if (!TM.getSubtarget().isMips1()) { BuildMI(MBB, I, DL, get(Mips::LDC1), DestReg).addImm(0).addFrameIndex(FI); } else { - const TargetRegisterInfo *TRI = + const TargetRegisterInfo *TRI = MBB.getParent()->getTarget().getRegisterInfo(); const unsigned *SubSet = TRI->getSubRegisters(DestReg); BuildMI(MBB, I, DL, get(Mips::LWC1), SubSet[0]) @@ -218,281 +218,202 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, // Branch Analysis //===----------------------------------------------------------------------===// -/// GetCondFromBranchOpc - Return the Mips CC that matches -/// the correspondent Branch instruction opcode. -static Mips::CondCode GetCondFromBranchOpc(unsigned BrOpc) -{ - switch (BrOpc) { - default: return Mips::COND_INVALID; - case Mips::BEQ : return Mips::COND_E; - case Mips::BNE : return Mips::COND_NE; - case Mips::BGTZ : return Mips::COND_GZ; - case Mips::BGEZ : return Mips::COND_GEZ; - case Mips::BLTZ : return Mips::COND_LZ; - case Mips::BLEZ : return Mips::COND_LEZ; +static unsigned GetAnalyzableBrOpc(unsigned Opc) { + return (Opc == Mips::BEQ || Opc == Mips::BNE || Opc == Mips::BGTZ || + Opc == Mips::BGEZ || Opc == Mips::BLTZ || Opc == Mips::BLEZ || + Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::J) ? Opc : 0; +} - // We dont do fp branch analysis yet! - case Mips::BC1T : - case Mips::BC1F : return Mips::COND_INVALID; +/// GetOppositeBranchOpc - Return the inverse of the specified +/// opcode, e.g. turning BEQ to BNE. +unsigned Mips::GetOppositeBranchOpc(unsigned Opc) +{ + switch (Opc) { + default: llvm_unreachable("Illegal opcode!"); + case Mips::BEQ : return Mips::BNE; + case Mips::BNE : return Mips::BEQ; + case Mips::BGTZ : return Mips::BLEZ; + case Mips::BGEZ : return Mips::BLTZ; + case Mips::BLTZ : return Mips::BGEZ; + case Mips::BLEZ : return Mips::BGTZ; + case Mips::BC1T : return Mips::BC1F; + case Mips::BC1F : return Mips::BC1T; } } -/// GetCondBranchFromCond - Return the Branch instruction -/// opcode that matches the cc. -unsigned Mips::GetCondBranchFromCond(Mips::CondCode CC) -{ - switch (CC) { - default: llvm_unreachable("Illegal condition code!"); - case Mips::COND_E : return Mips::BEQ; - case Mips::COND_NE : return Mips::BNE; - case Mips::COND_GZ : return Mips::BGTZ; - case Mips::COND_GEZ : return Mips::BGEZ; - case Mips::COND_LZ : return Mips::BLTZ; - case Mips::COND_LEZ : return Mips::BLEZ; +static void AnalyzeCondBr(const MachineInstr* Inst, unsigned Opc, + MachineBasicBlock *&BB, + SmallVectorImpl& Cond) { + assert(GetAnalyzableBrOpc(Opc) && "Not an analyzable branch"); + int NumOp = Inst->getNumExplicitOperands(); + + // for both int and fp branches, the last explicit operand is the + // MBB. + BB = Inst->getOperand(NumOp-1).getMBB(); + Cond.push_back(MachineOperand::CreateImm(Opc)); - case Mips::FCOND_F: - case Mips::FCOND_UN: - case Mips::FCOND_EQ: - case Mips::FCOND_UEQ: - case Mips::FCOND_OLT: - case Mips::FCOND_ULT: - case Mips::FCOND_OLE: - case Mips::FCOND_ULE: - case Mips::FCOND_SF: - case Mips::FCOND_NGLE: - case Mips::FCOND_SEQ: - case Mips::FCOND_NGL: - case Mips::FCOND_LT: - case Mips::FCOND_NGE: - case Mips::FCOND_LE: - case Mips::FCOND_NGT: return Mips::BC1T; - - case Mips::FCOND_T: - case Mips::FCOND_OR: - case Mips::FCOND_NEQ: - case Mips::FCOND_OGL: - case Mips::FCOND_UGE: - case Mips::FCOND_OGE: - case Mips::FCOND_UGT: - case Mips::FCOND_OGT: - case Mips::FCOND_ST: - case Mips::FCOND_GLE: - case Mips::FCOND_SNE: - case Mips::FCOND_GL: - case Mips::FCOND_NLT: - case Mips::FCOND_GE: - case Mips::FCOND_NLE: - case Mips::FCOND_GT: return Mips::BC1F; - } + for (int i=0; igetOperand(i)); } -/// GetOppositeBranchCondition - Return the inverse of the specified -/// condition, e.g. turning COND_E to COND_NE. -Mips::CondCode Mips::GetOppositeBranchCondition(Mips::CondCode CC) -{ - switch (CC) { - default: llvm_unreachable("Illegal condition code!"); - case Mips::COND_E : return Mips::COND_NE; - case Mips::COND_NE : return Mips::COND_E; - case Mips::COND_GZ : return Mips::COND_LEZ; - case Mips::COND_GEZ : return Mips::COND_LZ; - case Mips::COND_LZ : return Mips::COND_GEZ; - case Mips::COND_LEZ : return Mips::COND_GZ; - case Mips::FCOND_F : return Mips::FCOND_T; - case Mips::FCOND_UN : return Mips::FCOND_OR; - case Mips::FCOND_EQ : return Mips::FCOND_NEQ; - case Mips::FCOND_UEQ: return Mips::FCOND_OGL; - case Mips::FCOND_OLT: return Mips::FCOND_UGE; - case Mips::FCOND_ULT: return Mips::FCOND_OGE; - case Mips::FCOND_OLE: return Mips::FCOND_UGT; - case Mips::FCOND_ULE: return Mips::FCOND_OGT; - case Mips::FCOND_SF: return Mips::FCOND_ST; - case Mips::FCOND_NGLE:return Mips::FCOND_GLE; - case Mips::FCOND_SEQ: return Mips::FCOND_SNE; - case Mips::FCOND_NGL: return Mips::FCOND_GL; - case Mips::FCOND_LT: return Mips::FCOND_NLT; - case Mips::FCOND_NGE: return Mips::FCOND_GE; - case Mips::FCOND_LE: return Mips::FCOND_NLE; - case Mips::FCOND_NGT: return Mips::FCOND_GT; - } -} - -bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, +bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl &Cond, - bool AllowModify) const + bool AllowModify) const { - // If the block has no terminators, it just falls into the block after it. - MachineBasicBlock::iterator I = MBB.end(); - if (I == MBB.begin()) - return false; - --I; - while (I->isDebugValue()) { - if (I == MBB.begin()) - return false; - --I; - } - if (!isUnpredicatedTerminator(I)) - return false; - - // Get the last instruction in the block. - MachineInstr *LastInst = I; - - // If there is only one terminator instruction, process it. - unsigned LastOpc = LastInst->getOpcode(); - if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { - if (!LastInst->getDesc().isBranch()) - return true; + MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); + // Skip all the debug instructions. + while (I != REnd && I->isDebugValue()) + ++I; + + if (I == REnd || !isUnpredicatedTerminator(&*I)) { + // If this block ends with no branches (it just falls through to its succ) + // just return false, leaving TBB/FBB null. + TBB = FBB = NULL; + return false; + } + + MachineInstr *LastInst = &*I; + unsigned LastOpc = LastInst->getOpcode(); + + // Not an analyzable branch (must be an indirect jump). + if (!GetAnalyzableBrOpc(LastOpc)) + return true; + + // Get the second to last instruction in the block. + unsigned SecondLastOpc = 0; + MachineInstr *SecondLastInst = NULL; + + if (++I != REnd) { + SecondLastInst = &*I; + SecondLastOpc = GetAnalyzableBrOpc(SecondLastInst->getOpcode()); + + // Not an analyzable branch (must be an indirect jump). + if (isUnpredicatedTerminator(SecondLastInst) && !SecondLastOpc) + return true; + } + + // If there is only one terminator instruction, process it. + if (!SecondLastOpc) { // Unconditional branch if (LastOpc == Mips::J) { TBB = LastInst->getOperand(0).getMBB(); return false; } - Mips::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode()); - if (BranchCode == Mips::COND_INVALID) - return true; // Can't handle indirect branch. - // Conditional branch - // Block ends with fall-through condbranch. - if (LastOpc != Mips::COND_INVALID) { - int LastNumOp = LastInst->getNumOperands(); - - TBB = LastInst->getOperand(LastNumOp-1).getMBB(); - Cond.push_back(MachineOperand::CreateImm(BranchCode)); - - for (int i=0; igetOperand(i)); - } - - return false; - } + AnalyzeCondBr(LastInst, LastOpc, TBB, Cond); + return false; } - - // Get the instruction before it if it is a terminator. - MachineInstr *SecondLastInst = I; - + + // If we reached here, there are two branches. // If there are three terminators, we don't know what sort of block this is. - if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I)) + if (++I != REnd && isUnpredicatedTerminator(&*I)) return true; - // If the block ends with Mips::J and a Mips::BNE/Mips::BEQ, handle it. - unsigned SecondLastOpc = SecondLastInst->getOpcode(); - Mips::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc); + // If second to last instruction is an unconditional branch, + // analyze it and remove the last instruction. + if (SecondLastOpc == Mips::J) { + // Return if the last instruction cannot be removed. + if (!AllowModify) + return true; - if (BranchCode != Mips::COND_INVALID && LastOpc == Mips::J) { - int SecondNumOp = SecondLastInst->getNumOperands(); - - TBB = SecondLastInst->getOperand(SecondNumOp-1).getMBB(); - Cond.push_back(MachineOperand::CreateImm(BranchCode)); - - for (int i=0; igetOperand(i)); - } - - FBB = LastInst->getOperand(0).getMBB(); - return false; - } - - // If the block ends with two unconditional branches, handle it. The last - // one is not executed, so remove it. - if ((SecondLastOpc == Mips::J) && (LastOpc == Mips::J)) { TBB = SecondLastInst->getOperand(0).getMBB(); - I = LastInst; - if (AllowModify) - I->eraseFromParent(); + LastInst->eraseFromParent(); return false; } - // Otherwise, can't handle this. - return true; + // Conditional branch followed by an unconditional branch. + // The last one must be unconditional. + if (LastOpc != Mips::J) + return true; + + AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond); + FBB = LastInst->getOperand(0).getMBB(); + + return false; +} + +void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, + MachineBasicBlock *TBB, DebugLoc DL, + const SmallVectorImpl& Cond) + const { + unsigned Opc = Cond[0].getImm(); + const TargetInstrDesc &TID = get(Opc); + MachineInstrBuilder MIB = BuildMI(&MBB, DL, TID); + + for (unsigned i = 1; i < Cond.size(); ++i) + MIB.addReg(Cond[i].getReg()); + + MIB.addMBB(TBB); } unsigned MipsInstrInfo:: -InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, +InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl &Cond, DebugLoc DL) const { // Shouldn't be a fall through. assert(TBB && "InsertBranch must not be told to insert a fallthrough"); - assert((Cond.size() == 3 || Cond.size() == 2 || Cond.size() == 0) && - "Mips branch conditions can have two|three components!"); - if (FBB == 0) { // One way branch. - if (Cond.empty()) { - // Unconditional branch? - BuildMI(&MBB, DL, get(Mips::J)).addMBB(TBB); - } else { - // Conditional branch. - unsigned Opc = GetCondBranchFromCond((Mips::CondCode)Cond[0].getImm()); - const TargetInstrDesc &TID = get(Opc); + // # of condition operands: + // Unconditional branches: 0 + // Floating point branches: 1 (opc) + // Int BranchZero: 2 (opc, reg) + // Int Branch: 3 (opc, reg0, reg1) + assert((Cond.size() <= 3) && + "# of Mips branch conditions must be <= 3!"); - if (TID.getNumOperands() == 3) - BuildMI(&MBB, DL, TID).addReg(Cond[1].getReg()) - .addReg(Cond[2].getReg()) - .addMBB(TBB); - else - BuildMI(&MBB, DL, TID).addReg(Cond[1].getReg()) - .addMBB(TBB); - - } - return 1; - } - // Two-way Conditional branch. - unsigned Opc = GetCondBranchFromCond((Mips::CondCode)Cond[0].getImm()); - const TargetInstrDesc &TID = get(Opc); + if (FBB) { + BuildCondBr(MBB, TBB, DL, Cond); + BuildMI(&MBB, DL, get(Mips::J)).addMBB(FBB); + return 2; + } - if (TID.getNumOperands() == 3) - BuildMI(&MBB, DL, TID).addReg(Cond[1].getReg()).addReg(Cond[2].getReg()) - .addMBB(TBB); - else - BuildMI(&MBB, DL, TID).addReg(Cond[1].getReg()).addMBB(TBB); - - BuildMI(&MBB, DL, get(Mips::J)).addMBB(FBB); - return 2; + // One way branch. + // Unconditional branch. + if (Cond.empty()) + BuildMI(&MBB, DL, get(Mips::J)).addMBB(TBB); + else // Conditional branch. + BuildCondBr(MBB, TBB, DL, Cond); + return 1; } unsigned MipsInstrInfo:: -RemoveBranch(MachineBasicBlock &MBB) const +RemoveBranch(MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator I = MBB.end(); - if (I == MBB.begin()) return 0; - --I; - while (I->isDebugValue()) { - if (I == MBB.begin()) - return 0; - --I; - } - if (I->getOpcode() != Mips::J && - GetCondFromBranchOpc(I->getOpcode()) == Mips::COND_INVALID) - return 0; - - // Remove the branch. - I->eraseFromParent(); - - I = MBB.end(); - - if (I == MBB.begin()) return 1; - --I; - if (GetCondFromBranchOpc(I->getOpcode()) == Mips::COND_INVALID) - return 1; - - // Remove the branch. - I->eraseFromParent(); - return 2; + MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); + MachineBasicBlock::reverse_iterator FirstBr; + unsigned removed; + + // Skip all the debug instructions. + while (I != REnd && I->isDebugValue()) + ++I; + + FirstBr = I; + + // Up to 2 branches are removed. + // Note that indirect branches are not removed. + for(removed = 0; I != REnd && removed < 2; ++I, ++removed) + if (!GetAnalyzableBrOpc(I->getOpcode())) + break; + + MBB.erase(I.base(), FirstBr.base()); + + return removed; } -/// ReverseBranchCondition - Return the inverse opcode of the +/// ReverseBranchCondition - Return the inverse opcode of the /// specified Branch instruction. bool MipsInstrInfo:: -ReverseBranchCondition(SmallVectorImpl &Cond) const +ReverseBranchCondition(SmallVectorImpl &Cond) const { - assert( (Cond.size() == 3 || Cond.size() == 2) && + assert( (Cond.size() && Cond.size() <= 3) && "Invalid Mips branch condition!"); - Cond[0].setImm(GetOppositeBranchCondition((Mips::CondCode)Cond[0].getImm())); + Cond[0].setImm(Mips::GetOppositeBranchOpc(Cond[0].getImm())); return false; } diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h index 52a3d39840ba..5fdbf1f230a0 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h +++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h @@ -37,7 +37,7 @@ namespace Mips { // To be used with float branch True FCOND_F, FCOND_UN, - FCOND_EQ, + FCOND_OEQ, FCOND_UEQ, FCOND_OLT, FCOND_ULT, @@ -57,8 +57,8 @@ namespace Mips { // above ones, but are used with a branch False; FCOND_T, FCOND_OR, - FCOND_NEQ, - FCOND_OGL, + FCOND_UNE, + FCOND_ONE, FCOND_UGE, FCOND_OGE, FCOND_UGT, @@ -70,27 +70,15 @@ namespace Mips { FCOND_NLT, FCOND_GE, FCOND_NLE, - FCOND_GT, - - // Only integer conditions - COND_E, - COND_GZ, - COND_GEZ, - COND_LZ, - COND_LEZ, - COND_NE, - COND_INVALID + FCOND_GT }; - - // Turn condition code into conditional branch opcode. - unsigned GetCondBranchFromCond(CondCode CC); - /// GetOppositeBranchCondition - Return the inverse of the specified cond, - /// e.g. turning COND_E to COND_NE. - CondCode GetOppositeBranchCondition(Mips::CondCode CC); + /// GetOppositeBranchOpc - Return the inverse of the specified + /// opcode, e.g. turning BEQ to BNE. + unsigned GetOppositeBranchOpc(unsigned Opc); /// MipsCCToString - Map each FP condition code to its string - inline static const char *MipsFCCToString(Mips::CondCode CC) + inline static const char *MipsFCCToString(Mips::CondCode CC) { switch (CC) { default: llvm_unreachable("Unknown condition code"); @@ -98,10 +86,10 @@ namespace Mips { case FCOND_T: return "f"; case FCOND_UN: case FCOND_OR: return "un"; - case FCOND_EQ: - case FCOND_NEQ: return "eq"; + case FCOND_OEQ: + case FCOND_UNE: return "eq"; case FCOND_UEQ: - case FCOND_OGL: return "ueq"; + case FCOND_ONE: return "ueq"; case FCOND_OLT: case FCOND_UGE: return "olt"; case FCOND_ULT: @@ -121,11 +109,11 @@ namespace Mips { case FCOND_LT: case FCOND_NLT: return "lt"; case FCOND_NGE: - case FCOND_GE: return "ge"; + case FCOND_GE: return "nge"; case FCOND_LE: - case FCOND_NLE: return "nle"; + case FCOND_NLE: return "le"; case FCOND_NGT: - case FCOND_GT: return "gt"; + case FCOND_GT: return "ngt"; } } } @@ -138,27 +126,27 @@ namespace MipsII { enum TOF { //===------------------------------------------------------------------===// // Mips Specific MachineOperand flags. - + MO_NO_FLAG, /// MO_GOT - Represents the offset into the global offset table at which /// the address the relocation entry symbol resides during execution. MO_GOT, - /// MO_GOT_CALL - Represents the offset into the global offset table at - /// which the address of a call site relocation entry symbol resides + /// MO_GOT_CALL - Represents the offset into the global offset table at + /// which the address of a call site relocation entry symbol resides /// during execution. This is different from the above since this flag /// can only be present in call instructions. MO_GOT_CALL, - /// MO_GPREL - Represents the offset from the current gp value to be used + /// MO_GPREL - Represents the offset from the current gp value to be used /// for the relocatable object file being produced. MO_GPREL, - /// MO_ABS_HILO - Represents the hi or low part of an absolute symbol - /// address. - MO_ABS_HILO - + /// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol + /// address. + MO_ABS_HI, + MO_ABS_LO }; } @@ -181,7 +169,7 @@ class MipsInstrInfo : public TargetInstrInfoImpl { /// any side effects other than loading from the stack slot. virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, 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 /// the source reg along with the FrameIndex of the loaded stack slot. If @@ -189,13 +177,19 @@ class MipsInstrInfo : public TargetInstrInfoImpl { /// any side effects other than storing to the stack slot. virtual unsigned isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const; - + /// Branch Analysis virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl &Cond, bool AllowModify) const; virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + +private: + void BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, DebugLoc DL, + const SmallVectorImpl& Cond) const; + +public: virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl &Cond, @@ -220,7 +214,7 @@ class MipsInstrInfo : public TargetInstrInfoImpl { bool ReverseBranchCondition(SmallVectorImpl &Cond) const; /// Insert nop instruction when hazard condition is found - virtual void insertNoop(MachineBasicBlock &MBB, + virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; /// getGlobalBaseReg - Return a virtual register initialized with the diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td index b70266ac3e80..19b9c359ebb0 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -19,18 +19,19 @@ include "MipsInstrFormats.td" def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; -def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>, - SDTCisSameAs<2, 3>, SDTCisInt<1>]>; def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, - SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, - SDTCisInt<4>]>; + SDTCisSameAs<1, 2>, + SDTCisSameAs<3, 4>, + SDTCisInt<4>]>; def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; -def SDT_MipsMAddMSub : SDTypeProfile<0, 4, +def SDT_MipsMAddMSub : SDTypeProfile<0, 4, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, - SDTCisSameAs<1, 2>, + SDTCisSameAs<1, 2>, SDTCisSameAs<2, 3>]>; - +def SDT_MipsDivRem : SDTypeProfile<0, 2, + [SDTCisVT<0, i32>, + SDTCisSameAs<0, 1>]>; // Call def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, @@ -54,9 +55,6 @@ def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart, def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; -// Select Condition Code -def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>; - // MAdd*/MSub* nodes def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub, [SDNPOptInGlue, SDNPOutGlue]>; @@ -67,6 +65,12 @@ def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub, def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub, [SDNPOptInGlue, SDNPOutGlue]>; +// DivRem(u) nodes +def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsDivRem, + [SDNPOutGlue]>; +def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem, + [SDNPOutGlue]>; + //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. //===----------------------------------------------------------------------===// @@ -165,7 +169,7 @@ class ArithOverflowI op, string instr_asm, SDNode OpNode, let rd = 0, shamt = 0, Defs = [HI, LO], Uses = [HI, LO] in class MArithR func, string instr_asm, SDNode op> : FR<0x1c, func, (outs), (ins CPURegs:$rs, CPURegs:$rt), - !strconcat(instr_asm, "\t$rs, $rt"), + !strconcat(instr_asm, "\t$rs, $rt"), [(op CPURegs:$rs, CPURegs:$rt, LO, HI)], IIImul>; // Logical @@ -185,7 +189,7 @@ class LogicNOR op, bits<6> func, string instr_asm>: [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>; // Shifts -class LogicR_shift_rotate_imm func, bits<5> _rs, string instr_asm, +class LogicR_shift_rotate_imm func, bits<5> _rs, string instr_asm, SDNode OpNode>: FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, shamt:$c), !strconcat(instr_asm, "\t$dst, $b, $c"), @@ -193,7 +197,7 @@ class LogicR_shift_rotate_imm func, bits<5> _rs, string instr_asm, let rs = _rs; } -class LogicR_shift_rotate_reg func, bits<5> _shamt, string instr_asm, +class LogicR_shift_rotate_reg func, bits<5> _shamt, string instr_asm, SDNode OpNode>: FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b), !strconcat(instr_asm, "\t$dst, $b, $c"), @@ -283,9 +287,16 @@ let isCall=1, hasDelaySlot=1, } // Mul, Div -class MulDiv func, string instr_asm, InstrItinClass itin>: - FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), - !strconcat(instr_asm, "\t$a, $b"), [], itin>; +let Defs = [HI, LO] in { + class Mul func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, "\t$a, $b"), [], itin>; + + class Div func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, "\t$$zero, $a, $b"), + [(op CPURegs:$a, CPURegs:$b)], itin>; +} // Move from Hi/Lo class MoveFromLOHI func, string instr_asm>: @@ -348,6 +359,11 @@ def REORDER : MipsPseudo<(outs), (ins), ".set\treorder", []>; def NOMACRO : MipsPseudo<(outs), (ins), ".set\tnomacro", []>; def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>; +// These macros are inserted to prevent GAS from complaining +// when using the AT register. +def NOAT : MipsPseudo<(outs), (ins), ".set\tnoat", []>; +def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>; + // When handling PIC code the assembler needs .cpload and .cprestore // directives. If the real instructions corresponding these directives // are used, we have the same behavior, but get also a bunch of warnings @@ -355,18 +371,6 @@ def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>; def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>; def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>; -// The supported Mips ISAs dont have any instruction close to the SELECT_CC -// operation. The solution is to create a Mips pseudo SELECT_CC instruction -// (MipsSelectCC), use LowerSELECT_CC to generate this instruction and finally -// replace it for real supported nodes into EmitInstrWithCustomInserter -let usesCustomInserter = 1 in { - class PseudoSelCC: - MipsPseudo<(outs RC:$dst), (ins CPURegs:$CmpRes, RC:$T, RC:$F), asmstr, - [(set RC:$dst, (MipsSelectCC CPURegs:$CmpRes, RC:$T, RC:$F))]>; -} - -def Select_CC : PseudoSelCC; - //===----------------------------------------------------------------------===// // Instruction definition //===----------------------------------------------------------------------===// @@ -447,12 +451,10 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, "jr\t$target", [(MipsRet CPURegs:$target)], IIBranch>; /// Multiply and Divide Instructions. -let Defs = [HI, LO] in { - def MULT : MulDiv<0x18, "mult", IIImul>; - def MULTu : MulDiv<0x19, "multu", IIImul>; - def DIV : MulDiv<0x1a, "div", IIIdiv>; - def DIVu : MulDiv<0x1b, "divu", IIIdiv>; -} +def MULT : Mul<0x18, "mult", IIImul>; +def MULTu : Mul<0x19, "multu", IIImul>; +def SDIV : Div; +def UDIV : Div; let Defs = [HI] in def MTHI : MoveToLOHI<0x11, "mthi">; @@ -489,10 +491,19 @@ let Predicates = [HasSwap] in { def MIPS_CMOV_ZERO : PatLeaf<(i32 0)>; def MIPS_CMOV_NZERO : PatLeaf<(i32 1)>; -let Predicates = [HasCondMov], Constraints = "$F = $dst" in { - def MOVN : CondMov<0x0a, "movn", MIPS_CMOV_NZERO>; - def MOVZ : CondMov<0x0b, "movz", MIPS_CMOV_ZERO>; -} +// Conditional moves: +// These instructions are expanded in +// MipsISelLowering::EmitInstrWithCustomInserter if target does not have +// conditional move instructions. +// flag:int, data:int +let usesCustomInserter = 1, shamt = 0, Constraints = "$F = $dst" in + class CondMovIntInt funct, string instr_asm> : + FR<0, funct, (outs CPURegs:$dst), + (ins CPURegs:$T, CPURegs:$cond, CPURegs:$F), + !strconcat(instr_asm, "\t$dst, $T, $cond"), [], NoItinerary>; + +def MOVZ_I : CondMovIntInt<0x0a, "movz">; +def MOVN_I : CondMovIntInt<0x0b, "movn">; /// No operation let addr=0 in @@ -533,7 +544,7 @@ def : Pat<(subc CPURegs:$lhs, CPURegs:$rhs), (SUBu CPURegs:$lhs, CPURegs:$rhs)>; def : Pat<(addc CPURegs:$lhs, CPURegs:$rhs), (ADDu CPURegs:$lhs, CPURegs:$rhs)>; -def : Pat<(addc CPURegs:$src, imm:$imm), +def : Pat<(addc CPURegs:$src, immSExt16:$imm), (ADDiu CPURegs:$src, imm:$imm)>; // Call @@ -546,8 +557,11 @@ def : Pat<(MipsJmpLink (i32 texternalsym:$dst)), // hi/lo relocs def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; +def : Pat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>; def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)), (ADDiu CPURegs:$hi, tglobaladdr:$lo)>; +def : Pat<(add CPURegs:$hi, (MipsLo tblockaddress:$lo)), + (ADDiu CPURegs:$hi, tblockaddress:$lo)>; def : Pat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)), @@ -599,33 +613,43 @@ def : Pat<(brcond CPURegs:$cond, bb:$dst), (BNE CPURegs:$cond, ZERO, bb:$dst)>; // select patterns -def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs))>; -def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTiu CPURegs:$lh, immSExt16:$rh))>; +multiclass MovzPats { + def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLT CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs), RC:$F)>; + def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTiu CPURegs:$lh, immSExt16:$rh), RC:$F)>; + def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLT CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; + def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; + def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (seteq CPURegs:$lhs, 0), RC:$T, RC:$F), + (MOVZInst RC:$T, CPURegs:$lhs, RC:$F)>; +} -def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$rhs, CPURegs:$lhs))>; -def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs))>; +multiclass MovnPats { + def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVNInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select CPURegs:$cond, RC:$T, RC:$F), + (MOVNInst RC:$T, CPURegs:$cond, RC:$F)>; + def : Pat<(select (setne CPURegs:$lhs, 0), RC:$T, RC:$F), + (MOVNInst RC:$T, CPURegs:$lhs, RC:$F)>; +} -def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVN CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>; - -def : Pat<(select CPURegs:$cond, CPURegs:$T, CPURegs:$F), - (MOVN CPURegs:$F, CPURegs:$T, CPURegs:$cond)>; +defm : MovzPats; +defm : MovnPats; // select patterns with got access -def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), - (i32 tglobaladdr:$T), CPURegs:$F), - (MOVN CPURegs:$F, (ADDiu GP, tglobaladdr:$T), - (XOR CPURegs:$lhs, CPURegs:$rhs))>; +let AddedComplexity = 10 in + def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), + (i32 tglobaladdr:$T), CPURegs:$F), + (MOVN_I CPURegs:$F, (ADDiu GP, tglobaladdr:$T), + (XOR CPURegs:$lhs, CPURegs:$rhs))>; // setcc patterns def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs), diff --git a/contrib/llvm/lib/Target/Mips/MipsMCAsmInfo.h b/contrib/llvm/lib/Target/Mips/MipsMCAsmInfo.h index 15a867ead53e..41b719207b7b 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMCAsmInfo.h +++ b/contrib/llvm/lib/Target/Mips/MipsMCAsmInfo.h @@ -19,7 +19,7 @@ namespace llvm { class Target; - + class MipsMCAsmInfo : public MCAsmInfo { public: explicit MipsMCAsmInfo(const Target &T, StringRef TT); diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp index 3719e580425f..c09b129f6750 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp @@ -38,7 +38,7 @@ using namespace llvm; -MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST, +MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST, const TargetInstrInfo &tii) : MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), Subtarget(ST), TII(tii) {} @@ -46,7 +46,7 @@ MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST, /// getRegisterNumbering - Given the enum value for some register, e.g. /// Mips::RA, return the number that it corresponds to (e.g. 31). unsigned MipsRegisterInfo:: -getRegisterNumbering(unsigned RegEnum) +getRegisterNumbering(unsigned RegEnum) { switch (RegEnum) { case Mips::ZERO : case Mips::F0 : case Mips::D0 : return 0; @@ -82,30 +82,30 @@ getRegisterNumbering(unsigned RegEnum) case Mips::FP : case Mips::F30: case Mips::D15: return 30; case Mips::RA : case Mips::F31: return 31; default: llvm_unreachable("Unknown register number!"); - } + } return 0; // Not reached } unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; } //===----------------------------------------------------------------------===// -// Callee Saved Registers methods +// Callee Saved Registers methods //===----------------------------------------------------------------------===// /// Mips Callee Saved Registers const unsigned* MipsRegisterInfo:: -getCalleeSavedRegs(const MachineFunction *MF) const +getCalleeSavedRegs(const MachineFunction *MF) const { // Mips callee-save register range is $16-$23, $f20-$f30 static const unsigned SingleFloatOnlyCalleeSavedRegs[] = { - Mips::S0, Mips::S1, Mips::S2, Mips::S3, + Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5, Mips::S6, Mips::S7, - Mips::F20, Mips::F21, Mips::F22, Mips::F23, Mips::F24, Mips::F25, + Mips::F20, Mips::F21, Mips::F22, Mips::F23, Mips::F24, Mips::F25, Mips::F26, Mips::F27, Mips::F28, Mips::F29, Mips::F30, 0 }; static const unsigned BitMode32CalleeSavedRegs[] = { - Mips::S0, Mips::S1, Mips::S2, Mips::S3, + Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5, Mips::S6, Mips::S7, Mips::F20, Mips::F22, Mips::F24, Mips::F26, Mips::F28, Mips::F30, 0 }; @@ -132,11 +132,11 @@ getReservedRegs(const MachineFunction &MF) const { if (!Subtarget.isSingleFloat()) for (unsigned FReg=(Mips::F0)+1; FReg < Mips::F30; FReg+=2) Reserved.set(FReg); - + return Reserved; } -// This function eliminate ADJCALLSTACKDOWN, +// This function eliminate ADJCALLSTACKDOWN, // ADJCALLSTACKUP pseudo instructions void MipsRegisterInfo:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, @@ -157,7 +157,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned i = 0; while (!MI.getOperand(i).isFI()) { ++i; - assert(i < MI.getNumOperands() && + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); } @@ -179,8 +179,43 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); - MI.getOperand(i-1).ChangeToImmediate(Offset); - MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false); + unsigned NewReg = 0; + int NewImm = 0; + MachineBasicBlock &MBB = *MI.getParent(); + bool ATUsed; + unsigned OrigReg = getFrameRegister(MF); + int OrigImm = Offset; + +// OrigImm fits in the 16-bit field + if (OrigImm < 0x8000 && OrigImm >= -0x8000) { + NewReg = OrigReg; + NewImm = OrigImm; + ATUsed = false; + } + else { + const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); + DebugLoc DL = II->getDebugLoc(); + int ImmLo = OrigImm & 0xffff; + int ImmHi = (((unsigned)OrigImm & 0xffff0000) >> 16) + + ((OrigImm & 0x8000) != 0); + + // FIXME: change this when mips goes MC". + BuildMI(MBB, II, DL, TII->get(Mips::NOAT)); + BuildMI(MBB, II, DL, TII->get(Mips::LUi), Mips::AT).addImm(ImmHi); + BuildMI(MBB, II, DL, TII->get(Mips::ADDu), Mips::AT).addReg(OrigReg) + .addReg(Mips::AT); + NewReg = Mips::AT; + NewImm = ImmLo; + + ATUsed = true; + } + + // FIXME: change this when mips goes MC". + if (ATUsed) + BuildMI(MBB, ++II, MI.getDebugLoc(), TII.get(Mips::ATMACRO)); + + MI.getOperand(i).ChangeToRegister(NewReg, false); + MI.getOperand(i-1).ChangeToImmediate(NewImm); } void MipsRegisterInfo:: diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h index a7f4bf987ae9..767359fd6ed4 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h @@ -26,7 +26,7 @@ class Type; struct MipsRegisterInfo : public MipsGenRegisterInfo { const MipsSubtarget &Subtarget; const TargetInstrInfo &TII; - + MipsRegisterInfo(const MipsSubtarget &Subtarget, const TargetInstrInfo &tii); /// getRegisterNumbering - Given the enum value for some register, e.g. diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td index 60efe31fbaf8..9f9cae7d11f7 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td @@ -17,7 +17,7 @@ class MipsReg : Register { let Namespace = "Mips"; } -class MipsRegWithSubRegs subregs> +class MipsRegWithSubRegs subregs> : RegisterWithSubRegs { field bits<5> Num; let Namespace = "Mips"; @@ -83,7 +83,7 @@ let Namespace = "Mips" in { def SP : MipsGPRReg< 29, "SP">, DwarfRegNum<[29]>; def FP : MipsGPRReg< 30, "FP">, DwarfRegNum<[30]>; def RA : MipsGPRReg< 31, "RA">, DwarfRegNum<[31]>; - + /// Mips Single point precision FPU Registers def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>; def F1 : FPR< 1, "F1">, DwarfRegNum<[33]>; @@ -117,7 +117,7 @@ let Namespace = "Mips" in { def F29 : FPR<29, "F29">, DwarfRegNum<[61]>; def F30 : FPR<30, "F30">, DwarfRegNum<[62]>; def F31 : FPR<31, "F31">, DwarfRegNum<[63]>; - + /// Mips Double point precision FPU Registers (aliased /// with the single precision to hold 64 bit values) def D0 : AFPR< 0, "F0", [F0, F1]>, DwarfRegNum<[32]>; @@ -149,11 +149,11 @@ let Namespace = "Mips" in { // Register Classes //===----------------------------------------------------------------------===// -def CPURegs : RegisterClass<"Mips", [i32], 32, +def CPURegs : RegisterClass<"Mips", [i32], 32, // Return Values and Arguments [V0, V1, A0, A1, A2, A3, // Not preserved across procedure calls - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, // Callee save S0, S1, S2, S3, S4, S5, S6, S7, // Reserved @@ -173,16 +173,16 @@ def CPURegs : RegisterClass<"Mips", [i32], 32, // 64bit fp: // * FGR64 - 32 64-bit registers -// * AFGR64 - 16 32-bit even registers (32-bit FP Mode) +// * AFGR64 - 16 32-bit even registers (32-bit FP Mode) // // 32bit fp: // * FGR32 - 16 32-bit even registers // * FGR32 - 32 32-bit registers (single float only mode) -def FGR32 : RegisterClass<"Mips", [f32], 32, +def FGR32 : RegisterClass<"Mips", [f32], 32, // Return Values and Arguments [F0, F1, F2, F3, F12, F13, F14, F15, // Not preserved across procedure calls - F4, F5, F6, F7, F8, F9, F10, F11, F16, F17, F18, F19, + F4, F5, F6, F7, F8, F9, F10, F11, F16, F17, F18, F19, // Callee save F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, // Reserved @@ -195,17 +195,17 @@ def FGR32 : RegisterClass<"Mips", [f32], 32, let MethodBodies = [{ static const unsigned MIPS_FGR32[] = { - Mips::F0, Mips::F1, Mips::F2, Mips::F3, Mips::F12, Mips::F13, - Mips::F14, Mips::F15, Mips::F4, Mips::F5, Mips::F6, Mips::F7, - Mips::F8, Mips::F9, Mips::F10, Mips::F11, Mips::F16, Mips::F17, - Mips::F18, Mips::F19, Mips::F20, Mips::F21, Mips::F22, Mips::F23, - Mips::F24, Mips::F25, Mips::F26, Mips::F27, Mips::F28, Mips::F29, + Mips::F0, Mips::F1, Mips::F2, Mips::F3, Mips::F12, Mips::F13, + Mips::F14, Mips::F15, Mips::F4, Mips::F5, Mips::F6, Mips::F7, + Mips::F8, Mips::F9, Mips::F10, Mips::F11, Mips::F16, Mips::F17, + Mips::F18, Mips::F19, Mips::F20, Mips::F21, Mips::F22, Mips::F23, + Mips::F24, Mips::F25, Mips::F26, Mips::F27, Mips::F28, Mips::F29, Mips::F30 }; static const unsigned MIPS_SVR4_FGR32[] = { - Mips::F0, Mips::F2, Mips::F12, Mips::F14, Mips::F4, - Mips::F6, Mips::F8, Mips::F10, Mips::F16, Mips::F18, + Mips::F0, Mips::F2, Mips::F12, Mips::F14, Mips::F4, + Mips::F6, Mips::F8, Mips::F10, Mips::F16, Mips::F18, Mips::F20, Mips::F22, Mips::F24, Mips::F26, Mips::F28, Mips::F30, }; @@ -217,7 +217,7 @@ def FGR32 : RegisterClass<"Mips", [f32], 32, if (Subtarget.isSingleFloat()) return MIPS_FGR32; else - return MIPS_SVR4_FGR32; + return MIPS_SVR4_FGR32; } FGR32Class::iterator @@ -233,11 +233,11 @@ def FGR32 : RegisterClass<"Mips", [f32], 32, }]; } -def AFGR64 : RegisterClass<"Mips", [f64], 64, +def AFGR64 : RegisterClass<"Mips", [f64], 64, // Return Values and Arguments [D0, D1, D6, D7, // Not preserved across procedure calls - D2, D3, D4, D5, D8, D9, + D2, D3, D4, D5, D8, D9, // Callee save D10, D11, D12, D13, D14, // Reserved diff --git a/contrib/llvm/lib/Target/Mips/MipsSchedule.td b/contrib/llvm/lib/Target/Mips/MipsSchedule.td index 49ca5d19c9cf..00be8ee94431 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSchedule.td +++ b/contrib/llvm/lib/Target/Mips/MipsSchedule.td @@ -14,7 +14,7 @@ def ALU : FuncUnit; def IMULDIV : FuncUnit; //===----------------------------------------------------------------------===// -// Instruction Itinerary classes used for Mips +// Instruction Itinerary classes used for Mips //===----------------------------------------------------------------------===// def IIAlu : InstrItinClass; def IILoad : InstrItinClass; diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp b/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp index db114da00d73..70747f5da137 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -17,7 +17,7 @@ using namespace llvm; MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &FS, - bool little) : + bool little) : MipsArchVersion(Mips1), MipsABI(O32), IsLittle(little), IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true), HasSEInReg(false), HasCondMov(false), HasMulDivAdd(false), HasMinMax(false), @@ -33,7 +33,7 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &FS, if (TT.find("linux") == std::string::npos) IsLinux = false; - // When only the target triple is specified and is + // When only the target triple is specified and is // a allegrex target, set the features. We also match // big and little endian allegrex cores (dont really // know if a big one exists) diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h b/contrib/llvm/lib/Target/Mips/MipsSubtarget.h index e4f4b334e13a..096bbed7b047 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/contrib/llvm/lib/Target/Mips/MipsSubtarget.h @@ -26,7 +26,7 @@ class MipsSubtarget : public TargetSubtarget { public: enum MipsABIEnum { O32, O64, N32, N64, EABI - }; + }; protected: @@ -34,10 +34,10 @@ class MipsSubtarget : public TargetSubtarget { Mips1, Mips2, Mips3, Mips4, Mips32, Mips32r2 }; - // Mips architecture version + // Mips architecture version MipsArchEnum MipsArchVersion; - // Mips supported ABIs + // Mips supported ABIs MipsABIEnum MipsABI; // IsLittle - The target is Little Endian @@ -61,14 +61,14 @@ class MipsSubtarget : public TargetSubtarget { bool IsLinux; /// Features related to the presence of specific instructions. - + // HasSEInReg - SEB and SEH (signext in register) instructions. bool HasSEInReg; // HasCondMov - Conditional mov (MOVZ, MOVN) instructions. bool HasCondMov; - // HasMulDivAdd - Multiply add and sub (MADD, MADDu, MSUB, MSUBu) + // HasMulDivAdd - Multiply add and sub (MADD, MADDu, MSUB, MSUBu) // instructions. bool HasMulDivAdd; @@ -93,14 +93,14 @@ class MipsSubtarget : public TargetSubtarget { /// This constructor initializes the data members to match that /// of the specified triple. MipsSubtarget(const std::string &TT, const std::string &FS, bool little); - - /// ParseSubtargetFeatures - Parses features string setting specified + + /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. std::string ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); bool isMips1() const { return MipsArchVersion == Mips1; } - bool isMips32() const { return MipsArchVersion >= Mips32; } + bool isMips32() const { return MipsArchVersion >= Mips32; } bool isMips32r2() const { return MipsArchVersion == Mips32r2; } bool isLittle() const { return IsLittle; } diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp index 7a2dd1f651d2..53190b460041 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp @@ -75,3 +75,9 @@ addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) PM.add(createMipsDelaySlotFillerPass(*this)); return true; } + +bool MipsTargetMachine:: +addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { + PM.add(createMipsExpandPseudoPass(*this)); + return true; +} diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h index 43ab7984520e..badb652922b6 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h +++ b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h @@ -63,6 +63,7 @@ namespace llvm { CodeGenOpt::Level OptLevel); virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPostRegAlloc(PassManagerBase &, CodeGenOpt::Level); }; /// MipselTargetMachine - Mipsel target machine. diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h index 237b1602cf3d..c394a9dc02e4 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h +++ b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h @@ -18,22 +18,22 @@ namespace llvm { const MCSection *SmallDataSection; const MCSection *SmallBSSSection; public: - + void Initialize(MCContext &Ctx, const TargetMachine &TM); - + /// IsGlobalInSmallSection - Return true if this global address should be /// placed into small data/bss section. bool IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, SectionKind Kind)const; bool IsGlobalInSmallSection(const GlobalValue *GV, - const TargetMachine &TM) const; - + const TargetMachine &TM) const; + const MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const; - + // TODO: Classify globals as mips wishes. }; } // end namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp index cc3d61e4e71d..a8d6fe94b1ad 100644 --- a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp @@ -14,7 +14,7 @@ using namespace llvm; Target llvm::TheMipsTarget, llvm::TheMipselTarget; -extern "C" void LLVMInitializeMipsTargetInfo() { +extern "C" void LLVMInitializeMipsTargetInfo() { RegisterTarget X(TheMipsTarget, "mips", "Mips"); RegisterTarget Y(TheMipselTarget, "mipsel", "Mipsel"); diff --git a/contrib/llvm/lib/Target/PTX/Makefile b/contrib/llvm/lib/Target/PTX/Makefile deleted file mode 100644 index 2c40d6994094..000000000000 --- a/contrib/llvm/lib/Target/PTX/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -##===- lib/Target/PTX/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMPTXCodeGen -TARGET = PTX - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = PTXGenAsmWriter.inc \ - PTXGenDAGISel.inc \ - PTXGenInstrInfo.inc \ - PTXGenInstrNames.inc \ - PTXGenRegisterInfo.inc \ - PTXGenRegisterInfo.h.inc \ - PTXGenRegisterNames.inc \ - PTXGenSubtarget.inc - -DIRS = TargetInfo - -include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/Target/PTX/PTX.h b/contrib/llvm/lib/Target/PTX/PTX.h index 19385ba1ff8c..ec2be9291a04 100644 --- a/contrib/llvm/lib/Target/PTX/PTX.h +++ b/contrib/llvm/lib/Target/PTX/PTX.h @@ -29,6 +29,11 @@ namespace llvm { PARAMETER = 3, SHARED = 4 }; + + enum Predicate { + PRED_NORMAL = 0, + PRED_NEGATE = 1 + }; } // namespace PTX FunctionPass *createPTXISelDag(PTXTargetMachine &TM, @@ -37,7 +42,8 @@ namespace llvm { FunctionPass *createPTXMFInfoExtract(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel); - extern Target ThePTXTarget; + extern Target ThePTX32Target; + extern Target ThePTX64Target; } // namespace llvm; // Defines symbolic names for PTX registers. diff --git a/contrib/llvm/lib/Target/PTX/PTX.td b/contrib/llvm/lib/Target/PTX/PTX.td index 8b1a1b18da54..ae8326e3199c 100644 --- a/contrib/llvm/lib/Target/PTX/PTX.td +++ b/contrib/llvm/lib/Target/PTX/PTX.td @@ -19,8 +19,35 @@ include "llvm/Target/Target.td" // Subtarget Features. //===----------------------------------------------------------------------===// -def FeatureSM20 : SubtargetFeature<"sm20", "is_sm20", "true", - "Enable sm_20 target architecture">; +//===- Architectural Features ---------------------------------------------===// + +def FeatureDouble : SubtargetFeature<"double", "SupportsDouble", "true", + "Do not demote .f64 to .f32">; + +//===- PTX Version --------------------------------------------------------===// + +def FeaturePTX20 : SubtargetFeature<"ptx20", "PTXVersion", "PTX_VERSION_2_0", + "Use PTX Language Version 2.0", + []>; + +def FeaturePTX21 : SubtargetFeature<"ptx21", "PTXVersion", "PTX_VERSION_2_1", + "Use PTX Language Version 2.1", + [FeaturePTX20]>; + +def FeaturePTX22 : SubtargetFeature<"ptx22", "PTXVersion", "PTX_VERSION_2_2", + "Use PTX Language Version 2.2", + [FeaturePTX21]>; + +//===- PTX Shader Model ---------------------------------------------------===// + +def FeatureSM10 : SubtargetFeature<"sm10", "PTXShaderModel", "PTX_SM_1_0", + "Enable Shader Model 1.0 compliance">; +def FeatureSM13 : SubtargetFeature<"sm13", "PTXShaderModel", "PTX_SM_1_3", + "Enable Shader Model 1.3 compliance", + [FeatureSM10, FeatureDouble]>; +def FeatureSM20 : SubtargetFeature<"sm20", "PTXShaderModel", "PTX_SM_2_0", + "Enable Shader Model 2.0 compliance", + [FeatureSM13]>; //===----------------------------------------------------------------------===// // PTX supported processors. diff --git a/contrib/llvm/lib/Target/PTX/PTXAsmPrinter.cpp b/contrib/llvm/lib/Target/PTX/PTXAsmPrinter.cpp index a6059974ab3d..29c4781de654 100644 --- a/contrib/llvm/lib/Target/PTX/PTXAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/PTX/PTXAsmPrinter.cpp @@ -24,6 +24,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" @@ -37,13 +38,6 @@ using namespace llvm; -static cl::opt -OptPTXVersion("ptx-version", cl::desc("Set PTX version"), cl::init("1.4")); - -static cl::opt -OptPTXTarget("ptx-target", cl::desc("Set GPU target (comma-separated list)"), - cl::init("sm_10")); - namespace { class PTXAsmPrinter : public AsmPrinter { public: @@ -68,6 +62,7 @@ class PTXAsmPrinter : public AsmPrinter { const char *Modifier = 0); void printParamOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, const char *Modifier = 0); + void printPredicateOperand(const MachineInstr *MI, raw_ostream &O); // autogen'd. void printInstruction(const MachineInstr *MI, raw_ostream &OS); @@ -82,27 +77,20 @@ class PTXAsmPrinter : public AsmPrinter { static const char PARAM_PREFIX[] = "__param_"; static const char *getRegisterTypeName(unsigned RegNo) { -#define TEST_REGCLS(cls, clsstr) \ +#define TEST_REGCLS(cls, clsstr) \ if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr; - TEST_REGCLS(RRegs32, s32); TEST_REGCLS(Preds, pred); + TEST_REGCLS(RRegu16, u16); + TEST_REGCLS(RRegu32, u32); + TEST_REGCLS(RRegu64, u64); + TEST_REGCLS(RRegf32, f32); + TEST_REGCLS(RRegf64, f64); #undef TEST_REGCLS llvm_unreachable("Not in any register class!"); return NULL; } -static const char *getInstructionTypeName(const MachineInstr *MI) { - for (int i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (MO.getType() == MachineOperand::MO_Register) - return getRegisterTypeName(MO.getReg()); - } - - llvm_unreachable("No reg operand found in instruction!"); - return NULL; -} - static const char *getStateSpaceName(unsigned addressSpace) { switch (addressSpace) { default: llvm_unreachable("Unknown state space"); @@ -115,6 +103,28 @@ static const char *getStateSpaceName(unsigned addressSpace) { return NULL; } +static const char *getTypeName(const Type* type) { + while (true) { + switch (type->getTypeID()) { + default: llvm_unreachable("Unknown type"); + case Type::FloatTyID: return ".f32"; + case Type::DoubleTyID: return ".f64"; + case Type::IntegerTyID: + switch (type->getPrimitiveSizeInBits()) { + default: llvm_unreachable("Unknown integer bit-width"); + case 16: return ".u16"; + case 32: return ".u32"; + case 64: return ".u64"; + } + case Type::ArrayTyID: + case Type::PointerTyID: + type = dyn_cast(type)->getElementType(); + break; + } + } + return NULL; +} + bool PTXAsmPrinter::doFinalization(Module &M) { // XXX Temproarily remove global variables so that doFinalization() will not // emit them again (global variables are emitted at beginning). @@ -146,8 +156,12 @@ bool PTXAsmPrinter::doFinalization(Module &M) { void PTXAsmPrinter::EmitStartOfAsmFile(Module &M) { - OutStreamer.EmitRawText(Twine("\t.version " + OptPTXVersion)); - OutStreamer.EmitRawText(Twine("\t.target " + OptPTXTarget)); + const PTXSubtarget& ST = TM.getSubtarget(); + + OutStreamer.EmitRawText(Twine("\t.version " + ST.getPTXVersionString())); + OutStreamer.EmitRawText(Twine("\t.target " + ST.getTargetString() + + (ST.supportsDouble() ? "" + : ", map_f64_to_f32"))); OutStreamer.AddBlankLine(); // declare global variables @@ -186,17 +200,16 @@ void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) { std::string str; str.reserve(64); - // Write instruction to str raw_string_ostream OS(str); + + // Emit predicate + printPredicateOperand(MI, OS); + + // Write instruction to str printInstruction(MI, OS); OS << ';'; OS.flush(); - // Replace "%type" if found - size_t pos; - if ((pos = str.find("%type")) != std::string::npos) - str.replace(pos, /*strlen("%type")==*/5, getInstructionTypeName(MI)); - StringRef strref = StringRef(str); OutStreamer.EmitRawText(strref); } @@ -213,11 +226,36 @@ void PTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum, OS << *Mang->getSymbol(MO.getGlobal()); break; case MachineOperand::MO_Immediate: - OS << (int) MO.getImm(); + OS << (long) MO.getImm(); + break; + case MachineOperand::MO_MachineBasicBlock: + OS << *MO.getMBB()->getSymbol(); break; case MachineOperand::MO_Register: OS << getRegisterName(MO.getReg()); break; + case MachineOperand::MO_FPImmediate: + APInt constFP = MO.getFPImm()->getValueAPF().bitcastToAPInt(); + bool isFloat = MO.getFPImm()->getType()->getTypeID() == Type::FloatTyID; + // Emit 0F for 32-bit floats and 0D for 64-bit doubles. + if (isFloat) { + OS << "0F"; + } + else { + OS << "0D"; + } + // Emit the encoded floating-point value. + if (constFP.getZExtValue() > 0) { + OS << constFP.toString(16, false); + } + else { + OS << "00000000"; + // If We have a double-precision zero, pad to 8-bytes. + if (!isFloat) { + OS << "00000000"; + } + } + break; } } @@ -265,13 +303,77 @@ void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) { decl += " "; } - // TODO: add types - decl += ".s32 "; - decl += gvsym->getName(); + if (PointerType::classof(gv->getType())) { + const PointerType* pointerTy = dyn_cast(gv->getType()); + const Type* elementTy = pointerTy->getElementType(); - if (ArrayType::classof(gv->getType()) || PointerType::classof(gv->getType())) - decl += "[]"; + decl += ".b8 "; + decl += gvsym->getName(); + decl += "["; + + if (elementTy->isArrayTy()) + { + assert(elementTy->isArrayTy() && "Only pointers to arrays are supported"); + + const ArrayType* arrayTy = dyn_cast(elementTy); + elementTy = arrayTy->getElementType(); + + unsigned numElements = arrayTy->getNumElements(); + + while (elementTy->isArrayTy()) { + + arrayTy = dyn_cast(elementTy); + elementTy = arrayTy->getElementType(); + + numElements *= arrayTy->getNumElements(); + } + + // FIXME: isPrimitiveType() == false for i16? + assert(elementTy->isSingleValueType() && + "Non-primitive types are not handled"); + + // Compute the size of the array, in bytes. + uint64_t arraySize = (elementTy->getPrimitiveSizeInBits() >> 3) + * numElements; + + decl += utostr(arraySize); + } + + decl += "]"; + + // handle string constants (assume ConstantArray means string) + + if (gv->hasInitializer()) + { + Constant *C = gv->getInitializer(); + if (const ConstantArray *CA = dyn_cast(C)) + { + decl += " = {"; + + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) + { + if (i > 0) decl += ","; + + decl += "0x" + utohexstr(cast(CA->getOperand(i))->getZExtValue()); + } + + decl += "}"; + } + } + } + else { + // Note: this is currently the fall-through case and most likely generates + // incorrect code. + decl += getTypeName(gv->getType()); + decl += " "; + + decl += gvsym->getName(); + + if (ArrayType::classof(gv->getType()) || + PointerType::classof(gv->getType())) + decl += "[]"; + } decl += ";"; @@ -313,16 +415,24 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { if (!MFI->argRegEmpty()) { decl += " ("; if (isKernel) { - for (int i = 0, e = MFI->getNumArg(); i != e; ++i) { - if (i != 0) + unsigned cnt = 0; + for(PTXMachineFunctionInfo::reg_iterator + i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; + i != e; ++i) { + reg = *i; + assert(reg != PTX::NoRegister && "Not a valid register!"); + if (i != b) decl += ", "; - decl += ".param .s32 "; // TODO: add types + decl += ".param ."; + decl += getRegisterTypeName(reg); + decl += " "; decl += PARAM_PREFIX; - decl += utostr(i + 1); + decl += utostr(++cnt); } } else { for (PTXMachineFunctionInfo::reg_iterator - i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; i != e; ++i) { + i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; + i != e; ++i) { reg = *i; assert(reg != PTX::NoRegister && "Not a valid register!"); if (i != b) @@ -339,9 +449,29 @@ void PTXAsmPrinter::EmitFunctionDeclaration() { OutStreamer.EmitRawText(Twine(decl)); } +void PTXAsmPrinter:: +printPredicateOperand(const MachineInstr *MI, raw_ostream &O) { + int i = MI->findFirstPredOperandIdx(); + if (i == -1) + llvm_unreachable("missing predicate operand"); + + unsigned reg = MI->getOperand(i).getReg(); + int predOp = MI->getOperand(i+1).getImm(); + + DEBUG(dbgs() << "predicate: (" << reg << ", " << predOp << ")\n"); + + if (reg != PTX::NoRegister) { + O << '@'; + if (predOp == PTX::PRED_NEGATE) + O << '!'; + O << getRegisterName(reg); + } +} + #include "PTXGenAsmWriter.inc" // Force static initialization. extern "C" void LLVMInitializePTXAsmPrinter() { - RegisterAsmPrinter X(ThePTXTarget); + RegisterAsmPrinter X(ThePTX32Target); + RegisterAsmPrinter Y(ThePTX64Target); } diff --git a/contrib/llvm/lib/Target/PTX/PTXFrameLowering.h b/contrib/llvm/lib/Target/PTX/PTXFrameLowering.h index 574ae7a19dc2..9320676150df 100644 --- a/contrib/llvm/lib/Target/PTX/PTXFrameLowering.h +++ b/contrib/llvm/lib/Target/PTX/PTXFrameLowering.h @@ -27,7 +27,8 @@ class PTXFrameLowering : public TargetFrameLowering { public: explicit PTXFrameLowering(const PTXSubtarget &sti) - : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 2, -2), STI(sti) { + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 2, -2), + STI(sti) { } /// emitProlog/emitEpilog - These methods insert prolog and epilog code into diff --git a/contrib/llvm/lib/Target/PTX/PTXISelDAGToDAG.cpp b/contrib/llvm/lib/Target/PTX/PTXISelDAGToDAG.cpp index efb0e8b1af77..b3c85da7b446 100644 --- a/contrib/llvm/lib/Target/PTX/PTXISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/PTX/PTXISelDAGToDAG.cpp @@ -15,6 +15,7 @@ #include "PTXTargetMachine.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/DerivedTypes.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -42,8 +43,14 @@ class PTXDAGToDAGISel : public SelectionDAGISel { private: SDNode *SelectREAD_PARAM(SDNode *Node); + // We need this only because we can't match intruction BRAdp + // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td + SDNode *SelectBRCOND(SDNode *Node); + bool isImm(const SDValue &operand); bool SelectImm(const SDValue &operand, SDValue &imm); + + const PTXSubtarget& getSubtarget() const; }; // class PTXDAGToDAGISel } // namespace @@ -59,21 +66,62 @@ PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM, : SelectionDAGISel(TM, OptLevel) {} SDNode *PTXDAGToDAGISel::Select(SDNode *Node) { - if (Node->getOpcode() == PTXISD::READ_PARAM) - return SelectREAD_PARAM(Node); - else - return SelectCode(Node); + switch (Node->getOpcode()) { + case PTXISD::READ_PARAM: + return SelectREAD_PARAM(Node); + case ISD::BRCOND: + return SelectBRCOND(Node); + default: + return SelectCode(Node); + } } SDNode *PTXDAGToDAGISel::SelectREAD_PARAM(SDNode *Node) { - SDValue index = Node->getOperand(1); - DebugLoc dl = Node->getDebugLoc(); + SDValue index = Node->getOperand(1); + DebugLoc dl = Node->getDebugLoc(); + unsigned opcode; if (index.getOpcode() != ISD::TargetConstant) llvm_unreachable("READ_PARAM: index is not ISD::TargetConstant"); + if (Node->getValueType(0) == MVT::i16) { + opcode = PTX::LDpiU16; + } + else if (Node->getValueType(0) == MVT::i32) { + opcode = PTX::LDpiU32; + } + else if (Node->getValueType(0) == MVT::i64) { + opcode = PTX::LDpiU64; + } + else if (Node->getValueType(0) == MVT::f32) { + opcode = PTX::LDpiF32; + } + else if (Node->getValueType(0) == MVT::f64) { + opcode = PTX::LDpiF64; + } + else { + llvm_unreachable("Unknown parameter type for ld.param"); + } + return PTXInstrInfo:: - GetPTXMachineNode(CurDAG, PTX::LDpi, dl, MVT::i32, index); + GetPTXMachineNode(CurDAG, opcode, dl, Node->getValueType(0), index); +} + +SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) { + assert(Node->getNumOperands() >= 3); + + SDValue Chain = Node->getOperand(0); + SDValue Pred = Node->getOperand(1); + SDValue Target = Node->getOperand(2); // branch target + SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32); + DebugLoc dl = Node->getDebugLoc(); + + assert(Target.getOpcode() == ISD::BasicBlock); + assert(Pred.getValueType() == MVT::i1); + + // Emit BRAdp + SDValue Ops[] = { Target, Pred, PredOp, Chain }; + return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4); } // Match memory operand of the form [reg+reg] @@ -82,8 +130,11 @@ bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) { isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1))) return false; + assert(Addr.getValueType().isSimple() && "Type must be simple"); + R1 = Addr; - R2 = CurDAG->getTargetConstant(0, MVT::i32); + R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT()); + return true; } @@ -95,8 +146,12 @@ bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base, if (isImm(Addr)) return false; // it is [reg] + + assert(Addr.getValueType().isSimple() && "Type must be simple"); + Base = Addr; - Offset = CurDAG->getTargetConstant(0, MVT::i32); + Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT()); + return true; } @@ -129,7 +184,10 @@ bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base, // is [imm]? if (SelectImm(Addr, Base)) { - Offset = CurDAG->getTargetConstant(0, MVT::i32); + assert(Addr.getValueType().isSimple() && "Type must be simple"); + + Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT()); + return true; } @@ -146,6 +204,13 @@ bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) { return false; ConstantSDNode *CN = cast(node); - imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(), MVT::i32); + imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(), + operand.getValueType()); return true; } + +const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const +{ + return TM.getSubtarget(); +} + diff --git a/contrib/llvm/lib/Target/PTX/PTXISelLowering.cpp b/contrib/llvm/lib/Target/PTX/PTXISelLowering.cpp index e6d44907ed37..23b93daa433c 100644 --- a/contrib/llvm/lib/Target/PTX/PTXISelLowering.cpp +++ b/contrib/llvm/lib/Target/PTX/PTXISelLowering.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -27,21 +28,60 @@ PTXTargetLowering::PTXTargetLowering(TargetMachine &TM) : TargetLowering(TM, new TargetLoweringObjectFileELF()) { // Set up the register classes. addRegisterClass(MVT::i1, PTX::PredsRegisterClass); - addRegisterClass(MVT::i32, PTX::RRegs32RegisterClass); + addRegisterClass(MVT::i16, PTX::RRegu16RegisterClass); + addRegisterClass(MVT::i32, PTX::RRegu32RegisterClass); + addRegisterClass(MVT::i64, PTX::RRegu64RegisterClass); + addRegisterClass(MVT::f32, PTX::RRegf32RegisterClass); + addRegisterClass(MVT::f64, PTX::RRegf64RegisterClass); + setBooleanContents(ZeroOrOneBooleanContent); + setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); + setOperationAction(ISD::ConstantFP, MVT::f32, Legal); + setOperationAction(ISD::ConstantFP, MVT::f64, Legal); + + // Turn i16 (z)extload into load + (z)extend + setLoadExtAction(ISD::EXTLOAD, MVT::i16, Expand); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand); + + // Turn f32 extload into load + fextend + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + + // Turn f64 truncstore into trunc + store. + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + // Customize translation of memory addresses setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); + // Expand BR_CC into BRCOND + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + + // Expand SELECT_CC into SETCC + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); + setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); + setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); + + // need to lower SETCC of Preds into bitwise logic + setOperationAction(ISD::SETCC, MVT::i1, Custom); + // Compute derived properties from the register classes computeRegisterProperties(); } +MVT::SimpleValueType PTXTargetLowering::getSetCCResultType(EVT VT) const { + return MVT::i1; +} + SDValue PTXTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { - default: llvm_unreachable("Unimplemented operand"); - case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + default: + llvm_unreachable("Unimplemented operand"); + case ISD::SETCC: + return LowerSETCC(Op, DAG); + case ISD::GlobalAddress: + return LowerGlobalAddress(Op, DAG); } } @@ -49,6 +89,8 @@ const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { default: llvm_unreachable("Unknown opcode"); + case PTXISD::COPY_ADDRESS: + return "PTXISD::COPY_ADDRESS"; case PTXISD::READ_PARAM: return "PTXISD::READ_PARAM"; case PTXISD::EXIT: @@ -62,12 +104,43 @@ const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const { // Custom Lower Operation //===----------------------------------------------------------------------===// +SDValue PTXTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { + assert(Op.getValueType() == MVT::i1 && "SetCC type must be 1-bit integer"); + SDValue Op0 = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + SDValue Op2 = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + ISD::CondCode CC = cast(Op.getOperand(2))->get(); + + // Look for X == 0, X == 1, X != 0, or X != 1 + // We can simplify these to bitwise logic + + if (Op1.getOpcode() == ISD::Constant && + (cast(Op1)->getZExtValue() == 1 || + cast(Op1)->isNullValue()) && + (CC == ISD::SETEQ || CC == ISD::SETNE)) { + + return DAG.getNode(ISD::AND, dl, MVT::i1, Op0, Op1); + } + + return DAG.getNode(ISD::SETCC, dl, MVT::i1, Op0, Op1, Op2); +} + SDValue PTXTargetLowering:: LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { EVT PtrVT = getPointerTy(); DebugLoc dl = Op.getDebugLoc(); const GlobalValue *GV = cast(Op)->getGlobal(); - return DAG.getTargetGlobalAddress(GV, dl, PtrVT); + + assert(PtrVT.isSimple() && "Pointer must be to primitive type."); + + SDValue targetGlobal = DAG.getTargetGlobalAddress(GV, dl, PtrVT); + SDValue movInstr = DAG.getNode(PTXISD::COPY_ADDRESS, + dl, + PtrVT.getSimpleVT(), + targetGlobal); + + return movInstr; } //===----------------------------------------------------------------------===// @@ -87,9 +160,13 @@ struct argmap_entry { bool operator==(MVT::SimpleValueType _VT) const { return VT == _VT; } } argmap[] = { argmap_entry(MVT::i1, PTX::PredsRegisterClass), - argmap_entry(MVT::i32, PTX::RRegs32RegisterClass) + argmap_entry(MVT::i16, PTX::RRegu16RegisterClass), + argmap_entry(MVT::i32, PTX::RRegu32RegisterClass), + argmap_entry(MVT::i64, PTX::RRegu64RegisterClass), + argmap_entry(MVT::f32, PTX::RRegf32RegisterClass), + argmap_entry(MVT::f64, PTX::RRegf64RegisterClass) }; -} // end anonymous namespace +} // end anonymous namespace SDValue PTXTargetLowering:: LowerFormalArguments(SDValue Chain, @@ -185,10 +262,25 @@ SDValue PTXTargetLowering:: if (Outs.size() == 0) return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain); - assert(Outs[0].VT == MVT::i32 && "Can return only basic types"); - SDValue Flag; - unsigned reg = PTX::R0; + unsigned reg; + + if (Outs[0].VT == MVT::i16) { + reg = PTX::RH0; + } + else if (Outs[0].VT == MVT::i32) { + reg = PTX::R0; + } + else if (Outs[0].VT == MVT::i64) { + reg = PTX::RD0; + } + else if (Outs[0].VT == MVT::f32) { + reg = PTX::F0; + } + else { + assert(Outs[0].VT == MVT::f64 && "Can return only basic types"); + reg = PTX::FD0; + } MachineFunction &MF = DAG.getMachineFunction(); PTXMachineFunctionInfo *MFI = MF.getInfo(); diff --git a/contrib/llvm/lib/Target/PTX/PTXISelLowering.h b/contrib/llvm/lib/Target/PTX/PTXISelLowering.h index b03a9f66630f..6a7e3e6611bd 100644 --- a/contrib/llvm/lib/Target/PTX/PTXISelLowering.h +++ b/contrib/llvm/lib/Target/PTX/PTXISelLowering.h @@ -26,7 +26,8 @@ namespace PTXISD { FIRST_NUMBER = ISD::BUILTIN_OP_END, READ_PARAM, EXIT, - RET + RET, + COPY_ADDRESS }; } // namespace PTXISD @@ -41,6 +42,8 @@ class PTXTargetLowering : public TargetLowering { virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; + virtual SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; + virtual SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, @@ -58,7 +61,9 @@ class PTXTargetLowering : public TargetLowering { const SmallVectorImpl &OutVals, DebugLoc dl, SelectionDAG &DAG) const; - + + virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; + private: SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; }; // class PTXTargetLowering diff --git a/contrib/llvm/lib/Target/PTX/PTXInstrInfo.cpp b/contrib/llvm/lib/Target/PTX/PTXInstrInfo.cpp index 805759bcab1e..a12a6d01afa7 100644 --- a/contrib/llvm/lib/Target/PTX/PTXInstrInfo.cpp +++ b/contrib/llvm/lib/Target/PTX/PTXInstrInfo.cpp @@ -11,9 +11,15 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "ptx-instrinfo" + #include "PTX.h" #include "PTXInstrInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -27,20 +33,27 @@ static const struct map_entry { const TargetRegisterClass *cls; const int opcode; } map[] = { - { &PTX::RRegs32RegClass, PTX::MOVrr }, - { &PTX::PredsRegClass, PTX::MOVpp } + { &PTX::RRegu16RegClass, PTX::MOVU16rr }, + { &PTX::RRegu32RegClass, PTX::MOVU32rr }, + { &PTX::RRegu64RegClass, PTX::MOVU64rr }, + { &PTX::RRegf32RegClass, PTX::MOVF32rr }, + { &PTX::RRegf64RegClass, PTX::MOVF64rr }, + { &PTX::PredsRegClass, PTX::MOVPREDrr } }; void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DstReg, unsigned SrcReg, bool KillSrc) const { - for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) - if (PTX::RRegs32RegClass.contains(DstReg, SrcReg)) { - BuildMI(MBB, I, DL, - get(PTX::MOVrr), DstReg).addReg(SrcReg, getKillRegState(KillSrc)); + for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) { + if (map[i].cls->contains(DstReg, SrcReg)) { + const TargetInstrDesc &TID = get(map[i].opcode); + MachineInstr *MI = BuildMI(MBB, I, DL, TID, DstReg). + addReg(SrcReg, getKillRegState(KillSrc)); + AddDefaultPredicate(MI); return; } + } llvm_unreachable("Impossible reg-to-reg copy"); } @@ -56,12 +69,9 @@ bool PTXInstrInfo::copyRegToReg(MachineBasicBlock &MBB, for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) if (DstRC == map[i].cls) { - MachineInstr *MI = BuildMI(MBB, I, DL, get(map[i].opcode), - DstReg).addReg(SrcReg); - if (MI->findFirstPredOperandIdx() == -1) { - MI->addOperand(MachineOperand::CreateReg(0, false)); - MI->addOperand(MachineOperand::CreateImm(/*IsInv=*/0)); - } + const TargetInstrDesc &TID = get(map[i].opcode); + MachineInstr *MI = BuildMI(MBB, I, DL, TID, DstReg).addReg(SrcReg); + AddDefaultPredicate(MI); return true; } @@ -74,8 +84,12 @@ bool PTXInstrInfo::isMoveInstr(const MachineInstr& MI, switch (MI.getOpcode()) { default: return false; - case PTX::MOVpp: - case PTX::MOVrr: + case PTX::MOVU16rr: + case PTX::MOVU32rr: + case PTX::MOVU64rr: + case PTX::MOVF32rr: + case PTX::MOVF64rr: + case PTX::MOVPREDrr: assert(MI.getNumOperands() >= 2 && MI.getOperand(0).isReg() && MI.getOperand(1).isReg() && "Invalid register-register move instruction"); @@ -85,3 +99,239 @@ bool PTXInstrInfo::isMoveInstr(const MachineInstr& MI, return true; } } + +// predicate support + +bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const { + int i = MI->findFirstPredOperandIdx(); + return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister; +} + +bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { + return !isPredicated(MI) && get(MI->getOpcode()).isTerminator(); +} + +bool PTXInstrInfo:: +PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const { + if (Pred.size() < 2) + llvm_unreachable("lesser than 2 predicate operands are provided"); + + int i = MI->findFirstPredOperandIdx(); + if (i == -1) + llvm_unreachable("missing predicate operand"); + + MI->getOperand(i).setReg(Pred[0].getReg()); + MI->getOperand(i+1).setImm(Pred[1].getImm()); + + return true; +} + +bool PTXInstrInfo:: +SubsumesPredicate(const SmallVectorImpl &Pred1, + const SmallVectorImpl &Pred2) const { + const MachineOperand &PredReg1 = Pred1[0]; + const MachineOperand &PredReg2 = Pred2[0]; + if (PredReg1.getReg() != PredReg2.getReg()) + return false; + + const MachineOperand &PredOp1 = Pred1[1]; + const MachineOperand &PredOp2 = Pred2[1]; + if (PredOp1.getImm() != PredOp2.getImm()) + return false; + + return true; +} + +bool PTXInstrInfo:: +DefinesPredicate(MachineInstr *MI, + std::vector &Pred) const { + // If an instruction sets a predicate register, it defines a predicate. + + // TODO supprot 5-operand format of setp instruction + + if (MI->getNumOperands() < 1) + return false; + + const MachineOperand &MO = MI->getOperand(0); + + if (!MO.isReg() || RI.getRegClass(MO.getReg()) != &PTX::PredsRegClass) + return false; + + Pred.push_back(MO); + Pred.push_back(MachineOperand::CreateImm(PTX::PRED_NORMAL)); + return true; +} + +// branch support + +bool PTXInstrInfo:: +AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + // TODO implement cases when AllowModify is true + + if (MBB.empty()) + return true; + + MachineBasicBlock::const_iterator iter = MBB.end(); + const MachineInstr& instLast1 = *--iter; + const TargetInstrDesc &desc1 = instLast1.getDesc(); + // for special case that MBB has only 1 instruction + const bool IsSizeOne = MBB.size() == 1; + // if IsSizeOne is true, *--iter and instLast2 are invalid + // we put a dummy value in instLast2 and desc2 since they are used + const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter; + const TargetInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc(); + + DEBUG(dbgs() << "\n"); + DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n"); + DEBUG(dbgs() << "AnalyzeBranch: MBB: " << MBB.getName().str() << "\n"); + DEBUG(dbgs() << "AnalyzeBranch: TBB: " << TBB << "\n"); + DEBUG(dbgs() << "AnalyzeBranch: FBB: " << FBB << "\n"); + + // this block ends with no branches + if (!IsAnyKindOfBranch(instLast1)) { + DEBUG(dbgs() << "AnalyzeBranch: ends with no branch\n"); + return false; + } + + // this block ends with only an unconditional branch + if (desc1.isUnconditionalBranch() && + // when IsSizeOne is true, it "absorbs" the evaluation of instLast2 + (IsSizeOne || !IsAnyKindOfBranch(instLast2))) { + DEBUG(dbgs() << "AnalyzeBranch: ends with only uncond branch\n"); + TBB = GetBranchTarget(instLast1); + return false; + } + + // this block ends with a conditional branch and + // it falls through to a successor block + if (desc1.isConditionalBranch() && + IsAnySuccessorAlsoLayoutSuccessor(MBB)) { + DEBUG(dbgs() << "AnalyzeBranch: ends with cond branch and fall through\n"); + TBB = GetBranchTarget(instLast1); + int i = instLast1.findFirstPredOperandIdx(); + Cond.push_back(instLast1.getOperand(i)); + Cond.push_back(instLast1.getOperand(i+1)); + return false; + } + + // when IsSizeOne is true, we are done + if (IsSizeOne) + return true; + + // this block ends with a conditional branch + // followed by an unconditional branch + if (desc2.isConditionalBranch() && + desc1.isUnconditionalBranch()) { + DEBUG(dbgs() << "AnalyzeBranch: ends with cond and uncond branch\n"); + TBB = GetBranchTarget(instLast2); + FBB = GetBranchTarget(instLast1); + int i = instLast2.findFirstPredOperandIdx(); + Cond.push_back(instLast2.getOperand(i)); + Cond.push_back(instLast2.getOperand(i+1)); + return false; + } + + // branch cannot be understood + DEBUG(dbgs() << "AnalyzeBranch: cannot be understood\n"); + return true; +} + +unsigned PTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + unsigned count = 0; + while (!MBB.empty()) + if (IsAnyKindOfBranch(MBB.back())) { + MBB.pop_back(); + ++count; + } else + break; + DEBUG(dbgs() << "RemoveBranch: MBB: " << MBB.getName().str() << "\n"); + DEBUG(dbgs() << "RemoveBranch: remove " << count << " branch inst\n"); + return count; +} + +unsigned PTXInstrInfo:: +InsertBranch(MachineBasicBlock &MBB, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond, + DebugLoc DL) const { + DEBUG(dbgs() << "InsertBranch: MBB: " << MBB.getName().str() << "\n"); + DEBUG(if (TBB) dbgs() << "InsertBranch: TBB: " << TBB->getName().str() + << "\n"; + else dbgs() << "InsertBranch: TBB: (NULL)\n"); + DEBUG(if (FBB) dbgs() << "InsertBranch: FBB: " << FBB->getName().str() + << "\n"; + else dbgs() << "InsertBranch: FBB: (NULL)\n"); + DEBUG(dbgs() << "InsertBranch: Cond size: " << Cond.size() << "\n"); + + assert(TBB && "TBB is NULL"); + + if (FBB) { + BuildMI(&MBB, DL, get(PTX::BRAdp)) + .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm()); + BuildMI(&MBB, DL, get(PTX::BRAd)) + .addMBB(FBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL); + return 2; + } else if (Cond.size()) { + BuildMI(&MBB, DL, get(PTX::BRAdp)) + .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm()); + return 1; + } else { + BuildMI(&MBB, DL, get(PTX::BRAd)) + .addMBB(TBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL); + return 1; + } +} + +// static helper routines + +MachineSDNode *PTXInstrInfo:: +GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode, + DebugLoc dl, EVT VT, SDValue Op1) { + SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1); + SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32); + SDValue ops[] = { Op1, predReg, predOp }; + return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops)); +} + +MachineSDNode *PTXInstrInfo:: +GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode, + DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) { + SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1); + SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32); + SDValue ops[] = { Op1, Op2, predReg, predOp }; + return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops)); +} + +void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) { + if (MI->findFirstPredOperandIdx() == -1) { + MI->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false)); + MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL)); + } +} + +bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) { + const TargetInstrDesc &desc = inst.getDesc(); + return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch(); +} + +bool PTXInstrInfo:: +IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB) { + for (MachineBasicBlock::const_succ_iterator + i = MBB.succ_begin(), e = MBB.succ_end(); i != e; ++i) + if (MBB.isLayoutSuccessor((const MachineBasicBlock*) &*i)) + return true; + return false; +} + +MachineBasicBlock *PTXInstrInfo::GetBranchTarget(const MachineInstr& inst) { + // FIXME So far all branch instructions put destination in 1st operand + const MachineOperand& target = inst.getOperand(0); + assert(target.isMBB() && "FIXME: detect branch target operand"); + return target.getMBB(); +} diff --git a/contrib/llvm/lib/Target/PTX/PTXInstrInfo.h b/contrib/llvm/lib/Target/PTX/PTXInstrInfo.h index e7f00f09c2f1..a04be7728f88 100644 --- a/contrib/llvm/lib/Target/PTX/PTXInstrInfo.h +++ b/contrib/llvm/lib/Target/PTX/PTXInstrInfo.h @@ -15,61 +15,93 @@ #define PTX_INSTR_INFO_H #include "PTXRegisterInfo.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/Target/TargetInstrInfo.h" namespace llvm { class PTXTargetMachine; +class MachineSDNode; +class SDValue; +class SelectionDAG; + class PTXInstrInfo : public TargetInstrInfoImpl { - private: - const PTXRegisterInfo RI; - PTXTargetMachine &TM; +private: + const PTXRegisterInfo RI; + PTXTargetMachine &TM; - public: - explicit PTXInstrInfo(PTXTargetMachine &_TM); +public: + explicit PTXInstrInfo(PTXTargetMachine &_TM); - virtual const PTXRegisterInfo &getRegisterInfo() const { return RI; } + virtual const PTXRegisterInfo &getRegisterInfo() const { return RI; } - virtual void copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, DebugLoc DL, - unsigned DstReg, unsigned SrcReg, - bool KillSrc) const; + virtual void copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DstReg, unsigned SrcReg, + bool KillSrc) const; - virtual bool copyRegToReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned DstReg, unsigned SrcReg, - const TargetRegisterClass *DstRC, - const TargetRegisterClass *SrcRC, - DebugLoc DL) const; + virtual bool copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DstReg, unsigned SrcReg, + const TargetRegisterClass *DstRC, + const TargetRegisterClass *SrcRC, + DebugLoc DL) const; - virtual bool isMoveInstr(const MachineInstr& MI, - unsigned &SrcReg, unsigned &DstReg, - unsigned &SrcSubIdx, unsigned &DstSubIdx) const; + virtual bool isMoveInstr(const MachineInstr& MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned &SrcSubIdx, unsigned &DstSubIdx) const; - // static helper routines + // predicate support - static MachineSDNode *GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode, - DebugLoc dl, EVT VT, - SDValue Op1) { - SDValue pred_reg = DAG->getRegister(0, MVT::i1); - SDValue pred_imm = DAG->getTargetConstant(0, MVT::i32); - SDValue ops[] = { Op1, pred_reg, pred_imm }; - return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops)); - } + virtual bool isPredicated(const MachineInstr *MI) const; - static MachineSDNode *GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode, - DebugLoc dl, EVT VT, - SDValue Op1, - SDValue Op2) { - SDValue pred_reg = DAG->getRegister(0, MVT::i1); - SDValue pred_imm = DAG->getTargetConstant(0, MVT::i32); - SDValue ops[] = { Op1, Op2, pred_reg, pred_imm }; - return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops)); - } + virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; - }; // class PTXInstrInfo + virtual + bool PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const; + + virtual + bool SubsumesPredicate(const SmallVectorImpl &Pred1, + const SmallVectorImpl &Pred2) const; + + virtual bool DefinesPredicate(MachineInstr *MI, + std::vector &Pred) const; + + // PTX is fully-predicable + virtual bool isPredicable(MachineInstr *MI) const { return true; } + + // branch support + + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify = false) const; + + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond, + DebugLoc DL) const; + + // static helper routines + + static MachineSDNode *GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode, + DebugLoc dl, EVT VT, + SDValue Op1); + + static MachineSDNode *GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode, + DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2); + + static void AddDefaultPredicate(MachineInstr *MI); + + static bool IsAnyKindOfBranch(const MachineInstr& inst); + + static bool IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB); + + static MachineBasicBlock *GetBranchTarget(const MachineInstr& inst); +}; // class PTXInstrInfo } // namespace llvm #endif // PTX_INSTR_INFO_H diff --git a/contrib/llvm/lib/Target/PTX/PTXInstrInfo.td b/contrib/llvm/lib/Target/PTX/PTXInstrInfo.td index 9a747788f6a1..1ac9d3f3dc81 100644 --- a/contrib/llvm/lib/Target/PTX/PTXInstrInfo.td +++ b/contrib/llvm/lib/Target/PTX/PTXInstrInfo.td @@ -17,6 +17,26 @@ include "PTXInstrFormats.td" +//===----------------------------------------------------------------------===// +// Code Generation Predicates +//===----------------------------------------------------------------------===// + +// Addressing +def Use32BitAddresses : Predicate<"!getSubtarget().is64Bit()">; +def Use64BitAddresses : Predicate<"getSubtarget().is64Bit()">; + +// Shader Model Support +def SupportsSM13 : Predicate<"getSubtarget().supportsSM13()">; +def DoesNotSupportSM13 : Predicate<"!getSubtarget().supportsSM13()">; +def SupportsSM20 : Predicate<"getSubtarget().supportsSM20()">; +def DoesNotSupportSM20 : Predicate<"!getSubtarget().supportsSM20()">; + +// PTX Version Support +def SupportsPTX21 : Predicate<"getSubtarget().supportsPTX21()">; +def DoesNotSupportPTX21 : Predicate<"!getSubtarget().supportsPTX21()">; +def SupportsPTX22 : Predicate<"getSubtarget().supportsPTX22()">; +def DoesNotSupportPTX22 : Predicate<"!getSubtarget().supportsPTX22()">; + //===----------------------------------------------------------------------===// // Instruction Pattern Stuff //===----------------------------------------------------------------------===// @@ -107,24 +127,41 @@ def store_shared }]>; // Addressing modes. -def ADDRrr : ComplexPattern; -def ADDRri : ComplexPattern; -def ADDRii : ComplexPattern; +def ADDRrr32 : ComplexPattern; +def ADDRrr64 : ComplexPattern; +def ADDRri32 : ComplexPattern; +def ADDRri64 : ComplexPattern; +def ADDRii32 : ComplexPattern; +def ADDRii64 : ComplexPattern; // Address operands -def MEMri : Operand { +def MEMri32 : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops RRegs32, i32imm); + let MIOperandInfo = (ops RRegu32, i32imm); } -def MEMii : Operand { +def MEMri64 : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops RRegu64, i64imm); +} +def MEMii32 : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops i32imm, i32imm); } +def MEMii64 : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops i64imm, i64imm); +} +// The operand here does not correspond to an actual address, so we +// can use i32 in 64-bit address modes. def MEMpi : Operand { let PrintMethod = "printParamOperand"; let MIOperandInfo = (ops i32imm); } +// Branch & call targets have OtherVT type. +def brtarget : Operand; +def calltarget : Operand; + //===----------------------------------------------------------------------===// // PTX Specific Node Definitions //===----------------------------------------------------------------------===// @@ -138,66 +175,389 @@ def PTXexit : SDNode<"PTXISD::EXIT", SDTNone, [SDNPHasChain]>; def PTXret : SDNode<"PTXISD::RET", SDTNone, [SDNPHasChain]>; +def PTXcopyaddress + : SDNode<"PTXISD::COPY_ADDRESS", SDTypeProfile<1, 1, []>, []>; //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// +//===- Floating-Point Instructions - 2 Operand Form -----------------------===// +multiclass PTX_FLOAT_2OP { + def rr32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a), + !strconcat(opcstr, ".f32\t$d, $a"), + [(set RRegf32:$d, (opnode RRegf32:$a))]>; + def ri32 : InstPTX<(outs RRegf32:$d), + (ins f32imm:$a), + !strconcat(opcstr, ".f32\t$d, $a"), + [(set RRegf32:$d, (opnode fpimm:$a))]>; + def rr64 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a), + !strconcat(opcstr, ".f64\t$d, $a"), + [(set RRegf64:$d, (opnode RRegf64:$a))]>; + def ri64 : InstPTX<(outs RRegf64:$d), + (ins f64imm:$a), + !strconcat(opcstr, ".f64\t$d, $a"), + [(set RRegf64:$d, (opnode fpimm:$a))]>; +} + +//===- Floating-Point Instructions - 3 Operand Form -----------------------===// +multiclass PTX_FLOAT_3OP { + def rr32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a, RRegf32:$b), + !strconcat(opcstr, ".f32\t$d, $a, $b"), + [(set RRegf32:$d, (opnode RRegf32:$a, RRegf32:$b))]>; + def ri32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a, f32imm:$b), + !strconcat(opcstr, ".f32\t$d, $a, $b"), + [(set RRegf32:$d, (opnode RRegf32:$a, fpimm:$b))]>; + def rr64 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a, RRegf64:$b), + !strconcat(opcstr, ".f64\t$d, $a, $b"), + [(set RRegf64:$d, (opnode RRegf64:$a, RRegf64:$b))]>; + def ri64 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a, f64imm:$b), + !strconcat(opcstr, ".f64\t$d, $a, $b"), + [(set RRegf64:$d, (opnode RRegf64:$a, fpimm:$b))]>; +} + +//===- Floating-Point Instructions - 4 Operand Form -----------------------===// +multiclass PTX_FLOAT_4OP { + def rrr32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a, RRegf32:$b, RRegf32:$c), + !strconcat(opcstr, ".f32\t$d, $a, $b, $c"), + [(set RRegf32:$d, (opnode2 (opnode1 RRegf32:$a, + RRegf32:$b), + RRegf32:$c))]>; + def rri32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a, RRegf32:$b, f32imm:$c), + !strconcat(opcstr, ".f32\t$d, $a, $b, $c"), + [(set RRegf32:$d, (opnode2 (opnode1 RRegf32:$a, + RRegf32:$b), + fpimm:$c))]>; + def rrr64 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a, RRegf64:$b, RRegf64:$c), + !strconcat(opcstr, ".f64\t$d, $a, $b, $c"), + [(set RRegf64:$d, (opnode2 (opnode1 RRegf64:$a, + RRegf64:$b), + RRegf64:$c))]>; + def rri64 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a, RRegf64:$b, f64imm:$c), + !strconcat(opcstr, ".f64\t$d, $a, $b, $c"), + [(set RRegf64:$d, (opnode2 (opnode1 RRegf64:$a, + RRegf64:$b), + fpimm:$c))]>; +} + multiclass INT3 { - def rr : InstPTX<(outs RRegs32:$d), - (ins RRegs32:$a, RRegs32:$b), - !strconcat(opcstr, ".%type\t$d, $a, $b"), - [(set RRegs32:$d, (opnode RRegs32:$a, RRegs32:$b))]>; - def ri : InstPTX<(outs RRegs32:$d), - (ins RRegs32:$a, i32imm:$b), - !strconcat(opcstr, ".%type\t$d, $a, $b"), - [(set RRegs32:$d, (opnode RRegs32:$a, imm:$b))]>; + def rr16 : InstPTX<(outs RRegu16:$d), + (ins RRegu16:$a, RRegu16:$b), + !strconcat(opcstr, ".u16\t$d, $a, $b"), + [(set RRegu16:$d, (opnode RRegu16:$a, RRegu16:$b))]>; + def ri16 : InstPTX<(outs RRegu16:$d), + (ins RRegu16:$a, i16imm:$b), + !strconcat(opcstr, ".u16\t$d, $a, $b"), + [(set RRegu16:$d, (opnode RRegu16:$a, imm:$b))]>; + def rr32 : InstPTX<(outs RRegu32:$d), + (ins RRegu32:$a, RRegu32:$b), + !strconcat(opcstr, ".u32\t$d, $a, $b"), + [(set RRegu32:$d, (opnode RRegu32:$a, RRegu32:$b))]>; + def ri32 : InstPTX<(outs RRegu32:$d), + (ins RRegu32:$a, i32imm:$b), + !strconcat(opcstr, ".u32\t$d, $a, $b"), + [(set RRegu32:$d, (opnode RRegu32:$a, imm:$b))]>; + def rr64 : InstPTX<(outs RRegu64:$d), + (ins RRegu64:$a, RRegu64:$b), + !strconcat(opcstr, ".u64\t$d, $a, $b"), + [(set RRegu64:$d, (opnode RRegu64:$a, RRegu64:$b))]>; + def ri64 : InstPTX<(outs RRegu64:$d), + (ins RRegu64:$a, i64imm:$b), + !strconcat(opcstr, ".u64\t$d, $a, $b"), + [(set RRegu64:$d, (opnode RRegu64:$a, imm:$b))]>; +} + +multiclass PTX_LOGIC { + def ripreds : InstPTX<(outs Preds:$d), + (ins Preds:$a, i1imm:$b), + !strconcat(opcstr, ".pred\t$d, $a, $b"), + [(set Preds:$d, (opnode Preds:$a, imm:$b))]>; + def rrpreds : InstPTX<(outs Preds:$d), + (ins Preds:$a, Preds:$b), + !strconcat(opcstr, ".pred\t$d, $a, $b"), + [(set Preds:$d, (opnode Preds:$a, Preds:$b))]>; + def rr16 : InstPTX<(outs RRegu16:$d), + (ins RRegu16:$a, RRegu16:$b), + !strconcat(opcstr, ".b16\t$d, $a, $b"), + [(set RRegu16:$d, (opnode RRegu16:$a, RRegu16:$b))]>; + def ri16 : InstPTX<(outs RRegu16:$d), + (ins RRegu16:$a, i16imm:$b), + !strconcat(opcstr, ".b16\t$d, $a, $b"), + [(set RRegu16:$d, (opnode RRegu16:$a, imm:$b))]>; + def rr32 : InstPTX<(outs RRegu32:$d), + (ins RRegu32:$a, RRegu32:$b), + !strconcat(opcstr, ".b32\t$d, $a, $b"), + [(set RRegu32:$d, (opnode RRegu32:$a, RRegu32:$b))]>; + def ri32 : InstPTX<(outs RRegu32:$d), + (ins RRegu32:$a, i32imm:$b), + !strconcat(opcstr, ".b32\t$d, $a, $b"), + [(set RRegu32:$d, (opnode RRegu32:$a, imm:$b))]>; + def rr64 : InstPTX<(outs RRegu64:$d), + (ins RRegu64:$a, RRegu64:$b), + !strconcat(opcstr, ".b64\t$d, $a, $b"), + [(set RRegu64:$d, (opnode RRegu64:$a, RRegu64:$b))]>; + def ri64 : InstPTX<(outs RRegu64:$d), + (ins RRegu64:$a, i64imm:$b), + !strconcat(opcstr, ".b64\t$d, $a, $b"), + [(set RRegu64:$d, (opnode RRegu64:$a, imm:$b))]>; } -// no %type directive, non-communtable multiclass INT3ntnc { - def rr : InstPTX<(outs RRegs32:$d), - (ins RRegs32:$a, RRegs32:$b), - !strconcat(opcstr, "\t$d, $a, $b"), - [(set RRegs32:$d, (opnode RRegs32:$a, RRegs32:$b))]>; - def ri : InstPTX<(outs RRegs32:$d), - (ins RRegs32:$a, i32imm:$b), - !strconcat(opcstr, "\t$d, $a, $b"), - [(set RRegs32:$d, (opnode RRegs32:$a, imm:$b))]>; - def ir : InstPTX<(outs RRegs32:$d), - (ins i32imm:$a, RRegs32:$b), - !strconcat(opcstr, "\t$d, $a, $b"), - [(set RRegs32:$d, (opnode imm:$a, RRegs32:$b))]>; + def rr16 : InstPTX<(outs RRegu16:$d), + (ins RRegu16:$a, RRegu16:$b), + !strconcat(opcstr, "16\t$d, $a, $b"), + [(set RRegu16:$d, (opnode RRegu16:$a, RRegu16:$b))]>; + def rr32 : InstPTX<(outs RRegu32:$d), + (ins RRegu32:$a, RRegu32:$b), + !strconcat(opcstr, "32\t$d, $a, $b"), + [(set RRegu32:$d, (opnode RRegu32:$a, RRegu32:$b))]>; + def rr64 : InstPTX<(outs RRegu64:$d), + (ins RRegu64:$a, RRegu64:$b), + !strconcat(opcstr, "64\t$d, $a, $b"), + [(set RRegu64:$d, (opnode RRegu64:$a, RRegu64:$b))]>; + def ri16 : InstPTX<(outs RRegu16:$d), + (ins RRegu16:$a, i16imm:$b), + !strconcat(opcstr, "16\t$d, $a, $b"), + [(set RRegu16:$d, (opnode RRegu16:$a, imm:$b))]>; + def ri32 : InstPTX<(outs RRegu32:$d), + (ins RRegu32:$a, i32imm:$b), + !strconcat(opcstr, "32\t$d, $a, $b"), + [(set RRegu32:$d, (opnode RRegu32:$a, imm:$b))]>; + def ri64 : InstPTX<(outs RRegu64:$d), + (ins RRegu64:$a, i64imm:$b), + !strconcat(opcstr, "64\t$d, $a, $b"), + [(set RRegu64:$d, (opnode RRegu64:$a, imm:$b))]>; + def ir16 : InstPTX<(outs RRegu16:$d), + (ins i16imm:$a, RRegu16:$b), + !strconcat(opcstr, "16\t$d, $a, $b"), + [(set RRegu16:$d, (opnode imm:$a, RRegu16:$b))]>; + def ir32 : InstPTX<(outs RRegu32:$d), + (ins i32imm:$a, RRegu32:$b), + !strconcat(opcstr, "32\t$d, $a, $b"), + [(set RRegu32:$d, (opnode imm:$a, RRegu32:$b))]>; + def ir64 : InstPTX<(outs RRegu64:$d), + (ins i64imm:$a, RRegu64:$b), + !strconcat(opcstr, "64\t$d, $a, $b"), + [(set RRegu64:$d, (opnode imm:$a, RRegu64:$b))]>; } -multiclass PTX_LD { - def rr : InstPTX<(outs RC:$d), - (ins MEMri:$a), - !strconcat(opstr, ".%type\t$d, [$a]"), - [(set RC:$d, (pat_load ADDRrr:$a))]>; - def ri : InstPTX<(outs RC:$d), - (ins MEMri:$a), - !strconcat(opstr, ".%type\t$d, [$a]"), - [(set RC:$d, (pat_load ADDRri:$a))]>; - def ii : InstPTX<(outs RC:$d), - (ins MEMii:$a), - !strconcat(opstr, ".%type\t$d, [$a]"), - [(set RC:$d, (pat_load ADDRii:$a))]>; +multiclass PTX_SETP_I { + // TODO support 5-operand format: p|q, a, b, c + + def rr + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b), + !strconcat("setp.", cmpstr, ".", regclsname, "\t$p, $a, $b"), + [(set Preds:$p, (setcc RC:$a, RC:$b, cmp))]>; + def ri + : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b), + !strconcat("setp.", cmpstr, ".", regclsname, "\t$p, $a, $b"), + [(set Preds:$p, (setcc RC:$a, imm:$b, cmp))]>; + + def rr_and_r + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (and (setcc RC:$a, RC:$b, cmp), Preds:$c))]>; + def ri_and_r + : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (and (setcc RC:$a, imm:$b, cmp), Preds:$c))]>; + def rr_or_r + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (or (setcc RC:$a, RC:$b, cmp), Preds:$c))]>; + def ri_or_r + : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (or (setcc RC:$a, imm:$b, cmp), Preds:$c))]>; + def rr_xor_r + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (xor (setcc RC:$a, RC:$b, cmp), Preds:$c))]>; + def ri_xor_r + : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (xor (setcc RC:$a, imm:$b, cmp), Preds:$c))]>; + + def rr_and_not_r + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (and (setcc RC:$a, RC:$b, cmp), (not Preds:$c)))]>; + def ri_and_not_r + : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (and (setcc RC:$a, imm:$b, cmp), (not Preds:$c)))]>; + def rr_or_not_r + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (or (setcc RC:$a, RC:$b, cmp), (not Preds:$c)))]>; + def ri_or_not_r + : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (or (setcc RC:$a, imm:$b, cmp), (not Preds:$c)))]>; + def rr_xor_not_r + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (xor (setcc RC:$a, RC:$b, cmp), (not Preds:$c)))]>; + def ri_xor_not_r + : InstPTX<(outs Preds:$p), (ins RC:$a, immcls:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (xor (setcc RC:$a, imm:$b, cmp), (not Preds:$c)))]>; } -multiclass PTX_ST { - def rr : InstPTX<(outs), - (ins RC:$d, MEMri:$a), - !strconcat(opstr, ".%type\t[$a], $d"), - [(pat_store RC:$d, ADDRrr:$a)]>; - def ri : InstPTX<(outs), - (ins RC:$d, MEMri:$a), - !strconcat(opstr, ".%type\t[$a], $d"), - [(pat_store RC:$d, ADDRri:$a)]>; - def ii : InstPTX<(outs), - (ins RC:$d, MEMii:$a), - !strconcat(opstr, ".%type\t[$a], $d"), - [(pat_store RC:$d, ADDRii:$a)]>; +multiclass PTX_SETP_FP { + // TODO support 5-operand format: p|q, a, b, c + + def rr_u + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b), + !strconcat("setp.", cmpstr, "u.", regclsname, "\t$p, $a, $b"), + [(set Preds:$p, (setcc RC:$a, RC:$b, ucmp))]>; + def rr_o + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b), + !strconcat("setp.", cmpstr, ".", regclsname, "\t$p, $a, $b"), + [(set Preds:$p, (setcc RC:$a, RC:$b, ocmp))]>; + + def rr_and_r_u + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, "u.and.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (and (setcc RC:$a, RC:$b, ucmp), Preds:$c))]>; + def rr_and_r_o + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (and (setcc RC:$a, RC:$b, ocmp), Preds:$c))]>; + + def rr_or_r_u + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, "u.or.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (or (setcc RC:$a, RC:$b, ucmp), Preds:$c))]>; + def rr_or_r_o + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (or (setcc RC:$a, RC:$b, ocmp), Preds:$c))]>; + + def rr_xor_r_u + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, "u.xor.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (xor (setcc RC:$a, RC:$b, ucmp), Preds:$c))]>; + def rr_xor_r_o + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, $c"), + [(set Preds:$p, (xor (setcc RC:$a, RC:$b, ocmp), Preds:$c))]>; + + def rr_and_not_r_u + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, "u.and.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (and (setcc RC:$a, RC:$b, ucmp), (not Preds:$c)))]>; + def rr_and_not_r_o + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (and (setcc RC:$a, RC:$b, ocmp), (not Preds:$c)))]>; + + def rr_or_not_r_u + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, "u.or.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (or (setcc RC:$a, RC:$b, ucmp), (not Preds:$c)))]>; + def rr_or_not_r_o + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (or (setcc RC:$a, RC:$b, ocmp), (not Preds:$c)))]>; + + def rr_xor_not_r_u + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, "u.xor.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (xor (setcc RC:$a, RC:$b, ucmp), (not Preds:$c)))]>; + def rr_xor_not_r_o + : InstPTX<(outs Preds:$p), (ins RC:$a, RC:$b, Preds:$c), + !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, !$c"), + [(set Preds:$p, (xor (setcc RC:$a, RC:$b, ocmp), (not Preds:$c)))]>; +} + +multiclass PTX_SELP { + def rr + : InstPTX<(outs RC:$r), (ins Preds:$a, RC:$b, RC:$c), + !strconcat("selp.", regclsname, "\t$r, $b, $c, $a"), + [(set RC:$r, (select Preds:$a, RC:$b, RC:$c))]>; +} + +multiclass PTX_LD { + def rr32 : InstPTX<(outs RC:$d), + (ins MEMri32:$a), + !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")), + [(set RC:$d, (pat_load ADDRrr32:$a))]>, Requires<[Use32BitAddresses]>; + def rr64 : InstPTX<(outs RC:$d), + (ins MEMri64:$a), + !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")), + [(set RC:$d, (pat_load ADDRrr64:$a))]>, Requires<[Use64BitAddresses]>; + def ri32 : InstPTX<(outs RC:$d), + (ins MEMri32:$a), + !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")), + [(set RC:$d, (pat_load ADDRri32:$a))]>, Requires<[Use32BitAddresses]>; + def ri64 : InstPTX<(outs RC:$d), + (ins MEMri64:$a), + !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")), + [(set RC:$d, (pat_load ADDRri64:$a))]>, Requires<[Use64BitAddresses]>; + def ii32 : InstPTX<(outs RC:$d), + (ins MEMii32:$a), + !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")), + [(set RC:$d, (pat_load ADDRii32:$a))]>, Requires<[Use32BitAddresses]>; + def ii64 : InstPTX<(outs RC:$d), + (ins MEMii64:$a), + !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")), + [(set RC:$d, (pat_load ADDRii64:$a))]>, Requires<[Use64BitAddresses]>; +} + +multiclass PTX_LD_ALL { + defm u16 : PTX_LD; + defm u32 : PTX_LD; + defm u64 : PTX_LD; + defm f32 : PTX_LD; + defm f64 : PTX_LD; +} + +multiclass PTX_ST { + def rr32 : InstPTX<(outs), + (ins RC:$d, MEMri32:$a), + !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")), + [(pat_store RC:$d, ADDRrr32:$a)]>, Requires<[Use32BitAddresses]>; + def rr64 : InstPTX<(outs), + (ins RC:$d, MEMri64:$a), + !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")), + [(pat_store RC:$d, ADDRrr64:$a)]>, Requires<[Use64BitAddresses]>; + def ri32 : InstPTX<(outs), + (ins RC:$d, MEMri32:$a), + !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")), + [(pat_store RC:$d, ADDRri32:$a)]>, Requires<[Use32BitAddresses]>; + def ri64 : InstPTX<(outs), + (ins RC:$d, MEMri64:$a), + !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")), + [(pat_store RC:$d, ADDRri64:$a)]>, Requires<[Use64BitAddresses]>; + def ii32 : InstPTX<(outs), + (ins RC:$d, MEMii32:$a), + !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")), + [(pat_store RC:$d, ADDRii32:$a)]>, Requires<[Use32BitAddresses]>; + def ii64 : InstPTX<(outs), + (ins RC:$d, MEMii64:$a), + !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")), + [(pat_store RC:$d, ADDRii64:$a)]>, Requires<[Use64BitAddresses]>; +} + +multiclass PTX_ST_ALL { + defm u16 : PTX_ST; + defm u32 : PTX_ST; + defm u64 : PTX_ST; + defm f32 : PTX_ST; + defm f64 : PTX_ST; } //===----------------------------------------------------------------------===// @@ -208,50 +568,392 @@ multiclass PTX_ST { defm ADD : INT3<"add", add>; defm SUB : INT3<"sub", sub>; +defm MUL : INT3<"mul.lo", mul>; // FIXME: Allow 32x32 -> 64 multiplies +defm DIV : INT3<"div", udiv>; +defm REM : INT3<"rem", urem>; + +///===- Floating-Point Arithmetic Instructions ----------------------------===// + +// Standard Unary Operations +defm FNEG : PTX_FLOAT_2OP<"neg", fneg>; + +// Standard Binary Operations +defm FADD : PTX_FLOAT_3OP<"add", fadd>; +defm FSUB : PTX_FLOAT_3OP<"sub", fsub>; +defm FMUL : PTX_FLOAT_3OP<"mul", fmul>; + +// TODO: Allow user selection of rounding modes for fdiv. +// For division, we need to have f32 and f64 differently. +// For f32, we just always use .approx since it is supported on all hardware +// for PTX 1.4+, which is our minimum target. +def FDIVrr32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a, RRegf32:$b), + "div.approx.f32\t$d, $a, $b", + [(set RRegf32:$d, (fdiv RRegf32:$a, RRegf32:$b))]>; +def FDIVri32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a, f32imm:$b), + "div.approx.f32\t$d, $a, $b", + [(set RRegf32:$d, (fdiv RRegf32:$a, fpimm:$b))]>; + +// For f64, we must specify a rounding for sm 1.3+ but *not* for sm 1.0. +def FDIVrr64SM13 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a, RRegf64:$b), + "div.rn.f64\t$d, $a, $b", + [(set RRegf64:$d, (fdiv RRegf64:$a, RRegf64:$b))]>, + Requires<[SupportsSM13]>; +def FDIVri64SM13 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a, f64imm:$b), + "div.rn.f64\t$d, $a, $b", + [(set RRegf64:$d, (fdiv RRegf64:$a, fpimm:$b))]>, + Requires<[SupportsSM13]>; +def FDIVrr64SM10 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a, RRegf64:$b), + "div.f64\t$d, $a, $b", + [(set RRegf64:$d, (fdiv RRegf64:$a, RRegf64:$b))]>, + Requires<[DoesNotSupportSM13]>; +def FDIVri64SM10 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a, f64imm:$b), + "div.f64\t$d, $a, $b", + [(set RRegf64:$d, (fdiv RRegf64:$a, fpimm:$b))]>, + Requires<[DoesNotSupportSM13]>; + + + +// Multi-operation hybrid instructions + +// The selection of mad/fma is tricky. In some cases, they are the *same* +// instruction, but in other cases we may prefer one or the other. Also, +// different PTX versions differ on whether rounding mode flags are required. +// In the short term, mad is supported on all PTX versions and we use a +// default rounding mode no matter what shader model or PTX version. +// TODO: Allow the rounding mode to be selectable through llc. +defm FMADSM13 : PTX_FLOAT_4OP<"mad.rn", fmul, fadd>, Requires<[SupportsSM13]>; +defm FMAD : PTX_FLOAT_4OP<"mad", fmul, fadd>, Requires<[DoesNotSupportSM13]>; + +///===- Floating-Point Intrinsic Instructions -----------------------------===// + +def FSQRT32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a), + "sqrt.rn.f32\t$d, $a", + [(set RRegf32:$d, (fsqrt RRegf32:$a))]>; + +def FSQRT64 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a), + "sqrt.rn.f64\t$d, $a", + [(set RRegf64:$d, (fsqrt RRegf64:$a))]>; + +def FSIN32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a), + "sin.approx.f32\t$d, $a", + [(set RRegf32:$d, (fsin RRegf32:$a))]>; + +def FSIN64 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a), + "sin.approx.f64\t$d, $a", + [(set RRegf64:$d, (fsin RRegf64:$a))]>; + +def FCOS32 : InstPTX<(outs RRegf32:$d), + (ins RRegf32:$a), + "cos.approx.f32\t$d, $a", + [(set RRegf32:$d, (fcos RRegf32:$a))]>; + +def FCOS64 : InstPTX<(outs RRegf64:$d), + (ins RRegf64:$a), + "cos.approx.f64\t$d, $a", + [(set RRegf64:$d, (fcos RRegf64:$a))]>; + + +///===- Comparison and Selection Instructions -----------------------------===// + +// Compare u16 + +defm SETPEQu16 : PTX_SETP_I; +defm SETPNEu16 : PTX_SETP_I; +defm SETPLTu16 : PTX_SETP_I; +defm SETPLEu16 : PTX_SETP_I; +defm SETPGTu16 : PTX_SETP_I; +defm SETPGEu16 : PTX_SETP_I; + +// Compare u32 + +defm SETPEQu32 : PTX_SETP_I; +defm SETPNEu32 : PTX_SETP_I; +defm SETPLTu32 : PTX_SETP_I; +defm SETPLEu32 : PTX_SETP_I; +defm SETPGTu32 : PTX_SETP_I; +defm SETPGEu32 : PTX_SETP_I; + +// Compare u64 + +defm SETPEQu64 : PTX_SETP_I; +defm SETPNEu64 : PTX_SETP_I; +defm SETPLTu64 : PTX_SETP_I; +defm SETPLEu64 : PTX_SETP_I; +defm SETPGTu64 : PTX_SETP_I; +defm SETPGEu64 : PTX_SETP_I; + +// Compare f32 + +defm SETPEQf32 : PTX_SETP_FP; +defm SETPNEf32 : PTX_SETP_FP; +defm SETPLTf32 : PTX_SETP_FP; +defm SETPLEf32 : PTX_SETP_FP; +defm SETPGTf32 : PTX_SETP_FP; +defm SETPGEf32 : PTX_SETP_FP; + +// Compare f64 + +defm SETPEQf64 : PTX_SETP_FP; +defm SETPNEf64 : PTX_SETP_FP; +defm SETPLTf64 : PTX_SETP_FP; +defm SETPLEf64 : PTX_SETP_FP; +defm SETPGTf64 : PTX_SETP_FP; +defm SETPGEf64 : PTX_SETP_FP; + +// .selp + +defm PTX_SELPu16 : PTX_SELP; +defm PTX_SELPu32 : PTX_SELP; +defm PTX_SELPu64 : PTX_SELP; +defm PTX_SELPf32 : PTX_SELP; +defm PTX_SELPf64 : PTX_SELP; ///===- Logic and Shift Instructions --------------------------------------===// -defm SHL : INT3ntnc<"shl.b32", PTXshl>; -defm SRL : INT3ntnc<"shr.u32", PTXsrl>; -defm SRA : INT3ntnc<"shr.s32", PTXsra>; +defm SHL : INT3ntnc<"shl.b", PTXshl>; +defm SRL : INT3ntnc<"shr.u", PTXsrl>; +defm SRA : INT3ntnc<"shr.s", PTXsra>; + +defm AND : PTX_LOGIC<"and", and>; +defm OR : PTX_LOGIC<"or", or>; +defm XOR : PTX_LOGIC<"xor", xor>; ///===- Data Movement and Conversion Instructions -------------------------===// let neverHasSideEffects = 1 in { - // rely on isMoveInstr to separate MOVpp, MOVrr, etc. - def MOVpp + def MOVPREDrr : InstPTX<(outs Preds:$d), (ins Preds:$a), "mov.pred\t$d, $a", []>; - def MOVrr - : InstPTX<(outs RRegs32:$d), (ins RRegs32:$a), "mov.%type\t$d, $a", []>; + def MOVU16rr + : InstPTX<(outs RRegu16:$d), (ins RRegu16:$a), "mov.u16\t$d, $a", []>; + def MOVU32rr + : InstPTX<(outs RRegu32:$d), (ins RRegu32:$a), "mov.u32\t$d, $a", []>; + def MOVU64rr + : InstPTX<(outs RRegu64:$d), (ins RRegu64:$a), "mov.u64\t$d, $a", []>; + def MOVF32rr + : InstPTX<(outs RRegf32:$d), (ins RRegf32:$a), "mov.f32\t$d, $a", []>; + def MOVF64rr + : InstPTX<(outs RRegf64:$d), (ins RRegf64:$a), "mov.f64\t$d, $a", []>; } let isReMaterializable = 1, isAsCheapAsAMove = 1 in { - def MOVpi + def MOVPREDri : InstPTX<(outs Preds:$d), (ins i1imm:$a), "mov.pred\t$d, $a", [(set Preds:$d, imm:$a)]>; - def MOVri - : InstPTX<(outs RRegs32:$d), (ins i32imm:$a), "mov.s32\t$d, $a", - [(set RRegs32:$d, imm:$a)]>; + def MOVU16ri + : InstPTX<(outs RRegu16:$d), (ins i16imm:$a), "mov.u16\t$d, $a", + [(set RRegu16:$d, imm:$a)]>; + def MOVU32ri + : InstPTX<(outs RRegu32:$d), (ins i32imm:$a), "mov.u32\t$d, $a", + [(set RRegu32:$d, imm:$a)]>; + def MOVU64ri + : InstPTX<(outs RRegu64:$d), (ins i64imm:$a), "mov.u64\t$d, $a", + [(set RRegu64:$d, imm:$a)]>; + def MOVF32ri + : InstPTX<(outs RRegf32:$d), (ins f32imm:$a), "mov.f32\t$d, $a", + [(set RRegf32:$d, fpimm:$a)]>; + def MOVF64ri + : InstPTX<(outs RRegf64:$d), (ins f64imm:$a), "mov.f64\t$d, $a", + [(set RRegf64:$d, fpimm:$a)]>; } -defm LDg : PTX_LD<"ld.global", RRegs32, load_global>; -defm LDc : PTX_LD<"ld.const", RRegs32, load_constant>; -defm LDl : PTX_LD<"ld.local", RRegs32, load_local>; -defm LDp : PTX_LD<"ld.param", RRegs32, load_parameter>; -defm LDs : PTX_LD<"ld.shared", RRegs32, load_shared>; +let isReMaterializable = 1, isAsCheapAsAMove = 1 in { + def MOVaddr32 + : InstPTX<(outs RRegu32:$d), (ins i32imm:$a), "mov.u32\t$d, $a", + [(set RRegu32:$d, (PTXcopyaddress tglobaladdr:$a))]>; + def MOVaddr64 + : InstPTX<(outs RRegu64:$d), (ins i64imm:$a), "mov.u64\t$d, $a", + [(set RRegu64:$d, (PTXcopyaddress tglobaladdr:$a))]>; +} -def LDpi : InstPTX<(outs RRegs32:$d), (ins MEMpi:$a), - "ld.param.%type\t$d, [$a]", []>; +// Loads +defm LDg : PTX_LD_ALL<"ld.global", load_global>; +defm LDc : PTX_LD_ALL<"ld.const", load_constant>; +defm LDl : PTX_LD_ALL<"ld.local", load_local>; +defm LDs : PTX_LD_ALL<"ld.shared", load_shared>; -defm STg : PTX_ST<"st.global", RRegs32, store_global>; -defm STl : PTX_ST<"st.local", RRegs32, store_local>; -// Store to parameter state space requires PTX 2.0 or higher? -// defm STp : PTX_ST<"st.param", RRegs32, store_parameter>; -defm STs : PTX_ST<"st.shared", RRegs32, store_shared>; +// This is a special instruction that is manually inserted for kernel parameters +def LDpiU16 : InstPTX<(outs RRegu16:$d), (ins MEMpi:$a), + "ld.param.u16\t$d, [$a]", []>; +def LDpiU32 : InstPTX<(outs RRegu32:$d), (ins MEMpi:$a), + "ld.param.u32\t$d, [$a]", []>; +def LDpiU64 : InstPTX<(outs RRegu64:$d), (ins MEMpi:$a), + "ld.param.u64\t$d, [$a]", []>; +def LDpiF32 : InstPTX<(outs RRegf32:$d), (ins MEMpi:$a), + "ld.param.f32\t$d, [$a]", []>; +def LDpiF64 : InstPTX<(outs RRegf64:$d), (ins MEMpi:$a), + "ld.param.f64\t$d, [$a]", []>; + +// Stores +defm STg : PTX_ST_ALL<"st.global", store_global>; +defm STl : PTX_ST_ALL<"st.local", store_local>; +defm STs : PTX_ST_ALL<"st.shared", store_shared>; + +// defm STp : PTX_ST_ALL<"st.param", store_parameter>; +// defm LDp : PTX_LD_ALL<"ld.param", load_parameter>; +// TODO: Do something with st.param if/when it is needed. + +// Conversion to pred + +def CVT_pred_u16 + : InstPTX<(outs Preds:$d), (ins RRegu16:$a), "cvt.pred.u16\t$d, $a", + [(set Preds:$d, (trunc RRegu16:$a))]>; + +def CVT_pred_u32 + : InstPTX<(outs Preds:$d), (ins RRegu32:$a), "cvt.pred.u32\t$d, $a", + [(set Preds:$d, (trunc RRegu32:$a))]>; + +def CVT_pred_u64 + : InstPTX<(outs Preds:$d), (ins RRegu64:$a), "cvt.pred.u64\t$d, $a", + [(set Preds:$d, (trunc RRegu64:$a))]>; + +def CVT_pred_f32 + : InstPTX<(outs Preds:$d), (ins RRegf32:$a), "cvt.rni.pred.f32\t$d, $a", + [(set Preds:$d, (fp_to_uint RRegf32:$a))]>; + +def CVT_pred_f64 + : InstPTX<(outs Preds:$d), (ins RRegf64:$a), "cvt.rni.pred.f64\t$d, $a", + [(set Preds:$d, (fp_to_uint RRegf64:$a))]>; + +// Conversion to u16 + +def CVT_u16_pred + : InstPTX<(outs RRegu16:$d), (ins Preds:$a), "cvt.u16.pred\t$d, $a", + [(set RRegu16:$d, (zext Preds:$a))]>; + +def CVT_u16_u32 + : InstPTX<(outs RRegu16:$d), (ins RRegu32:$a), "cvt.u16.u32\t$d, $a", + [(set RRegu16:$d, (trunc RRegu32:$a))]>; + +def CVT_u16_u64 + : InstPTX<(outs RRegu16:$d), (ins RRegu64:$a), "cvt.u16.u64\t$d, $a", + [(set RRegu16:$d, (trunc RRegu64:$a))]>; + +def CVT_u16_f32 + : InstPTX<(outs RRegu16:$d), (ins RRegf32:$a), "cvt.rni.u16.f32\t$d, $a", + [(set RRegu16:$d, (fp_to_uint RRegf32:$a))]>; + +def CVT_u16_f64 + : InstPTX<(outs RRegu16:$d), (ins RRegf64:$a), "cvt.rni.u16.f64\t$d, $a", + [(set RRegu16:$d, (fp_to_uint RRegf64:$a))]>; + +// Conversion to u32 + +def CVT_u32_pred + : InstPTX<(outs RRegu32:$d), (ins Preds:$a), "cvt.u32.pred\t$d, $a", + [(set RRegu32:$d, (zext Preds:$a))]>; + +def CVT_u32_u16 + : InstPTX<(outs RRegu32:$d), (ins RRegu16:$a), "cvt.u32.u16\t$d, $a", + [(set RRegu32:$d, (zext RRegu16:$a))]>; + +def CVT_u32_u64 + : InstPTX<(outs RRegu32:$d), (ins RRegu64:$a), "cvt.u32.u64\t$d, $a", + [(set RRegu32:$d, (trunc RRegu64:$a))]>; + +def CVT_u32_f32 + : InstPTX<(outs RRegu32:$d), (ins RRegf32:$a), "cvt.rni.u32.f32\t$d, $a", + [(set RRegu32:$d, (fp_to_uint RRegf32:$a))]>; + +def CVT_u32_f64 + : InstPTX<(outs RRegu32:$d), (ins RRegf64:$a), "cvt.rni.u32.f64\t$d, $a", + [(set RRegu32:$d, (fp_to_uint RRegf64:$a))]>; + +// Conversion to u64 + +def CVT_u64_pred + : InstPTX<(outs RRegu64:$d), (ins Preds:$a), "cvt.u64.pred\t$d, $a", + [(set RRegu64:$d, (zext Preds:$a))]>; + +def CVT_u64_u16 + : InstPTX<(outs RRegu64:$d), (ins RRegu16:$a), "cvt.u64.u16\t$d, $a", + [(set RRegu64:$d, (zext RRegu16:$a))]>; + +def CVT_u64_u32 + : InstPTX<(outs RRegu64:$d), (ins RRegu32:$a), "cvt.u64.u32\t$d, $a", + [(set RRegu64:$d, (zext RRegu32:$a))]>; + +def CVT_u64_f32 + : InstPTX<(outs RRegu64:$d), (ins RRegf32:$a), "cvt.rni.u64.f32\t$d, $a", + [(set RRegu64:$d, (fp_to_uint RRegf32:$a))]>; + +def CVT_u64_f64 + : InstPTX<(outs RRegu64:$d), (ins RRegf64:$a), "cvt.rni.u64.f64\t$d, $a", + [(set RRegu64:$d, (fp_to_uint RRegf64:$a))]>; + +// Conversion to f32 + +def CVT_f32_pred + : InstPTX<(outs RRegf32:$d), (ins Preds:$a), "cvt.rn.f32.pred\t$d, $a", + [(set RRegf32:$d, (uint_to_fp Preds:$a))]>; + +def CVT_f32_u16 + : InstPTX<(outs RRegf32:$d), (ins RRegu16:$a), "cvt.rn.f32.u16\t$d, $a", + [(set RRegf32:$d, (uint_to_fp RRegu16:$a))]>; + +def CVT_f32_u32 + : InstPTX<(outs RRegf32:$d), (ins RRegu32:$a), "cvt.rn.f32.u32\t$d, $a", + [(set RRegf32:$d, (uint_to_fp RRegu32:$a))]>; + +def CVT_f32_u64 + : InstPTX<(outs RRegf32:$d), (ins RRegu64:$a), "cvt.rn.f32.u64\t$d, $a", + [(set RRegf32:$d, (uint_to_fp RRegu64:$a))]>; + +def CVT_f32_f64 + : InstPTX<(outs RRegf32:$d), (ins RRegf64:$a), "cvt.rn.f32.f64\t$d, $a", + [(set RRegf32:$d, (fround RRegf64:$a))]>; + +// Conversion to f64 + +def CVT_f64_pred + : InstPTX<(outs RRegf64:$d), (ins Preds:$a), "cvt.rn.f64.pred\t$d, $a", + [(set RRegf64:$d, (uint_to_fp Preds:$a))]>; + +def CVT_f64_u16 + : InstPTX<(outs RRegf64:$d), (ins RRegu16:$a), "cvt.rn.f64.u16\t$d, $a", + [(set RRegf64:$d, (uint_to_fp RRegu16:$a))]>; + +def CVT_f64_u32 + : InstPTX<(outs RRegf64:$d), (ins RRegu32:$a), "cvt.rn.f64.u32\t$d, $a", + [(set RRegf64:$d, (uint_to_fp RRegu32:$a))]>; + +def CVT_f64_u64 + : InstPTX<(outs RRegf64:$d), (ins RRegu64:$a), "cvt.rn.f64.u64\t$d, $a", + [(set RRegf64:$d, (uint_to_fp RRegu64:$a))]>; + +def CVT_f64_f32 + : InstPTX<(outs RRegf64:$d), (ins RRegf32:$a), "cvt.f64.f32\t$d, $a", + [(set RRegf64:$d, (fextend RRegf32:$a))]>; ///===- Control Flow Instructions -----------------------------------------===// +let isBranch = 1, isTerminator = 1, isBarrier = 1 in { + def BRAd + : InstPTX<(outs), (ins brtarget:$d), "bra\t$d", [(br bb:$d)]>; +} + +let isBranch = 1, isTerminator = 1 in { + // FIXME: The pattern part is blank because I cannot (or do not yet know + // how to) use the first operand of PredicateOperand (a Preds register) here + def BRAdp + : InstPTX<(outs), (ins brtarget:$d), "bra\t$d", + [/*(brcond pred:$_p, bb:$d)*/]>; +} + let isReturn = 1, isTerminator = 1, isBarrier = 1 in { def EXIT : InstPTX<(outs), (ins), "exit", [(PTXexit)]>; def RET : InstPTX<(outs), (ins), "ret", [(PTXret)]>; } + +///===- Intrinsic Instructions --------------------------------------------===// + +include "PTXIntrinsicInstrInfo.td" diff --git a/contrib/llvm/lib/Target/PTX/PTXIntrinsicInstrInfo.td b/contrib/llvm/lib/Target/PTX/PTXIntrinsicInstrInfo.td new file mode 100644 index 000000000000..320934a2228c --- /dev/null +++ b/contrib/llvm/lib/Target/PTX/PTXIntrinsicInstrInfo.td @@ -0,0 +1,84 @@ +//===- PTXIntrinsicInstrInfo.td - Defines PTX 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 PTX-specific intrinsic instructions. +// +//===----------------------------------------------------------------------===// + +// PTX Special Purpose Register Accessor Intrinsics + +class PTX_READ_SPECIAL_REGISTER_R64 + : InstPTX<(outs RRegu64:$d), (ins), + !strconcat("mov.u64\t$d, %", regname), + [(set RRegu64:$d, (intop))]>; + +class PTX_READ_SPECIAL_REGISTER_R32 + : InstPTX<(outs RRegu32:$d), (ins), + !strconcat("mov.u32\t$d, %", regname), + [(set RRegu32:$d, (intop))]>; + +// TODO Add read vector-version of special registers + +//def PTX_READ_TID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"tid", int_ptx_read_tid_r64>; +def PTX_READ_TID_X : PTX_READ_SPECIAL_REGISTER_R32<"tid.x", int_ptx_read_tid_x>; +def PTX_READ_TID_Y : PTX_READ_SPECIAL_REGISTER_R32<"tid.y", int_ptx_read_tid_y>; +def PTX_READ_TID_Z : PTX_READ_SPECIAL_REGISTER_R32<"tid.z", int_ptx_read_tid_z>; +def PTX_READ_TID_W : PTX_READ_SPECIAL_REGISTER_R32<"tid.w", int_ptx_read_tid_w>; + +//def PTX_READ_NTID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"ntid", int_ptx_read_ntid_r64>; +def PTX_READ_NTID_X : PTX_READ_SPECIAL_REGISTER_R32<"ntid.x", int_ptx_read_ntid_x>; +def PTX_READ_NTID_Y : PTX_READ_SPECIAL_REGISTER_R32<"ntid.y", int_ptx_read_ntid_y>; +def PTX_READ_NTID_Z : PTX_READ_SPECIAL_REGISTER_R32<"ntid.z", int_ptx_read_ntid_z>; +def PTX_READ_NTID_W : PTX_READ_SPECIAL_REGISTER_R32<"ntid.w", int_ptx_read_ntid_w>; + +def PTX_READ_LANEID : PTX_READ_SPECIAL_REGISTER_R32<"laneid", int_ptx_read_laneid>; +def PTX_READ_WARPID : PTX_READ_SPECIAL_REGISTER_R32<"warpid", int_ptx_read_warpid>; +def PTX_READ_NWARPID : PTX_READ_SPECIAL_REGISTER_R32<"nwarpid", int_ptx_read_nwarpid>; + +//def PTX_READ_CTAID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"ctaid", int_ptx_read_ctaid_r64>; +def PTX_READ_CTAID_X : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.x", int_ptx_read_ctaid_x>; +def PTX_READ_CTAID_Y : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.y", int_ptx_read_ctaid_y>; +def PTX_READ_CTAID_Z : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.z", int_ptx_read_ctaid_z>; +def PTX_READ_CTAID_W : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.w", int_ptx_read_ctaid_w>; + +//def PTX_READ_NCTAID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"nctaid", int_ptx_read_nctaid_r64>; +def PTX_READ_NCTAID_X : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.x", int_ptx_read_nctaid_x>; +def PTX_READ_NCTAID_Y : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.y", int_ptx_read_nctaid_y>; +def PTX_READ_NCTAID_Z : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.z", int_ptx_read_nctaid_z>; +def PTX_READ_NCTAID_W : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.w", int_ptx_read_nctaid_w>; + +def PTX_READ_SMID : PTX_READ_SPECIAL_REGISTER_R32<"smid", int_ptx_read_smid>; +def PTX_READ_NSMID : PTX_READ_SPECIAL_REGISTER_R32<"nsmid", int_ptx_read_nsmid>; +def PTX_READ_GRIDID : PTX_READ_SPECIAL_REGISTER_R32<"gridid", int_ptx_read_gridid>; + +def PTX_READ_LANEMASK_EQ + : PTX_READ_SPECIAL_REGISTER_R32<"lanemask_eq", int_ptx_read_lanemask_eq>; +def PTX_READ_LANEMASK_LE + : PTX_READ_SPECIAL_REGISTER_R32<"lanemask_le", int_ptx_read_lanemask_le>; +def PTX_READ_LANEMASK_LT + : PTX_READ_SPECIAL_REGISTER_R32<"lanemask_lt", int_ptx_read_lanemask_lt>; +def PTX_READ_LANEMASK_GE + : PTX_READ_SPECIAL_REGISTER_R32<"lanemask_ge", int_ptx_read_lanemask_ge>; +def PTX_READ_LANEMASK_GT + : PTX_READ_SPECIAL_REGISTER_R32<"lanemask_gt", int_ptx_read_lanemask_gt>; + +def PTX_READ_CLOCK + : PTX_READ_SPECIAL_REGISTER_R32<"clock", int_ptx_read_clock>; +def PTX_READ_CLOCK64 + : PTX_READ_SPECIAL_REGISTER_R64<"clock64", int_ptx_read_clock64>; + +def PTX_READ_PM0 : PTX_READ_SPECIAL_REGISTER_R32<"pm0", int_ptx_read_pm0>; +def PTX_READ_PM1 : PTX_READ_SPECIAL_REGISTER_R32<"pm1", int_ptx_read_pm1>; +def PTX_READ_PM2 : PTX_READ_SPECIAL_REGISTER_R32<"pm2", int_ptx_read_pm2>; +def PTX_READ_PM3 : PTX_READ_SPECIAL_REGISTER_R32<"pm3", int_ptx_read_pm3>; + +// PTX Parallel Synchronization and Communication Intrinsics + +def PTX_BAR_SYNC : InstPTX<(outs), (ins i32imm:$i), "bar.sync\t$i", + [(int_ptx_bar_sync imm:$i)]>; diff --git a/contrib/llvm/lib/Target/PTX/PTXMCAsmStreamer.cpp b/contrib/llvm/lib/Target/PTX/PTXMCAsmStreamer.cpp index 0886ba8008f3..1574670b6e9b 100644 --- a/contrib/llvm/lib/Target/PTX/PTXMCAsmStreamer.cpp +++ b/contrib/llvm/lib/Target/PTX/PTXMCAsmStreamer.cpp @@ -143,9 +143,9 @@ class PTXMCAsmStreamer : public MCStreamer { virtual void EmitBytes(StringRef Data, unsigned AddrSpace); virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - bool isPCRel, unsigned AddrSpace); - virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); - virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + unsigned AddrSpace); + virtual void EmitULEB128Value(const MCExpr *Value); + virtual void EmitSLEB128Value(const MCExpr *Value); virtual void EmitGPRel32Value(const MCExpr *Value); @@ -233,7 +233,7 @@ void PTXMCAsmStreamer::ChangeSection(const MCSection *Section) { void PTXMCAsmStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection() && "Cannot emit before setting section!"); + //assert(getCurrentSection() && "Cannot emit before setting section!"); OS << *Symbol << MAI.getLabelSuffix(); EmitEOL(); @@ -352,9 +352,8 @@ void PTXMCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { } void PTXMCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - bool isPCRel, unsigned AddrSpace) { + unsigned AddrSpace) { assert(getCurrentSection() && "Cannot emit contents before setting section!"); - assert(!isPCRel && "Cannot emit pc relative relocations!"); const char *Directive = 0; switch (Size) { default: break; @@ -383,15 +382,13 @@ void PTXMCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, EmitEOL(); } -void PTXMCAsmStreamer::EmitULEB128Value(const MCExpr *Value, - unsigned AddrSpace) { +void PTXMCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { assert(MAI.hasLEB128() && "Cannot print a .uleb"); OS << ".uleb128 " << *Value; EmitEOL(); } -void PTXMCAsmStreamer::EmitSLEB128Value(const MCExpr *Value, - unsigned AddrSpace) { +void PTXMCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { assert(MAI.hasLEB128() && "Cannot print a .sleb"); OS << ".sleb128 " << *Value; EmitEOL(); @@ -423,7 +420,8 @@ void PTXMCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace); } -void PTXMCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, +void PTXMCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, + int64_t Value, unsigned ValueSize, unsigned MaxBytesToEmit) { // Some assemblers don't support non-power of two alignments, so we always @@ -532,7 +530,7 @@ void PTXMCAsmStreamer::Finish() {} namespace llvm { MCStreamer *createPTXAsmStreamer(MCContext &Context, formatted_raw_ostream &OS, - bool isVerboseAsm, bool useLoc, + bool isVerboseAsm, bool useLoc, bool useCFI, MCInstPrinter *IP, MCCodeEmitter *CE, TargetAsmBackend *TAB, bool ShowInst) { diff --git a/contrib/llvm/lib/Target/PTX/PTXMFInfoExtract.cpp b/contrib/llvm/lib/Target/PTX/PTXMFInfoExtract.cpp index b37c740006f9..c5e191007239 100644 --- a/contrib/llvm/lib/Target/PTX/PTXMFInfoExtract.cpp +++ b/contrib/llvm/lib/Target/PTX/PTXMFInfoExtract.cpp @@ -79,12 +79,12 @@ bool PTXMFInfoExtract::runOnMachineFunction(MachineFunction &MF) { DEBUG(for (PTXMachineFunctionInfo::reg_iterator i = MFI->argRegBegin(), e = MFI->argRegEnd(); - i != e; ++i) + i != e; ++i) dbgs() << "Arg Reg: " << *i << "\n";); DEBUG(for (PTXMachineFunctionInfo::reg_iterator i = MFI->localVarRegBegin(), e = MFI->localVarRegEnd(); - i != e; ++i) + i != e; ++i) dbgs() << "Local Var Reg: " << *i << "\n";); return false; diff --git a/contrib/llvm/lib/Target/PTX/PTXMachineFunctionInfo.h b/contrib/llvm/lib/Target/PTX/PTXMachineFunctionInfo.h index 56d044b5fc0d..81df1c236cb2 100644 --- a/contrib/llvm/lib/Target/PTX/PTXMachineFunctionInfo.h +++ b/contrib/llvm/lib/Target/PTX/PTXMachineFunctionInfo.h @@ -42,36 +42,37 @@ class PTXMachineFunctionInfo : public MachineFunctionInfo { void setRetReg(unsigned reg) { reg_ret = reg; } void doneAddArg(void) { - std::sort(reg_arg.begin(), reg_arg.end()); _isDoneAddArg = true; } - void doneAddLocalVar(void) { - std::sort(reg_local_var.begin(), reg_local_var.end()); - } + void doneAddLocalVar(void) {} bool isDoneAddArg(void) { return _isDoneAddArg; } bool isKernel() const { return is_kernel; } - typedef std::vector::const_iterator reg_iterator; + typedef std::vector::const_iterator reg_iterator; + typedef std::vector::const_reverse_iterator reg_reverse_iterator; - bool argRegEmpty() const { return reg_arg.empty(); } - int getNumArg() const { return reg_arg.size(); } + bool argRegEmpty() const { return reg_arg.empty(); } + int getNumArg() const { return reg_arg.size(); } reg_iterator argRegBegin() const { return reg_arg.begin(); } reg_iterator argRegEnd() const { return reg_arg.end(); } + reg_reverse_iterator argRegReverseBegin() const { return reg_arg.rbegin(); } + reg_reverse_iterator argRegReverseEnd() const { return reg_arg.rend(); } - bool localVarRegEmpty() const { return reg_local_var.empty(); } + bool localVarRegEmpty() const { return reg_local_var.empty(); } reg_iterator localVarRegBegin() const { return reg_local_var.begin(); } reg_iterator localVarRegEnd() const { return reg_local_var.end(); } unsigned retReg() const { return reg_ret; } bool isArgReg(unsigned reg) const { - return std::binary_search(reg_arg.begin(), reg_arg.end(), reg); + return std::find(reg_arg.begin(), reg_arg.end(), reg) != reg_arg.end(); } bool isLocalVarReg(unsigned reg) const { - return std::binary_search(reg_local_var.begin(), reg_local_var.end(), reg); + return std::find(reg_local_var.begin(), reg_local_var.end(), reg) + != reg_local_var.end(); } }; // class PTXMachineFunctionInfo } // namespace llvm diff --git a/contrib/llvm/lib/Target/PTX/PTXRegisterInfo.td b/contrib/llvm/lib/Target/PTX/PTXRegisterInfo.td index 22e2b343a0e5..f6161419fec1 100644 --- a/contrib/llvm/lib/Target/PTX/PTXRegisterInfo.td +++ b/contrib/llvm/lib/Target/PTX/PTXRegisterInfo.td @@ -19,6 +19,8 @@ class PTXReg : Register { // Registers //===----------------------------------------------------------------------===// +///===- Predicate Registers -----------------------------------------------===// + def P0 : PTXReg<"p0">; def P1 : PTXReg<"p1">; def P2 : PTXReg<"p2">; @@ -51,6 +53,108 @@ def P28 : PTXReg<"p28">; def P29 : PTXReg<"p29">; def P30 : PTXReg<"p30">; def P31 : PTXReg<"p31">; +def P32 : PTXReg<"p32">; +def P33 : PTXReg<"p33">; +def P34 : PTXReg<"p34">; +def P35 : PTXReg<"p35">; +def P36 : PTXReg<"p36">; +def P37 : PTXReg<"p37">; +def P38 : PTXReg<"p38">; +def P39 : PTXReg<"p39">; +def P40 : PTXReg<"p40">; +def P41 : PTXReg<"p41">; +def P42 : PTXReg<"p42">; +def P43 : PTXReg<"p43">; +def P44 : PTXReg<"p44">; +def P45 : PTXReg<"p45">; +def P46 : PTXReg<"p46">; +def P47 : PTXReg<"p47">; +def P48 : PTXReg<"p48">; +def P49 : PTXReg<"p49">; +def P50 : PTXReg<"p50">; +def P51 : PTXReg<"p51">; +def P52 : PTXReg<"p52">; +def P53 : PTXReg<"p53">; +def P54 : PTXReg<"p54">; +def P55 : PTXReg<"p55">; +def P56 : PTXReg<"p56">; +def P57 : PTXReg<"p57">; +def P58 : PTXReg<"p58">; +def P59 : PTXReg<"p59">; +def P60 : PTXReg<"p60">; +def P61 : PTXReg<"p61">; +def P62 : PTXReg<"p62">; +def P63 : PTXReg<"p63">; + +///===- 16-bit Integer Registers ------------------------------------------===// + +def RH0 : PTXReg<"rh0">; +def RH1 : PTXReg<"rh1">; +def RH2 : PTXReg<"rh2">; +def RH3 : PTXReg<"rh3">; +def RH4 : PTXReg<"rh4">; +def RH5 : PTXReg<"rh5">; +def RH6 : PTXReg<"rh6">; +def RH7 : PTXReg<"rh7">; +def RH8 : PTXReg<"rh8">; +def RH9 : PTXReg<"rh9">; +def RH10 : PTXReg<"rh10">; +def RH11 : PTXReg<"rh11">; +def RH12 : PTXReg<"rh12">; +def RH13 : PTXReg<"rh13">; +def RH14 : PTXReg<"rh14">; +def RH15 : PTXReg<"rh15">; +def RH16 : PTXReg<"rh16">; +def RH17 : PTXReg<"rh17">; +def RH18 : PTXReg<"rh18">; +def RH19 : PTXReg<"rh19">; +def RH20 : PTXReg<"rh20">; +def RH21 : PTXReg<"rh21">; +def RH22 : PTXReg<"rh22">; +def RH23 : PTXReg<"rh23">; +def RH24 : PTXReg<"rh24">; +def RH25 : PTXReg<"rh25">; +def RH26 : PTXReg<"rh26">; +def RH27 : PTXReg<"rh27">; +def RH28 : PTXReg<"rh28">; +def RH29 : PTXReg<"rh29">; +def RH30 : PTXReg<"rh30">; +def RH31 : PTXReg<"rh31">; +def RH32 : PTXReg<"rh32">; +def RH33 : PTXReg<"rh33">; +def RH34 : PTXReg<"rh34">; +def RH35 : PTXReg<"rh35">; +def RH36 : PTXReg<"rh36">; +def RH37 : PTXReg<"rh37">; +def RH38 : PTXReg<"rh38">; +def RH39 : PTXReg<"rh39">; +def RH40 : PTXReg<"rh40">; +def RH41 : PTXReg<"rh41">; +def RH42 : PTXReg<"rh42">; +def RH43 : PTXReg<"rh43">; +def RH44 : PTXReg<"rh44">; +def RH45 : PTXReg<"rh45">; +def RH46 : PTXReg<"rh46">; +def RH47 : PTXReg<"rh47">; +def RH48 : PTXReg<"rh48">; +def RH49 : PTXReg<"rh49">; +def RH50 : PTXReg<"rh50">; +def RH51 : PTXReg<"rh51">; +def RH52 : PTXReg<"rh52">; +def RH53 : PTXReg<"rh53">; +def RH54 : PTXReg<"rh54">; +def RH55 : PTXReg<"rh55">; +def RH56 : PTXReg<"rh56">; +def RH57 : PTXReg<"rh57">; +def RH58 : PTXReg<"rh58">; +def RH59 : PTXReg<"rh59">; +def RH60 : PTXReg<"rh60">; +def RH61 : PTXReg<"rh61">; +def RH62 : PTXReg<"rh62">; +def RH63 : PTXReg<"rh63">; + + +///===- 32-bit Integer Registers ------------------------------------------===// def R0 : PTXReg<"r0">; def R1 : PTXReg<"r1">; @@ -84,6 +188,243 @@ def R28 : PTXReg<"r28">; def R29 : PTXReg<"r29">; def R30 : PTXReg<"r30">; def R31 : PTXReg<"r31">; +def R32 : PTXReg<"r32">; +def R33 : PTXReg<"r33">; +def R34 : PTXReg<"r34">; +def R35 : PTXReg<"r35">; +def R36 : PTXReg<"r36">; +def R37 : PTXReg<"r37">; +def R38 : PTXReg<"r38">; +def R39 : PTXReg<"r39">; +def R40 : PTXReg<"r40">; +def R41 : PTXReg<"r41">; +def R42 : PTXReg<"r42">; +def R43 : PTXReg<"r43">; +def R44 : PTXReg<"r44">; +def R45 : PTXReg<"r45">; +def R46 : PTXReg<"r46">; +def R47 : PTXReg<"r47">; +def R48 : PTXReg<"r48">; +def R49 : PTXReg<"r49">; +def R50 : PTXReg<"r50">; +def R51 : PTXReg<"r51">; +def R52 : PTXReg<"r52">; +def R53 : PTXReg<"r53">; +def R54 : PTXReg<"r54">; +def R55 : PTXReg<"r55">; +def R56 : PTXReg<"r56">; +def R57 : PTXReg<"r57">; +def R58 : PTXReg<"r58">; +def R59 : PTXReg<"r59">; +def R60 : PTXReg<"r60">; +def R61 : PTXReg<"r61">; +def R62 : PTXReg<"r62">; +def R63 : PTXReg<"r63">; + + +///===- 64-bit Integer Registers ------------------------------------------===// + +def RD0 : PTXReg<"rd0">; +def RD1 : PTXReg<"rd1">; +def RD2 : PTXReg<"rd2">; +def RD3 : PTXReg<"rd3">; +def RD4 : PTXReg<"rd4">; +def RD5 : PTXReg<"rd5">; +def RD6 : PTXReg<"rd6">; +def RD7 : PTXReg<"rd7">; +def RD8 : PTXReg<"rd8">; +def RD9 : PTXReg<"rd9">; +def RD10 : PTXReg<"rd10">; +def RD11 : PTXReg<"rd11">; +def RD12 : PTXReg<"rd12">; +def RD13 : PTXReg<"rd13">; +def RD14 : PTXReg<"rd14">; +def RD15 : PTXReg<"rd15">; +def RD16 : PTXReg<"rd16">; +def RD17 : PTXReg<"rd17">; +def RD18 : PTXReg<"rd18">; +def RD19 : PTXReg<"rd19">; +def RD20 : PTXReg<"rd20">; +def RD21 : PTXReg<"rd21">; +def RD22 : PTXReg<"rd22">; +def RD23 : PTXReg<"rd23">; +def RD24 : PTXReg<"rd24">; +def RD25 : PTXReg<"rd25">; +def RD26 : PTXReg<"rd26">; +def RD27 : PTXReg<"rd27">; +def RD28 : PTXReg<"rd28">; +def RD29 : PTXReg<"rd29">; +def RD30 : PTXReg<"rd30">; +def RD31 : PTXReg<"rd31">; +def RD32 : PTXReg<"rd32">; +def RD33 : PTXReg<"rd33">; +def RD34 : PTXReg<"rd34">; +def RD35 : PTXReg<"rd35">; +def RD36 : PTXReg<"rd36">; +def RD37 : PTXReg<"rd37">; +def RD38 : PTXReg<"rd38">; +def RD39 : PTXReg<"rd39">; +def RD40 : PTXReg<"rd40">; +def RD41 : PTXReg<"rd41">; +def RD42 : PTXReg<"rd42">; +def RD43 : PTXReg<"rd43">; +def RD44 : PTXReg<"rd44">; +def RD45 : PTXReg<"rd45">; +def RD46 : PTXReg<"rd46">; +def RD47 : PTXReg<"rd47">; +def RD48 : PTXReg<"rd48">; +def RD49 : PTXReg<"rd49">; +def RD50 : PTXReg<"rd50">; +def RD51 : PTXReg<"rd51">; +def RD52 : PTXReg<"rd52">; +def RD53 : PTXReg<"rd53">; +def RD54 : PTXReg<"rd54">; +def RD55 : PTXReg<"rd55">; +def RD56 : PTXReg<"rd56">; +def RD57 : PTXReg<"rd57">; +def RD58 : PTXReg<"rd58">; +def RD59 : PTXReg<"rd59">; +def RD60 : PTXReg<"rd60">; +def RD61 : PTXReg<"rd61">; +def RD62 : PTXReg<"rd62">; +def RD63 : PTXReg<"rd63">; + + +///===- 32-bit Floating-Point Registers -----------------------------------===// + +def F0 : PTXReg<"f0">; +def F1 : PTXReg<"f1">; +def F2 : PTXReg<"f2">; +def F3 : PTXReg<"f3">; +def F4 : PTXReg<"f4">; +def F5 : PTXReg<"f5">; +def F6 : PTXReg<"f6">; +def F7 : PTXReg<"f7">; +def F8 : PTXReg<"f8">; +def F9 : PTXReg<"f9">; +def F10 : PTXReg<"f10">; +def F11 : PTXReg<"f11">; +def F12 : PTXReg<"f12">; +def F13 : PTXReg<"f13">; +def F14 : PTXReg<"f14">; +def F15 : PTXReg<"f15">; +def F16 : PTXReg<"f16">; +def F17 : PTXReg<"f17">; +def F18 : PTXReg<"f18">; +def F19 : PTXReg<"f19">; +def F20 : PTXReg<"f20">; +def F21 : PTXReg<"f21">; +def F22 : PTXReg<"f22">; +def F23 : PTXReg<"f23">; +def F24 : PTXReg<"f24">; +def F25 : PTXReg<"f25">; +def F26 : PTXReg<"f26">; +def F27 : PTXReg<"f27">; +def F28 : PTXReg<"f28">; +def F29 : PTXReg<"f29">; +def F30 : PTXReg<"f30">; +def F31 : PTXReg<"f31">; +def F32 : PTXReg<"f32">; +def F33 : PTXReg<"f33">; +def F34 : PTXReg<"f34">; +def F35 : PTXReg<"f35">; +def F36 : PTXReg<"f36">; +def F37 : PTXReg<"f37">; +def F38 : PTXReg<"f38">; +def F39 : PTXReg<"f39">; +def F40 : PTXReg<"f40">; +def F41 : PTXReg<"f41">; +def F42 : PTXReg<"f42">; +def F43 : PTXReg<"f43">; +def F44 : PTXReg<"f44">; +def F45 : PTXReg<"f45">; +def F46 : PTXReg<"f46">; +def F47 : PTXReg<"f47">; +def F48 : PTXReg<"f48">; +def F49 : PTXReg<"f49">; +def F50 : PTXReg<"f50">; +def F51 : PTXReg<"f51">; +def F52 : PTXReg<"f52">; +def F53 : PTXReg<"f53">; +def F54 : PTXReg<"f54">; +def F55 : PTXReg<"f55">; +def F56 : PTXReg<"f56">; +def F57 : PTXReg<"f57">; +def F58 : PTXReg<"f58">; +def F59 : PTXReg<"f59">; +def F60 : PTXReg<"f60">; +def F61 : PTXReg<"f61">; +def F62 : PTXReg<"f62">; +def F63 : PTXReg<"f63">; + + +///===- 64-bit Floating-Point Registers -----------------------------------===// + +def FD0 : PTXReg<"fd0">; +def FD1 : PTXReg<"fd1">; +def FD2 : PTXReg<"fd2">; +def FD3 : PTXReg<"fd3">; +def FD4 : PTXReg<"fd4">; +def FD5 : PTXReg<"fd5">; +def FD6 : PTXReg<"fd6">; +def FD7 : PTXReg<"fd7">; +def FD8 : PTXReg<"fd8">; +def FD9 : PTXReg<"fd9">; +def FD10 : PTXReg<"fd10">; +def FD11 : PTXReg<"fd11">; +def FD12 : PTXReg<"fd12">; +def FD13 : PTXReg<"fd13">; +def FD14 : PTXReg<"fd14">; +def FD15 : PTXReg<"fd15">; +def FD16 : PTXReg<"fd16">; +def FD17 : PTXReg<"fd17">; +def FD18 : PTXReg<"fd18">; +def FD19 : PTXReg<"fd19">; +def FD20 : PTXReg<"fd20">; +def FD21 : PTXReg<"fd21">; +def FD22 : PTXReg<"fd22">; +def FD23 : PTXReg<"fd23">; +def FD24 : PTXReg<"fd24">; +def FD25 : PTXReg<"fd25">; +def FD26 : PTXReg<"fd26">; +def FD27 : PTXReg<"fd27">; +def FD28 : PTXReg<"fd28">; +def FD29 : PTXReg<"fd29">; +def FD30 : PTXReg<"fd30">; +def FD31 : PTXReg<"fd31">; +def FD32 : PTXReg<"fd32">; +def FD33 : PTXReg<"fd33">; +def FD34 : PTXReg<"fd34">; +def FD35 : PTXReg<"fd35">; +def FD36 : PTXReg<"fd36">; +def FD37 : PTXReg<"fd37">; +def FD38 : PTXReg<"fd38">; +def FD39 : PTXReg<"fd39">; +def FD40 : PTXReg<"fd40">; +def FD41 : PTXReg<"fd41">; +def FD42 : PTXReg<"fd42">; +def FD43 : PTXReg<"fd43">; +def FD44 : PTXReg<"fd44">; +def FD45 : PTXReg<"fd45">; +def FD46 : PTXReg<"f4d6">; +def FD47 : PTXReg<"fd47">; +def FD48 : PTXReg<"fd48">; +def FD49 : PTXReg<"fd49">; +def FD50 : PTXReg<"fd50">; +def FD51 : PTXReg<"fd51">; +def FD52 : PTXReg<"fd52">; +def FD53 : PTXReg<"fd53">; +def FD54 : PTXReg<"fd54">; +def FD55 : PTXReg<"fd55">; +def FD56 : PTXReg<"fd56">; +def FD57 : PTXReg<"fd57">; +def FD58 : PTXReg<"fd58">; +def FD59 : PTXReg<"fd59">; +def FD60 : PTXReg<"fd60">; +def FD61 : PTXReg<"fd61">; +def FD62 : PTXReg<"fd62">; +def FD63 : PTXReg<"fd63">; + //===----------------------------------------------------------------------===// // Register classes @@ -93,10 +434,58 @@ def Preds : RegisterClass<"PTX", [i1], 8, [P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, - P24, P25, P26, P27, P28, P29, P30, P31]>; + P24, P25, P26, P27, P28, P29, P30, P31, + P32, P33, P34, P35, P36, P37, P38, P39, + P40, P41, P42, P43, P44, P45, P46, P47, + P48, P49, P50, P51, P52, P53, P54, P55, + P56, P57, P58, P59, P60, P61, P62, P63]>; -def RRegs32 : RegisterClass<"PTX", [i32], 32, +def RRegu16 : RegisterClass<"PTX", [i16], 16, + [RH0, RH1, RH2, RH3, RH4, RH5, RH6, RH7, + RH8, RH9, RH10, RH11, RH12, RH13, RH14, RH15, + RH16, RH17, RH18, RH19, RH20, RH21, RH22, RH23, + RH24, RH25, RH26, RH27, RH28, RH29, RH30, RH31, + RH32, RH33, RH34, RH35, RH36, RH37, RH38, RH39, + RH40, RH41, RH42, RH43, RH44, RH45, RH46, RH47, + RH48, RH49, RH50, RH51, RH52, RH53, RH54, RH55, + RH56, RH57, RH58, RH59, RH60, RH61, RH62, RH63]>; + +def RRegu32 : RegisterClass<"PTX", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, - R24, R25, R26, R27, R28, R29, R30, R31]>; + R24, R25, R26, R27, R28, R29, R30, R31, + R32, R33, R34, R35, R36, R37, R38, R39, + R40, R41, R42, R43, R44, R45, R46, R47, + R48, R49, R50, R51, R52, R53, R54, R55, + R56, R57, R58, R59, R60, R61, R62, R63]>; + +def RRegu64 : RegisterClass<"PTX", [i64], 64, + [RD0, RD1, RD2, RD3, RD4, RD5, RD6, RD7, + RD8, RD9, RD10, RD11, RD12, RD13, RD14, RD15, + RD16, RD17, RD18, RD19, RD20, RD21, RD22, RD23, + RD24, RD25, RD26, RD27, RD28, RD29, RD30, RD31, + RD32, RD33, RD34, RD35, RD36, RD37, RD38, RD39, + RD40, RD41, RD42, RD43, RD44, RD45, RD46, RD47, + RD48, RD49, RD50, RD51, RD52, RD53, RD54, RD55, + RD56, RD57, RD58, RD59, RD60, RD61, RD62, RD63]>; + +def RRegf32 : RegisterClass<"PTX", [f32], 32, + [F0, F1, F2, F3, F4, F5, F6, F7, + F8, F9, F10, F11, F12, F13, F14, F15, + F16, F17, F18, F19, F20, F21, F22, F23, + F24, F25, F26, F27, F28, F29, F30, F31, + F32, F33, F34, F35, F36, F37, F38, F39, + F40, F41, F42, F43, F44, F45, F46, F47, + F48, F49, F50, F51, F52, F53, F54, F55, + F56, F57, F58, F59, F60, F61, F62, F63]>; + +def RRegf64 : RegisterClass<"PTX", [f64], 64, + [FD0, FD1, FD2, FD3, FD4, FD5, FD6, FD7, + FD8, FD9, FD10, FD11, FD12, FD13, FD14, FD15, + FD16, FD17, FD18, FD19, FD20, FD21, FD22, FD23, + FD24, FD25, FD26, FD27, FD28, FD29, FD30, FD31, + FD32, FD33, FD34, FD35, FD36, FD37, FD38, FD39, + FD40, FD41, FD42, FD43, FD44, FD45, FD46, FD47, + FD48, FD49, FD50, FD51, FD52, FD53, FD54, FD55, + FD56, FD57, FD58, FD59, FD60, FD61, FD62, FD63]>; diff --git a/contrib/llvm/lib/Target/PTX/PTXSubtarget.cpp b/contrib/llvm/lib/Target/PTX/PTXSubtarget.cpp index 00e2c882a5ca..a224f2b8be1a 100644 --- a/contrib/llvm/lib/Target/PTX/PTXSubtarget.cpp +++ b/contrib/llvm/lib/Target/PTX/PTXSubtarget.cpp @@ -12,12 +12,36 @@ //===----------------------------------------------------------------------===// #include "PTXSubtarget.h" +#include "llvm/Support/ErrorHandling.h" using namespace llvm; -PTXSubtarget::PTXSubtarget(const std::string &TT, const std::string &FS) { - std::string TARGET = "sm_20"; - // TODO: call ParseSubtargetFeatures(FS, TARGET); +PTXSubtarget::PTXSubtarget(const std::string &TT, const std::string &FS, + bool is64Bit) + : PTXShaderModel(PTX_SM_1_0), + PTXVersion(PTX_VERSION_2_0), + SupportsDouble(false), + Is64Bit(is64Bit) { + std::string TARGET = "generic"; + ParseSubtargetFeatures(FS, TARGET); +} + +std::string PTXSubtarget::getTargetString() const { + switch(PTXShaderModel) { + default: llvm_unreachable("Unknown shader model"); + case PTX_SM_1_0: return "sm_10"; + case PTX_SM_1_3: return "sm_13"; + case PTX_SM_2_0: return "sm_20"; + } +} + +std::string PTXSubtarget::getPTXVersionString() const { + switch(PTXVersion) { + default: llvm_unreachable("Unknown PTX version"); + case PTX_VERSION_2_0: return "2.0"; + case PTX_VERSION_2_1: return "2.1"; + case PTX_VERSION_2_2: return "2.2"; + } } #include "PTXGenSubtarget.inc" diff --git a/contrib/llvm/lib/Target/PTX/PTXSubtarget.h b/contrib/llvm/lib/Target/PTX/PTXSubtarget.h index 7fd85f873ae4..47d98424065b 100644 --- a/contrib/llvm/lib/Target/PTX/PTXSubtarget.h +++ b/contrib/llvm/lib/Target/PTX/PTXSubtarget.h @@ -19,10 +19,57 @@ namespace llvm { class PTXSubtarget : public TargetSubtarget { private: - bool is_sm20; + + /** + * Enumeration of Shader Models supported by the back-end. + */ + enum PTXShaderModelEnum { + PTX_SM_1_0, /*< Shader Model 1.0 */ + PTX_SM_1_3, /*< Shader Model 1.3 */ + PTX_SM_2_0 /*< Shader Model 2.0 */ + }; + + /** + * Enumeration of PTX versions supported by the back-end. + * + * Currently, PTX 2.0 is the minimum supported version. + */ + enum PTXVersionEnum { + PTX_VERSION_2_0, /*< PTX Version 2.0 */ + PTX_VERSION_2_1, /*< PTX Version 2.1 */ + PTX_VERSION_2_2 /*< PTX Version 2.2 */ + }; + + /// Shader Model supported on the target GPU. + PTXShaderModelEnum PTXShaderModel; + + /// PTX Language Version. + PTXVersionEnum PTXVersion; + + // The native .f64 type is supported on the hardware. + bool SupportsDouble; + + // Use .u64 instead of .u32 for addresses. + bool Is64Bit; public: - PTXSubtarget(const std::string &TT, const std::string &FS); + PTXSubtarget(const std::string &TT, const std::string &FS, bool is64Bit); + + std::string getTargetString() const; + + std::string getPTXVersionString() const; + + bool supportsDouble() const { return SupportsDouble; } + + bool is64Bit() const { return Is64Bit; } + + bool supportsSM13() const { return PTXShaderModel >= PTX_SM_1_3; } + + bool supportsSM20() const { return PTXShaderModel >= PTX_SM_2_0; } + + bool supportsPTX21() const { return PTXVersion >= PTX_VERSION_2_1; } + + bool supportsPTX22() const { return PTXVersion >= PTX_VERSION_2_2; } std::string ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); diff --git a/contrib/llvm/lib/Target/PTX/PTXTargetMachine.cpp b/contrib/llvm/lib/Target/PTX/PTXTargetMachine.cpp index b263813cb4e7..1b737c9d8634 100644 --- a/contrib/llvm/lib/Target/PTX/PTXTargetMachine.cpp +++ b/contrib/llvm/lib/Target/PTX/PTXTargetMachine.cpp @@ -16,12 +16,14 @@ #include "PTXTargetMachine.h" #include "llvm/PassManager.h" #include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace llvm { MCStreamer *createPTXAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, + bool useCFI, MCInstPrinter *InstPrint, MCCodeEmitter *CE, TargetAsmBackend *TAB, @@ -29,21 +31,47 @@ namespace llvm { } extern "C" void LLVMInitializePTXTarget() { - RegisterTargetMachine X(ThePTXTarget); - RegisterAsmInfo Y(ThePTXTarget); - TargetRegistry::RegisterAsmStreamer(ThePTXTarget, createPTXAsmStreamer); + + RegisterTargetMachine X(ThePTX32Target); + RegisterTargetMachine Y(ThePTX64Target); + + RegisterAsmInfo Z(ThePTX32Target); + RegisterAsmInfo W(ThePTX64Target); + + TargetRegistry::RegisterAsmStreamer(ThePTX32Target, createPTXAsmStreamer); + TargetRegistry::RegisterAsmStreamer(ThePTX64Target, createPTXAsmStreamer); +} + +namespace { + const char* DataLayout32 = + "e-p:32:32-i64:32:32-f64:32:32-v128:32:128-v64:32:64-n32:64"; + const char* DataLayout64 = + "e-p:64:64-i64:32:32-f64:32:32-v128:32:128-v64:32:64-n32:64"; } // DataLayout and FrameLowering are filled with dummy data PTXTargetMachine::PTXTargetMachine(const Target &T, const std::string &TT, - const std::string &FS) + const std::string &FS, + bool is64Bit) : LLVMTargetMachine(T, TT), - DataLayout("e-p:32:32-i64:32:32-f64:32:32-v128:32:128-v64:32:64-n32:64"), + DataLayout(is64Bit ? DataLayout64 : DataLayout32), + Subtarget(TT, FS, is64Bit), FrameLowering(Subtarget), InstrInfo(*this), - TLInfo(*this), - Subtarget(TT, FS) { + TLInfo(*this) { +} + +PTX32TargetMachine::PTX32TargetMachine(const Target &T, + const std::string& TT, + const std::string& FS) + : PTXTargetMachine(T, TT, FS, false) { +} + +PTX64TargetMachine::PTX64TargetMachine(const Target &T, + const std::string& TT, + const std::string& FS) + : PTXTargetMachine(T, TT, FS, true) { } bool PTXTargetMachine::addInstSelector(PassManagerBase &PM, diff --git a/contrib/llvm/lib/Target/PTX/PTXTargetMachine.h b/contrib/llvm/lib/Target/PTX/PTXTargetMachine.h index 728e36f56f01..149be8e3b7e9 100644 --- a/contrib/llvm/lib/Target/PTX/PTXTargetMachine.h +++ b/contrib/llvm/lib/Target/PTX/PTXTargetMachine.h @@ -25,15 +25,15 @@ namespace llvm { class PTXTargetMachine : public LLVMTargetMachine { private: - const TargetData DataLayout; - PTXFrameLowering FrameLowering; - PTXInstrInfo InstrInfo; + const TargetData DataLayout; + PTXSubtarget Subtarget; // has to be initialized before FrameLowering + PTXFrameLowering FrameLowering; + PTXInstrInfo InstrInfo; PTXTargetLowering TLInfo; - PTXSubtarget Subtarget; public: PTXTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &FS, bool is64Bit); virtual const TargetData *getTargetData() const { return &DataLayout; } @@ -55,6 +55,22 @@ class PTXTargetMachine : public LLVMTargetMachine { virtual bool addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel); }; // class PTXTargetMachine + + +class PTX32TargetMachine : public PTXTargetMachine { +public: + + PTX32TargetMachine(const Target &T, const std::string &TT, + const std::string& FS); +}; // class PTX32TargetMachine + +class PTX64TargetMachine : public PTXTargetMachine { +public: + + PTX64TargetMachine(const Target &T, const std::string &TT, + const std::string& FS); +}; // class PTX32TargetMachine + } // namespace llvm #endif // PTX_TARGET_MACHINE_H diff --git a/contrib/llvm/lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp b/contrib/llvm/lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp index a577d7755af5..9df6c7567bd1 100644 --- a/contrib/llvm/lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp +++ b/contrib/llvm/lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp @@ -13,9 +13,13 @@ using namespace llvm; -Target llvm::ThePTXTarget; +Target llvm::ThePTX32Target; +Target llvm::ThePTX64Target; extern "C" void LLVMInitializePTXTargetInfo() { // see llvm/ADT/Triple.h - RegisterTarget X(ThePTXTarget, "ptx", "PTX"); + RegisterTarget X32(ThePTX32Target, "ptx32", + "PTX (32-bit) [Experimental]"); + RegisterTarget X64(ThePTX64Target, "ptx64", + "PTX (64-bit) [Experimental]"); } diff --git a/contrib/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h b/contrib/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h index ebc10daa5f16..9cf9db9c26b7 100644 --- a/contrib/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h +++ b/contrib/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h @@ -17,13 +17,16 @@ #include "llvm/MC/MCInstPrinter.h" namespace llvm { - class MCOperand; + +class MCOperand; +class TargetMachine; class PPCInstPrinter : public MCInstPrinter { // 0 -> AIX, 1 -> Darwin. unsigned SyntaxVariant; public: - PPCInstPrinter(const MCAsmInfo &MAI, unsigned syntaxVariant) + PPCInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI, + unsigned syntaxVariant) : MCInstPrinter(MAI), SyntaxVariant(syntaxVariant) {} bool isDarwinSyntax() const { diff --git a/contrib/llvm/lib/Target/PowerPC/PPCAsmBackend.cpp b/contrib/llvm/lib/Target/PowerPC/PPCAsmBackend.cpp index c4d4ac9b3eb9..f562a3f4f9e8 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCAsmBackend.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCAsmBackend.cpp @@ -110,10 +110,8 @@ namespace { TargetAsmBackend *llvm::createPPCAsmBackend(const Target &T, const std::string &TT) { - switch (Triple(TT).getOS()) { - case Triple::Darwin: + if (Triple(TT).isOSDarwin()) return new DarwinPPCAsmBackend(T); - default: - return 0; - } + + return 0; } diff --git a/contrib/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/contrib/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 8ed5d7f0ee71..09a9be998247 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -680,9 +680,10 @@ static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm, } static MCInstPrinter *createPPCMCInstPrinter(const Target &T, + TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { - return new PPCInstPrinter(MAI, SyntaxVariant); + return new PPCInstPrinter(TM, MAI, SyntaxVariant); } diff --git a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 70d00e4b5cc5..128522c88431 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -899,7 +899,8 @@ bool PPCTargetLowering::SelectAddressRegImm(SDValue N, SDValue &Disp, short Imm; if (isIntS16Immediate(CN, Imm)) { Disp = DAG.getTargetConstant(Imm, CN->getValueType(0)); - Base = DAG.getRegister(PPC::R0, CN->getValueType(0)); + Base = DAG.getRegister(PPCSubTarget.isPPC64() ? PPC::X0 : PPC::R0, + CN->getValueType(0)); return true; } @@ -947,7 +948,8 @@ bool PPCTargetLowering::SelectAddressRegRegOnly(SDValue N, SDValue &Base, } // Otherwise, do it the hard way, using R0 as the base register. - Base = DAG.getRegister(PPC::R0, N.getValueType()); + Base = DAG.getRegister(PPCSubTarget.isPPC64() ? PPC::X0 : PPC::R0, + N.getValueType()); Index = N; return true; } @@ -2153,7 +2155,7 @@ CalculateParameterAndLinkageAreaSize(SelectionDAG &DAG, } /// CalculateTailCallSPDiff - Get the amount the stack pointer has to be -/// adjusted to accomodate the arguments for the tailcall. +/// adjusted to accommodate the arguments for the tailcall. static int CalculateTailCallSPDiff(SelectionDAG& DAG, bool isTailCall, unsigned ParamSize) { @@ -2394,7 +2396,7 @@ void PrepareTailCall(SelectionDAG &DAG, SDValue &InFlag, SDValue &Chain, // Emit a sequence of copyto/copyfrom virtual registers for arguments that // might overwrite each other in case of tail call optimization. SmallVector MemOpChains2; - // Do not flag preceeding copytoreg stuff together with the following stuff. + // Do not flag preceding copytoreg stuff together with the following stuff. InFlag = SDValue(); StoreTailCallArgumentsToStackSlot(DAG, Chain, TailCallArguments, MemOpChains2, dl); @@ -2442,7 +2444,8 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, if (!DAG.getTarget().getSubtarget().isJITCodeModel()) { unsigned OpFlags = 0; if (DAG.getTarget().getRelocationModel() != Reloc::Static && - PPCSubTarget.getDarwinVers() < 9 && + (!PPCSubTarget.getTargetTriple().isMacOSX() || + PPCSubTarget.getTargetTriple().isMacOSXVersionLT(10, 5)) && (G->getGlobal()->isDeclaration() || G->getGlobal()->isWeakForLinker())) { // PC-relative references to external symbols should go through $stub, @@ -2465,7 +2468,8 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, unsigned char OpFlags = 0; if (DAG.getTarget().getRelocationModel() != Reloc::Static && - PPCSubTarget.getDarwinVers() < 9) { + (!PPCSubTarget.getTargetTriple().isMacOSX() || + PPCSubTarget.getTargetTriple().isMacOSXVersionLT(10, 5))) { // PC-relative references to external symbols should go through $stub, // unless we're building with the leopard linker or later, which // automatically synthesizes these stubs. @@ -4571,6 +4575,7 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr *MI, // registers without caring whether they're 32 or 64, but here we're // doing actual arithmetic on the addresses. bool is64bit = PPCSubTarget.isPPC64(); + unsigned ZeroReg = is64bit ? PPC::X0 : PPC::R0; const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineFunction *F = BB->getParent(); @@ -4634,8 +4639,7 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr *MI, // bne- loopMBB // fallthrough --> exitMBB // srw dest, tmpDest, shift - - if (ptrA!=PPC::R0) { + if (ptrA != ZeroReg) { Ptr1Reg = RegInfo.createVirtualRegister(RC); BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg) .addReg(ptrA).addReg(ptrB); @@ -4665,7 +4669,7 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr *MI, BB = loopMBB; BuildMI(BB, dl, TII->get(PPC::LWARX), TmpDestReg) - .addReg(PPC::R0).addReg(PtrReg); + .addReg(ZeroReg).addReg(PtrReg); if (BinOpcode) BuildMI(BB, dl, TII->get(BinOpcode), TmpReg) .addReg(Incr2Reg).addReg(TmpDestReg); @@ -4676,7 +4680,7 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr *MI, BuildMI(BB, dl, TII->get(is64bit ? PPC::OR8 : PPC::OR), Tmp4Reg) .addReg(Tmp3Reg).addReg(Tmp2Reg); BuildMI(BB, dl, TII->get(PPC::STWCX)) - .addReg(Tmp4Reg).addReg(PPC::R0).addReg(PtrReg); + .addReg(Tmp4Reg).addReg(ZeroReg).addReg(PtrReg); BuildMI(BB, dl, TII->get(PPC::BCC)) .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB); BB->addSuccessor(loopMBB); @@ -4685,7 +4689,8 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr *MI, // exitMBB: // ... BB = exitMBB; - BuildMI(BB, dl, TII->get(PPC::SRW), dest).addReg(TmpDestReg).addReg(ShiftReg); + BuildMI(*BB, BB->begin(), dl, TII->get(PPC::SRW), dest).addReg(TmpDestReg) + .addReg(ShiftReg); return BB; } @@ -4933,6 +4938,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, unsigned TmpDestReg = RegInfo.createVirtualRegister(RC); unsigned Ptr1Reg; unsigned TmpReg = RegInfo.createVirtualRegister(RC); + unsigned ZeroReg = is64bit ? PPC::X0 : PPC::R0; // thisMBB: // ... // fallthrough --> loopMBB @@ -4965,7 +4971,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, // stwcx. tmpDest, ptr // exitBB: // srw dest, tmpDest, shift - if (ptrA!=PPC::R0) { + if (ptrA != ZeroReg) { Ptr1Reg = RegInfo.createVirtualRegister(RC); BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg) .addReg(ptrA).addReg(ptrB); @@ -5002,7 +5008,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, BB = loop1MBB; BuildMI(BB, dl, TII->get(PPC::LWARX), TmpDestReg) - .addReg(PPC::R0).addReg(PtrReg); + .addReg(ZeroReg).addReg(PtrReg); BuildMI(BB, dl, TII->get(PPC::AND),TmpReg) .addReg(TmpDestReg).addReg(MaskReg); BuildMI(BB, dl, TII->get(PPC::CMPW), PPC::CR0) @@ -5018,7 +5024,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, BuildMI(BB, dl, TII->get(PPC::OR),Tmp4Reg) .addReg(Tmp2Reg).addReg(NewVal3Reg); BuildMI(BB, dl, TII->get(PPC::STWCX)).addReg(Tmp4Reg) - .addReg(PPC::R0).addReg(PtrReg); + .addReg(ZeroReg).addReg(PtrReg); BuildMI(BB, dl, TII->get(PPC::BCC)) .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loop1MBB); BuildMI(BB, dl, TII->get(PPC::B)).addMBB(exitMBB); @@ -5027,13 +5033,14 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, BB = midMBB; BuildMI(BB, dl, TII->get(PPC::STWCX)).addReg(TmpDestReg) - .addReg(PPC::R0).addReg(PtrReg); + .addReg(ZeroReg).addReg(PtrReg); BB->addSuccessor(exitMBB); // exitMBB: // ... BB = exitMBB; - BuildMI(BB, dl, TII->get(PPC::SRW),dest).addReg(TmpReg).addReg(ShiftReg); + BuildMI(*BB, BB->begin(), dl, TII->get(PPC::SRW),dest).addReg(TmpReg) + .addReg(ShiftReg); } else { llvm_unreachable("Unexpected instr type to insert"); } diff --git a/contrib/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/contrib/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index 6636b6927191..9f0fae53ec08 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/contrib/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -130,7 +130,7 @@ def : Pat<(PPCnop), // Atomic operations let usesCustomInserter = 1 in { - let Uses = [CR0] in { + let Defs = [CR0] in { def ATOMIC_LOAD_ADD_I64 : Pseudo< (outs G8RC:$dst), (ins memrr:$ptr, G8RC:$incr), "", [(set G8RC:$dst, (atomic_load_add_64 xoaddr:$ptr, G8RC:$incr))]>; diff --git a/contrib/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/contrib/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 82aadeb47ad1..24071b79ab06 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/contrib/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -550,7 +550,7 @@ def DCBZL : DCB_Form<1014, 1, (outs), (ins memrr:$dst), // Atomic operations let usesCustomInserter = 1 in { - let Uses = [CR0] in { + let Defs = [CR0] in { def ATOMIC_LOAD_ADD_I8 : Pseudo< (outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr), "", [(set GPRC:$dst, (atomic_load_add_8 xoaddr:$ptr, GPRC:$incr))]>; diff --git a/contrib/llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp b/contrib/llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp index d1178dd7e1ff..9e508cc9babb 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCMCAsmInfo.cpp @@ -17,7 +17,7 @@ using namespace llvm; PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit) { PCSymbol = "."; CommentString = ";"; - ExceptionsType = ExceptionHandling::DwarfTable; + ExceptionsType = ExceptionHandling::DwarfCFI; if (!is64Bit) Data64bitsDirective = 0; // We can't emit a 64-bit unit in PPC32 mode. diff --git a/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index 72a1deeced44..5f3aa2328f9e 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -70,7 +70,7 @@ PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &FS, , HasSTFIWX(false) , HasLazyResolverStubs(false) , IsJITCodeModel(false) - , DarwinVers(0) { + , TargetTriple(TT) { // Determine default and user specified characteristics std::string CPU = "generic"; @@ -92,19 +92,6 @@ PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &FS, // support it, ignore. if (use64BitRegs() && !has64BitSupport()) Use64BitRegs = false; - - // Set the boolean corresponding to the current target triple, or the default - // if one cannot be determined, to true. - if (TT.length() > 7) { - // Determine which version of darwin this is. - size_t DarwinPos = TT.find("-darwin"); - if (DarwinPos != std::string::npos) { - if (isdigit(TT[DarwinPos+7])) - DarwinVers = atoi(&TT[DarwinPos+7]); - else - DarwinVers = 8; // Minimum supported darwin is Tiger. - } - } // Set up darwin-specific properties. if (isDarwin()) diff --git a/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.h b/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.h index 00ec7474c9e3..8fd1a447692d 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.h +++ b/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.h @@ -14,6 +14,7 @@ #ifndef POWERPCSUBTARGET_H #define POWERPCSUBTARGET_H +#include "llvm/ADT/Triple.h" #include "llvm/Target/TargetInstrItineraries.h" #include "llvm/Target/TargetSubtarget.h" @@ -65,9 +66,9 @@ class PPCSubtarget : public TargetSubtarget { bool HasLazyResolverStubs; bool IsJITCodeModel; - /// DarwinVers - Nonzero if this is a darwin platform. Otherwise, the numeric - /// version of the platform, e.g. 8 = 10.4 (Tiger), 9 = 10.5 (Leopard), etc. - unsigned char DarwinVers; // Is any darwin-ppc platform. + /// TargetTriple - What processor and OS we're targeting. + Triple TargetTriple; + public: /// This constructor initializes the data members to match that /// of the specified triple. @@ -134,13 +135,10 @@ class PPCSubtarget : public TargetSubtarget { bool hasAltivec() const { return HasAltivec; } bool isGigaProcessor() const { return IsGigaProcessor; } - /// isDarwin - True if this is any darwin platform. - bool isDarwin() const { return DarwinVers != 0; } - /// isDarwin - True if this is darwin9 (leopard, 10.5) or above. - bool isDarwin9() const { return DarwinVers >= 9; } + const Triple &getTargetTriple() const { return TargetTriple; } - /// getDarwinVers - Return the darwin version number, 8 = tiger, 9 = leopard. - unsigned getDarwinVers() const { return DarwinVers; } + /// isDarwin - True if this is any darwin platform. + bool isDarwin() const { return TargetTriple.isMacOSX(); } bool isDarwinABI() const { return isDarwin(); } bool isSVR4ABI() const { return !isDarwin(); } diff --git a/contrib/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/contrib/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp index 212b450e7db9..d27e54e56699 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -24,7 +24,7 @@ using namespace llvm; static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { Triple TheTriple(TT); bool isPPC64 = TheTriple.getArch() == Triple::ppc64; - if (TheTriple.getOS() == Triple::Darwin) + if (TheTriple.isOSDarwin()) return new PPCMCAsmInfoDarwin(isPPC64); return new PPCLinuxMCAsmInfo(isPPC64); @@ -37,12 +37,10 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCCodeEmitter *Emitter, bool RelaxAll, bool NoExecStack) { - switch (Triple(TT).getOS()) { - case Triple::Darwin: + if (Triple(TT).isOSDarwin()) return createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll); - default: - return NULL; - } + + return NULL; } extern "C" void LLVMInitializePowerPCTarget() { diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 70574c370f35..edb62fa0c625 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -544,7 +544,7 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. - // The InFlag in necessary since all emited instructions must be + // The InFlag in necessary since all emitted instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { diff --git a/contrib/llvm/lib/Target/SubtargetFeature.cpp b/contrib/llvm/lib/Target/SubtargetFeature.cpp index 3cf95b57c5dc..e0a9de82983f 100644 --- a/contrib/llvm/lib/Target/SubtargetFeature.cpp +++ b/contrib/llvm/lib/Target/SubtargetFeature.cpp @@ -211,7 +211,7 @@ const std::string & SubtargetFeatures::getCPU() const { /// feature, set it. /// static -void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, +void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, const SubtargetFeatureKV *FeatureTable, size_t FeatureTableSize) { for (size_t i = 0; i < FeatureTableSize; ++i) { @@ -230,7 +230,7 @@ void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, /// feature, clear it. /// static -void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, +void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, const SubtargetFeatureKV *FeatureTable, size_t FeatureTableSize) { for (size_t i = 0; i < FeatureTableSize; ++i) { @@ -247,7 +247,7 @@ void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, /// getBits - Get feature bits. /// -uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, +uint64_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, const SubtargetFeatureKV *FeatureTable, size_t FeatureTableSize) { @@ -263,7 +263,7 @@ uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, "CPU features table is not sorted"); } #endif - uint32_t Bits = 0; // Resulting bits + uint64_t Bits = 0; // Resulting bits // Check if help is needed if (Features[0] == "help") diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 90939c312065..d331614400e4 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -451,7 +451,7 @@ SystemZTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, // Build a sequence of copy-to-reg nodes chained together with token chain and // flag operands which copy the outgoing args into registers. The InFlag in - // necessary since all emited instructions must be stuck together. + // necessary since all emitted instructions must be stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, diff --git a/contrib/llvm/lib/Target/TargetData.cpp b/contrib/llvm/lib/Target/TargetData.cpp index c628df04e710..1990bc7b929c 100644 --- a/contrib/llvm/lib/Target/TargetData.cpp +++ b/contrib/llvm/lib/Target/TargetData.cpp @@ -617,10 +617,14 @@ uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices, unsigned TargetData::getPreferredAlignment(const GlobalVariable *GV) const { const Type *ElemType = GV->getType()->getElementType(); unsigned Alignment = getPrefTypeAlignment(ElemType); - if (GV->getAlignment() > Alignment) - Alignment = GV->getAlignment(); + unsigned GVAlignment = GV->getAlignment(); + if (GVAlignment >= Alignment) { + Alignment = GVAlignment; + } else if (GVAlignment != 0) { + Alignment = std::max(GVAlignment, getABITypeAlignment(ElemType)); + } - if (GV->hasInitializer()) { + if (GV->hasInitializer() && GVAlignment == 0) { if (Alignment < 16) { // If the global is not external, see if it is large. If so, give it a // larger alignment. diff --git a/contrib/llvm/lib/Target/TargetInstrInfo.cpp b/contrib/llvm/lib/Target/TargetInstrInfo.cpp index 97f3bf6e57ad..d4b76972e49a 100644 --- a/contrib/llvm/lib/Target/TargetInstrInfo.cpp +++ b/contrib/llvm/lib/Target/TargetInstrInfo.cpp @@ -149,10 +149,10 @@ bool TargetInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { /// Measure the specified inline asm to determine an approximation of its /// length. -/// Comments (which run till the next SeparatorChar or newline) do not +/// Comments (which run till the next SeparatorString or newline) do not /// count as an instruction. /// Any other non-whitespace text is considered an instruction, with -/// multiple instructions separated by SeparatorChar or newlines. +/// multiple instructions separated by SeparatorString or newlines. /// Variable-length instructions are not handled here; this function /// may be overloaded in the target code to do that. unsigned TargetInstrInfo::getInlineAsmLength(const char *Str, @@ -163,7 +163,8 @@ unsigned TargetInstrInfo::getInlineAsmLength(const char *Str, bool atInsnStart = true; unsigned Length = 0; for (; *Str; ++Str) { - if (*Str == '\n' || *Str == MAI.getSeparatorChar()) + if (*Str == '\n' || strncmp(Str, MAI.getSeparatorString(), + strlen(MAI.getSeparatorString())) == 0) atInsnStart = true; if (atInsnStart && !std::isspace(*Str)) { Length += MAI.getMaxInstLength(); diff --git a/contrib/llvm/lib/Target/TargetLibraryInfo.cpp b/contrib/llvm/lib/Target/TargetLibraryInfo.cpp index c8bed18ffabe..e336b09291a4 100644 --- a/contrib/llvm/lib/Target/TargetLibraryInfo.cpp +++ b/contrib/llvm/lib/Target/TargetLibraryInfo.cpp @@ -28,9 +28,22 @@ static void initialize(TargetLibraryInfo &TLI, const Triple &T) { // memset_pattern16 is only available on iOS 3.0 and Mac OS/X 10.5 and later. - if (T.getOS() != Triple::Darwin || T.getDarwinMajorNumber() < 9) + if (T.isMacOSX()) { + if (T.isMacOSXVersionLT(10, 5)) + TLI.setUnavailable(LibFunc::memset_pattern16); + } else if (T.getOS() == Triple::IOS) { + if (T.isOSVersionLT(3, 0)) + TLI.setUnavailable(LibFunc::memset_pattern16); + } else { TLI.setUnavailable(LibFunc::memset_pattern16); - + } + + // iprintf and friends are only available on XCore. + if (T.getArch() != Triple::xcore) { + TLI.setUnavailable(LibFunc::iprintf); + TLI.setUnavailable(LibFunc::siprintf); + TLI.setUnavailable(LibFunc::fiprintf); + } } diff --git a/contrib/llvm/lib/Target/TargetLoweringObjectFile.cpp b/contrib/llvm/lib/Target/TargetLoweringObjectFile.cpp index 5d34c7d7fa3d..717ad4122013 100644 --- a/contrib/llvm/lib/Target/TargetLoweringObjectFile.cpp +++ b/contrib/llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -120,6 +120,18 @@ static bool IsNullTerminatedString(const Constant *C) { return false; } +MCSymbol *TargetLoweringObjectFile:: +getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI) const { + return Mang->getSymbol(GV); +} + +void TargetLoweringObjectFile::emitPersonalityValue(MCStreamer &Streamer, + const TargetMachine &TM, + const MCSymbol *Sym) const { +} + + /// getKindForGlobal - This is a top-level target-independent classifier for /// a global variable. Given an global variable and information from TM, it /// classifies the global in a variety of ways that make various target @@ -305,16 +317,15 @@ getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, MachineModuleInfo *MMI, unsigned Encoding, MCStreamer &Streamer) const { const MCSymbol *Sym = Mang->getSymbol(GV); - return getExprForDwarfReference(Sym, Mang, MMI, Encoding, Streamer); + return getExprForDwarfReference(Sym, Encoding, Streamer); } const MCExpr *TargetLoweringObjectFile:: -getExprForDwarfReference(const MCSymbol *Sym, Mangler *Mang, - MachineModuleInfo *MMI, unsigned Encoding, +getExprForDwarfReference(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const { const MCExpr *Res = MCSymbolRefExpr::Create(Sym, getContext()); - switch (Encoding & 0xF0) { + switch (Encoding & 0x70) { default: report_fatal_error("We do not support this DWARF encoding yet!"); case dwarf::DW_EH_PE_absptr: @@ -339,7 +350,7 @@ unsigned TargetLoweringObjectFile::getLSDAEncoding() const { return dwarf::DW_EH_PE_absptr; } -unsigned TargetLoweringObjectFile::getFDEEncoding() const { +unsigned TargetLoweringObjectFile::getFDEEncoding(bool CFI) const { return dwarf::DW_EH_PE_absptr; } diff --git a/contrib/llvm/lib/Target/TargetMachine.cpp b/contrib/llvm/lib/Target/TargetMachine.cpp index d579d95a99c4..76ccc09195a0 100644 --- a/contrib/llvm/lib/Target/TargetMachine.cpp +++ b/contrib/llvm/lib/Target/TargetMachine.cpp @@ -48,6 +48,7 @@ namespace llvm { bool RealignStack; bool DisableJumpTables; bool StrongPHIElim; + bool HasDivModLibcall; bool AsmVerbosityDefault(false); } @@ -205,6 +206,10 @@ EnableStrongPHIElim(cl::Hidden, "strong-phi-elim", cl::desc("Use strong PHI elimination."), cl::location(StrongPHIElim), cl::init(false)); +static cl::opt +TrapFuncName("trap-func", cl::Hidden, + cl::desc("Emit a call to trap function rather than a trap instruction"), + cl::init("")); static cl::opt DataSections("fdata-sections", cl::desc("Emit data into separate sections"), @@ -221,7 +226,9 @@ TargetMachine::TargetMachine(const Target &T) : TheTarget(T), AsmInfo(0), MCRelaxAll(false), MCNoExecStack(false), - MCUseLoc(true) { + MCSaveTempLabels(false), + MCUseLoc(true), + MCUseCFI(true) { // Typically it will be subtargets that will adjust FloatABIType from Default // to Soft or Hard. if (UseSoftFloat) @@ -303,4 +310,11 @@ namespace llvm { bool HonorSignDependentRoundingFPMath() { return !UnsafeFPMath && HonorSignDependentRoundingFPMathOption; } + + /// getTrapFunctionName - If this returns a non-empty string, this means isel + /// should lower Intrinsic::trap to a call to the specified function name + /// instead of an ISD::TRAP node. + StringRef getTrapFunctionName() { + return TrapFuncName; + } } diff --git a/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 8fe549ba3126..c352bfcd8cce 100644 --- a/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -53,6 +53,14 @@ class X86ATTAsmParser : public TargetAsmParser { SmallVectorImpl &Operands, MCStreamer &Out); + /// isSrcOp - Returns true if operand is either (%rsi) or %ds:%(rsi) + /// in 64bit mode or (%edi) or %es:(%edi) in 32bit mode. + bool isSrcOp(X86Operand &Op); + + /// isDstOp - Returns true if operand is either %es:(%rdi) in 64bit mode + /// or %es:(%edi) in 32bit mode. + bool isDstOp(X86Operand &Op); + /// @name Auto-generated Matcher Functions /// { @@ -356,6 +364,24 @@ struct X86Operand : public MCParsedAsmOperand { } // end anonymous namespace. +bool X86ATTAsmParser::isSrcOp(X86Operand &Op) { + unsigned basereg = Is64Bit ? X86::RSI : X86::ESI; + + return (Op.isMem() && + (Op.Mem.SegReg == 0 || Op.Mem.SegReg == X86::DS) && + isa(Op.Mem.Disp) && + cast(Op.Mem.Disp)->getValue() == 0 && + Op.Mem.BaseReg == basereg && Op.Mem.IndexReg == 0); +} + +bool X86ATTAsmParser::isDstOp(X86Operand &Op) { + unsigned basereg = Is64Bit ? X86::RDI : X86::EDI; + + return Op.isMem() && Op.Mem.SegReg == X86::ES && + isa(Op.Mem.Disp) && + cast(Op.Mem.Disp)->getValue() == 0 && + Op.Mem.BaseReg == basereg && Op.Mem.IndexReg == 0; +} bool X86ATTAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { @@ -788,7 +814,106 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, delete &Op; } } - + // Transform "ins[bwl] %dx, %es:(%edi)" into "ins[bwl]" + if (Name.startswith("ins") && Operands.size() == 3 && + (Name == "insb" || Name == "insw" || Name == "insl")) { + X86Operand &Op = *(X86Operand*)Operands.begin()[1]; + X86Operand &Op2 = *(X86Operand*)Operands.begin()[2]; + if (Op.isReg() && Op.getReg() == X86::DX && isDstOp(Op2)) { + Operands.pop_back(); + Operands.pop_back(); + delete &Op; + delete &Op2; + } + } + + // Transform "outs[bwl] %ds:(%esi), %dx" into "out[bwl]" + if (Name.startswith("outs") && Operands.size() == 3 && + (Name == "outsb" || Name == "outsw" || Name == "outsl")) { + X86Operand &Op = *(X86Operand*)Operands.begin()[1]; + X86Operand &Op2 = *(X86Operand*)Operands.begin()[2]; + if (isSrcOp(Op) && Op2.isReg() && Op2.getReg() == X86::DX) { + Operands.pop_back(); + Operands.pop_back(); + delete &Op; + delete &Op2; + } + } + + // Transform "movs[bwl] %ds:(%esi), %es:(%edi)" into "movs[bwl]" + if (Name.startswith("movs") && Operands.size() == 3 && + (Name == "movsb" || Name == "movsw" || Name == "movsl" || + (Is64Bit && Name == "movsq"))) { + X86Operand &Op = *(X86Operand*)Operands.begin()[1]; + X86Operand &Op2 = *(X86Operand*)Operands.begin()[2]; + if (isSrcOp(Op) && isDstOp(Op2)) { + Operands.pop_back(); + Operands.pop_back(); + delete &Op; + delete &Op2; + } + } + // Transform "lods[bwl] %ds:(%esi),{%al,%ax,%eax,%rax}" into "lods[bwl]" + if (Name.startswith("lods") && Operands.size() == 3 && + (Name == "lods" || Name == "lodsb" || Name == "lodsw" || + Name == "lodsl" || (Is64Bit && Name == "lodsq"))) { + X86Operand *Op1 = static_cast(Operands[1]); + X86Operand *Op2 = static_cast(Operands[2]); + if (isSrcOp(*Op1) && Op2->isReg()) { + const char *ins; + unsigned reg = Op2->getReg(); + bool isLods = Name == "lods"; + if (reg == X86::AL && (isLods || Name == "lodsb")) + ins = "lodsb"; + else if (reg == X86::AX && (isLods || Name == "lodsw")) + ins = "lodsw"; + else if (reg == X86::EAX && (isLods || Name == "lodsl")) + ins = "lodsl"; + else if (reg == X86::RAX && (isLods || Name == "lodsq")) + ins = "lodsq"; + else + ins = NULL; + if (ins != NULL) { + Operands.pop_back(); + Operands.pop_back(); + delete Op1; + delete Op2; + if (Name != ins) + static_cast(Operands[0])->setTokenValue(ins); + } + } + } + // Transform "stos[bwl] {%al,%ax,%eax,%rax},%es:(%edi)" into "stos[bwl]" + if (Name.startswith("stos") && Operands.size() == 3 && + (Name == "stos" || Name == "stosb" || Name == "stosw" || + Name == "stosl" || (Is64Bit && Name == "stosq"))) { + X86Operand *Op1 = static_cast(Operands[1]); + X86Operand *Op2 = static_cast(Operands[2]); + if (isDstOp(*Op2) && Op1->isReg()) { + const char *ins; + unsigned reg = Op1->getReg(); + bool isStos = Name == "stos"; + if (reg == X86::AL && (isStos || Name == "stosb")) + ins = "stosb"; + else if (reg == X86::AX && (isStos || Name == "stosw")) + ins = "stosw"; + else if (reg == X86::EAX && (isStos || Name == "stosl")) + ins = "stosl"; + else if (reg == X86::RAX && (isStos || Name == "stosq")) + ins = "stosq"; + else + ins = NULL; + if (ins != NULL) { + Operands.pop_back(); + Operands.pop_back(); + delete Op1; + delete Op2; + if (Name != ins) + static_cast(Operands[0])->setTokenValue(ins); + } + } + } + // FIXME: Hack to handle recognize s{hr,ar,hl} $1, . Canonicalize to // "shift ". if ((Name.startswith("shr") || Name.startswith("sar") || @@ -803,6 +928,18 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, Operands.erase(Operands.begin() + 1); } } + + // Transforms "int $3" into "int3" as a size optimization. We can't write an + // instalias with an immediate operand yet. + if (Name == "int" && Operands.size() == 2) { + X86Operand *Op1 = static_cast(Operands[1]); + if (Op1->isImm() && isa(Op1->getImm()) && + cast(Op1->getImm())->getValue() == 3) { + delete Operands[1]; + Operands.erase(Operands.begin() + 1); + static_cast(Operands[0])->setTokenValue("int3"); + } + } return false; } diff --git a/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp index f7777561b6a7..d8a105e7e9d2 100644 --- a/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -409,6 +409,7 @@ static bool translateRM(MCInst &mcInst, const OperandSpecifier &operand, case TYPE_XMM32: case TYPE_XMM64: case TYPE_XMM128: + case TYPE_XMM256: case TYPE_DEBUGREG: case TYPE_CONTROLREG: return translateRMRegister(mcInst, insn); @@ -418,6 +419,7 @@ static bool translateRM(MCInst &mcInst, const OperandSpecifier &operand, case TYPE_M32: case TYPE_M64: case TYPE_M128: + case TYPE_M256: case TYPE_M512: case TYPE_Mv: case TYPE_M32FP: @@ -500,6 +502,9 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand, case ENCODING_Rv: translateRegister(mcInst, insn.opcodeRegister); return false; + case ENCODING_VVVV: + translateRegister(mcInst, insn.vvvv); + return false; case ENCODING_DUP: return translateOperand(mcInst, insn.spec->operands[operand.type - TYPE_DUP0], diff --git a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c index b6546fc9e86c..de1610ba3d66 100644 --- a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c +++ b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c @@ -75,6 +75,12 @@ static int modRMRequired(OpcodeType type, case THREEBYTE_3A: decision = &THREEBYTE3A_SYM; break; + case THREEBYTE_A6: + decision = &THREEBYTEA6_SYM; + break; + case THREEBYTE_A7: + decision = &THREEBYTEA7_SYM; + break; } return decision->opcodeDecisions[insnContext].modRMDecisions[opcode]. @@ -115,6 +121,12 @@ static InstrUID decode(OpcodeType type, case THREEBYTE_3A: dec = &THREEBYTE3A_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode]; break; + case THREEBYTE_A6: + dec = &THREEBYTEA6_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode]; + break; + case THREEBYTE_A7: + dec = &THREEBYTEA7_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode]; + break; } switch (dec->modrm_type) { @@ -368,29 +380,109 @@ static int readPrefixes(struct InternalInstruction* insn) { if (isPrefix) dbgprintf(insn, "Found prefix 0x%hhx", byte); } + + insn->vexSize = 0; - if (insn->mode == MODE_64BIT) { - if ((byte & 0xf0) == 0x40) { - uint8_t opcodeByte; + if (byte == 0xc4) { + uint8_t byte1; - if (lookAtByte(insn, &opcodeByte) || ((opcodeByte & 0xf0) == 0x40)) { - dbgprintf(insn, "Redundant REX prefix"); - return -1; - } - - insn->rexPrefix = byte; - insn->necessaryPrefixLocation = insn->readerCursor - 2; - - dbgprintf(insn, "Found REX prefix 0x%hhx", byte); - } else { + if (lookAtByte(insn, &byte1)) { + dbgprintf(insn, "Couldn't read second byte of VEX"); + return -1; + } + + if (insn->mode == MODE_64BIT || byte1 & 0x8) { + insn->vexSize = 3; + insn->necessaryPrefixLocation = insn->readerCursor - 1; + } + else { unconsumeByte(insn); insn->necessaryPrefixLocation = insn->readerCursor - 1; } - } else { - unconsumeByte(insn); - insn->necessaryPrefixLocation = insn->readerCursor - 1; + + if (insn->vexSize == 3) { + insn->vexPrefix[0] = byte; + consumeByte(insn, &insn->vexPrefix[1]); + consumeByte(insn, &insn->vexPrefix[2]); + + /* We simulate the REX prefix for simplicity's sake */ + + insn->rexPrefix = 0x40 + | (wFromVEX3of3(insn->vexPrefix[2]) << 3) + | (rFromVEX2of3(insn->vexPrefix[1]) << 2) + | (xFromVEX2of3(insn->vexPrefix[1]) << 1) + | (bFromVEX2of3(insn->vexPrefix[1]) << 0); + + switch (ppFromVEX3of3(insn->vexPrefix[2])) + { + default: + break; + case VEX_PREFIX_66: + hasOpSize = TRUE; + break; + } + + dbgprintf(insn, "Found VEX prefix 0x%hhx 0x%hhx 0x%hhx", insn->vexPrefix[0], insn->vexPrefix[1], insn->vexPrefix[2]); + } } - + else if (byte == 0xc5) { + uint8_t byte1; + + if (lookAtByte(insn, &byte1)) { + dbgprintf(insn, "Couldn't read second byte of VEX"); + return -1; + } + + if (insn->mode == MODE_64BIT || byte1 & 0x8) { + insn->vexSize = 2; + } + else { + unconsumeByte(insn); + } + + if (insn->vexSize == 2) { + insn->vexPrefix[0] = byte; + consumeByte(insn, &insn->vexPrefix[1]); + + insn->rexPrefix = 0x40 + | (rFromVEX2of2(insn->vexPrefix[1]) << 2); + + switch (ppFromVEX2of2(insn->vexPrefix[1])) + { + default: + break; + case VEX_PREFIX_66: + hasOpSize = TRUE; + break; + } + + dbgprintf(insn, "Found VEX prefix 0x%hhx 0x%hhx", insn->vexPrefix[0], insn->vexPrefix[1]); + } + } + else { + if (insn->mode == MODE_64BIT) { + if ((byte & 0xf0) == 0x40) { + uint8_t opcodeByte; + + if (lookAtByte(insn, &opcodeByte) || ((opcodeByte & 0xf0) == 0x40)) { + dbgprintf(insn, "Redundant REX prefix"); + return -1; + } + + insn->rexPrefix = byte; + insn->necessaryPrefixLocation = insn->readerCursor - 2; + + dbgprintf(insn, "Found REX prefix 0x%hhx", byte); + } else { + unconsumeByte(insn); + insn->necessaryPrefixLocation = insn->readerCursor - 1; + } + } else { + unconsumeByte(insn); + insn->necessaryPrefixLocation = insn->readerCursor - 1; + } + } + if (insn->mode == MODE_16BIT) { insn->registerSize = (hasOpSize ? 4 : 2); insn->addressSize = (hasAdSize ? 4 : 2); @@ -438,6 +530,39 @@ static int readOpcode(struct InternalInstruction* insn) { dbgprintf(insn, "readOpcode()"); insn->opcodeType = ONEBYTE; + + if (insn->vexSize == 3) + { + switch (mmmmmFromVEX2of3(insn->vexPrefix[1])) + { + default: + dbgprintf(insn, "Unhandled m-mmmm field for instruction (0x%hhx)", mmmmmFromVEX2of3(insn->vexPrefix[1])); + return -1; + case 0: + break; + case VEX_LOB_0F: + insn->twoByteEscape = 0x0f; + insn->opcodeType = TWOBYTE; + return consumeByte(insn, &insn->opcode); + case VEX_LOB_0F38: + insn->twoByteEscape = 0x0f; + insn->threeByteEscape = 0x38; + insn->opcodeType = THREEBYTE_38; + return consumeByte(insn, &insn->opcode); + case VEX_LOB_0F3A: + insn->twoByteEscape = 0x0f; + insn->threeByteEscape = 0x3a; + insn->opcodeType = THREEBYTE_3A; + return consumeByte(insn, &insn->opcode); + } + } + else if (insn->vexSize == 2) + { + insn->twoByteEscape = 0x0f; + insn->opcodeType = TWOBYTE; + return consumeByte(insn, &insn->opcode); + } + if (consumeByte(insn, ¤t)) return -1; @@ -467,6 +592,24 @@ static int readOpcode(struct InternalInstruction* insn) { return -1; insn->opcodeType = THREEBYTE_3A; + } else if (current == 0xa6) { + dbgprintf(insn, "Found a three-byte escape prefix (0x%hhx)", current); + + insn->threeByteEscape = current; + + if (consumeByte(insn, ¤t)) + return -1; + + insn->opcodeType = THREEBYTE_A6; + } else if (current == 0xa7) { + dbgprintf(insn, "Found a three-byte escape prefix (0x%hhx)", current); + + insn->threeByteEscape = current; + + if (consumeByte(insn, ¤t)) + return -1; + + insn->opcodeType = THREEBYTE_A7; } else { dbgprintf(insn, "Didn't find a three-byte escape prefix"); @@ -600,20 +743,64 @@ static int getID(struct InternalInstruction* insn) { dbgprintf(insn, "getID()"); attrMask = ATTR_NONE; - + if (insn->mode == MODE_64BIT) attrMask |= ATTR_64BIT; + + if (insn->vexSize) { + attrMask |= ATTR_VEX; + + if (insn->vexSize == 3) { + switch (ppFromVEX3of3(insn->vexPrefix[2])) { + case VEX_PREFIX_66: + attrMask |= ATTR_OPSIZE; + break; + case VEX_PREFIX_F3: + attrMask |= ATTR_XS; + break; + case VEX_PREFIX_F2: + attrMask |= ATTR_XD; + break; + } + + if (wFromVEX3of3(insn->vexPrefix[2])) + attrMask |= ATTR_REXW; + if (lFromVEX3of3(insn->vexPrefix[2])) + attrMask |= ATTR_VEXL; + } + else if (insn->vexSize == 2) { + switch (ppFromVEX2of2(insn->vexPrefix[1])) { + case VEX_PREFIX_66: + attrMask |= ATTR_OPSIZE; + break; + case VEX_PREFIX_F3: + attrMask |= ATTR_XS; + break; + case VEX_PREFIX_F2: + attrMask |= ATTR_XD; + break; + } + + if (lFromVEX2of2(insn->vexPrefix[1])) + attrMask |= ATTR_VEXL; + } + else { + return -1; + } + } + else { + if (insn->rexPrefix & 0x08) + attrMask |= ATTR_REXW; - if (insn->rexPrefix & 0x08) - attrMask |= ATTR_REXW; - - if (isPrefixAtLocation(insn, 0x66, insn->necessaryPrefixLocation)) - attrMask |= ATTR_OPSIZE; - else if (isPrefixAtLocation(insn, 0xf3, insn->necessaryPrefixLocation)) - attrMask |= ATTR_XS; - else if (isPrefixAtLocation(insn, 0xf2, insn->necessaryPrefixLocation)) - attrMask |= ATTR_XD; - + if (isPrefixAtLocation(insn, 0x66, insn->necessaryPrefixLocation)) + attrMask |= ATTR_OPSIZE; + else if (isPrefixAtLocation(insn, 0xf3, insn->necessaryPrefixLocation)) + attrMask |= ATTR_XS; + else if (isPrefixAtLocation(insn, 0xf2, insn->necessaryPrefixLocation)) + attrMask |= ATTR_XD; + + } + if (getIDWithAttrMask(&instructionID, insn, attrMask)) return -1; @@ -749,7 +936,7 @@ static int readSIB(struct InternalInstruction* insn) { insn->sibIndex = SIB_INDEX_NONE; break; default: - insn->sibIndex = (EABase)(sibIndexBase + index); + insn->sibIndex = (SIBIndex)(sibIndexBase + index); if (insn->sibIndex == SIB_INDEX_sib || insn->sibIndex == SIB_INDEX_sib64) insn->sibIndex = SIB_INDEX_NONE; @@ -796,7 +983,7 @@ static int readSIB(struct InternalInstruction* insn) { } break; default: - insn->sibBase = (EABase)(sibBaseBase + base); + insn->sibBase = (SIBBase)(sibBaseBase + base); break; } @@ -1012,6 +1199,8 @@ static int readModRM(struct InternalInstruction* insn) { return prefix##_EAX + index; \ case TYPE_R64: \ return prefix##_RAX + index; \ + case TYPE_XMM256: \ + return prefix##_YMM0 + index; \ case TYPE_XMM128: \ case TYPE_XMM64: \ case TYPE_XMM32: \ @@ -1073,6 +1262,14 @@ static int fixupReg(struct InternalInstruction *insn, default: debug("Expected a REG or R/M encoding in fixupReg"); return -1; + case ENCODING_VVVV: + insn->vvvv = (Reg)fixupRegValue(insn, + (OperandType)op->type, + insn->vvvv, + &valid); + if (!valid) + return -1; + break; case ENCODING_REG: insn->reg = (Reg)fixupRegValue(insn, (OperandType)op->type, @@ -1236,6 +1433,27 @@ static int readImmediate(struct InternalInstruction* insn, uint8_t size) { return 0; } +/* + * readVVVV - Consumes an immediate operand from an instruction, given the + * desired operand size. + * + * @param insn - The instruction whose operand is to be read. + * @return - 0 if the immediate was successfully consumed; nonzero + * otherwise. + */ +static int readVVVV(struct InternalInstruction* insn) { + dbgprintf(insn, "readVVVV()"); + + if (insn->vexSize == 3) + insn->vvvv = vvvvFromVEX3of3(insn->vexPrefix[2]); + else if (insn->vexSize == 2) + insn->vvvv = vvvvFromVEX2of2(insn->vexPrefix[1]); + else + return -1; + + return 0; +} + /* * readOperands - Consults the specifier for an instruction and consumes all * operands for that instruction, interpreting them as it goes. @@ -1317,6 +1535,13 @@ static int readOperands(struct InternalInstruction* insn) { case ENCODING_I: if (readOpcodeModifier(insn)) return -1; + break; + case ENCODING_VVVV: + if (readVVVV(insn)) + return -1; + if (fixupReg(insn, &insn->spec->operands[index])) + return -1; + break; case ENCODING_DUP: break; default: diff --git a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h index d0dc8b56aea5..a9c90f8f9bda 100644 --- a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h +++ b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h @@ -34,16 +34,30 @@ extern "C" { /* * Accessor functions for various fields of an Intel instruction */ -#define modFromModRM(modRM) ((modRM & 0xc0) >> 6) -#define regFromModRM(modRM) ((modRM & 0x38) >> 3) -#define rmFromModRM(modRM) (modRM & 0x7) -#define scaleFromSIB(sib) ((sib & 0xc0) >> 6) -#define indexFromSIB(sib) ((sib & 0x38) >> 3) -#define baseFromSIB(sib) (sib & 0x7) -#define wFromREX(rex) ((rex & 0x8) >> 3) -#define rFromREX(rex) ((rex & 0x4) >> 2) -#define xFromREX(rex) ((rex & 0x2) >> 1) -#define bFromREX(rex) (rex & 0x1) +#define modFromModRM(modRM) (((modRM) & 0xc0) >> 6) +#define regFromModRM(modRM) (((modRM) & 0x38) >> 3) +#define rmFromModRM(modRM) ((modRM) & 0x7) +#define scaleFromSIB(sib) (((sib) & 0xc0) >> 6) +#define indexFromSIB(sib) (((sib) & 0x38) >> 3) +#define baseFromSIB(sib) ((sib) & 0x7) +#define wFromREX(rex) (((rex) & 0x8) >> 3) +#define rFromREX(rex) (((rex) & 0x4) >> 2) +#define xFromREX(rex) (((rex) & 0x2) >> 1) +#define bFromREX(rex) ((rex) & 0x1) + +#define rFromVEX2of3(vex) (((~(vex)) & 0x80) >> 7) +#define xFromVEX2of3(vex) (((~(vex)) & 0x40) >> 6) +#define bFromVEX2of3(vex) (((~(vex)) & 0x20) >> 5) +#define mmmmmFromVEX2of3(vex) ((vex) & 0x1f) +#define wFromVEX3of3(vex) (((vex) & 0x80) >> 7) +#define vvvvFromVEX3of3(vex) (((~(vex)) & 0x78) >> 3) +#define lFromVEX3of3(vex) (((vex) & 0x4) >> 2) +#define ppFromVEX3of3(vex) ((vex) & 0x3) + +#define rFromVEX2of2(vex) (((~(vex)) & 0x80) >> 7) +#define vvvvFromVEX2of2(vex) (((~(vex)) & 0x78) >> 3) +#define lFromVEX2of2(vex) (((vex) & 0x4) >> 2) +#define ppFromVEX2of2(vex) ((vex) & 0x3) /* * These enums represent Intel registers for use by the decoder. @@ -206,7 +220,25 @@ extern "C" { ENTRY(XMM13) \ ENTRY(XMM14) \ ENTRY(XMM15) - + +#define REGS_YMM \ + ENTRY(YMM0) \ + ENTRY(YMM1) \ + ENTRY(YMM2) \ + ENTRY(YMM3) \ + ENTRY(YMM4) \ + ENTRY(YMM5) \ + ENTRY(YMM6) \ + ENTRY(YMM7) \ + ENTRY(YMM8) \ + ENTRY(YMM9) \ + ENTRY(YMM10) \ + ENTRY(YMM11) \ + ENTRY(YMM12) \ + ENTRY(YMM13) \ + ENTRY(YMM14) \ + ENTRY(YMM15) + #define REGS_SEGMENT \ ENTRY(ES) \ ENTRY(CS) \ @@ -252,6 +284,7 @@ extern "C" { REGS_64BIT \ REGS_MMX \ REGS_XMM \ + REGS_YMM \ REGS_SEGMENT \ REGS_DEBUG \ REGS_CONTROL \ @@ -332,6 +365,27 @@ typedef enum { SEG_OVERRIDE_GS, SEG_OVERRIDE_max } SegmentOverride; + +/* + * VEXLeadingOpcodeByte - Possible values for the VEX.m-mmmm field + */ + +typedef enum { + VEX_LOB_0F = 0x1, + VEX_LOB_0F38 = 0x2, + VEX_LOB_0F3A = 0x3 +} VEXLeadingOpcodeByte; + +/* + * VEXPrefixCode - Possible values for the VEX.pp field + */ + +typedef enum { + VEX_PREFIX_NONE = 0x0, + VEX_PREFIX_66 = 0x1, + VEX_PREFIX_F3 = 0x2, + VEX_PREFIX_F2 = 0x3 +} VEXPrefixCode; typedef uint8_t BOOL; @@ -389,10 +443,12 @@ struct InternalInstruction { uint8_t prefixPresent[0x100]; /* contains the location (for use with the reader) of the prefix byte */ uint64_t prefixLocations[0x100]; + /* The value of the VEX prefix, if present */ + uint8_t vexPrefix[3]; + /* The length of the VEX prefix (0 if not present) */ + uint8_t vexSize; /* The value of the REX prefix, if present */ uint8_t rexPrefix; - /* The location of the REX prefix */ - uint64_t rexLocation; /* The location where a mandatory prefix would have to be (i.e., right before the opcode, or right before the REX prefix if one is present) */ uint64_t necessaryPrefixLocation; @@ -428,6 +484,10 @@ struct InternalInstruction { /* state for additional bytes, consumed during operand decode. Pattern: consumed___ indicates that the byte was already consumed and does not need to be consumed again */ + + /* The VEX.vvvv field, which contains a third register operand for some AVX + instructions */ + Reg vvvv; /* The ModR/M byte, which contains most register operands and some portion of all memory operands */ diff --git a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h index 1425b86ba53f..70315ed572b4 100644 --- a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h +++ b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h @@ -30,6 +30,8 @@ #define TWOBYTE_SYM x86DisassemblerTwoByteOpcodes #define THREEBYTE38_SYM x86DisassemblerThreeByte38Opcodes #define THREEBYTE3A_SYM x86DisassemblerThreeByte3AOpcodes +#define THREEBYTEA6_SYM x86DisassemblerThreeByteA6Opcodes +#define THREEBYTEA7_SYM x86DisassemblerThreeByteA7Opcodes #define INSTRUCTIONS_STR "x86DisassemblerInstrSpecifiers" #define CONTEXTS_STR "x86DisassemblerContexts" @@ -37,6 +39,8 @@ #define TWOBYTE_STR "x86DisassemblerTwoByteOpcodes" #define THREEBYTE38_STR "x86DisassemblerThreeByte38Opcodes" #define THREEBYTE3A_STR "x86DisassemblerThreeByte3AOpcodes" +#define THREEBYTEA6_STR "x86DisassemblerThreeByteA6Opcodes" +#define THREEBYTEA7_STR "x86DisassemblerThreeByteA7Opcodes" /* * Attributes of an instruction that must be known before the opcode can be @@ -49,7 +53,9 @@ ENUM_ENTRY(ATTR_XS, 0x02) \ ENUM_ENTRY(ATTR_XD, 0x04) \ ENUM_ENTRY(ATTR_REXW, 0x08) \ - ENUM_ENTRY(ATTR_OPSIZE, 0x10) + ENUM_ENTRY(ATTR_OPSIZE, 0x10) \ + ENUM_ENTRY(ATTR_VEX, 0x20) \ + ENUM_ENTRY(ATTR_VEXL, 0x40) #define ENUM_ENTRY(n, v) n = v, enum attributeBits { @@ -87,7 +93,20 @@ enum attributeBits { "IC_64BIT_REXW_XS") \ ENUM_ENTRY(IC_64BIT_REXW_OPSIZE, 7, "The Dynamic Duo! Prefer over all " \ "else because this changes most " \ - "operands' meaning") + "operands' meaning") \ + ENUM_ENTRY(IC_VEX, 1, "requires a VEX prefix") \ + ENUM_ENTRY(IC_VEX_XS, 2, "requires VEX and the XS prefix") \ + ENUM_ENTRY(IC_VEX_XD, 2, "requires VEX and the XD prefix") \ + ENUM_ENTRY(IC_VEX_OPSIZE, 2, "requires VEX and the OpSize prefix") \ + ENUM_ENTRY(IC_VEX_W, 3, "requires VEX and the W prefix") \ + ENUM_ENTRY(IC_VEX_W_XS, 4, "requires VEX, W, and XS prefix") \ + ENUM_ENTRY(IC_VEX_W_XD, 4, "requires VEX, W, and XD prefix") \ + ENUM_ENTRY(IC_VEX_W_OPSIZE, 4, "requires VEX, W, and OpSize") \ + ENUM_ENTRY(IC_VEX_L, 3, "requires VEX and the L prefix") \ + ENUM_ENTRY(IC_VEX_L_XS, 4, "requires VEX and the L and XS prefix")\ + ENUM_ENTRY(IC_VEX_L_XD, 4, "requires VEX and the L and XS prefix")\ + ENUM_ENTRY(IC_VEX_L_OPSIZE, 4, "requires VEX, L, and OpSize") + #define ENUM_ENTRY(n, r, d) n, typedef enum { @@ -104,7 +123,9 @@ typedef enum { ONEBYTE = 0, TWOBYTE = 1, THREEBYTE_38 = 2, - THREEBYTE_3A = 3 + THREEBYTE_3A = 3, + THREEBYTE_A6 = 4, + THREEBYTE_A7 = 5 } OpcodeType; /* @@ -183,6 +204,7 @@ struct ContextDecision { ENUM_ENTRY(ENCODING_NONE, "") \ ENUM_ENTRY(ENCODING_REG, "Register operand in ModR/M byte.") \ ENUM_ENTRY(ENCODING_RM, "R/M operand in ModR/M byte.") \ + ENUM_ENTRY(ENCODING_VVVV, "Register operand in VEX.vvvv byte.") \ ENUM_ENTRY(ENCODING_CB, "1-byte code offset (possible new CS value)") \ ENUM_ENTRY(ENCODING_CW, "2-byte") \ ENUM_ENTRY(ENCODING_CD, "4-byte") \ @@ -278,6 +300,7 @@ struct ContextDecision { ENUM_ENTRY(TYPE_XMM32, "4-byte XMM register or memory operand") \ ENUM_ENTRY(TYPE_XMM64, "8-byte") \ ENUM_ENTRY(TYPE_XMM128, "16-byte") \ + ENUM_ENTRY(TYPE_XMM256, "32-byte") \ ENUM_ENTRY(TYPE_XMM0, "Implicit use of XMM0") \ ENUM_ENTRY(TYPE_SEGMENTREG, "Segment register operand") \ ENUM_ENTRY(TYPE_DEBUGREG, "Debug register operand") \ diff --git a/contrib/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/contrib/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp index d6950f49f824..dd6e3533849d 100644 --- a/contrib/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp +++ b/contrib/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp @@ -15,6 +15,7 @@ #define DEBUG_TYPE "asm-printer" #include "X86ATTInstPrinter.h" #include "X86InstComments.h" +#include "X86Subtarget.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" @@ -22,24 +23,38 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "X86GenInstrNames.inc" +#include using namespace llvm; // Include the auto-generated portion of the assembly writer. #define GET_INSTRUCTION_NAME +#define PRINT_ALIAS_INSTR +#include "X86GenRegisterNames.inc" #include "X86GenAsmWriter.inc" +#undef PRINT_ALIAS_INSTR +#undef GET_INSTRUCTION_NAME + +X86ATTInstPrinter::X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) + : MCInstPrinter(MAI) { + // Initialize the set of available features. + setAvailableFeatures(ComputeAvailableFeatures( + &TM.getSubtarget())); +} void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) { - printInstruction(MI, OS); + // Try to print any aliases first. + if (!printAliasInstr(MI, OS)) + printInstruction(MI, OS); // If verbose assembly is enabled, we can print some informative comments. if (CommentStream) EmitAnyX86InstComments(MI, *CommentStream, getRegisterName); } + StringRef X86ATTInstPrinter::getOpcodeName(unsigned Opcode) const { return getInstructionName(Opcode); } - void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op, raw_ostream &O) { switch (MI->getOperand(Op).getImm()) { diff --git a/contrib/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h b/contrib/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h index eb986643014c..8d69391c968b 100644 --- a/contrib/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h +++ b/contrib/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h @@ -17,16 +17,24 @@ #include "llvm/MC/MCInstPrinter.h" namespace llvm { - class MCOperand; + +class MCOperand; +class X86Subtarget; +class TargetMachine; class X86ATTInstPrinter : public MCInstPrinter { public: - X86ATTInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} - + X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI); virtual void printInst(const MCInst *MI, raw_ostream &OS); virtual StringRef getOpcodeName(unsigned Opcode) const; + // Methods used to print the alias of an instruction. + unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const; + // Autogenerated by tblgen, returns true if we successfully printed an + // alias. + bool printAliasInstr(const MCInst *MI, raw_ostream &OS); + // Autogenerated by tblgen. void printInstruction(const MCInst *MI, raw_ostream &OS); static const char *getRegisterName(unsigned RegNo); diff --git a/contrib/llvm/lib/Target/X86/InstPrinter/X86InstComments.cpp b/contrib/llvm/lib/Target/X86/InstPrinter/X86InstComments.cpp index 12144e3f5056..c642acc3b9a2 100644 --- a/contrib/llvm/lib/Target/X86/InstPrinter/X86InstComments.cpp +++ b/contrib/llvm/lib/Target/X86/InstPrinter/X86InstComments.cpp @@ -111,28 +111,28 @@ void llvm::EmitAnyX86InstComments(const MCInst *MI, raw_ostream &OS, // FALL THROUGH. case X86::PUNPCKLBWrm: Src1Name = getRegName(MI->getOperand(0).getReg()); - DecodePUNPCKLMask(16, ShuffleMask); + DecodePUNPCKLBWMask(16, ShuffleMask); break; case X86::PUNPCKLWDrr: Src2Name = getRegName(MI->getOperand(2).getReg()); // FALL THROUGH. case X86::PUNPCKLWDrm: Src1Name = getRegName(MI->getOperand(0).getReg()); - DecodePUNPCKLMask(8, ShuffleMask); + DecodePUNPCKLWDMask(8, ShuffleMask); break; case X86::PUNPCKLDQrr: Src2Name = getRegName(MI->getOperand(2).getReg()); // FALL THROUGH. case X86::PUNPCKLDQrm: Src1Name = getRegName(MI->getOperand(0).getReg()); - DecodePUNPCKLMask(4, ShuffleMask); + DecodePUNPCKLDQMask(4, ShuffleMask); break; case X86::PUNPCKLQDQrr: Src2Name = getRegName(MI->getOperand(2).getReg()); // FALL THROUGH. case X86::PUNPCKLQDQrm: Src1Name = getRegName(MI->getOperand(0).getReg()); - DecodePUNPCKLMask(2, ShuffleMask); + DecodePUNPCKLQDQMask(2, ShuffleMask); break; case X86::SHUFPDrri: @@ -153,16 +153,44 @@ void llvm::EmitAnyX86InstComments(const MCInst *MI, raw_ostream &OS, Src2Name = getRegName(MI->getOperand(2).getReg()); // FALL THROUGH. case X86::UNPCKLPDrm: - DecodeUNPCKLPMask(2, ShuffleMask); + DecodeUNPCKLPDMask(2, ShuffleMask); Src1Name = getRegName(MI->getOperand(0).getReg()); break; + case X86::VUNPCKLPDrr: + Src2Name = getRegName(MI->getOperand(2).getReg()); + // FALL THROUGH. + case X86::VUNPCKLPDrm: + DecodeUNPCKLPDMask(2, ShuffleMask); + Src1Name = getRegName(MI->getOperand(1).getReg()); + break; + case X86::VUNPCKLPDYrr: + Src2Name = getRegName(MI->getOperand(2).getReg()); + // FALL THROUGH. + case X86::VUNPCKLPDYrm: + DecodeUNPCKLPDMask(4, ShuffleMask); + Src1Name = getRegName(MI->getOperand(1).getReg()); + break; case X86::UNPCKLPSrr: Src2Name = getRegName(MI->getOperand(2).getReg()); // FALL THROUGH. case X86::UNPCKLPSrm: - DecodeUNPCKLPMask(4, ShuffleMask); + DecodeUNPCKLPSMask(4, ShuffleMask); Src1Name = getRegName(MI->getOperand(0).getReg()); break; + case X86::VUNPCKLPSrr: + Src2Name = getRegName(MI->getOperand(2).getReg()); + // FALL THROUGH. + case X86::VUNPCKLPSrm: + DecodeUNPCKLPSMask(4, ShuffleMask); + Src1Name = getRegName(MI->getOperand(1).getReg()); + break; + case X86::VUNPCKLPSYrr: + Src2Name = getRegName(MI->getOperand(2).getReg()); + // FALL THROUGH. + case X86::VUNPCKLPSYrm: + DecodeUNPCKLPSMask(8, ShuffleMask); + Src1Name = getRegName(MI->getOperand(1).getReg()); + break; case X86::UNPCKHPDrr: Src2Name = getRegName(MI->getOperand(2).getReg()); // FALL THROUGH. diff --git a/contrib/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp b/contrib/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp index 048452985089..47253ebd202e 100644 --- a/contrib/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp +++ b/contrib/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp @@ -15,6 +15,7 @@ #define DEBUG_TYPE "asm-printer" #include "X86IntelInstPrinter.h" #include "X86InstComments.h" +#include "X86Subtarget.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" diff --git a/contrib/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h b/contrib/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h index 6f120322742b..ca99dc09b8a4 100644 --- a/contrib/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h +++ b/contrib/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h @@ -18,13 +18,15 @@ #include "llvm/Support/raw_ostream.h" namespace llvm { - class MCOperand; + +class MCOperand; +class TargetMachine; class X86IntelInstPrinter : public MCInstPrinter { public: - X86IntelInstPrinter(const MCAsmInfo &MAI) + X86IntelInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} - + virtual void printInst(const MCInst *MI, raw_ostream &OS); virtual StringRef getOpcodeName(unsigned Opcode) const; @@ -33,7 +35,6 @@ class X86IntelInstPrinter : public MCInstPrinter { static const char *getRegisterName(unsigned RegNo); static const char *getInstructionName(unsigned Opcode); - void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printMemReference(const MCInst *MI, unsigned Op, raw_ostream &O); void printSSECC(const MCInst *MI, unsigned Op, raw_ostream &O); diff --git a/contrib/llvm/lib/Target/X86/Utils/X86ShuffleDecode.cpp b/contrib/llvm/lib/Target/X86/Utils/X86ShuffleDecode.cpp index 12879774d780..cd06060748b7 100644 --- a/contrib/llvm/lib/Target/X86/Utils/X86ShuffleDecode.cpp +++ b/contrib/llvm/lib/Target/X86/Utils/X86ShuffleDecode.cpp @@ -1,4 +1,4 @@ -//===-- X86ShuffleDecode.h - X86 shuffle decode logic ---------------------===// +//===-- X86ShuffleDecode.cpp - X86 shuffle decode logic -------------------===// // // The LLVM Compiler Infrastructure // @@ -95,12 +95,29 @@ void DecodePSHUFLWMask(unsigned Imm, ShuffleMask.push_back(7); } -void DecodePUNPCKLMask(unsigned NElts, +void DecodePUNPCKLBWMask(unsigned NElts, + SmallVectorImpl &ShuffleMask) { + DecodeUNPCKLPMask(MVT::getVectorVT(MVT::i8, NElts), ShuffleMask); +} + +void DecodePUNPCKLWDMask(unsigned NElts, + SmallVectorImpl &ShuffleMask) { + DecodeUNPCKLPMask(MVT::getVectorVT(MVT::i16, NElts), ShuffleMask); +} + +void DecodePUNPCKLDQMask(unsigned NElts, + SmallVectorImpl &ShuffleMask) { + DecodeUNPCKLPMask(MVT::getVectorVT(MVT::i32, NElts), ShuffleMask); +} + +void DecodePUNPCKLQDQMask(unsigned NElts, + SmallVectorImpl &ShuffleMask) { + DecodeUNPCKLPMask(MVT::getVectorVT(MVT::i64, NElts), ShuffleMask); +} + +void DecodePUNPCKLMask(EVT VT, SmallVectorImpl &ShuffleMask) { - for (unsigned i = 0; i != NElts/2; ++i) { - ShuffleMask.push_back(i); - ShuffleMask.push_back(i+NElts); - } + DecodeUNPCKLPMask(VT, ShuffleMask); } void DecodePUNPCKHMask(unsigned NElts, @@ -133,15 +150,40 @@ void DecodeUNPCKHPMask(unsigned NElts, } } +void DecodeUNPCKLPSMask(unsigned NElts, + SmallVectorImpl &ShuffleMask) { + DecodeUNPCKLPMask(MVT::getVectorVT(MVT::i32, NElts), ShuffleMask); +} + +void DecodeUNPCKLPDMask(unsigned NElts, + SmallVectorImpl &ShuffleMask) { + DecodeUNPCKLPMask(MVT::getVectorVT(MVT::i64, NElts), ShuffleMask); +} /// DecodeUNPCKLPMask - This decodes the shuffle masks for unpcklps/unpcklpd -/// etc. NElts indicates the number of elements in the vector allowing it to -/// handle different datatypes and vector widths. -void DecodeUNPCKLPMask(unsigned NElts, +/// etc. VT indicates the type of the vector allowing it to handle different +/// datatypes and vector widths. +void DecodeUNPCKLPMask(EVT VT, SmallVectorImpl &ShuffleMask) { - for (unsigned i = 0; i != NElts/2; ++i) { - ShuffleMask.push_back(i); // Reads from dest - ShuffleMask.push_back(i+NElts); // Reads from src + unsigned NumElts = VT.getVectorNumElements(); + + // Handle vector lengths > 128 bits. Define a "section" as a set of + // 128 bits. AVX defines UNPCK* to operate independently on 128-bit + // sections. + unsigned NumSections = VT.getSizeInBits() / 128; + if (NumSections == 0 ) NumSections = 1; // Handle MMX + unsigned NumSectionElts = NumElts / NumSections; + + unsigned Start = 0; + unsigned End = NumSectionElts / 2; + for (unsigned s = 0; s < NumSections; ++s) { + for (unsigned i = Start; i != End; ++i) { + ShuffleMask.push_back(i); // Reads from dest/src1 + ShuffleMask.push_back(i+NumSectionElts); // Reads from src/src2 + } + // Process the next 128 bits. + Start += NumSectionElts; + End += NumSectionElts; } } diff --git a/contrib/llvm/lib/Target/X86/Utils/X86ShuffleDecode.h b/contrib/llvm/lib/Target/X86/Utils/X86ShuffleDecode.h index 50d9ccbfa68c..b18f67033096 100644 --- a/contrib/llvm/lib/Target/X86/Utils/X86ShuffleDecode.h +++ b/contrib/llvm/lib/Target/X86/Utils/X86ShuffleDecode.h @@ -16,6 +16,7 @@ #define X86_SHUFFLE_DECODE_H #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ValueTypes.h" //===----------------------------------------------------------------------===// // Vector Mask Decoding @@ -45,7 +46,19 @@ void DecodePSHUFHWMask(unsigned Imm, void DecodePSHUFLWMask(unsigned Imm, SmallVectorImpl &ShuffleMask); -void DecodePUNPCKLMask(unsigned NElts, +void DecodePUNPCKLBWMask(unsigned NElts, + SmallVectorImpl &ShuffleMask); + +void DecodePUNPCKLWDMask(unsigned NElts, + SmallVectorImpl &ShuffleMask); + +void DecodePUNPCKLDQMask(unsigned NElts, + SmallVectorImpl &ShuffleMask); + +void DecodePUNPCKLQDQMask(unsigned NElts, + SmallVectorImpl &ShuffleMask); + +void DecodePUNPCKLMask(EVT VT, SmallVectorImpl &ShuffleMask); void DecodePUNPCKHMask(unsigned NElts, @@ -57,11 +70,16 @@ void DecodeSHUFPSMask(unsigned NElts, unsigned Imm, void DecodeUNPCKHPMask(unsigned NElts, SmallVectorImpl &ShuffleMask); +void DecodeUNPCKLPSMask(unsigned NElts, + SmallVectorImpl &ShuffleMask); + +void DecodeUNPCKLPDMask(unsigned NElts, + SmallVectorImpl &ShuffleMask); /// DecodeUNPCKLPMask - This decodes the shuffle masks for unpcklps/unpcklpd -/// etc. NElts indicates the number of elements in the vector allowing it to -/// handle different datatypes and vector widths. -void DecodeUNPCKLPMask(unsigned NElts, +/// etc. VT indicates the type of the vector allowing it to handle different +/// datatypes and vector widths. +void DecodeUNPCKLPMask(EVT VT, SmallVectorImpl &ShuffleMask); } // llvm namespace diff --git a/contrib/llvm/lib/Target/X86/X86.td b/contrib/llvm/lib/Target/X86/X86.td index efb6c8c0adc6..25b8d3ea1d21 100644 --- a/contrib/llvm/lib/Target/X86/X86.td +++ b/contrib/llvm/lib/Target/X86/X86.td @@ -1,13 +1,13 @@ //===- X86.td - Target definition file for the Intel X86 ---*- tablegen -*-===// -// +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This is a target description file for the Intel i386 architecture, refered to +// This is a target description file for the Intel i386 architecture, referred to // here as the "X86" architecture. // //===----------------------------------------------------------------------===// @@ -32,7 +32,7 @@ def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX", def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", "Enable SSE instructions", // SSE codegen depends on cmovs, and all - // SSE1+ processors support them. + // SSE1+ processors support them. [FeatureMMX, FeatureCMOV]>; def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", "Enable SSE2 instructions", @@ -50,7 +50,8 @@ def FeatureSSE42 : SubtargetFeature<"sse42", "X86SSELevel", "SSE42", "Enable SSE 4.2 instructions", [FeatureSSE41, FeaturePOPCNT]>; def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", - "Enable 3DNow! instructions">; + "Enable 3DNow! instructions", + [FeatureMMX]>; def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", "Enable 3DNow! Athlon instructions", [Feature3DNow]>; @@ -125,10 +126,10 @@ def : Proc<"sandybridge", [FeatureSSE42, Feature64Bit, FeatureAES, FeatureCLMUL]>; def : Proc<"k6", [FeatureMMX]>; -def : Proc<"k6-2", [FeatureMMX, Feature3DNow]>; -def : Proc<"k6-3", [FeatureMMX, Feature3DNow]>; -def : Proc<"athlon", [FeatureMMX, Feature3DNowA, FeatureSlowBTMem]>; -def : Proc<"athlon-tbird", [FeatureMMX, Feature3DNowA, FeatureSlowBTMem]>; +def : Proc<"k6-2", [Feature3DNow]>; +def : Proc<"k6-3", [Feature3DNow]>; +def : Proc<"athlon", [Feature3DNowA, FeatureSlowBTMem]>; +def : Proc<"athlon-tbird", [Feature3DNowA, FeatureSlowBTMem]>; def : Proc<"athlon-4", [FeatureSSE1, Feature3DNowA, FeatureSlowBTMem]>; def : Proc<"athlon-xp", [FeatureSSE1, Feature3DNowA, FeatureSlowBTMem]>; def : Proc<"athlon-mp", [FeatureSSE1, Feature3DNowA, FeatureSlowBTMem]>; @@ -156,8 +157,8 @@ def : Proc<"shanghai", [Feature3DNowA, Feature64Bit, FeatureSSE4A, Feature3DNowA]>; def : Proc<"winchip-c6", [FeatureMMX]>; -def : Proc<"winchip2", [FeatureMMX, Feature3DNow]>; -def : Proc<"c3", [FeatureMMX, Feature3DNow]>; +def : Proc<"winchip2", [Feature3DNow]>; +def : Proc<"c3", [Feature3DNow]>; def : Proc<"c3-2", [FeatureSSE1]>; //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Target/X86/X86AsmBackend.cpp b/contrib/llvm/lib/Target/X86/X86AsmBackend.cpp index da5f5b182ce9..4d7d96dcb36b 100644 --- a/contrib/llvm/lib/Target/X86/X86AsmBackend.cpp +++ b/contrib/llvm/lib/Target/X86/X86AsmBackend.cpp @@ -21,6 +21,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/Object/MachOFormat.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -28,6 +29,13 @@ #include "llvm/Target/TargetAsmBackend.h" using namespace llvm; +// Option to allow disabling arithmetic relaxation to workaround PR9807, which +// is useful when running bitwise comparison experiments on Darwin. We should be +// able to remove this once PR9807 is resolved. +static cl::opt +MCDisableArithRelaxation("mc-x86-disable-arith-relaxation", + cl::desc("Disable relaxation of arithmetic instruction for X86")); + static unsigned getFixupKindLog2Size(unsigned Kind) { switch (Kind) { default: assert(0 && "invalid fixup kind!"); @@ -201,6 +209,9 @@ bool X86AsmBackend::MayNeedRelaxation(const MCInst &Inst) const { if (getRelaxedOpcodeBranch(Inst.getOpcode()) != Inst.getOpcode()) return true; + if (MCDisableArithRelaxation) + return false; + // Check if this instruction is ever relaxable. if (getRelaxedOpcodeArith(Inst.getOpcode()) == Inst.getOpcode()) return false; @@ -307,10 +318,13 @@ class ELFX86_32AsmBackend : public ELFX86AsmBackend { : ELFX86AsmBackend(T, OSType) {} MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - return createELFObjectWriter(new X86ELFObjectWriter(false, OSType, - ELF::EM_386, false), + return createELFObjectWriter(createELFObjectTargetWriter(), OS, /*IsLittleEndian*/ true); } + + MCELFObjectTargetWriter *createELFObjectTargetWriter() const { + return new X86ELFObjectWriter(false, OSType, ELF::EM_386, false); + } }; class ELFX86_64AsmBackend : public ELFX86AsmBackend { @@ -319,10 +333,13 @@ class ELFX86_64AsmBackend : public ELFX86AsmBackend { : ELFX86AsmBackend(T, OSType) {} MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - return createELFObjectWriter(new X86ELFObjectWriter(true, OSType, - ELF::EM_X86_64, true), + return createELFObjectWriter(createELFObjectTargetWriter(), OS, /*IsLittleEndian*/ true); } + + MCELFObjectTargetWriter *createELFObjectTargetWriter() const { + return new X86ELFObjectWriter(true, OSType, ELF::EM_X86_64, true); + } }; class WindowsX86AsmBackend : public X86AsmBackend { @@ -408,34 +425,26 @@ class DarwinX86_64AsmBackend : public DarwinX86AsmBackend { TargetAsmBackend *llvm::createX86_32AsmBackend(const Target &T, const std::string &TT) { - switch (Triple(TT).getOS()) { - case Triple::Darwin: + Triple TheTriple(TT); + + if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) return new DarwinX86_32AsmBackend(T); - case Triple::MinGW32: - case Triple::Cygwin: - case Triple::Win32: - if (Triple(TT).getEnvironment() == Triple::MachO) - return new DarwinX86_32AsmBackend(T); - else - return new WindowsX86AsmBackend(T, false); - default: - return new ELFX86_32AsmBackend(T, Triple(TT).getOS()); - } + + if (TheTriple.isOSWindows()) + return new WindowsX86AsmBackend(T, false); + + return new ELFX86_32AsmBackend(T, TheTriple.getOS()); } TargetAsmBackend *llvm::createX86_64AsmBackend(const Target &T, const std::string &TT) { - switch (Triple(TT).getOS()) { - case Triple::Darwin: + Triple TheTriple(TT); + + if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) return new DarwinX86_64AsmBackend(T); - case Triple::MinGW32: - case Triple::Cygwin: - case Triple::Win32: - if (Triple(TT).getEnvironment() == Triple::MachO) - return new DarwinX86_64AsmBackend(T); - else - return new WindowsX86AsmBackend(T, true); - default: - return new ELFX86_64AsmBackend(T, Triple(TT).getOS()); - } + + if (TheTriple.isOSWindows()) + return new WindowsX86AsmBackend(T, true); + + return new ELFX86_64AsmBackend(T, TheTriple.getOS()); } diff --git a/contrib/llvm/lib/Target/X86/X86AsmPrinter.cpp b/contrib/llvm/lib/Target/X86/X86AsmPrinter.cpp index 99b4479a9fc9..c2d53c4dd26c 100644 --- a/contrib/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/contrib/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -709,12 +709,13 @@ void X86AsmPrinter::PrintDebugValueComment(const MachineInstr *MI, //===----------------------------------------------------------------------===// static MCInstPrinter *createX86MCInstPrinter(const Target &T, + TargetMachine &TM, unsigned SyntaxVariant, const MCAsmInfo &MAI) { if (SyntaxVariant == 0) - return new X86ATTInstPrinter(MAI); + return new X86ATTInstPrinter(TM, MAI); if (SyntaxVariant == 1) - return new X86IntelInstPrinter(MAI); + return new X86IntelInstPrinter(TM, MAI); return 0; } diff --git a/contrib/llvm/lib/Target/X86/X86CallingConv.td b/contrib/llvm/lib/Target/X86/X86CallingConv.td index a44fb694e725..56351756e8dd 100644 --- a/contrib/llvm/lib/Target/X86/X86CallingConv.td +++ b/contrib/llvm/lib/Target/X86/X86CallingConv.td @@ -215,6 +215,13 @@ def CC_X86_Win64_C : CallingConv<[ // The first 4 integer arguments are passed in integer registers. CCIfType<[i32], CCAssignToRegWithShadow<[ECX , EDX , R8D , R9D ], [XMM0, XMM1, XMM2, XMM3]>>, + + // Do not pass the sret argument in RCX, the Win64 thiscall calling + // convention requires "this" to be passed in RCX. + CCIfCC<"CallingConv::X86_ThisCall", + CCIfSRet>>>, + CCIfType<[i64], CCAssignToRegWithShadow<[RCX , RDX , R8 , R9 ], [XMM0, XMM1, XMM2, XMM3]>>, diff --git a/contrib/llvm/lib/Target/X86/X86CodeEmitter.cpp b/contrib/llvm/lib/Target/X86/X86CodeEmitter.cpp index 60d9d4ad064e..421e221d205c 100644 --- a/contrib/llvm/lib/Target/X86/X86CodeEmitter.cpp +++ b/contrib/llvm/lib/Target/X86/X86CodeEmitter.cpp @@ -652,6 +652,8 @@ void Emitter::emitInstruction(MachineInstr &MI, case X86II::TB: // Two-byte opcode prefix case X86II::T8: // 0F 38 case X86II::TA: // 0F 3A + case X86II::A6: // 0F A6 + case X86II::A7: // 0F A7 Need0FPrefix = true; break; case X86II::TF: // F2 0F 38 @@ -695,6 +697,12 @@ void Emitter::emitInstruction(MachineInstr &MI, case X86II::TA: // 0F 3A MCE.emitByte(0x3A); break; + case X86II::A6: // 0F A6 + MCE.emitByte(0xA6); + break; + case X86II::A7: // 0F A7 + MCE.emitByte(0xA7); + break; } // If this is a two-address instruction, skip one of the register operands. diff --git a/contrib/llvm/lib/Target/X86/X86FastISel.cpp b/contrib/llvm/lib/Target/X86/X86FastISel.cpp index 6fa928462b28..1382f184c343 100644 --- a/contrib/llvm/lib/Target/X86/X86FastISel.cpp +++ b/contrib/llvm/lib/Target/X86/X86FastISel.cpp @@ -23,6 +23,7 @@ #include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" @@ -77,10 +78,8 @@ class X86FastISel : public FastISel { bool X86FastEmitLoad(EVT VT, const X86AddressMode &AM, unsigned &RR); - bool X86FastEmitStore(EVT VT, const Value *Val, - const X86AddressMode &AM); - bool X86FastEmitStore(EVT VT, unsigned Val, - const X86AddressMode &AM); + bool X86FastEmitStore(EVT VT, const Value *Val, const X86AddressMode &AM); + bool X86FastEmitStore(EVT VT, unsigned Val, const X86AddressMode &AM); bool X86FastEmitExtend(ISD::NodeType Opc, EVT DstVT, unsigned Src, EVT SrcVT, unsigned &ResultReg); @@ -125,6 +124,8 @@ class X86FastISel : public FastISel { unsigned TargetMaterializeAlloca(const AllocaInst *C); + unsigned TargetMaterializeFloatZero(const ConstantFP *CF); + /// isScalarFPTypeInSSEReg - Return true if the specified scalar FP type is /// computed in an SSE register, not on the X87 floating point stack. bool isScalarFPTypeInSSEReg(EVT VT) const { @@ -133,6 +134,9 @@ class X86FastISel : public FastISel { } bool isTypeLegal(const Type *Ty, MVT &VT, bool AllowI1 = false); + + bool TryEmitSmallMemcpy(X86AddressMode DestAM, + X86AddressMode SrcAM, uint64_t Len); }; } // end anonymous namespace. @@ -224,8 +228,7 @@ bool X86FastISel::X86FastEmitLoad(EVT VT, const X86AddressMode &AM, /// and a displacement offset, or a GlobalAddress, /// i.e. V. Return true if it is possible. bool -X86FastISel::X86FastEmitStore(EVT VT, unsigned Val, - const X86AddressMode &AM) { +X86FastISel::X86FastEmitStore(EVT VT, unsigned Val, const X86AddressMode &AM) { // Get opcode and regclass of the output for the given store instruction. unsigned Opc = 0; switch (VT.getSimpleVT().SimpleTy) { @@ -395,37 +398,45 @@ bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) { const Value *Op = *i; if (const StructType *STy = dyn_cast(*GTI)) { const StructLayout *SL = TD.getStructLayout(STy); - unsigned Idx = cast(Op)->getZExtValue(); - Disp += SL->getElementOffset(Idx); - } else { - uint64_t S = TD.getTypeAllocSize(GTI.getIndexedType()); - SmallVector Worklist; - Worklist.push_back(Op); - do { - Op = Worklist.pop_back_val(); - if (const ConstantInt *CI = dyn_cast(Op)) { - // Constant-offset addressing. - Disp += CI->getSExtValue() * S; - } else if (isa(Op) && - isa(cast(Op)->getOperand(1))) { - // An add with a constant operand. Fold the constant. - ConstantInt *CI = - cast(cast(Op)->getOperand(1)); - Disp += CI->getSExtValue() * S; - // Add the other operand back to the work list. - Worklist.push_back(cast(Op)->getOperand(0)); - } else if (IndexReg == 0 && - (!AM.GV || !Subtarget->isPICStyleRIPRel()) && - (S == 1 || S == 2 || S == 4 || S == 8)) { - // Scaled-index addressing. - Scale = S; - IndexReg = getRegForGEPIndex(Op).first; - if (IndexReg == 0) - return false; - } else - // Unsupported. - goto unsupported_gep; - } while (!Worklist.empty()); + Disp += SL->getElementOffset(cast(Op)->getZExtValue()); + continue; + } + + // A array/variable index is always of the form i*S where S is the + // constant scale size. See if we can push the scale into immediates. + uint64_t S = TD.getTypeAllocSize(GTI.getIndexedType()); + for (;;) { + if (const ConstantInt *CI = dyn_cast(Op)) { + // Constant-offset addressing. + Disp += CI->getSExtValue() * S; + break; + } + if (isa(Op) && + (!isa(Op) || + FuncInfo.MBBMap[cast(Op)->getParent()] + == FuncInfo.MBB) && + isa(cast(Op)->getOperand(1))) { + // An add (in the same block) with a constant operand. Fold the + // constant. + ConstantInt *CI = + cast(cast(Op)->getOperand(1)); + Disp += CI->getSExtValue() * S; + // Iterate on the other operand. + Op = cast(Op)->getOperand(0); + continue; + } + if (IndexReg == 0 && + (!AM.GV || !Subtarget->isPICStyleRIPRel()) && + (S == 1 || S == 2 || S == 4 || S == 8)) { + // Scaled-index addressing. + Scale = S; + IndexReg = getRegForGEPIndex(Op).first; + if (IndexReg == 0) + return false; + break; + } + // Unsupported. + goto unsupported_gep; } } // Check for displacement overflow. @@ -439,7 +450,7 @@ bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) { if (X86SelectAddress(U->getOperand(0), AM)) return true; - // If we couldn't merge the sub value into this addr mode, revert back to + // If we couldn't merge the gep value into this addr mode, revert back to // our address and just match the value instead of completely failing. AM = SavedAM; break; @@ -451,91 +462,91 @@ bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) { // Handle constant address. if (const GlobalValue *GV = dyn_cast(V)) { - // Can't handle alternate code models yet. + // Can't handle alternate code models or TLS yet. if (TM.getCodeModel() != CodeModel::Small) return false; - // RIP-relative addresses can't have additional register operands. - if (Subtarget->isPICStyleRIPRel() && - (AM.Base.Reg != 0 || AM.IndexReg != 0)) - return false; - - // Can't handle TLS yet. if (const GlobalVariable *GVar = dyn_cast(GV)) if (GVar->isThreadLocal()) return false; + + // RIP-relative addresses can't have additional register operands, so if + // we've already folded stuff into the addressing mode, just force the + // global value into its own register, which we can use as the basereg. + if (!Subtarget->isPICStyleRIPRel() || + (AM.Base.Reg == 0 && AM.IndexReg == 0)) { + // Okay, we've committed to selecting this global. Set up the address. + AM.GV = GV; - // Okay, we've committed to selecting this global. Set up the basic address. - AM.GV = GV; + // Allow the subtarget to classify the global. + unsigned char GVFlags = Subtarget->ClassifyGlobalReference(GV, TM); - // Allow the subtarget to classify the global. - unsigned char GVFlags = Subtarget->ClassifyGlobalReference(GV, TM); - - // If this reference is relative to the pic base, set it now. - if (isGlobalRelativeToPICBase(GVFlags)) { - // FIXME: How do we know Base.Reg is free?? - AM.Base.Reg = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF); - } - - // Unless the ABI requires an extra load, return a direct reference to - // the global. - if (!isGlobalStubReference(GVFlags)) { - if (Subtarget->isPICStyleRIPRel()) { - // Use rip-relative addressing if we can. Above we verified that the - // base and index registers are unused. - assert(AM.Base.Reg == 0 && AM.IndexReg == 0); - AM.Base.Reg = X86::RIP; + // If this reference is relative to the pic base, set it now. + if (isGlobalRelativeToPICBase(GVFlags)) { + // FIXME: How do we know Base.Reg is free?? + AM.Base.Reg = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF); } - AM.GVOpFlags = GVFlags; + + // Unless the ABI requires an extra load, return a direct reference to + // the global. + if (!isGlobalStubReference(GVFlags)) { + if (Subtarget->isPICStyleRIPRel()) { + // Use rip-relative addressing if we can. Above we verified that the + // base and index registers are unused. + assert(AM.Base.Reg == 0 && AM.IndexReg == 0); + AM.Base.Reg = X86::RIP; + } + AM.GVOpFlags = GVFlags; + return true; + } + + // Ok, we need to do a load from a stub. If we've already loaded from + // this stub, reuse the loaded pointer, otherwise emit the load now. + DenseMap::iterator I = LocalValueMap.find(V); + unsigned LoadReg; + if (I != LocalValueMap.end() && I->second != 0) { + LoadReg = I->second; + } else { + // Issue load from stub. + unsigned Opc = 0; + const TargetRegisterClass *RC = NULL; + X86AddressMode StubAM; + StubAM.Base.Reg = AM.Base.Reg; + StubAM.GV = GV; + StubAM.GVOpFlags = GVFlags; + + // Prepare for inserting code in the local-value area. + SavePoint SaveInsertPt = enterLocalValueArea(); + + if (TLI.getPointerTy() == MVT::i64) { + Opc = X86::MOV64rm; + RC = X86::GR64RegisterClass; + + if (Subtarget->isPICStyleRIPRel()) + StubAM.Base.Reg = X86::RIP; + } else { + Opc = X86::MOV32rm; + RC = X86::GR32RegisterClass; + } + + LoadReg = createResultReg(RC); + MachineInstrBuilder LoadMI = + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), LoadReg); + addFullAddress(LoadMI, StubAM); + + // Ok, back to normal mode. + leaveLocalValueArea(SaveInsertPt); + + // Prevent loading GV stub multiple times in same MBB. + LocalValueMap[V] = LoadReg; + } + + // Now construct the final address. Note that the Disp, Scale, + // and Index values may already be set here. + AM.Base.Reg = LoadReg; + AM.GV = 0; return true; } - - // Ok, we need to do a load from a stub. If we've already loaded from this - // stub, reuse the loaded pointer, otherwise emit the load now. - DenseMap::iterator I = LocalValueMap.find(V); - unsigned LoadReg; - if (I != LocalValueMap.end() && I->second != 0) { - LoadReg = I->second; - } else { - // Issue load from stub. - unsigned Opc = 0; - const TargetRegisterClass *RC = NULL; - X86AddressMode StubAM; - StubAM.Base.Reg = AM.Base.Reg; - StubAM.GV = GV; - StubAM.GVOpFlags = GVFlags; - - // Prepare for inserting code in the local-value area. - SavePoint SaveInsertPt = enterLocalValueArea(); - - if (TLI.getPointerTy() == MVT::i64) { - Opc = X86::MOV64rm; - RC = X86::GR64RegisterClass; - - if (Subtarget->isPICStyleRIPRel()) - StubAM.Base.Reg = X86::RIP; - } else { - Opc = X86::MOV32rm; - RC = X86::GR32RegisterClass; - } - - LoadReg = createResultReg(RC); - MachineInstrBuilder LoadMI = - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), LoadReg); - addFullAddress(LoadMI, StubAM); - - // Ok, back to normal mode. - leaveLocalValueArea(SaveInsertPt); - - // Prevent loading GV stub multiple times in same MBB. - LocalValueMap[V] = LoadReg; - } - - // Now construct the final address. Note that the Disp, Scale, - // and Index values may already be set here. - AM.Base.Reg = LoadReg; - AM.GV = 0; - return true; } // If all else fails, try to materialize the value in a register. @@ -856,12 +867,9 @@ bool X86FastISel::X86SelectCmp(const Instruction *I) { unsigned NEReg = createResultReg(&X86::GR8RegClass); unsigned PReg = createResultReg(&X86::GR8RegClass); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, - TII.get(X86::SETNEr), NEReg); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, - TII.get(X86::SETPr), PReg); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, - TII.get(X86::OR8rr), ResultReg) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::SETNEr), NEReg); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::SETPr), PReg); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::OR8rr),ResultReg) .addReg(PReg).addReg(NEReg); UpdateValueMap(I, ResultReg); return true; @@ -1059,14 +1067,49 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) { } } } + } else if (TruncInst *TI = dyn_cast(BI->getCondition())) { + // Handle things like "%cond = trunc i32 %X to i1 / br i1 %cond", which + // typically happen for _Bool and C++ bools. + MVT SourceVT; + if (TI->hasOneUse() && TI->getParent() == I->getParent() && + isTypeLegal(TI->getOperand(0)->getType(), SourceVT)) { + unsigned TestOpc = 0; + switch (SourceVT.SimpleTy) { + default: break; + case MVT::i8: TestOpc = X86::TEST8ri; break; + case MVT::i16: TestOpc = X86::TEST16ri; break; + case MVT::i32: TestOpc = X86::TEST32ri; break; + case MVT::i64: TestOpc = X86::TEST64ri32; break; + } + if (TestOpc) { + unsigned OpReg = getRegForValue(TI->getOperand(0)); + if (OpReg == 0) return false; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TestOpc)) + .addReg(OpReg).addImm(1); + + unsigned JmpOpc = X86::JNE_4; + if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) { + std::swap(TrueMBB, FalseMBB); + JmpOpc = X86::JE_4; + } + + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(JmpOpc)) + .addMBB(TrueMBB); + FastEmitBranch(FalseMBB, DL); + FuncInfo.MBB->addSuccessor(TrueMBB); + return true; + } + } } // Otherwise do a clumsy setcc and re-test it. + // Note that i1 essentially gets ANY_EXTEND'ed to i8 where it isn't used + // in an explicit cast, so make sure to handle that correctly. unsigned OpReg = getRegForValue(BI->getCondition()); if (OpReg == 0) return false; - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::TEST8rr)) - .addReg(OpReg).addReg(OpReg); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::TEST8ri)) + .addReg(OpReg).addImm(1); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::JNE_4)) .addMBB(TrueMBB); FastEmitBranch(FalseMBB, DL); @@ -1075,42 +1118,42 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) { } bool X86FastISel::X86SelectShift(const Instruction *I) { - unsigned CReg = 0, OpReg = 0, OpImm = 0; + unsigned CReg = 0, OpReg = 0; const TargetRegisterClass *RC = NULL; if (I->getType()->isIntegerTy(8)) { CReg = X86::CL; RC = &X86::GR8RegClass; switch (I->getOpcode()) { - case Instruction::LShr: OpReg = X86::SHR8rCL; OpImm = X86::SHR8ri; break; - case Instruction::AShr: OpReg = X86::SAR8rCL; OpImm = X86::SAR8ri; break; - case Instruction::Shl: OpReg = X86::SHL8rCL; OpImm = X86::SHL8ri; break; + case Instruction::LShr: OpReg = X86::SHR8rCL; break; + case Instruction::AShr: OpReg = X86::SAR8rCL; break; + case Instruction::Shl: OpReg = X86::SHL8rCL; break; default: return false; } } else if (I->getType()->isIntegerTy(16)) { CReg = X86::CX; RC = &X86::GR16RegClass; switch (I->getOpcode()) { - case Instruction::LShr: OpReg = X86::SHR16rCL; OpImm = X86::SHR16ri; break; - case Instruction::AShr: OpReg = X86::SAR16rCL; OpImm = X86::SAR16ri; break; - case Instruction::Shl: OpReg = X86::SHL16rCL; OpImm = X86::SHL16ri; break; + case Instruction::LShr: OpReg = X86::SHR16rCL; break; + case Instruction::AShr: OpReg = X86::SAR16rCL; break; + case Instruction::Shl: OpReg = X86::SHL16rCL; break; default: return false; } } else if (I->getType()->isIntegerTy(32)) { CReg = X86::ECX; RC = &X86::GR32RegClass; switch (I->getOpcode()) { - case Instruction::LShr: OpReg = X86::SHR32rCL; OpImm = X86::SHR32ri; break; - case Instruction::AShr: OpReg = X86::SAR32rCL; OpImm = X86::SAR32ri; break; - case Instruction::Shl: OpReg = X86::SHL32rCL; OpImm = X86::SHL32ri; break; + case Instruction::LShr: OpReg = X86::SHR32rCL; break; + case Instruction::AShr: OpReg = X86::SAR32rCL; break; + case Instruction::Shl: OpReg = X86::SHL32rCL; break; default: return false; } } else if (I->getType()->isIntegerTy(64)) { CReg = X86::RCX; RC = &X86::GR64RegClass; switch (I->getOpcode()) { - case Instruction::LShr: OpReg = X86::SHR64rCL; OpImm = X86::SHR64ri; break; - case Instruction::AShr: OpReg = X86::SAR64rCL; OpImm = X86::SAR64ri; break; - case Instruction::Shl: OpReg = X86::SHL64rCL; OpImm = X86::SHL64ri; break; + case Instruction::LShr: OpReg = X86::SHR64rCL; break; + case Instruction::AShr: OpReg = X86::SAR64rCL; break; + case Instruction::Shl: OpReg = X86::SHL64rCL; break; default: return false; } } else { @@ -1124,15 +1167,6 @@ bool X86FastISel::X86SelectShift(const Instruction *I) { unsigned Op0Reg = getRegForValue(I->getOperand(0)); if (Op0Reg == 0) return false; - // Fold immediate in shl(x,3). - if (const ConstantInt *CI = dyn_cast(I->getOperand(1))) { - unsigned ResultReg = createResultReg(RC); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(OpImm), - ResultReg).addReg(Op0Reg).addImm(CI->getZExtValue() & 0xff); - UpdateValueMap(I, ResultReg); - return true; - } - unsigned Op1Reg = getRegForValue(I->getOperand(1)); if (Op1Reg == 0) return false; BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), @@ -1294,10 +1328,61 @@ bool X86FastISel::X86SelectExtractValue(const Instruction *I) { return false; } +bool X86FastISel::TryEmitSmallMemcpy(X86AddressMode DestAM, + X86AddressMode SrcAM, uint64_t Len) { + // Make sure we don't bloat code by inlining very large memcpy's. + bool i64Legal = TLI.isTypeLegal(MVT::i64); + if (Len > (i64Legal ? 32 : 16)) return false; + + // We don't care about alignment here since we just emit integer accesses. + while (Len) { + MVT VT; + if (Len >= 8 && i64Legal) + VT = MVT::i64; + else if (Len >= 4) + VT = MVT::i32; + else if (Len >= 2) + VT = MVT::i16; + else { + assert(Len == 1); + VT = MVT::i8; + } + + unsigned Reg; + bool RV = X86FastEmitLoad(VT, SrcAM, Reg); + RV &= X86FastEmitStore(VT, Reg, DestAM); + assert(RV && "Failed to emit load or store??"); + + unsigned Size = VT.getSizeInBits()/8; + Len -= Size; + DestAM.Disp += Size; + SrcAM.Disp += Size; + } + + return true; +} + bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) { // FIXME: Handle more intrinsics. switch (I.getIntrinsicID()) { default: return false; + case Intrinsic::memcpy: { + const MemCpyInst &MCI = cast(I); + // Don't handle volatile or variable length memcpys. + if (MCI.isVolatile() || !isa(MCI.getLength())) + return false; + + uint64_t Len = cast(MCI.getLength())->getZExtValue(); + + // Get the address of the dest and source addresses. + X86AddressMode DestAM, SrcAM; + if (!X86SelectAddress(MCI.getRawDest(), DestAM) || + !X86SelectAddress(MCI.getRawSource(), SrcAM)) + return false; + + return TryEmitSmallMemcpy(DestAM, SrcAM, Len); + } + case Intrinsic::stackprotector: { // Emit code inline code to store the stack guard onto the stack. EVT PtrTy = TLI.getPointerTy(); @@ -1308,17 +1393,14 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) { // Grab the frame index. X86AddressMode AM; if (!X86SelectAddress(Slot, AM)) return false; - if (!X86FastEmitStore(PtrTy, Op1, AM)) return false; - return true; } case Intrinsic::objectsize: { - ConstantInt *CI = dyn_cast(I.getArgOperand(1)); + // FIXME: This should be moved to generic code! + ConstantInt *CI = cast(I.getArgOperand(1)); const Type *Ty = I.getCalledFunction()->getReturnType(); - assert(CI && "Non-constant type in Intrinsic::objectsize?"); - MVT VT; if (!isTypeLegal(Ty, VT)) return false; @@ -1356,6 +1438,8 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) { } case Intrinsic::sadd_with_overflow: case Intrinsic::uadd_with_overflow: { + // FIXME: Should fold immediates. + // Replace "add with overflow" intrinsics with an "add" instruction followed // by a seto/setc instruction. Later on, when the "extractvalue" // instructions are encountered, we use the fact that two registers were @@ -1427,8 +1511,7 @@ bool X86FastISel::X86SelectCall(const Instruction *I) { // Handle only C and fastcc calling conventions for now. ImmutableCallSite CS(CI); CallingConv::ID CC = CS.getCallingConv(); - if (CC != CallingConv::C && - CC != CallingConv::Fast && + if (CC != CallingConv::C && CC != CallingConv::Fast && CC != CallingConv::X86_FastCall) return false; @@ -1437,14 +1520,17 @@ bool X86FastISel::X86SelectCall(const Instruction *I) { if (CC == CallingConv::Fast && GuaranteedTailCallOpt) return false; - // Let SDISel handle vararg functions. const PointerType *PT = cast(CS.getCalledValue()->getType()); const FunctionType *FTy = cast(PT->getElementType()); - if (FTy->isVarArg()) + bool isVarArg = FTy->isVarArg(); + + // Don't know how to handle Win64 varargs yet. Nothing special needed for + // x86-32. Special handling for x86-64 is implemented. + if (isVarArg && Subtarget->isTargetWin64()) return false; // Fast-isel doesn't know about callee-pop yet. - if (Subtarget->IsCalleePop(FTy->isVarArg(), CC)) + if (Subtarget->IsCalleePop(isVarArg, CC)) return false; // Handle *simple* calls for now. @@ -1487,9 +1573,7 @@ bool X86FastISel::X86SelectCall(const Instruction *I) { ArgFlags.reserve(CS.arg_size()); for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end(); i != e; ++i) { - unsigned Arg = getRegForValue(*i); - if (Arg == 0) - return false; + Value *ArgVal = *i; ISD::ArgFlagsTy Flags; unsigned AttrInd = i - CS.arg_begin() + 1; if (CS.paramHasAttr(AttrInd, Attribute::SExt)) @@ -1497,34 +1581,67 @@ bool X86FastISel::X86SelectCall(const Instruction *I) { if (CS.paramHasAttr(AttrInd, Attribute::ZExt)) Flags.setZExt(); + // If this is an i1/i8/i16 argument, promote to i32 to avoid an extra + // instruction. This is safe because it is common to all fastisel supported + // calling conventions on x86. + if (ConstantInt *CI = dyn_cast(ArgVal)) { + if (CI->getBitWidth() == 1 || CI->getBitWidth() == 8 || + CI->getBitWidth() == 16) { + if (Flags.isSExt()) + ArgVal = ConstantExpr::getSExt(CI,Type::getInt32Ty(CI->getContext())); + else + ArgVal = ConstantExpr::getZExt(CI,Type::getInt32Ty(CI->getContext())); + } + } + + unsigned ArgReg; + + // Passing bools around ends up doing a trunc to i1 and passing it. + // Codegen this as an argument + "and 1". + if (ArgVal->getType()->isIntegerTy(1) && isa(ArgVal) && + cast(ArgVal)->getParent() == I->getParent() && + ArgVal->hasOneUse()) { + ArgVal = cast(ArgVal)->getOperand(0); + ArgReg = getRegForValue(ArgVal); + if (ArgReg == 0) return false; + + MVT ArgVT; + if (!isTypeLegal(ArgVal->getType(), ArgVT)) return false; + + ArgReg = FastEmit_ri(ArgVT, ArgVT, ISD::AND, ArgReg, + ArgVal->hasOneUse(), 1); + } else { + ArgReg = getRegForValue(ArgVal); + } + + if (ArgReg == 0) return false; + // FIXME: Only handle *easy* calls for now. if (CS.paramHasAttr(AttrInd, Attribute::InReg) || - CS.paramHasAttr(AttrInd, Attribute::StructRet) || CS.paramHasAttr(AttrInd, Attribute::Nest) || CS.paramHasAttr(AttrInd, Attribute::ByVal)) return false; - const Type *ArgTy = (*i)->getType(); + const Type *ArgTy = ArgVal->getType(); MVT ArgVT; if (!isTypeLegal(ArgTy, ArgVT)) return false; unsigned OriginalAlignment = TD.getABITypeAlignment(ArgTy); Flags.setOrigAlign(OriginalAlignment); - Args.push_back(Arg); - ArgVals.push_back(*i); + Args.push_back(ArgReg); + ArgVals.push_back(ArgVal); ArgVTs.push_back(ArgVT); ArgFlags.push_back(Flags); } // Analyze operands of the call, assigning locations to each operand. SmallVector ArgLocs; - CCState CCInfo(CC, false, TM, ArgLocs, I->getParent()->getContext()); + CCState CCInfo(CC, isVarArg, TM, ArgLocs, I->getParent()->getContext()); // Allocate shadow area for Win64 - if (Subtarget->isTargetWin64()) { + if (Subtarget->isTargetWin64()) CCInfo.AllocateStack(32, 8); - } CCInfo.AnalyzeCallOperands(ArgVTs, ArgFlags, CC_X86); @@ -1618,6 +1735,17 @@ bool X86FastISel::X86SelectCall(const Instruction *I) { X86::EBX).addReg(Base); } + if (Subtarget->is64Bit() && isVarArg && !Subtarget->isTargetWin64()) { + // Count the number of XMM registers allocated. + static const unsigned XMMArgRegs[] = { + X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3, + X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7 + }; + unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs, 8); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::MOV8ri), + X86::AL).addImm(NumXMMRegs); + } + // Issue the call. MachineInstrBuilder MIB; if (CalleeOp) { @@ -1656,7 +1784,8 @@ bool X86FastISel::X86SelectCall(const Instruction *I) { OpFlags = X86II::MO_PLT; } else if (Subtarget->isPICStyleStubAny() && (GV->isDeclaration() || GV->isWeakForLinker()) && - Subtarget->getDarwinVers() < 9) { + (!Subtarget->getTargetTriple().isMacOSX() || + Subtarget->getTargetTriple().isMacOSXVersionLT(10, 5))) { // PC-relative references to external symbols should go through $stub, // unless we're building with the leopard linker or later, which // automatically synthesizes these stubs. @@ -1672,14 +1801,20 @@ bool X86FastISel::X86SelectCall(const Instruction *I) { if (Subtarget->isPICStyleGOT()) MIB.addReg(X86::EBX); + if (Subtarget->is64Bit() && isVarArg && !Subtarget->isTargetWin64()) + MIB.addReg(X86::AL); + // Add implicit physical register uses to the call. for (unsigned i = 0, e = RegArgs.size(); i != e; ++i) MIB.addReg(RegArgs[i]); // Issue CALLSEQ_END unsigned AdjStackUp = TM.getRegisterInfo()->getCallFrameDestroyOpcode(); + unsigned NumBytesCallee = 0; + if (!Subtarget->is64Bit() && CS.paramHasAttr(1, Attribute::StructRet)) + NumBytesCallee = 4; BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(AdjStackUp)) - .addImm(NumBytes).addImm(0); + .addImm(NumBytes).addImm(NumBytesCallee); // Now handle call return value (if any). SmallVector UsedRegs; @@ -1850,10 +1985,13 @@ unsigned X86FastISel::TargetMaterializeConstant(const Constant *C) { if (isa(C)) { X86AddressMode AM; if (X86SelectAddress(C, AM)) { - if (TLI.getPointerTy() == MVT::i32) - Opc = X86::LEA32r; - else - Opc = X86::LEA64r; + // If the expression is just a basereg, then we're done, otherwise we need + // to emit an LEA. + if (AM.BaseType == X86AddressMode::RegBase && + AM.IndexReg == 0 && AM.Disp == 0 && AM.GV == 0) + return AM.Base.Reg; + + Opc = TLI.getPointerTy() == MVT::i32 ? X86::LEA32r : X86::LEA64r; unsigned ResultReg = createResultReg(RC); addFullAddress(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), ResultReg), AM); @@ -1915,6 +2053,45 @@ unsigned X86FastISel::TargetMaterializeAlloca(const AllocaInst *C) { return ResultReg; } +unsigned X86FastISel::TargetMaterializeFloatZero(const ConstantFP *CF) { + MVT VT; + if (!isTypeLegal(CF->getType(), VT)) + return false; + + // Get opcode and regclass for the given zero. + unsigned Opc = 0; + const TargetRegisterClass *RC = NULL; + switch (VT.SimpleTy) { + default: return false; + case MVT::f32: + if (Subtarget->hasSSE1()) { + Opc = X86::FsFLD0SS; + RC = X86::FR32RegisterClass; + } else { + Opc = X86::LD_Fp032; + RC = X86::RFP32RegisterClass; + } + break; + case MVT::f64: + if (Subtarget->hasSSE2()) { + Opc = X86::FsFLD0SD; + RC = X86::FR64RegisterClass; + } else { + Opc = X86::LD_Fp064; + RC = X86::RFP64RegisterClass; + } + break; + case MVT::f80: + // No f80 support yet. + return false; + } + + unsigned ResultReg = createResultReg(RC); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), ResultReg); + return ResultReg; +} + + /// TryToFoldLoad - The specified machine instr operand is a vreg, and that /// vreg is being provided by the specified load instruction. If possible, /// try to fold the load as an operand to the instruction, returning true if diff --git a/contrib/llvm/lib/Target/X86/X86FloatingPoint.cpp b/contrib/llvm/lib/Target/X86/X86FloatingPoint.cpp index 3aaa69327976..325d0611817d 100644 --- a/contrib/llvm/lib/Target/X86/X86FloatingPoint.cpp +++ b/contrib/llvm/lib/Target/X86/X86FloatingPoint.cpp @@ -1307,7 +1307,7 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { // set up by FpSET_ST0, and our StackTop is off by one because of it. unsigned Op0 = getFPReg(MI->getOperand(0)); // Restore the actual StackTop from before Fp_SET_ST0. - // Note we can't handle Fp_SET_ST1 without a preceeding Fp_SET_ST0, and we + // Note we can't handle Fp_SET_ST1 without a preceding Fp_SET_ST0, and we // are not enforcing the constraint. ++StackTop; unsigned RegOnTop = getStackEntry(0); // This reg must remain in st(0). diff --git a/contrib/llvm/lib/Target/X86/X86FrameLowering.cpp b/contrib/llvm/lib/Target/X86/X86FrameLowering.cpp index 0a3f931acf93..06d12fc04a34 100644 --- a/contrib/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/contrib/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -22,6 +22,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/CommandLine.h" @@ -296,7 +297,7 @@ void X86FrameLowering::emitCalleeSavedFrameMoves(MachineFunction &MF, // FIXME: This is dirty hack. The code itself is pretty mess right now. // It should be rewritten from scratch and generalized sometimes. - // Determine maximum offset (minumum due to stack growth). + // Determine maximum offset (minimum due to stack growth). int64_t MaxOffset = 0; for (std::vector::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) @@ -551,65 +552,71 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const { // responsible for adjusting the stack pointer. Touching the stack at 4K // increments is necessary to ensure that the guard pages used by the OS // virtual memory manager are allocated in correct sequence. - if (NumBytes >= 4096 && - (STI.isTargetCygMing() || STI.isTargetWin32()) && - !STI.isTargetEnvMacho()) { + if (NumBytes >= 4096 && STI.isTargetCOFF() && !STI.isTargetEnvMacho()) { + const char *StackProbeSymbol; + bool isSPUpdateNeeded = false; + + if (Is64Bit) { + if (STI.isTargetCygMing()) + StackProbeSymbol = "___chkstk"; + else { + StackProbeSymbol = "__chkstk"; + isSPUpdateNeeded = true; + } + } else if (STI.isTargetCygMing()) + StackProbeSymbol = "_alloca"; + else + StackProbeSymbol = "_chkstk"; + // Check whether EAX is livein for this function. bool isEAXAlive = isEAXLiveIn(MF); - const char *StackProbeSymbol = - STI.isTargetWindows() ? "_chkstk" : "_alloca"; - if (Is64Bit && STI.isTargetCygMing()) - StackProbeSymbol = "__chkstk"; - unsigned CallOp = Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32; - if (!isEAXAlive) { - BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) - .addImm(NumBytes); - BuildMI(MBB, MBBI, DL, TII.get(CallOp)) - .addExternalSymbol(StackProbeSymbol) - .addReg(StackPtr, RegState::Define | RegState::Implicit) - .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit); - } else { + if (isEAXAlive) { + // Sanity check that EAX is not livein for this function. + // It should not be, so throw an assert. + assert(!Is64Bit && "EAX is livein in x64 case!"); + // Save EAX BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r)) .addReg(X86::EAX, RegState::Kill); - - // Allocate NumBytes-4 bytes on stack. We'll also use 4 already - // allocated bytes for EAX. - BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) - .addImm(NumBytes - 4); - BuildMI(MBB, MBBI, DL, TII.get(CallOp)) - .addExternalSymbol(StackProbeSymbol) - .addReg(StackPtr, RegState::Define | RegState::Implicit) - .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit); - - // Restore EAX - MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm), - X86::EAX), - StackPtr, false, NumBytes - 4); - MBB.insert(MBBI, MI); } - } else if (NumBytes >= 4096 && - STI.isTargetWin64() && - !STI.isTargetEnvMacho()) { - // Sanity check that EAX is not livein for this function. It should - // not be, so throw an assert. - assert(!isEAXLiveIn(MF) && "EAX is livein in the Win64 case!"); - // Handle the 64-bit Windows ABI case where we need to call __chkstk. - // Function prologue is responsible for adjusting the stack pointer. - BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) - .addImm(NumBytes); - BuildMI(MBB, MBBI, DL, TII.get(X86::WINCALL64pcrel32)) - .addExternalSymbol("__chkstk") - .addReg(StackPtr, RegState::Define | RegState::Implicit); - emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, - TII, *RegInfo); + if (Is64Bit) { + // Handle the 64-bit Windows ABI case where we need to call __chkstk. + // Function prologue is responsible for adjusting the stack pointer. + BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), X86::RAX) + .addImm(NumBytes); + } else { + // Allocate NumBytes-4 bytes on stack in case of isEAXAlive. + // We'll also use 4 already allocated bytes for EAX. + BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) + .addImm(isEAXAlive ? NumBytes - 4 : NumBytes); + } + + BuildMI(MBB, MBBI, DL, + TII.get(Is64Bit ? X86::W64ALLOCA : X86::CALLpcrel32)) + .addExternalSymbol(StackProbeSymbol) + .addReg(StackPtr, RegState::Define | RegState::Implicit) + .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit); + + // MSVC x64's __chkstk needs to adjust %rsp. + // FIXME: %rax preserves the offset and should be available. + if (isSPUpdateNeeded) + emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, + TII, *RegInfo); + + if (isEAXAlive) { + // Restore EAX + MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm), + X86::EAX), + StackPtr, false, NumBytes - 4); + MBB.insert(MBBI, MI); + } } else if (NumBytes) emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII, *RegInfo); - if ((NumBytes || PushedRegs) && needsFrameMoves) { + if (( (!HasFP && NumBytes) || PushedRegs) && needsFrameMoves) { // Mark end of stack pointer adjustment. MCSymbol *Label = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(Label); @@ -779,7 +786,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, assert(Offset >= 0 && "Offset should never be negative"); if (Offset) { - // Check for possible merge with preceeding ADD instruction. + // Check for possible merge with preceding ADD instruction. Offset += mergeSPUpdates(MBB, MBBI, StackPtr, true); emitSPUpdate(MBB, MBBI, StackPtr, Offset, Is64Bit, TII, *RegInfo); } @@ -823,7 +830,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, int delta = -1*X86FI->getTCReturnAddrDelta(); MBBI = MBB.getLastNonDebugInstr(); - // Check for possible merge with preceeding ADD instruction. + // Check for possible merge with preceding ADD instruction. delta += mergeSPUpdates(MBB, MBBI, StackPtr, true); emitSPUpdate(MBB, MBBI, StackPtr, delta, Is64Bit, TII, *RegInfo); } @@ -892,7 +899,6 @@ bool X86FrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineFunction &MF = *MBB.getParent(); - bool isWin64 = STI.isTargetWin64(); unsigned SlotSize = STI.is64Bit() ? 8 : 4; unsigned FPReg = TRI->getFrameRegister(MF); unsigned CalleeFrameSize = 0; @@ -900,25 +906,39 @@ bool X86FrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); X86MachineFunctionInfo *X86FI = MF.getInfo(); + // Push GPRs. It increases frame size. unsigned Opc = STI.is64Bit() ? X86::PUSH64r : X86::PUSH32r; for (unsigned i = CSI.size(); i != 0; --i) { unsigned Reg = CSI[i-1].getReg(); + if (!X86::GR64RegClass.contains(Reg) && + !X86::GR32RegClass.contains(Reg)) + continue; // Add the callee-saved register as live-in. It's killed at the spill. MBB.addLiveIn(Reg); if (Reg == FPReg) // X86RegisterInfo::emitPrologue will handle spilling of frame register. continue; - if (!X86::VR128RegClass.contains(Reg) && !isWin64) { - CalleeFrameSize += SlotSize; - BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, RegState::Kill); - } else { - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i-1].getFrameIdx(), - RC, TRI); - } + CalleeFrameSize += SlotSize; + BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, RegState::Kill); } X86FI->setCalleeSavedFrameSize(CalleeFrameSize); + + // Make XMM regs spilled. X86 does not have ability of push/pop XMM. + // It can be done by spilling XMMs to stack frame. + // Note that only Win64 ABI might spill XMMs. + for (unsigned i = CSI.size(); i != 0; --i) { + unsigned Reg = CSI[i-1].getReg(); + if (X86::GR64RegClass.contains(Reg) || + X86::GR32RegClass.contains(Reg)) + continue; + // Add the callee-saved register as live-in. It's killed at the spill. + MBB.addLiveIn(Reg); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i-1].getFrameIdx(), + RC, TRI); + } + return true; } @@ -933,21 +953,30 @@ bool X86FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineFunction &MF = *MBB.getParent(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + // Reload XMMs from stack frame. + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + if (X86::GR64RegClass.contains(Reg) || + X86::GR32RegClass.contains(Reg)) + continue; + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), + RC, TRI); + } + + // POP GPRs. unsigned FPReg = TRI->getFrameRegister(MF); - bool isWin64 = STI.isTargetWin64(); unsigned Opc = STI.is64Bit() ? X86::POP64r : X86::POP32r; for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); + if (!X86::GR64RegClass.contains(Reg) && + !X86::GR32RegClass.contains(Reg)) + continue; if (Reg == FPReg) // X86RegisterInfo::emitEpilogue will handle restoring of frame register. continue; - if (!X86::VR128RegClass.contains(Reg) && !isWin64) { - BuildMI(MBB, MI, DL, TII.get(Opc), Reg); - } else { - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), - RC, TRI); - } + BuildMI(MBB, MI, DL, TII.get(Opc), Reg); } return true; } diff --git a/contrib/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/contrib/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 9b0ec6e123fe..4534e853914d 100644 --- a/contrib/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1580,6 +1580,81 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) { return RetVal; break; } + case ISD::AND: + case ISD::OR: + case ISD::XOR: { + // For operations of the form (x << C1) op C2, check if we can use a smaller + // encoding for C2 by transforming it into (x op (C2>>C1)) << C1. + SDValue N0 = Node->getOperand(0); + SDValue N1 = Node->getOperand(1); + + if (N0->getOpcode() != ISD::SHL || !N0->hasOneUse()) + break; + + // i8 is unshrinkable, i16 should be promoted to i32. + if (NVT != MVT::i32 && NVT != MVT::i64) + break; + + ConstantSDNode *Cst = dyn_cast(N1); + ConstantSDNode *ShlCst = dyn_cast(N0->getOperand(1)); + if (!Cst || !ShlCst) + break; + + int64_t Val = Cst->getSExtValue(); + uint64_t ShlVal = ShlCst->getZExtValue(); + + // Make sure that we don't change the operation by removing bits. + // This only matters for OR and XOR, AND is unaffected. + if (Opcode != ISD::AND && ((Val >> ShlVal) << ShlVal) != Val) + break; + + unsigned ShlOp, Op = 0; + EVT CstVT = NVT; + + // Check the minimum bitwidth for the new constant. + // TODO: AND32ri is the same as AND64ri32 with zext imm. + // TODO: MOV32ri+OR64r is cheaper than MOV64ri64+OR64rr + // TODO: Using 16 and 8 bit operations is also possible for or32 & xor32. + if (!isInt<8>(Val) && isInt<8>(Val >> ShlVal)) + CstVT = MVT::i8; + else if (!isInt<32>(Val) && isInt<32>(Val >> ShlVal)) + CstVT = MVT::i32; + + // Bail if there is no smaller encoding. + if (NVT == CstVT) + break; + + switch (NVT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unsupported VT!"); + case MVT::i32: + assert(CstVT == MVT::i8); + ShlOp = X86::SHL32ri; + + switch (Opcode) { + case ISD::AND: Op = X86::AND32ri8; break; + case ISD::OR: Op = X86::OR32ri8; break; + case ISD::XOR: Op = X86::XOR32ri8; break; + } + break; + case MVT::i64: + assert(CstVT == MVT::i8 || CstVT == MVT::i32); + ShlOp = X86::SHL64ri; + + switch (Opcode) { + case ISD::AND: Op = CstVT==MVT::i8? X86::AND64ri8 : X86::AND64ri32; break; + case ISD::OR: Op = CstVT==MVT::i8? X86::OR64ri8 : X86::OR64ri32; break; + case ISD::XOR: Op = CstVT==MVT::i8? X86::XOR64ri8 : X86::XOR64ri32; break; + } + break; + } + + // Emit the smaller op and the shift. + SDValue NewCst = CurDAG->getTargetConstant(Val >> ShlVal, CstVT); + SDNode *New = CurDAG->getMachineNode(Op, dl, NVT, N0->getOperand(0),NewCst); + return CurDAG->SelectNodeTo(Node, ShlOp, NVT, SDValue(New, 0), + getI8Imm(ShlVal)); + break; + } case X86ISD::UMUL: { SDValue N0 = Node->getOperand(0); SDValue N1 = Node->getOperand(1); diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp index 2f49dbcebf3c..703c01d373ef 100644 --- a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -45,6 +45,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/VectorExtras.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" @@ -221,7 +222,13 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) // X86 is weird, it always uses i8 for shift amounts and setcc results. setBooleanContents(ZeroOrOneBooleanContent); - setSchedulingPreference(Sched::RegPressure); + + // For 64-bit since we have so many registers use the ILP scheduler, for + // 32-bit code use the register pressure specific scheduling. + if (Subtarget->is64Bit()) + setSchedulingPreference(Sched::ILP); + else + setSchedulingPreference(Sched::RegPressure); setStackPointerRegisterToSaveRestore(X86StackPtr); if (Subtarget->isTargetWindows() && !Subtarget->isTargetCygMing()) { @@ -543,12 +550,11 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); - if (Subtarget->is64Bit()) - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand); - if (Subtarget->isTargetCygMing() || Subtarget->isTargetWindows()) - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom); - else - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); + setOperationAction(ISD::DYNAMIC_STACKALLOC, + (Subtarget->is64Bit() ? MVT::i64 : MVT::i32), + (Subtarget->isTargetCOFF() + && !Subtarget->isTargetEnvMacho() + ? Custom : Expand)); if (!UseSoftFloat && X86ScalarSSEf64) { // f32 and f64 use SSE. @@ -921,6 +927,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) // Can turn SHL into an integer multiply. setOperationAction(ISD::SHL, MVT::v4i32, Custom); setOperationAction(ISD::SHL, MVT::v16i8, Custom); + setOperationAction(ISD::SRL, MVT::v4i32, Legal); // i8 and i16 vectors are custom , because the source register and source // source memory operand types are not the same width. f32 vectors are @@ -1271,27 +1278,6 @@ X86TargetLowering::findRepresentativeClass(EVT VT) const{ return std::make_pair(RRC, Cost); } -// FIXME: Why this routine is here? Move to RegInfo! -unsigned -X86TargetLowering::getRegPressureLimit(const TargetRegisterClass *RC, - MachineFunction &MF) const { - const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); - - unsigned FPDiff = TFI->hasFP(MF) ? 1 : 0; - switch (RC->getID()) { - default: - return 0; - case X86::GR32RegClassID: - return 4 - FPDiff; - case X86::GR64RegClassID: - return 8 - FPDiff; - case X86::VR128RegClassID: - return Subtarget->is64Bit() ? 10 : 4; - case X86::VR64RegClassID: - return 4; - } -} - bool X86TargetLowering::getStackCookieLocation(unsigned &AddressSpace, unsigned &Offset) const { if (!Subtarget->isTargetLinux()) @@ -1463,6 +1449,20 @@ bool X86TargetLowering::isUsedByReturnOnly(SDNode *N) const { return HasRet; } +EVT +X86TargetLowering::getTypeForExtArgOrReturn(LLVMContext &Context, EVT VT, + ISD::NodeType ExtendKind) const { + MVT ReturnMVT; + // TODO: Is this also valid on 32-bit? + if (Subtarget->is64Bit() && VT == MVT::i1 && ExtendKind == ISD::ZERO_EXTEND) + ReturnMVT = MVT::i8; + else + ReturnMVT = MVT::i32; + + EVT MinVT = getRegisterType(Context, ReturnMVT); + return VT.bitsLT(MinVT) ? MinVT : VT; +} + /// LowerCallResult - Lower the result values of a call into the /// appropriate copies out of appropriate physical registers. /// @@ -1595,6 +1595,18 @@ static bool IsTailCallConvention(CallingConv::ID CC) { return (CC == CallingConv::Fast || CC == CallingConv::GHC); } +bool X86TargetLowering::mayBeEmittedAsTailCall(CallInst *CI) const { + if (!CI->isTailCall()) + return false; + + CallSite CS(CI); + CallingConv::ID CalleeCC = CS.getCallingConv(); + if (!IsTailCallConvention(CalleeCC) && CalleeCC != CallingConv::C) + return false; + + return true; +} + /// FuncIsMadeTailCallSafe - Return true if the function is being made into /// a tailcall target by changing its ABI. static bool FuncIsMadeTailCallSafe(CallingConv::ID CC) { @@ -1627,8 +1639,9 @@ X86TargetLowering::LowerMemArgument(SDValue Chain, // In case of tail call optimization mark all arguments mutable. Since they // could be overwritten by lowering of arguments in case of a tail call. if (Flags.isByVal()) { - int FI = MFI->CreateFixedObject(Flags.getByValSize(), - VA.getLocMemOffset(), isImmutable); + unsigned Bytes = Flags.getByValSize(); + if (Bytes == 0) Bytes = 1; // Don't create zero-sized stack objects. + int FI = MFI->CreateFixedObject(Bytes, VA.getLocMemOffset(), isImmutable); return DAG.getFrameIndex(FI, getPointerTy()); } else { int FI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, @@ -1765,8 +1778,8 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, // If the function takes variable number of arguments, make a frame index for // the start of the first vararg value... for expansion of llvm.va_start. if (isVarArg) { - if (!IsWin64 && (Is64Bit || (CallConv != CallingConv::X86_FastCall && - CallConv != CallingConv::X86_ThisCall))) { + if (Is64Bit || (CallConv != CallingConv::X86_FastCall && + CallConv != CallingConv::X86_ThisCall)) { FuncInfo->setVarArgsFrameIndex(MFI->CreateFixedObject(1, StackSize,true)); } if (Is64Bit) { @@ -1818,7 +1831,9 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, int HomeOffset = TFI.getOffsetOfLocalArea() + 8; FuncInfo->setRegSaveFrameIndex( MFI->CreateFixedObject(1, NumIntRegs * 8 + HomeOffset, false)); - FuncInfo->setVarArgsFrameIndex(FuncInfo->getRegSaveFrameIndex()); + // Fixup to set vararg frame on shadow area (4 x i64). + if (NumIntRegs < 4) + FuncInfo->setVarArgsFrameIndex(FuncInfo->getRegSaveFrameIndex()); } else { // For X86-64, if there are vararg parameters that are passed via // registers, then we must store them to their spots on the stack so they @@ -1937,7 +1952,7 @@ X86TargetLowering::EmitTailCallLoadRetAddr(SelectionDAG &DAG, return SDValue(OutRetAddr.getNode(), 1); } -/// EmitTailCallStoreRetAddr - Emit a store of the return adress if tail call +/// EmitTailCallStoreRetAddr - Emit a store of the return address if tail call /// optimization is performed and it is required (FPDiff!=0). static SDValue EmitTailCallStoreRetAddr(SelectionDAG & DAG, MachineFunction &MF, @@ -2028,7 +2043,7 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); SDValue RetAddrFrIdx; - // Load return adress for tail calls. + // Load return address for tail calls. if (isTailCall && FPDiff) Chain = EmitTailCallLoadRetAddr(DAG, RetAddrFrIdx, Chain, isTailCall, Is64Bit, FPDiff, dl); @@ -2185,7 +2200,7 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, SmallVector MemOpChains2; SDValue FIN; int FI = 0; - // Do not flag preceeding copytoreg stuff together with the following stuff. + // Do not flag preceding copytoreg stuff together with the following stuff. InFlag = SDValue(); if (GuaranteedTailCallOpt) { for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { @@ -2266,7 +2281,8 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, OpFlags = X86II::MO_PLT; } else if (Subtarget->isPICStyleStubAny() && (GV->isDeclaration() || GV->isWeakForLinker()) && - Subtarget->getDarwinVers() < 9) { + (!Subtarget->getTargetTriple().isMacOSX() || + Subtarget->getTargetTriple().isMacOSXVersionLT(10, 5))) { // PC-relative references to external symbols should go through $stub, // unless we're building with the leopard linker or later, which // automatically synthesizes these stubs. @@ -2285,7 +2301,8 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, getTargetMachine().getRelocationModel() == Reloc::PIC_) { OpFlags = X86II::MO_PLT; } else if (Subtarget->isPICStyleStubAny() && - Subtarget->getDarwinVers() < 9) { + (!Subtarget->getTargetTriple().isMacOSX() || + Subtarget->getTargetTriple().isMacOSXVersionLT(10, 5))) { // PC-relative references to external symbols should go through $stub, // unless we're building with the leopard linker or later, which // automatically synthesizes these stubs. @@ -3173,7 +3190,8 @@ bool X86::isMOVLPMask(ShuffleVectorSDNode *N) { bool X86::isMOVLHPSMask(ShuffleVectorSDNode *N) { unsigned NumElems = N->getValueType(0).getVectorNumElements(); - if (NumElems != 2 && NumElems != 4) + if ((NumElems != 2 && NumElems != 4) + || N->getValueType(0).getSizeInBits() > 128) return false; for (unsigned i = 0; i < NumElems/2; ++i) @@ -3195,19 +3213,36 @@ static bool isUNPCKLMask(const SmallVectorImpl &Mask, EVT VT, if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) return false; - for (int i = 0, j = 0; i != NumElts; i += 2, ++j) { - int BitI = Mask[i]; - int BitI1 = Mask[i+1]; - if (!isUndefOrEqual(BitI, j)) - return false; - if (V2IsSplat) { - if (!isUndefOrEqual(BitI1, NumElts)) - return false; - } else { - if (!isUndefOrEqual(BitI1, j + NumElts)) + // Handle vector lengths > 128 bits. Define a "section" as a set of + // 128 bits. AVX defines UNPCK* to operate independently on 128-bit + // sections. + unsigned NumSections = VT.getSizeInBits() / 128; + if (NumSections == 0 ) NumSections = 1; // Handle MMX + unsigned NumSectionElts = NumElts / NumSections; + + unsigned Start = 0; + unsigned End = NumSectionElts; + for (unsigned s = 0; s < NumSections; ++s) { + for (unsigned i = Start, j = s * NumSectionElts; + i != End; + i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; + if (!isUndefOrEqual(BitI, j)) return false; + if (V2IsSplat) { + if (!isUndefOrEqual(BitI1, NumElts)) + return false; + } else { + if (!isUndefOrEqual(BitI1, j + NumElts)) + return false; + } } + // Process the next 128 bits. + Start += NumSectionElts; + End += NumSectionElts; } + return true; } @@ -3255,14 +3290,27 @@ static bool isUNPCKL_v_undef_Mask(const SmallVectorImpl &Mask, EVT VT) { if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16) return false; - for (int i = 0, j = 0; i != NumElems; i += 2, ++j) { - int BitI = Mask[i]; - int BitI1 = Mask[i+1]; - if (!isUndefOrEqual(BitI, j)) - return false; - if (!isUndefOrEqual(BitI1, j)) - return false; + // Handle vector lengths > 128 bits. Define a "section" as a set of + // 128 bits. AVX defines UNPCK* to operate independently on 128-bit + // sections. + unsigned NumSections = VT.getSizeInBits() / 128; + if (NumSections == 0 ) NumSections = 1; // Handle MMX + unsigned NumSectionElts = NumElems / NumSections; + + for (unsigned s = 0; s < NumSections; ++s) { + for (unsigned i = s * NumSectionElts, j = s * NumSectionElts; + i != NumSectionElts * (s + 1); + i += 2, ++j) { + int BitI = Mask[i]; + int BitI1 = Mask[i+1]; + + if (!isUndefOrEqual(BitI, j)) + return false; + if (!isUndefOrEqual(BitI1, j)) + return false; + } } + return true; } @@ -3846,8 +3894,8 @@ static SDValue getShuffleVectorZeroOrUndef(SDValue V2, unsigned Idx, /// getShuffleScalarElt - Returns the scalar element that will make up the ith /// element of the result of the vector shuffle. -SDValue getShuffleScalarElt(SDNode *N, int Index, SelectionDAG &DAG, - unsigned Depth) { +static SDValue getShuffleScalarElt(SDNode *N, int Index, SelectionDAG &DAG, + unsigned Depth) { if (Depth == 6) return SDValue(); // Limit search depth. @@ -3895,11 +3943,15 @@ SDValue getShuffleScalarElt(SDNode *N, int Index, SelectionDAG &DAG, case X86ISD::PUNPCKLWD: case X86ISD::PUNPCKLDQ: case X86ISD::PUNPCKLQDQ: - DecodePUNPCKLMask(NumElems, ShuffleMask); + DecodePUNPCKLMask(VT, ShuffleMask); break; case X86ISD::UNPCKLPS: case X86ISD::UNPCKLPD: - DecodeUNPCKLPMask(NumElems, ShuffleMask); + case X86ISD::VUNPCKLPS: + case X86ISD::VUNPCKLPD: + case X86ISD::VUNPCKLPSY: + case X86ISD::VUNPCKLPDY: + DecodeUNPCKLPMask(VT, ShuffleMask); break; case X86ISD::MOVHLPS: DecodeMOVHLPSMask(NumElems, ShuffleMask); @@ -3968,7 +4020,7 @@ SDValue getShuffleScalarElt(SDNode *N, int Index, SelectionDAG &DAG, /// getNumOfConsecutiveZeros - Return the number of elements of a vector /// shuffle operation which come from a consecutively from a zero. The -/// search can start in two diferent directions, from left or right. +/// search can start in two different directions, from left or right. static unsigned getNumOfConsecutiveZeros(SDNode *N, int NumElems, bool ZerosFromLeft, SelectionDAG &DAG) { @@ -5263,6 +5315,7 @@ LowerVECTOR_SHUFFLE_4wide(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { // Break it into (shuffle shuffle_hi, shuffle_lo). Locs.clear(); + Locs.resize(4); SmallVector LoMask(4U, -1); SmallVector HiMask(4U, -1); @@ -5508,12 +5561,16 @@ SDValue getMOVLP(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG, bool HasSSE2) { X86::getShuffleSHUFImmediate(SVOp), DAG); } -static inline unsigned getUNPCKLOpcode(EVT VT) { +static inline unsigned getUNPCKLOpcode(EVT VT, const X86Subtarget *Subtarget) { switch(VT.getSimpleVT().SimpleTy) { case MVT::v4i32: return X86ISD::PUNPCKLDQ; case MVT::v2i64: return X86ISD::PUNPCKLQDQ; - case MVT::v4f32: return X86ISD::UNPCKLPS; - case MVT::v2f64: return X86ISD::UNPCKLPD; + case MVT::v4f32: + return Subtarget->hasAVX() ? X86ISD::VUNPCKLPS : X86ISD::UNPCKLPS; + case MVT::v2f64: + return Subtarget->hasAVX() ? X86ISD::VUNPCKLPD : X86ISD::UNPCKLPD; + case MVT::v8f32: return X86ISD::VUNPCKLPSY; + case MVT::v4f64: return X86ISD::VUNPCKLPDY; case MVT::v16i8: return X86ISD::PUNPCKLBW; case MVT::v8i16: return X86ISD::PUNPCKLWD; default: @@ -5641,7 +5698,7 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const { // unpckh_undef). Only use pshufd if speed is more important than size. if (OptForSize && X86::isUNPCKL_v_undef_Mask(SVOp)) if (VT != MVT::v2i64 && VT != MVT::v2f64) - return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V1, V1, DAG); + return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()), dl, VT, V1, V1, DAG); if (OptForSize && X86::isUNPCKH_v_undef_Mask(SVOp)) if (VT != MVT::v2i64 && VT != MVT::v2f64) return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V1, DAG); @@ -5762,7 +5819,8 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const { } if (X86::isUNPCKLMask(SVOp)) - return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V1, V2, DAG); + return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()), + dl, VT, V1, V2, DAG); if (X86::isUNPCKHMask(SVOp)) return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V2, DAG); @@ -5789,7 +5847,8 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const { ShuffleVectorSDNode *NewSVOp = cast(NewOp); if (X86::isUNPCKLMask(NewSVOp)) - return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V2, V1, DAG); + return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()), + dl, VT, V2, V1, DAG); if (X86::isUNPCKHMask(NewSVOp)) return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V2, V1, DAG); @@ -5812,8 +5871,11 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const { if (ShuffleVectorSDNode::isSplatMask(&M[0], VT) && SVOp->getSplatIndex() == 0 && V2IsUndef) { - if (VT == MVT::v2f64) - return getTargetShuffleNode(X86ISD::UNPCKLPD, dl, VT, V1, V1, DAG); + if (VT == MVT::v2f64) { + X86ISD::NodeType Opcode = + getSubtarget()->hasAVX() ? X86ISD::VUNPCKLPD : X86ISD::UNPCKLPD; + return getTargetShuffleNode(Opcode, dl, VT, V1, V1, DAG); + } if (VT == MVT::v2i64) return getTargetShuffleNode(X86ISD::PUNPCKLQDQ, dl, VT, V1, V1, DAG); } @@ -5840,7 +5902,8 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const { if (X86::isUNPCKL_v_undef_Mask(SVOp)) if (VT != MVT::v2i64 && VT != MVT::v2f64) - return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V1, V1, DAG); + return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()), + dl, VT, V1, V1, DAG); if (X86::isUNPCKH_v_undef_Mask(SVOp)) if (VT != MVT::v2i64 && VT != MVT::v2f64) return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V1, DAG); @@ -7868,6 +7931,7 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const { assert((Subtarget->isTargetCygMing() || Subtarget->isTargetWindows()) && "This should be used only on Windows targets"); + assert(!Subtarget->isTargetEnvMacho()); DebugLoc dl = Op.getDebugLoc(); // Get the inputs. @@ -7878,8 +7942,9 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SDValue Flag; EVT SPTy = Subtarget->is64Bit() ? MVT::i64 : MVT::i32; + unsigned Reg = (Subtarget->is64Bit() ? X86::RAX : X86::EAX); - Chain = DAG.getCopyToReg(Chain, dl, X86::EAX, Size, Flag); + Chain = DAG.getCopyToReg(Chain, dl, Reg, Size, Flag); Flag = Chain.getValue(1); SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); @@ -8809,8 +8874,8 @@ SDValue X86TargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const { case ISD::SADDO: // A subtract of one will be selected as a INC. Note that INC doesn't // set CF, so we can't do this for UADDO. - if (ConstantSDNode *C = dyn_cast(Op)) - if (C->getAPIntValue() == 1) { + if (ConstantSDNode *C = dyn_cast(RHS)) + if (C->isOne()) { BaseOp = X86ISD::INC; Cond = X86::COND_O; break; @@ -8825,8 +8890,8 @@ SDValue X86TargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const { case ISD::SSUBO: // A subtract of one will be selected as a DEC. Note that DEC doesn't // set CF, so we can't do this for USUBO. - if (ConstantSDNode *C = dyn_cast(Op)) - if (C->getAPIntValue() == 1) { + if (ConstantSDNode *C = dyn_cast(RHS)) + if (C->isOne()) { BaseOp = X86ISD::DEC; Cond = X86::COND_O; break; @@ -10351,21 +10416,48 @@ X86TargetLowering::EmitLoweredWinAlloca(MachineInstr *MI, const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); + assert(!Subtarget->isTargetEnvMacho()); + // The lowering is pretty easy: we're just emitting the call to _alloca. The // non-trivial part is impdef of ESP. - // FIXME: The code should be tweaked as soon as we'll try to do codegen for - // mingw-w64. - const char *StackProbeSymbol = + if (Subtarget->isTargetWin64()) { + if (Subtarget->isTargetCygMing()) { + // ___chkstk(Mingw64): + // Clobbers R10, R11, RAX and EFLAGS. + // Updates RSP. + BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA)) + .addExternalSymbol("___chkstk") + .addReg(X86::RAX, RegState::Implicit) + .addReg(X86::RSP, RegState::Implicit) + .addReg(X86::RAX, RegState::Define | RegState::Implicit) + .addReg(X86::RSP, RegState::Define | RegState::Implicit) + .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit); + } else { + // __chkstk(MSVCRT): does not update stack pointer. + // Clobbers R10, R11 and EFLAGS. + // FIXME: RAX(allocated size) might be reused and not killed. + BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA)) + .addExternalSymbol("__chkstk") + .addReg(X86::RAX, RegState::Implicit) + .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit); + // RAX has the offset to subtracted from RSP. + BuildMI(*BB, MI, DL, TII->get(X86::SUB64rr), X86::RSP) + .addReg(X86::RSP) + .addReg(X86::RAX); + } + } else { + const char *StackProbeSymbol = Subtarget->isTargetWindows() ? "_chkstk" : "_alloca"; - BuildMI(*BB, MI, DL, TII->get(X86::CALLpcrel32)) - .addExternalSymbol(StackProbeSymbol) - .addReg(X86::EAX, RegState::Implicit) - .addReg(X86::ESP, RegState::Implicit) - .addReg(X86::EAX, RegState::Define | RegState::Implicit) - .addReg(X86::ESP, RegState::Define | RegState::Implicit) - .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit); + BuildMI(*BB, MI, DL, TII->get(X86::CALLpcrel32)) + .addExternalSymbol(StackProbeSymbol) + .addReg(X86::EAX, RegState::Implicit) + .addReg(X86::ESP, RegState::Implicit) + .addReg(X86::EAX, RegState::Define | RegState::Implicit) + .addReg(X86::ESP, RegState::Define | RegState::Implicit) + .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit); + } MI->eraseFromParent(); // The pseudo instruction is gone now. return BB; @@ -12126,7 +12218,7 @@ bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const { AsmPieces.clear(); SplitString(AsmStr, AsmPieces, " \t"); // Split with whitespace. - // FIXME: this should verify that we are targetting a 486 or better. If not, + // FIXME: this should verify that we are targeting a 486 or better. If not, // we will turn this bswap into something that will be lowered to logical ops // instead of emitting the bswap asm. For now, we don't support 486 or lower // so don't worry about this. diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.h b/contrib/llvm/lib/Target/X86/X86ISelLowering.h index 6ec4a7de7558..630105739899 100644 --- a/contrib/llvm/lib/Target/X86/X86ISelLowering.h +++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.h @@ -677,9 +677,6 @@ namespace llvm { /// getFunctionAlignment - Return the Log2 alignment of this function. virtual unsigned getFunctionAlignment(const Function *F) const; - unsigned getRegPressureLimit(const TargetRegisterClass *RC, - MachineFunction &MF) const; - /// getStackCookieLocation - Return true if the target stores stack /// protector cookies at a fixed offset in some non-standard address /// space, and populates the address space and offset as @@ -846,6 +843,12 @@ namespace llvm { virtual bool isUsedByReturnOnly(SDNode *N) const; + virtual bool mayBeEmittedAsTailCall(CallInst *CI) const; + + virtual EVT + getTypeForExtArgOrReturn(LLVMContext &Context, EVT VT, + ISD::NodeType ExtendKind) const; + virtual bool CanLowerReturn(CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl &Outs, diff --git a/contrib/llvm/lib/Target/X86/X86Instr3DNow.td b/contrib/llvm/lib/Target/X86/X86Instr3DNow.td index 45d1c6bc9d29..dd4f6a5a85a4 100644 --- a/contrib/llvm/lib/Target/X86/X86Instr3DNow.td +++ b/contrib/llvm/lib/Target/X86/X86Instr3DNow.td @@ -12,66 +12,91 @@ // //===----------------------------------------------------------------------===// -// FIXME: We don't support any intrinsics for these instructions yet. - -class I3DNow o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, TB, Requires<[Has3DNow]> { +class I3DNow o, Format F, dag outs, dag ins, string asm, list pat> + : I, TB, Requires<[Has3DNow]> { } -class I3DNow_binop o, Format F, dag ins, string Mnemonic> - : I, - TB, Requires<[Has3DNow]>, Has3DNow0F0FOpcode { +class I3DNow_binop o, Format F, dag ins, string Mnemonic, list pat> + : I3DNow, + Has3DNow0F0FOpcode { + // FIXME: The disassembler doesn't support Has3DNow0F0FOpcode yet. + let isAsmParserOnly = 1; + let Constraints = "$src1 = $dst"; +} + +class I3DNow_conv o, Format F, dag ins, string Mnemonic, list pat> + : I3DNow, + Has3DNow0F0FOpcode { // FIXME: The disassembler doesn't support Has3DNow0F0FOpcode yet. let isAsmParserOnly = 1; } - -let Constraints = "$src1 = $dst" in { - // MMXI_binop_rm_int - Simple MMX binary operator based on intrinsic. - // When this is cleaned up, remove the FIXME from X86RecognizableInstr.cpp. - multiclass I3DNow_binop_rm opc, string Mn> { - def rr : I3DNow_binop; - def rm : I3DNow_binop; - } +multiclass I3DNow_binop_rm opc, string Mn> { + def rr : I3DNow_binop; + def rm : I3DNow_binop; } -defm PAVGUSB : I3DNow_binop_rm<0xBF, "pavgusb">; -defm PF2ID : I3DNow_binop_rm<0x1D, "pf2id">; -defm PFACC : I3DNow_binop_rm<0xAE, "pfacc">; -defm PFADD : I3DNow_binop_rm<0x9E, "pfadd">; -defm PFCMPEQ : I3DNow_binop_rm<0xB0, "pfcmpeq">; -defm PFCMPGE : I3DNow_binop_rm<0x90, "pfcmpge">; -defm PFCMPGT : I3DNow_binop_rm<0xA0, "pfcmpgt">; -defm PFMAX : I3DNow_binop_rm<0xA4, "pfmax">; -defm PFMIN : I3DNow_binop_rm<0x94, "pfmin">; -defm PFMUL : I3DNow_binop_rm<0xB4, "pfmul">; -defm PFRCP : I3DNow_binop_rm<0x96, "pfrcp">; -defm PFRCPIT1 : I3DNow_binop_rm<0xA6, "pfrcpit1">; -defm PFRCPIT2 : I3DNow_binop_rm<0xB6, "pfrcpit2">; -defm PFRSQIT1 : I3DNow_binop_rm<0xA7, "pfrsqit1">; -defm PFRSQRT : I3DNow_binop_rm<0x97, "pfrsqrt">; -defm PFSUB : I3DNow_binop_rm<0x9A, "pfsub">; -defm PFSUBR : I3DNow_binop_rm<0xAA, "pfsubr">; -defm PI2FD : I3DNow_binop_rm<0x0D, "pi2fd">; -defm PMULHRW : I3DNow_binop_rm<0xB7, "pmulhrw">; +multiclass I3DNow_binop_rm_int opc, string Mn, string Ver = ""> { + def rr : I3DNow_binop( + !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1, VR64:$src2))]>; + def rm : I3DNow_binop( + !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1, + (bitconvert (load_mmx addr:$src2))))]>; +} + +multiclass I3DNow_conv_rm opc, string Mn> { + def rr : I3DNow_conv; + def rm : I3DNow_conv; +} + +multiclass I3DNow_conv_rm_int opc, string Mn, string Ver = ""> { + def rr : I3DNow_conv( + !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src))]>; + def rm : I3DNow_conv( + !strconcat("int_x86_3dnow", Ver, "_", Mn)) + (bitconvert (load_mmx addr:$src))))]>; +} + +defm PAVGUSB : I3DNow_binop_rm_int<0xBF, "pavgusb">; +defm PF2ID : I3DNow_conv_rm_int<0x1D, "pf2id">; +defm PFACC : I3DNow_binop_rm_int<0xAE, "pfacc">; +defm PFADD : I3DNow_binop_rm_int<0x9E, "pfadd">; +defm PFCMPEQ : I3DNow_binop_rm_int<0xB0, "pfcmpeq">; +defm PFCMPGE : I3DNow_binop_rm_int<0x90, "pfcmpge">; +defm PFCMPGT : I3DNow_binop_rm_int<0xA0, "pfcmpgt">; +defm PFMAX : I3DNow_binop_rm_int<0xA4, "pfmax">; +defm PFMIN : I3DNow_binop_rm_int<0x94, "pfmin">; +defm PFMUL : I3DNow_binop_rm_int<0xB4, "pfmul">; +defm PFRCP : I3DNow_conv_rm_int<0x96, "pfrcp">; +defm PFRCPIT1 : I3DNow_binop_rm_int<0xA6, "pfrcpit1">; +defm PFRCPIT2 : I3DNow_binop_rm_int<0xB6, "pfrcpit2">; +defm PFRSQIT1 : I3DNow_binop_rm_int<0xA7, "pfrsqit1">; +defm PFRSQRT : I3DNow_conv_rm_int<0x97, "pfrsqrt">; +defm PFSUB : I3DNow_binop_rm_int<0x9A, "pfsub">; +defm PFSUBR : I3DNow_binop_rm_int<0xAA, "pfsubr">; +defm PI2FD : I3DNow_conv_rm_int<0x0D, "pi2fd">; +defm PMULHRW : I3DNow_binop_rm_int<0xB7, "pmulhrw">; def FEMMS : I3DNow<0x0E, RawFrm, (outs), (ins), "femms", [(int_x86_mmx_femms)]>; def PREFETCH : I3DNow<0x0D, MRM0m, (outs), (ins i32mem:$addr), "prefetch $addr", []>; - + // FIXME: Diassembler gets a bogus decode conflict. -let isAsmParserOnly = 1 in { +let isAsmParserOnly = 1 in def PREFETCHW : I3DNow<0x0D, MRM1m, (outs), (ins i16mem:$addr), "prefetchw $addr", []>; -} // "3DNowA" instructions -defm PF2IW : I3DNow_binop_rm<0x1C, "pf2iw">; -defm PI2FW : I3DNow_binop_rm<0x0C, "pi2fw">; -defm PFNACC : I3DNow_binop_rm<0x8A, "pfnacc">; -defm PFPNACC : I3DNow_binop_rm<0x8E, "pfpnacc">; -defm PSWAPD : I3DNow_binop_rm<0xBB, "pswapd">; +defm PF2IW : I3DNow_conv_rm_int<0x1C, "pf2iw", "a">; +defm PI2FW : I3DNow_conv_rm_int<0x0C, "pi2fw", "a">; +defm PFNACC : I3DNow_binop_rm_int<0x8A, "pfnacc", "a">; +defm PFPNACC : I3DNow_binop_rm_int<0x8E, "pfpnacc", "a">; +defm PSWAPD : I3DNow_conv_rm_int<0xBB, "pswapd", "a">; diff --git a/contrib/llvm/lib/Target/X86/X86InstrArithmetic.td b/contrib/llvm/lib/Target/X86/X86InstrArithmetic.td index f0ea06870869..9f7a4b06dc6f 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrArithmetic.td +++ b/contrib/llvm/lib/Target/X86/X86InstrArithmetic.td @@ -163,7 +163,7 @@ def IMUL64rm : RI<0xAF, MRMSrcMem, (outs GR64:$dst), } // Defs = [EFLAGS] -// Suprisingly enough, these are not two address instructions! +// Surprisingly enough, these are not two address instructions! let Defs = [EFLAGS] in { // Register-Integer Signed Integer Multiply def IMUL16rri : Ii16<0x69, MRMSrcReg, // GR16 = GR16*I16 diff --git a/contrib/llvm/lib/Target/X86/X86InstrControl.td b/contrib/llvm/lib/Target/X86/X86InstrControl.td index 77f47250e9fd..c228a0aed59c 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrControl.td +++ b/contrib/llvm/lib/Target/X86/X86InstrControl.td @@ -263,6 +263,16 @@ let isCall = 1, isCodeGenOnly = 1 in Requires<[IsWin64]>; } +let isCall = 1, isCodeGenOnly = 1 in + // __chkstk(MSVC): clobber R10, R11 and EFLAGS. + // ___chkstk(Mingw64): clobber R10, R11, RAX and EFLAGS, and update RSP. + let Defs = [RAX, R10, R11, RSP, EFLAGS], + Uses = [RSP] in { + def W64ALLOCA : Ii32PCRel<0xE8, RawFrm, + (outs), (ins i64i32imm_pcrel:$dst, variable_ops), + "call{q}\t$dst", []>, + Requires<[IsWin64]>; + } let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, isCodeGenOnly = 1 in diff --git a/contrib/llvm/lib/Target/X86/X86InstrFormats.td b/contrib/llvm/lib/Target/X86/X86InstrFormats.td index 0660072589e4..7daa26492274 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrFormats.td +++ b/contrib/llvm/lib/Target/X86/X86InstrFormats.td @@ -91,21 +91,23 @@ class REX_W { bit hasREX_WPrefix = 1; } class LOCK { bit hasLockPrefix = 1; } class SegFS { bits<2> SegOvrBits = 1; } class SegGS { bits<2> SegOvrBits = 2; } -class TB { bits<4> Prefix = 1; } -class REP { bits<4> Prefix = 2; } -class D8 { bits<4> Prefix = 3; } -class D9 { bits<4> Prefix = 4; } -class DA { bits<4> Prefix = 5; } -class DB { bits<4> Prefix = 6; } -class DC { bits<4> Prefix = 7; } -class DD { bits<4> Prefix = 8; } -class DE { bits<4> Prefix = 9; } -class DF { bits<4> Prefix = 10; } -class XD { bits<4> Prefix = 11; } -class XS { bits<4> Prefix = 12; } -class T8 { bits<4> Prefix = 13; } -class TA { bits<4> Prefix = 14; } -class TF { bits<4> Prefix = 15; } +class TB { bits<5> Prefix = 1; } +class REP { bits<5> Prefix = 2; } +class D8 { bits<5> Prefix = 3; } +class D9 { bits<5> Prefix = 4; } +class DA { bits<5> Prefix = 5; } +class DB { bits<5> Prefix = 6; } +class DC { bits<5> Prefix = 7; } +class DD { bits<5> Prefix = 8; } +class DE { bits<5> Prefix = 9; } +class DF { bits<5> Prefix = 10; } +class XD { bits<5> Prefix = 11; } +class XS { bits<5> Prefix = 12; } +class T8 { bits<5> Prefix = 13; } +class TA { bits<5> Prefix = 14; } +class A6 { bits<5> Prefix = 15; } +class A7 { bits<5> Prefix = 16; } +class TF { bits<5> Prefix = 17; } class VEX { bit hasVEXPrefix = 1; } class VEX_W { bit hasVEX_WPrefix = 1; } class VEX_4V : VEX { bit hasVEX_4VPrefix = 1; } @@ -136,7 +138,7 @@ class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix? bit hasAdSizePrefix = 0; // Does this inst have a 0x67 prefix? - bits<4> Prefix = 0; // Which prefix byte does this inst have? + bits<5> Prefix = 0; // Which prefix byte does this inst have? bit hasREX_WPrefix = 0; // Does this inst require the REX.W prefix? FPFormat FPForm = NotFP; // What flavor of FP instruction is this? bit hasLockPrefix = 0; // Does this inst have a 0xF0 prefix? @@ -154,20 +156,20 @@ class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, let TSFlags{5-0} = FormBits; let TSFlags{6} = hasOpSizePrefix; let TSFlags{7} = hasAdSizePrefix; - let TSFlags{11-8} = Prefix; - let TSFlags{12} = hasREX_WPrefix; - let TSFlags{15-13} = ImmT.Value; - let TSFlags{18-16} = FPForm.Value; - let TSFlags{19} = hasLockPrefix; - let TSFlags{21-20} = SegOvrBits; - let TSFlags{23-22} = ExeDomain.Value; - let TSFlags{31-24} = Opcode; - let TSFlags{32} = hasVEXPrefix; - let TSFlags{33} = hasVEX_WPrefix; - let TSFlags{34} = hasVEX_4VPrefix; - let TSFlags{35} = hasVEX_i8ImmReg; - let TSFlags{36} = hasVEX_L; - let TSFlags{37} = has3DNow0F0FOpcode; + let TSFlags{12-8} = Prefix; + let TSFlags{13} = hasREX_WPrefix; + let TSFlags{16-14} = ImmT.Value; + let TSFlags{19-17} = FPForm.Value; + let TSFlags{20} = hasLockPrefix; + let TSFlags{22-21} = SegOvrBits; + let TSFlags{24-23} = ExeDomain.Value; + let TSFlags{32-25} = Opcode; + let TSFlags{33} = hasVEXPrefix; + let TSFlags{34} = hasVEX_WPrefix; + let TSFlags{35} = hasVEX_4VPrefix; + let TSFlags{36} = hasVEX_i8ImmReg; + let TSFlags{37} = hasVEX_L; + let TSFlags{38} = has3DNow0F0FOpcode; } class PseudoI pattern> @@ -319,7 +321,7 @@ class VSSI o, Format F, dag outs, dag ins, string asm, Requires<[HasAVX]>; class VPSI o, Format F, dag outs, dag ins, string asm, list pattern> - : I, + : I, TB, Requires<[HasAVX]>; // SSE2 Instruction Templates: @@ -353,7 +355,7 @@ class VSDI o, Format F, dag outs, dag ins, string asm, Requires<[HasAVX]>; class VPDI o, Format F, dag outs, dag ins, string asm, list pattern> - : I, + : I, TB, OpSize, Requires<[HasAVX]>; // SSE3 Instruction Templates: diff --git a/contrib/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td b/contrib/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td index 5016c0f171ae..3cbfac1c1a9f 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td +++ b/contrib/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td @@ -132,6 +132,8 @@ def X86Movlpd : SDNode<"X86ISD::MOVLPD", SDTShuff2Op>; def X86Unpcklps : SDNode<"X86ISD::UNPCKLPS", SDTShuff2Op>; def X86Unpcklpd : SDNode<"X86ISD::UNPCKLPD", SDTShuff2Op>; +def X86Unpcklpsy : SDNode<"X86ISD::VUNPCKLPSY", SDTShuff2Op>; +def X86Unpcklpdy : SDNode<"X86ISD::VUNPCKLPDY", SDTShuff2Op>; def X86Unpckhps : SDNode<"X86ISD::UNPCKHPS", SDTShuff2Op>; def X86Unpckhpd : SDNode<"X86ISD::UNPCKHPD", SDTShuff2Op>; diff --git a/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp b/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp index 76a9b12b8aad..83f0260d63b4 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -232,7 +232,7 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) assert(!RegOp2MemOpTable2Addr.count(RegOp) && "Duplicated entries?"); RegOp2MemOpTable2Addr[RegOp] = std::make_pair(MemOp, 0U); - // If this is not a reversable operation (because there is a many->one) + // If this is not a reversible operation (because there is a many->one) // mapping, don't insert the reverse of the operation into MemOp2RegOpTable. if (OpTbl2Addr[i][1] & TB_NOT_REVERSABLE) continue; @@ -335,7 +335,7 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) assert(!RegOp2MemOpTable0.count(RegOp) && "Duplicated entries?"); RegOp2MemOpTable0[RegOp] = std::make_pair(MemOp, Align); - // If this is not a reversable operation (because there is a many->one) + // If this is not a reversible operation (because there is a many->one) // mapping, don't insert the reverse of the operation into MemOp2RegOpTable. if (OpTbl0[i][1] & TB_NOT_REVERSABLE) continue; @@ -460,7 +460,7 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) assert(!RegOp2MemOpTable1.count(RegOp) && "Duplicate entries"); RegOp2MemOpTable1[RegOp] = std::make_pair(MemOp, Align); - // If this is not a reversable operation (because there is a many->one) + // If this is not a reversible operation (because there is a many->one) // mapping, don't insert the reverse of the operation into MemOp2RegOpTable. if (OpTbl1[i][1] & TB_NOT_REVERSABLE) continue; @@ -682,7 +682,7 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) assert(!RegOp2MemOpTable2.count(RegOp) && "Duplicate entry!"); RegOp2MemOpTable2[RegOp] = std::make_pair(MemOp, Align); - // If this is not a reversable operation (because there is a many->one) + // If this is not a reversible operation (because there is a many->one) // mapping, don't insert the reverse of the operation into MemOp2RegOpTable. if (OpTbl2[i][1] & TB_NOT_REVERSABLE) continue; @@ -916,7 +916,6 @@ X86InstrInfo::isReallyTriviallyReMaterializable(const MachineInstr *MI, case X86::MOVSDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: - case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MMX_MOVD64rm: @@ -2241,6 +2240,12 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, bool isTwoAddr = NumOps > 1 && MI->getDesc().getOperandConstraint(1, TOI::TIED_TO) != -1; + // FIXME: AsmPrinter doesn't know how to handle + // X86II::MO_GOT_ABSOLUTE_ADDRESS after folding. + if (MI->getOpcode() == X86::ADD32ri && + MI->getOperand(2).getTargetFlags() == X86II::MO_GOT_ABSOLUTE_ADDRESS) + return NULL; + MachineInstr *NewMI = NULL; // Folding a memory location into the two-address part of a two-address // instruction is different than folding it other places. It requires @@ -2535,6 +2540,12 @@ bool X86InstrInfo::canFoldMemoryOperand(const MachineInstr *MI, case X86::TEST32rr: case X86::TEST64rr: return true; + case X86::ADD32ri: + // FIXME: AsmPrinter doesn't know how to handle + // X86II::MO_GOT_ABSOLUTE_ADDRESS after folding. + if (MI->getOperand(2).getTargetFlags() == X86II::MO_GOT_ABSOLUTE_ADDRESS) + return false; + break; } } @@ -2845,11 +2856,9 @@ X86InstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, case X86::FsMOVAPDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: - case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: - case X86::MOVDQUrm_Int: break; } switch (Opc2) { @@ -2869,11 +2878,9 @@ X86InstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, case X86::FsMOVAPDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: - case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: - case X86::MOVDQUrm_Int: break; } @@ -3085,12 +3092,8 @@ void X86InstrInfo::getNoopForMachoTarget(MCInst &NopInst) const { NopInst.setOpcode(X86::NOOP); } -bool X86InstrInfo:: -hasHighOperandLatency(const InstrItineraryData *ItinData, - const MachineRegisterInfo *MRI, - const MachineInstr *DefMI, unsigned DefIdx, - const MachineInstr *UseMI, unsigned UseIdx) const { - switch (DefMI->getOpcode()) { +bool X86InstrInfo::isHighLatencyDef(int opc) const { + switch (opc) { default: return false; case X86::DIVSDrm: case X86::DIVSDrm_Int: @@ -3120,6 +3123,14 @@ hasHighOperandLatency(const InstrItineraryData *ItinData, } } +bool X86InstrInfo:: +hasHighOperandLatency(const InstrItineraryData *ItinData, + const MachineRegisterInfo *MRI, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx) const { + return isHighLatencyDef(DefMI->getOpcode()); +} + namespace { /// CGBR - Create Global Base Reg pass. This initializes the PIC /// global base register for x86-32. diff --git a/contrib/llvm/lib/Target/X86/X86InstrInfo.h b/contrib/llvm/lib/Target/X86/X86InstrInfo.h index fcb5a25104ac..8da68b570177 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrInfo.h +++ b/contrib/llvm/lib/Target/X86/X86InstrInfo.h @@ -33,15 +33,15 @@ namespace X86 { AddrScaleAmt = 1, AddrIndexReg = 2, AddrDisp = 3, - + /// AddrSegmentReg - The operand # of the segment in the memory operand. AddrSegmentReg = 4, /// AddrNumOperands - Total number of operands in a memory reference. AddrNumOperands = 5 }; - - + + // X86 specific condition code. These correspond to X86_*_COND in // X86InstrInfo.td. They must be kept in synch. enum CondCode { @@ -72,16 +72,16 @@ namespace X86 { COND_INVALID }; - + // Turn condition code into conditional branch opcode. unsigned GetCondBranchFromCond(CondCode CC); - + /// GetOppositeBranchCondition - Return the inverse of the specified cond, /// e.g. turning COND_E to COND_NE. CondCode GetOppositeBranchCondition(X86::CondCode CC); } - + /// X86II - This namespace holds all of the target specific flags that /// instruction info tracks. /// @@ -90,14 +90,14 @@ namespace X86II { enum TOF { //===------------------------------------------------------------------===// // X86 Specific MachineOperand flags. - + MO_NO_FLAG, - + /// MO_GOT_ABSOLUTE_ADDRESS - On a symbol operand, this represents a /// relocation of: /// SYMBOL_LABEL + [. - PICBASELABEL] MO_GOT_ABSOLUTE_ADDRESS, - + /// MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the /// immediate should get the value of the symbol minus the PIC base label: /// SYMBOL_LABEL - PICBASELABEL @@ -106,77 +106,77 @@ namespace X86II { /// MO_GOT - On a symbol operand this indicates that the immediate is the /// offset to the GOT entry for the symbol name from the base of the GOT. /// - /// See the X86-64 ELF ABI supplement for more details. + /// See the X86-64 ELF ABI supplement for more details. /// SYMBOL_LABEL @GOT MO_GOT, - + /// MO_GOTOFF - On a symbol operand this indicates that the immediate is - /// the offset to the location of the symbol name from the base of the GOT. + /// the offset to the location of the symbol name from the base of the GOT. /// - /// See the X86-64 ELF ABI supplement for more details. + /// See the X86-64 ELF ABI supplement for more details. /// SYMBOL_LABEL @GOTOFF MO_GOTOFF, - + /// MO_GOTPCREL - On a symbol operand this indicates that the immediate is /// offset to the GOT entry for the symbol name from the current code - /// location. + /// location. /// - /// See the X86-64 ELF ABI supplement for more details. + /// See the X86-64 ELF ABI supplement for more details. /// SYMBOL_LABEL @GOTPCREL MO_GOTPCREL, - + /// MO_PLT - On a symbol operand this indicates that the immediate is - /// offset to the PLT entry of symbol name from the current code location. + /// offset to the PLT entry of symbol name from the current code location. /// - /// See the X86-64 ELF ABI supplement for more details. + /// See the X86-64 ELF ABI supplement for more details. /// SYMBOL_LABEL @PLT MO_PLT, - + /// MO_TLSGD - On a symbol operand this indicates that the immediate is /// some TLS offset. /// - /// See 'ELF Handling for Thread-Local Storage' for more details. + /// See 'ELF Handling for Thread-Local Storage' for more details. /// SYMBOL_LABEL @TLSGD MO_TLSGD, - + /// MO_GOTTPOFF - On a symbol operand this indicates that the immediate is /// some TLS offset. /// - /// See 'ELF Handling for Thread-Local Storage' for more details. + /// See 'ELF Handling for Thread-Local Storage' for more details. /// SYMBOL_LABEL @GOTTPOFF MO_GOTTPOFF, - + /// MO_INDNTPOFF - On a symbol operand this indicates that the immediate is /// some TLS offset. /// - /// See 'ELF Handling for Thread-Local Storage' for more details. + /// See 'ELF Handling for Thread-Local Storage' for more details. /// SYMBOL_LABEL @INDNTPOFF MO_INDNTPOFF, - + /// MO_TPOFF - On a symbol operand this indicates that the immediate is /// some TLS offset. /// - /// See 'ELF Handling for Thread-Local Storage' for more details. + /// See 'ELF Handling for Thread-Local Storage' for more details. /// SYMBOL_LABEL @TPOFF MO_TPOFF, - + /// MO_NTPOFF - On a symbol operand this indicates that the immediate is /// some TLS offset. /// - /// See 'ELF Handling for Thread-Local Storage' for more details. + /// See 'ELF Handling for Thread-Local Storage' for more details. /// SYMBOL_LABEL @NTPOFF MO_NTPOFF, - + /// MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the /// reference is actually to the "__imp_FOO" symbol. This is used for /// dllimport linkage on windows. MO_DLLIMPORT, - + /// MO_DARWIN_STUB - On a symbol operand "FOO", this indicates that the /// reference is actually to the "FOO$stub" symbol. This is used for calls /// and jumps to external functions on Tiger and earlier. MO_DARWIN_STUB, - + /// MO_DARWIN_NONLAZY - On a symbol operand "FOO", this indicates that the /// reference is actually to the "FOO$non_lazy_ptr" symbol, which is a /// non-PIC-base-relative reference to a non-hidden dyld lazy pointer stub. @@ -186,19 +186,19 @@ namespace X86II { /// that the reference is actually to "FOO$non_lazy_ptr - PICBASE", which is /// a PIC-base-relative reference to a non-hidden dyld lazy pointer stub. MO_DARWIN_NONLAZY_PIC_BASE, - + /// MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE - On a symbol operand "FOO", this /// indicates that the reference is actually to "FOO$non_lazy_ptr -PICBASE", /// which is a PIC-base-relative reference to a hidden dyld lazy pointer /// stub. MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE, - + /// MO_TLVP - On a symbol operand this indicates that the immediate is /// some TLS offset. /// /// This is the TLS offset for the Darwin TLS mechanism. MO_TLVP, - + /// MO_TLVP_PIC_BASE - On a symbol operand this indicates that the immediate /// is some TLS offset from the picbase. /// @@ -239,7 +239,7 @@ inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) { return false; } } - + /// X86II - This namespace holds all of the target specific flags that /// instruction info tracks. /// @@ -299,7 +299,7 @@ namespace X86II { // MRMInitReg - This form is used for instructions whose source and // destinations are the same register. MRMInitReg = 32, - + //// MRM_C1 - A mod/rm byte of exactly 0xC1. MRM_C1 = 33, MRM_C2 = 34, @@ -318,7 +318,7 @@ namespace X86II { /// immediates, the first of which is a 16-bit immediate (specified by /// the imm encoding) and the second is a 8-bit fixed value. RawFrmImm8 = 43, - + /// RawFrmImm16 - This is used for CALL FAR instructions, which have two /// immediates, the first of which is a 16 or 32-bit immediate (specified by /// the imm encoding) and the second is a 16-bit fixed value. In the AMD @@ -347,7 +347,7 @@ namespace X86II { // set, there is no prefix byte for obtaining a multibyte opcode. // Op0Shift = 8, - Op0Mask = 0xF << Op0Shift, + Op0Mask = 0x1F << Op0Shift, // TB - TwoByte - Set if this instruction has a two byte opcode, which // starts with a 0x0F byte before the real opcode. @@ -368,11 +368,12 @@ namespace X86II { // floating point operations performed in the SSE registers. XD = 11 << Op0Shift, XS = 12 << Op0Shift, - // T8, TA - Prefix after the 0x0F prefix. + // T8, TA, A6, A7 - Prefix after the 0x0F prefix. T8 = 13 << Op0Shift, TA = 14 << Op0Shift, - + A6 = 15 << Op0Shift, A7 = 16 << Op0Shift, + // TF - Prefix before and after 0x0F - TF = 15 << Op0Shift, + TF = 17 << Op0Shift, //===------------------------------------------------------------------===// // REX_W - REX prefixes are instruction prefixes used in 64-bit mode. @@ -380,13 +381,13 @@ namespace X86II { // etc. We only cares about REX.W and REX.R bits and only the former is // statically determined. // - REXShift = 12, + REXShift = Op0Shift + 5, REX_W = 1 << REXShift, //===------------------------------------------------------------------===// // This three-bit field describes the size of an immediate operand. Zero is // unused so that we can tell if we forgot to set a value. - ImmShift = 13, + ImmShift = REXShift + 1, ImmMask = 7 << ImmShift, Imm8 = 1 << ImmShift, Imm8PCRel = 2 << ImmShift, @@ -400,7 +401,7 @@ namespace X86II { // FP Instruction Classification... Zero is non-fp instruction. // FPTypeMask - Mask for all of the FP types... - FPTypeShift = 16, + FPTypeShift = ImmShift + 3, FPTypeMask = 7 << FPTypeShift, // NotFP - The default, set for instructions that do not use FP registers. @@ -433,25 +434,26 @@ namespace X86II { SpecialFP = 7 << FPTypeShift, // Lock prefix - LOCKShift = 19, + LOCKShift = FPTypeShift + 3, LOCK = 1 << LOCKShift, // Segment override prefixes. Currently we just need ability to address // stuff in gs and fs segments. - SegOvrShift = 20, + SegOvrShift = LOCKShift + 1, SegOvrMask = 3 << SegOvrShift, FS = 1 << SegOvrShift, GS = 2 << SegOvrShift, - // Execution domain for SSE instructions in bits 22, 23. - // 0 in bits 22-23 means normal, non-SSE instruction. - SSEDomainShift = 22, + // Execution domain for SSE instructions in bits 23, 24. + // 0 in bits 23-24 means normal, non-SSE instruction. + SSEDomainShift = SegOvrShift + 2, - OpcodeShift = 24, - OpcodeMask = 0xFF << OpcodeShift, + OpcodeShift = SSEDomainShift + 2, + OpcodeMask = 0xFFULL << OpcodeShift, //===------------------------------------------------------------------===// /// VEX - The opcode prefix used by AVX instructions + VEXShift = OpcodeShift + 8, VEX = 1U << 0, /// VEX_W - Has a opcode specific functionality, but is used in the same @@ -473,7 +475,7 @@ namespace X86II { /// if a VR256 register is used, but some AVX instructions also have this /// field marked when using a f256 memory references. VEX_L = 1U << 4, - + /// Has3DNow0F0FOpcode - This flag indicates that the instruction uses the /// wacky 0x0F 0x0F prefix for 3DNow! instructions. The manual documents /// this as having a 0x0F prefix with a 0x0F opcode, and each instruction @@ -482,18 +484,18 @@ namespace X86II { /// this flag to indicate that the encoder should do the wacky 3DNow! thing. Has3DNow0F0FOpcode = 1U << 5 }; - + // getBaseOpcodeFor - This function returns the "base" X86 opcode for the // specified machine instruction. // static inline unsigned char getBaseOpcodeFor(uint64_t TSFlags) { return TSFlags >> X86II::OpcodeShift; } - + static inline bool hasImm(uint64_t TSFlags) { return (TSFlags & X86II::ImmMask) != 0; } - + /// getSizeOfImm - Decode the "size of immediate" field from the TSFlags field /// of the specified instruction. static inline unsigned getSizeOfImm(uint64_t TSFlags) { @@ -508,7 +510,7 @@ namespace X86II { case X86II::Imm64: return 8; } } - + /// isImmPCRel - Return true if the immediate of the specified instruction's /// TSFlags indicates that it is pc relative. static inline unsigned isImmPCRel(uint64_t TSFlags) { @@ -525,7 +527,7 @@ namespace X86II { return false; } } - + /// getMemoryOperandNo - The function returns the MCInst operand # for the /// first field of the memory operand. If the instruction doesn't have a /// memory operand, this returns -1. @@ -549,11 +551,11 @@ namespace X86II { case X86II::MRMDestMem: return 0; case X86II::MRMSrcMem: { - bool HasVEX_4V = (TSFlags >> 32) & X86II::VEX_4V; + bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V; unsigned FirstMemOp = 1; if (HasVEX_4V) ++FirstMemOp;// Skip the register source (which is encoded in VEX_VVVV). - + // FIXME: Maybe lea should have its own form? This is a horrible hack. //if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r || // Opcode == X86::LEA16r || Opcode == X86::LEA32r) @@ -613,7 +615,7 @@ inline static bool isMem(const MachineInstr *MI, unsigned Op) { class X86InstrInfo : public TargetInstrInfoImpl { X86TargetMachine &TM; const X86RegisterInfo RI; - + /// RegOp2MemOpTable2Addr, RegOp2MemOpTable0, RegOp2MemOpTable1, /// RegOp2MemOpTable2 - Load / store folding opcode maps. /// @@ -621,7 +623,7 @@ class X86InstrInfo : public TargetInstrInfoImpl { DenseMap > RegOp2MemOpTable0; DenseMap > RegOp2MemOpTable1; DenseMap > RegOp2MemOpTable2; - + /// MemOp2RegOpTable - Load / store unfolding opcode map. /// DenseMap > MemOp2RegOpTable; @@ -795,7 +797,7 @@ class X86InstrInfo : public TargetInstrInfoImpl { virtual unsigned getOpcodeAfterMemoryUnfold(unsigned Opc, bool UnfoldLoad, bool UnfoldStore, unsigned *LoadRegIndex = 0) const; - + /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler /// to determine if two loads are loading from the same base address. It /// should only return true if the base pointers are the same and the @@ -805,7 +807,7 @@ class X86InstrInfo : public TargetInstrInfoImpl { int64_t &Offset1, int64_t &Offset2) const; /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to - /// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should + /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads should /// be scheduled togther. On some targets if two loads are loading from /// addresses in the same cache line, it's better if they are scheduled /// together. This function takes two integers that represent the load offsets @@ -829,7 +831,7 @@ class X86InstrInfo : public TargetInstrInfoImpl { return (reg == X86::SPL || reg == X86::BPL || reg == X86::SIL || reg == X86::DIL); } - + static bool isX86_64ExtendedReg(const MachineOperand &MO) { if (!MO.isReg()) return false; return isX86_64ExtendedReg(MO.getReg()); @@ -858,11 +860,13 @@ class X86InstrInfo : public TargetInstrInfoImpl { const SmallVectorImpl &MOs, unsigned Size, unsigned Alignment) const; + bool isHighLatencyDef(int opc) const; + bool hasHighOperandLatency(const InstrItineraryData *ItinData, const MachineRegisterInfo *MRI, const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *UseMI, unsigned UseIdx) const; - + private: MachineInstr * convertToThreeAddressWithLEA(unsigned MIOpc, MachineFunction::iterator &MFI, diff --git a/contrib/llvm/lib/Target/X86/X86InstrInfo.td b/contrib/llvm/lib/Target/X86/X86InstrInfo.td index f832a7c85a8a..03a0b0c3aedd 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrInfo.td +++ b/contrib/llvm/lib/Target/X86/X86InstrInfo.td @@ -459,7 +459,7 @@ def CallImmAddr : Predicate<"Subtarget->IsLegalToCallImmediateAddr(TM)">; include "X86InstrFormats.td" //===----------------------------------------------------------------------===// -// Pattern fragments... +// Pattern fragments. // // X86 specific condition code. These correspond to CondCode in @@ -481,21 +481,21 @@ def X86_COND_O : PatLeaf<(i8 13)>; def X86_COND_P : PatLeaf<(i8 14)>; // alt. COND_PE def X86_COND_S : PatLeaf<(i8 15)>; -def immSext8 : PatLeaf<(imm), [{ return immSext8(N); }]>; +let FastIselShouldIgnore = 1 in { // FastIsel should ignore all simm8 instrs. + def i16immSExt8 : ImmLeaf; + def i32immSExt8 : ImmLeaf; + def i64immSExt8 : ImmLeaf; +} -def i16immSExt8 : PatLeaf<(i16 immSext8)>; -def i32immSExt8 : PatLeaf<(i32 immSext8)>; -def i64immSExt8 : PatLeaf<(i64 immSext8)>; -def i64immSExt32 : PatLeaf<(i64 imm), [{ return i64immSExt32(N); }]>; -def i64immZExt32 : PatLeaf<(i64 imm), [{ - // i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit - // unsignedsign extended field. - return (uint64_t)N->getZExtValue() == (uint32_t)N->getZExtValue(); -}]>; +def i64immSExt32 : ImmLeaf; -def i64immZExt32SExt8 : PatLeaf<(i64 imm), [{ - uint64_t v = N->getZExtValue(); - return v == (uint32_t)v && (int32_t)v == (int8_t)v; + +// i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit +// unsigned field. +def i64immZExt32 : ImmLeaf; + +def i64immZExt32SExt8 : ImmLeaf; // Helper fragments for loads. @@ -1437,7 +1437,7 @@ def : InstAlias<"idivq $src, %rax", (IDIV64m i64mem:$src)>; // Various unary fpstack operations default to operating on on ST1. // For example, "fxch" -> "fxch %st(1)" -def : InstAlias<"faddp", (ADD_FPrST0 ST1)>; +def : InstAlias<"faddp", (ADD_FPrST0 ST1), 0>; def : InstAlias<"fsubp", (SUBR_FPrST0 ST1)>; def : InstAlias<"fsubrp", (SUB_FPrST0 ST1)>; def : InstAlias<"fmulp", (MUL_FPrST0 ST1)>; @@ -1455,13 +1455,15 @@ def : InstAlias<"fucompi", (UCOM_FIPr ST1)>; // For example, "fadd %st(4), %st(0)" -> "fadd %st(4)". We also disambiguate // instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with // gas. -multiclass FpUnaryAlias { - def : InstAlias; - def : InstAlias; +multiclass FpUnaryAlias { + def : InstAlias; + def : InstAlias; } defm : FpUnaryAlias<"fadd", ADD_FST0r>; -defm : FpUnaryAlias<"faddp", ADD_FPrST0>; +defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; defm : FpUnaryAlias<"fsub", SUB_FST0r>; defm : FpUnaryAlias<"fsubp", SUBR_FPrST0>; defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; @@ -1472,8 +1474,8 @@ defm : FpUnaryAlias<"fdiv", DIV_FST0r>; defm : FpUnaryAlias<"fdivp", DIVR_FPrST0>; defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; defm : FpUnaryAlias<"fdivrp", DIV_FPrST0>; -defm : FpUnaryAlias<"fcomi", COM_FIr>; -defm : FpUnaryAlias<"fucomi", UCOM_FIr>; +defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; +defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; defm : FpUnaryAlias<"fcompi", COM_FIPr>; defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; @@ -1481,7 +1483,7 @@ defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; // Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they // commute. We also allow fdiv[r]p/fsubrp even though they don't commute, // solely because gas supports it. -def : InstAlias<"faddp %st(0), $op", (ADD_FPrST0 RST:$op)>; +def : InstAlias<"faddp %st(0), $op", (ADD_FPrST0 RST:$op), 0>; def : InstAlias<"fmulp %st(0), $op", (MUL_FPrST0 RST:$op)>; def : InstAlias<"fsubrp %st(0), $op", (SUB_FPrST0 RST:$op)>; def : InstAlias<"fdivp %st(0), $op", (DIVR_FPrST0 RST:$op)>; @@ -1534,29 +1536,31 @@ def : InstAlias<"mov $seg, $mem", (MOV32ms i32mem:$mem, SEGMENT_REG:$seg)>; def : InstAlias<"movq $imm, $reg", (MOV64ri GR64:$reg, i64imm:$imm)>; // Match 'movq GR64, MMX' as an alias for movd. -def : InstAlias<"movq $src, $dst", (MMX_MOVD64to64rr VR64:$dst, GR64:$src)>; -def : InstAlias<"movq $src, $dst", (MMX_MOVD64from64rr GR64:$dst, VR64:$src)>; +def : InstAlias<"movq $src, $dst", + (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0>; +def : InstAlias<"movq $src, $dst", + (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0>; // movsd with no operands (as opposed to the SSE scalar move of a double) is an // alias for movsl. (as in rep; movsd) def : InstAlias<"movsd", (MOVSD)>; // movsx aliases -def : InstAlias<"movsx $src, $dst", (MOVSX16rr8W GR16:$dst, GR8:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX16rm8W GR16:$dst, i8mem:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX32rr8 GR32:$dst, GR8:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX32rr16 GR32:$dst, GR16:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX64rr8 GR64:$dst, GR8:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX64rr16 GR64:$dst, GR16:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX64rr32 GR64:$dst, GR32:$src)>; +def : InstAlias<"movsx $src, $dst", (MOVSX16rr8W GR16:$dst, GR8:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX16rm8W GR16:$dst, i8mem:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX32rr8 GR32:$dst, GR8:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX32rr16 GR32:$dst, GR16:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX64rr8 GR64:$dst, GR8:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX64rr16 GR64:$dst, GR16:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX64rr32 GR64:$dst, GR32:$src), 0>; // movzx aliases -def : InstAlias<"movzx $src, $dst", (MOVZX16rr8W GR16:$dst, GR8:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX16rm8W GR16:$dst, i8mem:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX32rr8 GR32:$dst, GR8:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX32rr16 GR32:$dst, GR16:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX64rr8_Q GR64:$dst, GR8:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX64rr16_Q GR64:$dst, GR16:$src)>; +def : InstAlias<"movzx $src, $dst", (MOVZX16rr8W GR16:$dst, GR8:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX16rm8W GR16:$dst, i8mem:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX32rr8 GR32:$dst, GR8:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX32rr16 GR32:$dst, GR16:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX64rr8_Q GR64:$dst, GR8:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX64rr16_Q GR64:$dst, GR16:$src), 0>; // Note: No GR32->GR64 movzx form. // outb %dx -> outb %al, %dx diff --git a/contrib/llvm/lib/Target/X86/X86InstrSSE.td b/contrib/llvm/lib/Target/X86/X86InstrSSE.td index b912949d482f..cde3f6b7d3c2 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrSSE.td +++ b/contrib/llvm/lib/Target/X86/X86InstrSSE.td @@ -135,18 +135,16 @@ class sse12_move_rm, XS, VEX_4V; - def VMOVSDrr : sse12_move_rr, XD, VEX_4V; +def VMOVSSrr : sse12_move_rr, XS, VEX_4V; +def VMOVSDrr : sse12_move_rr, XD, VEX_4V; - let canFoldAsLoad = 1, isReMaterializable = 1 in { - def VMOVSSrm : sse12_move_rm, XS, VEX; +let canFoldAsLoad = 1, isReMaterializable = 1 in { + def VMOVSSrm : sse12_move_rm, XS, VEX; - let AddedComplexity = 20 in - def VMOVSDrm : sse12_move_rm, XD, VEX; - } + let AddedComplexity = 20 in + def VMOVSDrm : sse12_move_rm, XD, VEX; } let Constraints = "$src1 = $dst" in { @@ -218,14 +216,12 @@ def MOVSDmr : SDI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, FR64:$src), "movsd\t{$src, $dst|$dst, $src}", [(store FR64:$src, addr:$dst)]>; -let isAsmParserOnly = 1 in { def VMOVSSmr : SI<0x11, MRMDestMem, (outs), (ins f32mem:$dst, FR32:$src), "movss\t{$src, $dst|$dst, $src}", [(store FR32:$src, addr:$dst)]>, XS, VEX; def VMOVSDmr : SI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, FR64:$src), "movsd\t{$src, $dst|$dst, $src}", [(store FR64:$src, addr:$dst)]>, XD, VEX; -} // Extract and store. def : Pat<(store (f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))), @@ -251,7 +247,6 @@ let canFoldAsLoad = 1, isReMaterializable = IsReMaterializable in [(set RC:$dst, (ld_frag addr:$src))], d>; } -let isAsmParserOnly = 1 in { defm VMOVAPS : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv4f32, "movaps", SSEPackedSingle>, VEX; defm VMOVAPD : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv2f64, @@ -269,7 +264,6 @@ defm VMOVUPSY : sse12_mov_packed<0x10, VR256, f256mem, loadv8f32, "movups", SSEPackedSingle>, VEX; defm VMOVUPDY : sse12_mov_packed<0x10, VR256, f256mem, loadv4f64, "movupd", SSEPackedDouble, 0>, OpSize, VEX; -} defm MOVAPS : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv4f32, "movaps", SSEPackedSingle>, TB; defm MOVAPD : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv2f64, @@ -279,7 +273,6 @@ defm MOVUPS : sse12_mov_packed<0x10, VR128, f128mem, loadv4f32, defm MOVUPD : sse12_mov_packed<0x10, VR128, f128mem, loadv2f64, "movupd", SSEPackedDouble, 0>, TB, OpSize; -let isAsmParserOnly = 1 in { def VMOVAPSmr : VPSI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movaps\t{$src, $dst|$dst, $src}", [(alignedstore (v4f32 VR128:$src), addr:$dst)]>, VEX; @@ -304,7 +297,6 @@ def VMOVUPSYmr : VPSI<0x11, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), def VMOVUPDYmr : VPDI<0x11, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), "movupd\t{$src, $dst|$dst, $src}", [(store (v4f64 VR256:$src), addr:$dst)]>, VEX; -} def : Pat<(int_x86_avx_loadu_ps_256 addr:$src), (VMOVUPSYrm addr:$src)>; def : Pat<(int_x86_avx_storeu_ps_256 addr:$dst, VR256:$src), @@ -328,32 +320,14 @@ def MOVUPDmr : PDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), [(store (v2f64 VR128:$src), addr:$dst)]>; // Intrinsic forms of MOVUPS/D load and store -let isAsmParserOnly = 1 in { - let canFoldAsLoad = 1, isReMaterializable = 1 in - def VMOVUPSrm_Int : VPSI<0x10, MRMSrcMem, (outs VR128:$dst), - (ins f128mem:$src), - "movups\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>, VEX; - def VMOVUPDrm_Int : VPDI<0x10, MRMSrcMem, (outs VR128:$dst), - (ins f128mem:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>, VEX; - def VMOVUPSmr_Int : VPSI<0x11, MRMDestMem, (outs), - (ins f128mem:$dst, VR128:$src), - "movups\t{$src, $dst|$dst, $src}", - [(int_x86_sse_storeu_ps addr:$dst, VR128:$src)]>, VEX; - def VMOVUPDmr_Int : VPDI<0x11, MRMDestMem, (outs), - (ins f128mem:$dst, VR128:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(int_x86_sse2_storeu_pd addr:$dst, VR128:$src)]>, VEX; -} -let canFoldAsLoad = 1, isReMaterializable = 1 in -def MOVUPSrm_Int : PSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "movups\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>; -def MOVUPDrm_Int : PDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>; +def VMOVUPSmr_Int : VPSI<0x11, MRMDestMem, (outs), + (ins f128mem:$dst, VR128:$src), + "movups\t{$src, $dst|$dst, $src}", + [(int_x86_sse_storeu_ps addr:$dst, VR128:$src)]>, VEX; +def VMOVUPDmr_Int : VPDI<0x11, MRMDestMem, (outs), + (ins f128mem:$dst, VR128:$src), + "movupd\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_storeu_pd addr:$dst, VR128:$src)]>, VEX; def MOVUPSmr_Int : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movups\t{$src, $dst|$dst, $src}", @@ -382,7 +356,7 @@ multiclass sse12_mov_hilo_packedopc, RegisterClass RC, SSEPackedDouble>, TB, OpSize; } -let isAsmParserOnly = 1, AddedComplexity = 20 in { +let AddedComplexity = 20 in { defm VMOVL : sse12_mov_hilo_packed<0x12, VR128, movlp, "movlp", "\t{$src2, $src1, $dst|$dst, $src1, $src2}">, VEX_4V; defm VMOVH : sse12_mov_hilo_packed<0x16, VR128, movlhps, "movhp", @@ -395,7 +369,6 @@ let Constraints = "$src1 = $dst", AddedComplexity = 20 in { "\t{$src2, $dst|$dst, $src2}">; } -let isAsmParserOnly = 1 in { def VMOVLPSmr : VPSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movlps\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract (bc_v2f64 (v4f32 VR128:$src)), @@ -404,7 +377,6 @@ def VMOVLPDmr : VPDI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movlpd\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract (v2f64 VR128:$src), (iPTR 0))), addr:$dst)]>, VEX; -} def MOVLPSmr : PSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movlps\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract (bc_v2f64 (v4f32 VR128:$src)), @@ -416,7 +388,6 @@ def MOVLPDmr : PDI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), // v2f64 extract element 1 is always custom lowered to unpack high to low // and extract element 0 so the non-store version isn't too horrible. -let isAsmParserOnly = 1 in { def VMOVHPSmr : VPSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movhps\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract @@ -429,7 +400,6 @@ def VMOVHPDmr : VPDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), (v2f64 (unpckh VR128:$src, (undef))), (iPTR 0))), addr:$dst)]>, VEX; -} def MOVHPSmr : PSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movhps\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract @@ -441,7 +411,7 @@ def MOVHPDmr : PDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), (v2f64 (unpckh VR128:$src, (undef))), (iPTR 0))), addr:$dst)]>; -let isAsmParserOnly = 1, AddedComplexity = 20 in { +let AddedComplexity = 20 in { def VMOVLHPSrr : VPSI<0x16, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "movlhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", @@ -516,7 +486,6 @@ multiclass sse12_vcvt_avx opc, RegisterClass SrcRC, RegisterClass DstRC, !strconcat(asm,"\t{$src, $src1, $dst|$dst, $src1, $src}"), []>; } -let isAsmParserOnly = 1 in { defm VCVTTSS2SI : sse12_cvt_s<0x2C, FR32, GR32, fp_to_sint, f32mem, loadf32, "cvttss2si\t{$src, $dst|$dst, $src}">, XS, VEX; defm VCVTTSS2SI64 : sse12_cvt_s<0x2C, FR32, GR64, fp_to_sint, f32mem, loadf32, @@ -542,7 +511,6 @@ defm VCVTSI2SDL : sse12_vcvt_avx<0x2A, GR32, FR64, i32mem, "cvtsi2sd{l}">, XD, VEX_4V; defm VCVTSI2SD64 : sse12_vcvt_avx<0x2A, GR64, FR64, i64mem, "cvtsi2sd{q}">, XD, VEX_4V, VEX_W; -} defm CVTTSS2SI : sse12_cvt_s<0x2C, FR32, GR32, fp_to_sint, f32mem, loadf32, "cvttss2si\t{$src, $dst|$dst, $src}">, XS; @@ -591,27 +559,25 @@ multiclass sse12_cvt_sint_3addr opc, RegisterClass SrcRC, [(set DstRC:$dst, (Int DstRC:$src1, (ld_frag addr:$src2)))]>; } -let isAsmParserOnly = 1 in { - defm Int_VCVTSS2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse_cvtss2si, - f32mem, load, "cvtss2si">, XS, VEX; - defm Int_VCVTSS2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, - int_x86_sse_cvtss2si64, f32mem, load, "cvtss2si">, - XS, VEX, VEX_W; - defm Int_VCVTSD2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse2_cvtsd2si, - f128mem, load, "cvtsd2si">, XD, VEX; - defm Int_VCVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, - int_x86_sse2_cvtsd2si64, f128mem, load, "cvtsd2si">, - XD, VEX, VEX_W; +defm Int_VCVTSS2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse_cvtss2si, + f32mem, load, "cvtss2si">, XS, VEX; +defm Int_VCVTSS2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, + int_x86_sse_cvtss2si64, f32mem, load, "cvtss2si">, + XS, VEX, VEX_W; +defm Int_VCVTSD2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse2_cvtsd2si, + f128mem, load, "cvtsd2si">, XD, VEX; +defm Int_VCVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, + int_x86_sse2_cvtsd2si64, f128mem, load, "cvtsd2si">, + XD, VEX, VEX_W; - // FIXME: The asm matcher has a hack to ignore instructions with _Int and Int_ - // Get rid of this hack or rename the intrinsics, there are several - // intructions that only match with the intrinsic form, why create duplicates - // to let them be recognized by the assembler? - defm VCVTSD2SI_alt : sse12_cvt_s_np<0x2D, FR64, GR32, f64mem, - "cvtsd2si\t{$src, $dst|$dst, $src}">, XD, VEX; - defm VCVTSD2SI64 : sse12_cvt_s_np<0x2D, FR64, GR64, f64mem, - "cvtsd2si\t{$src, $dst|$dst, $src}">, XD, VEX, VEX_W; -} +// FIXME: The asm matcher has a hack to ignore instructions with _Int and Int_ +// Get rid of this hack or rename the intrinsics, there are several +// intructions that only match with the intrinsic form, why create duplicates +// to let them be recognized by the assembler? +defm VCVTSD2SI_alt : sse12_cvt_s_np<0x2D, FR64, GR32, f64mem, + "cvtsd2si\t{$src, $dst|$dst, $src}">, XD, VEX; +defm VCVTSD2SI64 : sse12_cvt_s_np<0x2D, FR64, GR64, f64mem, + "cvtsd2si\t{$src, $dst|$dst, $src}">, XD, VEX, VEX_W; defm Int_CVTSS2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse_cvtss2si, f32mem, load, "cvtss2si">, XS; defm Int_CVTSS2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse_cvtss2si64, @@ -622,18 +588,16 @@ defm CVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse2_cvtsd2si64, f128mem, load, "cvtsd2si{q}">, XD, REX_W; -let isAsmParserOnly = 1 in { - defm Int_VCVTSI2SS : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - int_x86_sse_cvtsi2ss, i32mem, loadi32, "cvtsi2ss", 0>, XS, VEX_4V; - defm Int_VCVTSI2SS64 : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - int_x86_sse_cvtsi642ss, i64mem, loadi64, "cvtsi2ss", 0>, XS, VEX_4V, - VEX_W; - defm Int_VCVTSI2SD : sse12_cvt_sint_3addr<0x2A, GR32, VR128, - int_x86_sse2_cvtsi2sd, i32mem, loadi32, "cvtsi2sd", 0>, XD, VEX_4V; - defm Int_VCVTSI2SD64 : sse12_cvt_sint_3addr<0x2A, GR64, VR128, - int_x86_sse2_cvtsi642sd, i64mem, loadi64, "cvtsi2sd", 0>, XD, - VEX_4V, VEX_W; -} +defm Int_VCVTSI2SS : sse12_cvt_sint_3addr<0x2A, GR32, VR128, + int_x86_sse_cvtsi2ss, i32mem, loadi32, "cvtsi2ss", 0>, XS, VEX_4V; +defm Int_VCVTSI2SS64 : sse12_cvt_sint_3addr<0x2A, GR64, VR128, + int_x86_sse_cvtsi642ss, i64mem, loadi64, "cvtsi2ss", 0>, XS, VEX_4V, + VEX_W; +defm Int_VCVTSI2SD : sse12_cvt_sint_3addr<0x2A, GR32, VR128, + int_x86_sse2_cvtsi2sd, i32mem, loadi32, "cvtsi2sd", 0>, XD, VEX_4V; +defm Int_VCVTSI2SD64 : sse12_cvt_sint_3addr<0x2A, GR64, VR128, + int_x86_sse2_cvtsi642sd, i64mem, loadi64, "cvtsi2sd", 0>, XD, + VEX_4V, VEX_W; let Constraints = "$src1 = $dst" in { defm Int_CVTSI2SS : sse12_cvt_sint_3addr<0x2A, GR32, VR128, @@ -653,7 +617,6 @@ let Constraints = "$src1 = $dst" in { /// SSE 1 Only // Aliases for intrinsics -let isAsmParserOnly = 1 in { defm Int_VCVTTSS2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse_cvttss2si, f32mem, load, "cvttss2si">, XS, VEX; defm Int_VCVTTSS2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, @@ -664,7 +627,6 @@ defm Int_VCVTTSD2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse2_cvttsd2si, defm Int_VCVTTSD2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, int_x86_sse2_cvttsd2si64, f128mem, load, "cvttsd2si">, XD, VEX, VEX_W; -} defm Int_CVTTSS2SI : sse12_cvt_sint<0x2C, VR128, GR32, int_x86_sse_cvttss2si, f32mem, load, "cvttss2si">, XS; defm Int_CVTTSS2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, @@ -676,7 +638,7 @@ defm Int_CVTTSD2SI64 : sse12_cvt_sint<0x2C, VR128, GR64, int_x86_sse2_cvttsd2si64, f128mem, load, "cvttsd2si{q}">, XD, REX_W; -let isAsmParserOnly = 1, Pattern = [] in { +let Pattern = [] in { defm VCVTSS2SI : sse12_cvt_s<0x2D, FR32, GR32, undef, f32mem, load, "cvtss2si{l}\t{$src, $dst|$dst, $src}">, XS, VEX; defm VCVTSS2SI64 : sse12_cvt_s<0x2D, FR32, GR64, undef, f32mem, load, @@ -702,7 +664,6 @@ defm CVTDQ2PS : sse12_cvt_p<0x5B, VR128, VR128, undef, i128mem, load /*dummy*/, /// SSE 2 Only // Convert scalar double to scalar single -let isAsmParserOnly = 1 in { def VCVTSD2SSrr : VSDI<0x5A, MRMSrcReg, (outs FR32:$dst), (ins FR64:$src1, FR64:$src2), "cvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, @@ -711,7 +672,6 @@ def VCVTSD2SSrm : I<0x5A, MRMSrcMem, (outs FR32:$dst), (ins FR64:$src1, f64mem:$src2), "vcvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, XD, Requires<[HasAVX, OptForSize]>, VEX_4V; -} def : Pat<(f32 (fround FR64:$src)), (VCVTSD2SSrr FR64:$src, FR64:$src)>, Requires<[HasAVX]>; @@ -723,7 +683,6 @@ def CVTSD2SSrm : I<0x5A, MRMSrcMem, (outs FR32:$dst), (ins f64mem:$src), [(set FR32:$dst, (fround (loadf64 addr:$src)))]>, XD, Requires<[HasSSE2, OptForSize]>; -let isAsmParserOnly = 1 in defm Int_VCVTSD2SS: sse12_cvt_sint_3addr<0x5A, VR128, VR128, int_x86_sse2_cvtsd2ss, f64mem, load, "cvtsd2ss", 0>, XS, VEX_4V; @@ -732,7 +691,7 @@ defm Int_CVTSD2SS: sse12_cvt_sint_3addr<0x5A, VR128, VR128, int_x86_sse2_cvtsd2ss, f64mem, load, "cvtsd2ss">, XS; // Convert scalar single to scalar double -let isAsmParserOnly = 1 in { // SSE2 instructions with XS prefix +// SSE2 instructions with XS prefix def VCVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst), (ins FR32:$src1, FR32:$src2), "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", @@ -741,7 +700,6 @@ def VCVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), (ins FR32:$src1, f32mem:$src2), "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>, XS, VEX_4V, Requires<[HasAVX, OptForSize]>; -} def : Pat<(f64 (fextend FR32:$src)), (VCVTSS2SDrr FR32:$src, FR32:$src)>, Requires<[HasAVX]>; @@ -754,7 +712,6 @@ def CVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), (ins f32mem:$src), [(set FR64:$dst, (extloadf32 addr:$src))]>, XS, Requires<[HasSSE2, OptForSize]>; -let isAsmParserOnly = 1 in { def Int_VCVTSS2SDrr: I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), "vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}", @@ -767,7 +724,6 @@ def Int_VCVTSS2SDrm: I<0x5A, MRMSrcMem, [(set VR128:$dst, (int_x86_sse2_cvtss2sd VR128:$src1, (load addr:$src2)))]>, XS, VEX_4V, Requires<[HasAVX]>; -} let Constraints = "$src1 = $dst" in { // SSE2 instructions with XS prefix def Int_CVTSS2SDrr: I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), @@ -788,7 +744,7 @@ def : Pat<(extloadf32 addr:$src), Requires<[HasSSE2, OptForSpeed]>; // Convert doubleword to packed single/double fp -let isAsmParserOnly = 1 in { // SSE2 instructions without OpSize prefix +// SSE2 instructions without OpSize prefix def Int_VCVTDQ2PSrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "vcvtdq2ps\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtdq2ps VR128:$src))]>, @@ -798,7 +754,6 @@ def Int_VCVTDQ2PSrm : I<0x5B, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), [(set VR128:$dst, (int_x86_sse2_cvtdq2ps (bitconvert (memopv2i64 addr:$src))))]>, TB, VEX, Requires<[HasAVX]>; -} def Int_CVTDQ2PSrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtdq2ps\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtdq2ps VR128:$src))]>, @@ -810,7 +765,7 @@ def Int_CVTDQ2PSrm : I<0x5B, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), TB, Requires<[HasSSE2]>; // FIXME: why the non-intrinsic version is described as SSE3? -let isAsmParserOnly = 1 in { // SSE2 instructions with XS prefix +// SSE2 instructions with XS prefix def Int_VCVTDQ2PDrr : I<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "vcvtdq2pd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtdq2pd VR128:$src))]>, @@ -820,7 +775,6 @@ def Int_VCVTDQ2PDrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), [(set VR128:$dst, (int_x86_sse2_cvtdq2pd (bitconvert (memopv2i64 addr:$src))))]>, XS, VEX, Requires<[HasAVX]>; -} def Int_CVTDQ2PDrr : I<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtdq2pd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtdq2pd VR128:$src))]>, @@ -833,7 +787,6 @@ def Int_CVTDQ2PDrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), // Convert packed single/double fp to doubleword -let isAsmParserOnly = 1 in { def VCVTPS2DQrr : VPDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtps2dq\t{$src, $dst|$dst, $src}", []>, VEX; def VCVTPS2DQrm : VPDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), @@ -842,13 +795,11 @@ def VCVTPS2DQYrr : VPDI<0x5B, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), "cvtps2dq\t{$src, $dst|$dst, $src}", []>, VEX; def VCVTPS2DQYrm : VPDI<0x5B, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src), "cvtps2dq\t{$src, $dst|$dst, $src}", []>, VEX; -} def CVTPS2DQrr : PDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtps2dq\t{$src, $dst|$dst, $src}", []>; def CVTPS2DQrm : PDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "cvtps2dq\t{$src, $dst|$dst, $src}", []>; -let isAsmParserOnly = 1 in { def Int_VCVTPS2DQrr : VPDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtps2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtps2dq VR128:$src))]>, @@ -858,7 +809,6 @@ def Int_VCVTPS2DQrm : VPDI<0x5B, MRMSrcMem, (outs VR128:$dst), "cvtps2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtps2dq (memop addr:$src)))]>, VEX; -} def Int_CVTPS2DQrr : PDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtps2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtps2dq VR128:$src))]>; @@ -867,7 +817,7 @@ def Int_CVTPS2DQrm : PDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), [(set VR128:$dst, (int_x86_sse2_cvtps2dq (memop addr:$src)))]>; -let isAsmParserOnly = 1 in { // SSE2 packed instructions with XD prefix +// SSE2 packed instructions with XD prefix def Int_VCVTPD2DQrr : I<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "vcvtpd2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtpd2dq VR128:$src))]>, @@ -877,7 +827,6 @@ def Int_VCVTPD2DQrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), [(set VR128:$dst, (int_x86_sse2_cvtpd2dq (memop addr:$src)))]>, XD, VEX, Requires<[HasAVX]>; -} def Int_CVTPD2DQrr : I<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtpd2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtpd2dq VR128:$src))]>, @@ -890,7 +839,7 @@ def Int_CVTPD2DQrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), // Convert with truncation packed single/double fp to doubleword -let isAsmParserOnly = 1 in { // SSE2 packed instructions with XS prefix +// SSE2 packed instructions with XS prefix def VCVTTPS2DQrr : VSSI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX; def VCVTTPS2DQrm : VSSI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), @@ -899,7 +848,6 @@ def VCVTTPS2DQYrr : VSSI<0x5B, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), "cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX; def VCVTTPS2DQYrm : VSSI<0x5B, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src), "cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX; -} def CVTTPS2DQrr : SSI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvttps2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, @@ -910,7 +858,6 @@ def CVTTPS2DQrm : SSI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), (int_x86_sse2_cvttps2dq (memop addr:$src)))]>; -let isAsmParserOnly = 1 in { def Int_VCVTTPS2DQrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "vcvttps2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, @@ -921,9 +868,7 @@ def Int_VCVTTPS2DQrm : I<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), [(set VR128:$dst, (int_x86_sse2_cvttps2dq (memop addr:$src)))]>, XS, VEX, Requires<[HasAVX]>; -} -let isAsmParserOnly = 1 in { def Int_VCVTTPD2DQrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvttpd2dq\t{$src, $dst|$dst, $src}", @@ -934,7 +879,6 @@ def Int_VCVTTPD2DQrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), "cvttpd2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvttpd2dq (memop addr:$src)))]>, VEX; -} def CVTTPD2DQrr : PDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvttpd2dq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvttpd2dq VR128:$src))]>; @@ -943,7 +887,6 @@ def CVTTPD2DQrm : PDI<0xE6, MRMSrcMem, (outs VR128:$dst),(ins f128mem:$src), [(set VR128:$dst, (int_x86_sse2_cvttpd2dq (memop addr:$src)))]>; -let isAsmParserOnly = 1 in { // The assembler can recognize rr 256-bit instructions by seeing a ymm // register, but the same isn't true when using memory operands instead. // Provide other assembly rr and rm forms to address this explicitly. @@ -963,10 +906,9 @@ def VCVTTPD2DQYrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src), "cvttpd2dqy\t{$src, $dst|$dst, $src}", []>, VEX; def VCVTTPD2DQYrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src), "cvttpd2dqy\t{$src, $dst|$dst, $src}", []>, VEX, VEX_L; -} // Convert packed single to packed double -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { // SSE2 instructions without OpSize prefix def VCVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX; @@ -982,7 +924,6 @@ def CVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), def CVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), "cvtps2pd\t{$src, $dst|$dst, $src}", []>, TB; -let isAsmParserOnly = 1 in { def Int_VCVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "vcvtps2pd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtps2pd VR128:$src))]>, @@ -992,7 +933,6 @@ def Int_VCVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), [(set VR128:$dst, (int_x86_sse2_cvtps2pd (load addr:$src)))]>, VEX, Requires<[HasAVX]>; -} def Int_CVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtps2pd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtps2pd VR128:$src))]>, @@ -1004,7 +944,6 @@ def Int_CVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), TB, Requires<[HasSSE2]>; // Convert packed double to packed single -let isAsmParserOnly = 1 in { // The assembler can recognize rr 256-bit instructions by seeing a ymm // register, but the same isn't true when using memory operands instead. // Provide other assembly rr and rm forms to address this explicitly. @@ -1024,14 +963,12 @@ def VCVTPD2PSYrr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src), "cvtpd2psy\t{$src, $dst|$dst, $src}", []>, VEX; def VCVTPD2PSYrm : VPDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src), "cvtpd2psy\t{$src, $dst|$dst, $src}", []>, VEX, VEX_L; -} def CVTPD2PSrr : PDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtpd2ps\t{$src, $dst|$dst, $src}", []>; def CVTPD2PSrm : PDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "cvtpd2ps\t{$src, $dst|$dst, $src}", []>; -let isAsmParserOnly = 1 in { def Int_VCVTPD2PSrr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtpd2ps\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtpd2ps VR128:$src))]>; @@ -1040,7 +977,6 @@ def Int_VCVTPD2PSrm : VPDI<0x5A, MRMSrcMem, (outs VR128:$dst), "cvtpd2ps\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtpd2ps (memop addr:$src)))]>; -} def Int_CVTPD2PSrr : PDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtpd2ps\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse2_cvtpd2ps VR128:$src))]>; @@ -1089,26 +1025,27 @@ def : Pat<(int_x86_avx_cvtt_ps2dq_256 (memopv8f32 addr:$src)), // sse12_cmp_scalar - sse 1 & 2 compare scalar instructions multiclass sse12_cmp_scalar { - def rr : SIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src, SSECC:$cc), - asm, []>; - let mayLoad = 1 in - def rm : SIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src, SSECC:$cc), - asm, []>; - // Accept explicit immediate argument form instead of comparison code. let isAsmParserOnly = 1 in { - def rr_alt : SIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src, i8imm:$src2), - asm_alt, []>; + def rr : SIi8<0xC2, MRMSrcReg, + (outs RC:$dst), (ins RC:$src1, RC:$src, SSECC:$cc), + asm, []>; let mayLoad = 1 in - def rm_alt : SIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src, i8imm:$src2), - asm_alt, []>; + def rm : SIi8<0xC2, MRMSrcMem, + (outs RC:$dst), (ins RC:$src1, x86memop:$src, SSECC:$cc), + asm, []>; } + + // Accept explicit immediate argument form instead of comparison code. + def rr_alt : SIi8<0xC2, MRMSrcReg, + (outs RC:$dst), (ins RC:$src1, RC:$src, i8imm:$src2), + asm_alt, []>; + let mayLoad = 1 in + def rm_alt : SIi8<0xC2, MRMSrcMem, + (outs RC:$dst), (ins RC:$src1, x86memop:$src, i8imm:$src2), + asm_alt, []>; } -let neverHasSideEffects = 1, isAsmParserOnly = 1 in { +let neverHasSideEffects = 1 in { defm VCMPSS : sse12_cmp_scalar, @@ -1141,14 +1078,12 @@ multiclass sse12_cmp_scalar_int, - XS, VEX_4V; - defm Int_VCMPSD : sse12_cmp_scalar_int, - XD, VEX_4V; -} +defm Int_VCMPSS : sse12_cmp_scalar_int, + XS, VEX_4V; +defm Int_VCMPSD : sse12_cmp_scalar_int, + XD, VEX_4V; let Constraints = "$src1 = $dst" in { defm Int_CMPSS : sse12_cmp_scalar_int, XS; @@ -1171,28 +1106,26 @@ multiclass sse12_ord_cmp opc, RegisterClass RC, SDNode OpNode, } let Defs = [EFLAGS] in { - let isAsmParserOnly = 1 in { - defm VUCOMISS : sse12_ord_cmp<0x2E, FR32, X86cmp, f32, f32mem, loadf32, - "ucomiss", SSEPackedSingle>, VEX; - defm VUCOMISD : sse12_ord_cmp<0x2E, FR64, X86cmp, f64, f64mem, loadf64, - "ucomisd", SSEPackedDouble>, OpSize, VEX; - let Pattern = [] in { - defm VCOMISS : sse12_ord_cmp<0x2F, VR128, undef, v4f32, f128mem, load, - "comiss", SSEPackedSingle>, VEX; - defm VCOMISD : sse12_ord_cmp<0x2F, VR128, undef, v2f64, f128mem, load, - "comisd", SSEPackedDouble>, OpSize, VEX; - } - - defm Int_VUCOMISS : sse12_ord_cmp<0x2E, VR128, X86ucomi, v4f32, f128mem, - load, "ucomiss", SSEPackedSingle>, VEX; - defm Int_VUCOMISD : sse12_ord_cmp<0x2E, VR128, X86ucomi, v2f64, f128mem, - load, "ucomisd", SSEPackedDouble>, OpSize, VEX; - - defm Int_VCOMISS : sse12_ord_cmp<0x2F, VR128, X86comi, v4f32, f128mem, - load, "comiss", SSEPackedSingle>, VEX; - defm Int_VCOMISD : sse12_ord_cmp<0x2F, VR128, X86comi, v2f64, f128mem, - load, "comisd", SSEPackedDouble>, OpSize, VEX; + defm VUCOMISS : sse12_ord_cmp<0x2E, FR32, X86cmp, f32, f32mem, loadf32, + "ucomiss", SSEPackedSingle>, VEX; + defm VUCOMISD : sse12_ord_cmp<0x2E, FR64, X86cmp, f64, f64mem, loadf64, + "ucomisd", SSEPackedDouble>, OpSize, VEX; + let Pattern = [] in { + defm VCOMISS : sse12_ord_cmp<0x2F, VR128, undef, v4f32, f128mem, load, + "comiss", SSEPackedSingle>, VEX; + defm VCOMISD : sse12_ord_cmp<0x2F, VR128, undef, v2f64, f128mem, load, + "comisd", SSEPackedDouble>, OpSize, VEX; } + + defm Int_VUCOMISS : sse12_ord_cmp<0x2E, VR128, X86ucomi, v4f32, f128mem, + load, "ucomiss", SSEPackedSingle>, VEX; + defm Int_VUCOMISD : sse12_ord_cmp<0x2E, VR128, X86ucomi, v2f64, f128mem, + load, "ucomisd", SSEPackedDouble>, OpSize, VEX; + + defm Int_VCOMISS : sse12_ord_cmp<0x2F, VR128, X86comi, v4f32, f128mem, + load, "comiss", SSEPackedSingle>, VEX; + defm Int_VCOMISD : sse12_ord_cmp<0x2F, VR128, X86comi, v2f64, f128mem, + load, "comisd", SSEPackedDouble>, OpSize, VEX; defm UCOMISS : sse12_ord_cmp<0x2E, FR32, X86cmp, f32, f32mem, loadf32, "ucomiss", SSEPackedSingle>, TB; defm UCOMISD : sse12_ord_cmp<0x2E, FR64, X86cmp, f64, f64mem, loadf64, @@ -1220,41 +1153,40 @@ let Defs = [EFLAGS] in { multiclass sse12_cmp_packed { - def rri : PIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src, SSECC:$cc), asm, - [(set RC:$dst, (Int RC:$src1, RC:$src, imm:$cc))], d>; - def rmi : PIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, f128mem:$src, SSECC:$cc), asm, - [(set RC:$dst, (Int RC:$src1, (memop addr:$src), imm:$cc))], d>; - // Accept explicit immediate argument form instead of comparison code. let isAsmParserOnly = 1 in { - def rri_alt : PIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src, i8imm:$src2), - asm_alt, [], d>; - def rmi_alt : PIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, f128mem:$src, i8imm:$src2), - asm_alt, [], d>; + def rri : PIi8<0xC2, MRMSrcReg, + (outs RC:$dst), (ins RC:$src1, RC:$src, SSECC:$cc), asm, + [(set RC:$dst, (Int RC:$src1, RC:$src, imm:$cc))], d>; + def rmi : PIi8<0xC2, MRMSrcMem, + (outs RC:$dst), (ins RC:$src1, f128mem:$src, SSECC:$cc), asm, + [(set RC:$dst, (Int RC:$src1, (memop addr:$src), imm:$cc))], d>; } + + // Accept explicit immediate argument form instead of comparison code. + def rri_alt : PIi8<0xC2, MRMSrcReg, + (outs RC:$dst), (ins RC:$src1, RC:$src, i8imm:$src2), + asm_alt, [], d>; + def rmi_alt : PIi8<0xC2, MRMSrcMem, + (outs RC:$dst), (ins RC:$src1, f128mem:$src, i8imm:$src2), + asm_alt, [], d>; } -let isAsmParserOnly = 1 in { - defm VCMPPS : sse12_cmp_packed, VEX_4V; - defm VCMPPD : sse12_cmp_packed, OpSize, VEX_4V; - defm VCMPPSY : sse12_cmp_packed, VEX_4V; - defm VCMPPDY : sse12_cmp_packed, OpSize, VEX_4V; -} +defm VCMPPS : sse12_cmp_packed, VEX_4V; +defm VCMPPD : sse12_cmp_packed, OpSize, VEX_4V; +defm VCMPPSY : sse12_cmp_packed, VEX_4V; +defm VCMPPDY : sse12_cmp_packed, OpSize, VEX_4V; let Constraints = "$src1 = $dst" in { defm CMPPS : sse12_cmp_packed; } -let isAsmParserOnly = 1 in { - defm VSHUFPS : sse12_shuffle, VEX_4V; - defm VSHUFPSY : sse12_shuffle, VEX_4V; - defm VSHUFPD : sse12_shuffle, OpSize, VEX_4V; - defm VSHUFPDY : sse12_shuffle, OpSize, VEX_4V; -} +defm VSHUFPS : sse12_shuffle, TB, VEX_4V; +defm VSHUFPSY : sse12_shuffle, TB, VEX_4V; +defm VSHUFPD : sse12_shuffle, TB, OpSize, VEX_4V; +defm VSHUFPDY : sse12_shuffle, TB, OpSize, VEX_4V; let Constraints = "$src1 = $dst" in { defm SHUFPS : sse12_shuffle opc, PatFrag OpNode, ValueType vt, } let AddedComplexity = 10 in { - let isAsmParserOnly = 1 in { - defm VUNPCKHPS: sse12_unpack_interleave<0x15, unpckh, v4f32, memopv4f32, - VR128, f128mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SSEPackedSingle>, VEX_4V; - defm VUNPCKHPD: sse12_unpack_interleave<0x15, unpckh, v2f64, memopv2f64, - VR128, f128mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SSEPackedDouble>, OpSize, VEX_4V; - defm VUNPCKLPS: sse12_unpack_interleave<0x14, unpckl, v4f32, memopv4f32, - VR128, f128mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SSEPackedSingle>, VEX_4V; - defm VUNPCKLPD: sse12_unpack_interleave<0x14, unpckl, v2f64, memopv2f64, - VR128, f128mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SSEPackedDouble>, OpSize, VEX_4V; + defm VUNPCKHPS: sse12_unpack_interleave<0x15, unpckh, v4f32, memopv4f32, + VR128, f128mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", + SSEPackedSingle>, VEX_4V; + defm VUNPCKHPD: sse12_unpack_interleave<0x15, unpckh, v2f64, memopv2f64, + VR128, f128mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", + SSEPackedDouble>, OpSize, VEX_4V; + defm VUNPCKLPS: sse12_unpack_interleave<0x14, unpckl, v4f32, memopv4f32, + VR128, f128mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}", + SSEPackedSingle>, VEX_4V; + defm VUNPCKLPD: sse12_unpack_interleave<0x14, unpckl, v2f64, memopv2f64, + VR128, f128mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", + SSEPackedDouble>, OpSize, VEX_4V; - defm VUNPCKHPSY: sse12_unpack_interleave<0x15, unpckh, v8f32, memopv8f32, - VR256, f256mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SSEPackedSingle>, VEX_4V; - defm VUNPCKHPDY: sse12_unpack_interleave<0x15, unpckh, v4f64, memopv4f64, - VR256, f256mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SSEPackedDouble>, OpSize, VEX_4V; - defm VUNPCKLPSY: sse12_unpack_interleave<0x14, unpckl, v8f32, memopv8f32, - VR256, f256mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SSEPackedSingle>, VEX_4V; - defm VUNPCKLPDY: sse12_unpack_interleave<0x14, unpckl, v4f64, memopv4f64, - VR256, f256mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", - SSEPackedDouble>, OpSize, VEX_4V; - } + defm VUNPCKHPSY: sse12_unpack_interleave<0x15, unpckh, v8f32, memopv8f32, + VR256, f256mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}", + SSEPackedSingle>, VEX_4V; + defm VUNPCKHPDY: sse12_unpack_interleave<0x15, unpckh, v4f64, memopv4f64, + VR256, f256mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", + SSEPackedDouble>, OpSize, VEX_4V; + defm VUNPCKLPSY: sse12_unpack_interleave<0x14, unpckl, v8f32, memopv8f32, + VR256, f256mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}", + SSEPackedSingle>, VEX_4V; + defm VUNPCKLPDY: sse12_unpack_interleave<0x14, unpckl, v4f64, memopv4f64, + VR256, f256mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}", + SSEPackedDouble>, OpSize, VEX_4V; let Constraints = "$src1 = $dst" in { defm UNPCKHPS: sse12_unpack_interleave<0x15, unpckh, v4f32, memopv4f32, @@ -1404,30 +1332,28 @@ defm MOVMSKPS : sse12_extr_sign_mask, TB, OpSize; -let isAsmParserOnly = 1 in { - defm VMOVMSKPS : sse12_extr_sign_mask, VEX; - defm VMOVMSKPD : sse12_extr_sign_mask, OpSize, - VEX; - defm VMOVMSKPSY : sse12_extr_sign_mask, VEX; - defm VMOVMSKPDY : sse12_extr_sign_mask, OpSize, - VEX; +defm VMOVMSKPS : sse12_extr_sign_mask, VEX; +defm VMOVMSKPD : sse12_extr_sign_mask, OpSize, + VEX; +defm VMOVMSKPSY : sse12_extr_sign_mask, VEX; +defm VMOVMSKPDY : sse12_extr_sign_mask, OpSize, + VEX; - // Assembler Only - def VMOVMSKPSr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src), - "movmskps\t{$src, $dst|$dst, $src}", [], SSEPackedSingle>, VEX; - def VMOVMSKPDr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src), - "movmskpd\t{$src, $dst|$dst, $src}", [], SSEPackedDouble>, OpSize, - VEX; - def VMOVMSKPSYr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR256:$src), - "movmskps\t{$src, $dst|$dst, $src}", [], SSEPackedSingle>, VEX; - def VMOVMSKPDYr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR256:$src), - "movmskpd\t{$src, $dst|$dst, $src}", [], SSEPackedDouble>, OpSize, - VEX; -} +// Assembler Only +def VMOVMSKPSr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src), + "movmskps\t{$src, $dst|$dst, $src}", [], SSEPackedSingle>, VEX; +def VMOVMSKPDr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src), + "movmskpd\t{$src, $dst|$dst, $src}", [], SSEPackedDouble>, OpSize, + VEX; +def VMOVMSKPSYr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR256:$src), + "movmskps\t{$src, $dst|$dst, $src}", [], SSEPackedSingle>, VEX; +def VMOVMSKPDYr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR256:$src), + "movmskpd\t{$src, $dst|$dst, $src}", [], SSEPackedDouble>, OpSize, + VEX; //===----------------------------------------------------------------------===// // SSE 1 & 2 - Misc aliasing of packed SSE 1 & 2 instructions @@ -1482,13 +1408,11 @@ def FsMOVAPDrm : PDI<0x28, MRMSrcMem, (outs FR64:$dst), (ins f128mem:$src), /// multiclass sse12_fp_alias_pack_logical opc, string OpcodeStr, SDNode OpNode> { - let isAsmParserOnly = 1 in { - defm V#NAME#PS : sse12_fp_packed, VEX_4V; + defm V#NAME#PS : sse12_fp_packed, VEX_4V; - defm V#NAME#PD : sse12_fp_packed, OpSize, VEX_4V; - } + defm V#NAME#PD : sse12_fp_packed, OpSize, VEX_4V; let Constraints = "$src1 = $dst" in { defm PS : sse12_fp_packed, isCommutable = 0 in multiclass sse12_fp_packed_logical opc, string OpcodeStr, SDNode OpNode, int HasPat = 0, list> Pattern = []> { - let isAsmParserOnly = 1, Pattern = [] in { + let Pattern = [] in { defm V#NAME#PS : sse12_fp_packed_logical_rm opc, string OpcodeStr, /// sse12_fp_packed_logical_y - AVX 256-bit SSE 1 & 2 logical ops forms /// -let isAsmParserOnly = 1 in { multiclass sse12_fp_packed_logical_y opc, string OpcodeStr> { defm PSY : sse12_fp_packed_logical_rm, VEX_4V; @@ -1569,7 +1492,6 @@ multiclass sse12_fp_packed_logical_y opc, string OpcodeStr> { defm PDY : sse12_fp_packed_logical_rm, OpSize, VEX_4V; } -} // AVX 256-bit packed logical ops forms defm VAND : sse12_fp_packed_logical_y<0x54, "and">; @@ -1667,38 +1589,36 @@ multiclass basic_sse12_fp_binop_p_y_int opc, string OpcodeStr> { } // Binary Arithmetic instructions -let isAsmParserOnly = 1 in { - defm VADD : basic_sse12_fp_binop_s<0x58, "add", fadd, 0>, - basic_sse12_fp_binop_s_int<0x58, "add", 0>, - basic_sse12_fp_binop_p<0x58, "add", fadd, 0>, - basic_sse12_fp_binop_p_y<0x58, "add", fadd>, VEX_4V; - defm VMUL : basic_sse12_fp_binop_s<0x59, "mul", fmul, 0>, - basic_sse12_fp_binop_s_int<0x59, "mul", 0>, - basic_sse12_fp_binop_p<0x59, "mul", fmul, 0>, - basic_sse12_fp_binop_p_y<0x59, "mul", fmul>, VEX_4V; +defm VADD : basic_sse12_fp_binop_s<0x58, "add", fadd, 0>, + basic_sse12_fp_binop_s_int<0x58, "add", 0>, + basic_sse12_fp_binop_p<0x58, "add", fadd, 0>, + basic_sse12_fp_binop_p_y<0x58, "add", fadd>, VEX_4V; +defm VMUL : basic_sse12_fp_binop_s<0x59, "mul", fmul, 0>, + basic_sse12_fp_binop_s_int<0x59, "mul", 0>, + basic_sse12_fp_binop_p<0x59, "mul", fmul, 0>, + basic_sse12_fp_binop_p_y<0x59, "mul", fmul>, VEX_4V; - let isCommutable = 0 in { - defm VSUB : basic_sse12_fp_binop_s<0x5C, "sub", fsub, 0>, - basic_sse12_fp_binop_s_int<0x5C, "sub", 0>, - basic_sse12_fp_binop_p<0x5C, "sub", fsub, 0>, - basic_sse12_fp_binop_p_y<0x5C, "sub", fsub>, VEX_4V; - defm VDIV : basic_sse12_fp_binop_s<0x5E, "div", fdiv, 0>, - basic_sse12_fp_binop_s_int<0x5E, "div", 0>, - basic_sse12_fp_binop_p<0x5E, "div", fdiv, 0>, - basic_sse12_fp_binop_p_y<0x5E, "div", fdiv>, VEX_4V; - defm VMAX : basic_sse12_fp_binop_s<0x5F, "max", X86fmax, 0>, - basic_sse12_fp_binop_s_int<0x5F, "max", 0>, - basic_sse12_fp_binop_p<0x5F, "max", X86fmax, 0>, - basic_sse12_fp_binop_p_int<0x5F, "max", 0>, - basic_sse12_fp_binop_p_y<0x5F, "max", X86fmax>, - basic_sse12_fp_binop_p_y_int<0x5F, "max">, VEX_4V; - defm VMIN : basic_sse12_fp_binop_s<0x5D, "min", X86fmin, 0>, - basic_sse12_fp_binop_s_int<0x5D, "min", 0>, - basic_sse12_fp_binop_p<0x5D, "min", X86fmin, 0>, - basic_sse12_fp_binop_p_int<0x5D, "min", 0>, - basic_sse12_fp_binop_p_y_int<0x5D, "min">, - basic_sse12_fp_binop_p_y<0x5D, "min", X86fmin>, VEX_4V; - } +let isCommutable = 0 in { + defm VSUB : basic_sse12_fp_binop_s<0x5C, "sub", fsub, 0>, + basic_sse12_fp_binop_s_int<0x5C, "sub", 0>, + basic_sse12_fp_binop_p<0x5C, "sub", fsub, 0>, + basic_sse12_fp_binop_p_y<0x5C, "sub", fsub>, VEX_4V; + defm VDIV : basic_sse12_fp_binop_s<0x5E, "div", fdiv, 0>, + basic_sse12_fp_binop_s_int<0x5E, "div", 0>, + basic_sse12_fp_binop_p<0x5E, "div", fdiv, 0>, + basic_sse12_fp_binop_p_y<0x5E, "div", fdiv>, VEX_4V; + defm VMAX : basic_sse12_fp_binop_s<0x5F, "max", X86fmax, 0>, + basic_sse12_fp_binop_s_int<0x5F, "max", 0>, + basic_sse12_fp_binop_p<0x5F, "max", X86fmax, 0>, + basic_sse12_fp_binop_p_int<0x5F, "max", 0>, + basic_sse12_fp_binop_p_y<0x5F, "max", X86fmax>, + basic_sse12_fp_binop_p_y_int<0x5F, "max">, VEX_4V; + defm VMIN : basic_sse12_fp_binop_s<0x5D, "min", X86fmin, 0>, + basic_sse12_fp_binop_s_int<0x5D, "min", 0>, + basic_sse12_fp_binop_p<0x5D, "min", X86fmin, 0>, + basic_sse12_fp_binop_p_int<0x5D, "min", 0>, + basic_sse12_fp_binop_p_y_int<0x5D, "min">, + basic_sse12_fp_binop_p_y<0x5D, "min", X86fmin>, VEX_4V; } let Constraints = "$src1 = $dst" in { @@ -1899,7 +1819,7 @@ multiclass sse2_fp_unop_p_y_int opc, string OpcodeStr, [(set VR256:$dst, (V2F64Int (memopv4f64 addr:$src)))]>; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { // Square root. defm VSQRT : sse1_fp_unop_s_avx<0x51, "vsqrt", fsqrt, int_x86_sse_sqrt_ss>, sse2_fp_unop_s_avx<0x51, "vsqrt", fsqrt, int_x86_sse2_sqrt_sd>, @@ -1955,67 +1875,65 @@ defm RCP : sse1_fp_unop_s<0x53, "rcp", X86frcp, int_x86_sse_rcp_ss>, // SSE 1 & 2 - Non-temporal stores //===----------------------------------------------------------------------===// -let isAsmParserOnly = 1 in { - def VMOVNTPSmr_Int : VPSI<0x2B, MRMDestMem, (outs), - (ins i128mem:$dst, VR128:$src), - "movntps\t{$src, $dst|$dst, $src}", - [(int_x86_sse_movnt_ps addr:$dst, VR128:$src)]>, VEX; - def VMOVNTPDmr_Int : VPDI<0x2B, MRMDestMem, (outs), - (ins i128mem:$dst, VR128:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(int_x86_sse2_movnt_pd addr:$dst, VR128:$src)]>, VEX; +def VMOVNTPSmr_Int : VPSI<0x2B, MRMDestMem, (outs), + (ins i128mem:$dst, VR128:$src), + "movntps\t{$src, $dst|$dst, $src}", + [(int_x86_sse_movnt_ps addr:$dst, VR128:$src)]>, VEX; +def VMOVNTPDmr_Int : VPDI<0x2B, MRMDestMem, (outs), + (ins i128mem:$dst, VR128:$src), + "movntpd\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_movnt_pd addr:$dst, VR128:$src)]>, VEX; - let ExeDomain = SSEPackedInt in - def VMOVNTDQmr_Int : VPDI<0xE7, MRMDestMem, (outs), +let ExeDomain = SSEPackedInt in + def VMOVNTDQmr_Int : VPDI<0xE7, MRMDestMem, (outs), + (ins f128mem:$dst, VR128:$src), + "movntdq\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_movnt_dq addr:$dst, VR128:$src)]>, VEX; + +let AddedComplexity = 400 in { // Prefer non-temporal versions + def VMOVNTPSmr : VPSI<0x2B, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(int_x86_sse2_movnt_dq addr:$dst, VR128:$src)]>, VEX; - - let AddedComplexity = 400 in { // Prefer non-temporal versions - def VMOVNTPSmr : VPSI<0x2B, MRMDestMem, (outs), - (ins f128mem:$dst, VR128:$src), - "movntps\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f32 VR128:$src), - addr:$dst)]>, VEX; - def VMOVNTPDmr : VPDI<0x2B, MRMDestMem, (outs), - (ins f128mem:$dst, VR128:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v2f64 VR128:$src), - addr:$dst)]>, VEX; - def VMOVNTDQ_64mr : VPDI<0xE7, MRMDestMem, (outs), - (ins f128mem:$dst, VR128:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v2f64 VR128:$src), - addr:$dst)]>, VEX; - let ExeDomain = SSEPackedInt in - def VMOVNTDQmr : VPDI<0xE7, MRMDestMem, (outs), + "movntps\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore (v4f32 VR128:$src), + addr:$dst)]>, VEX; + def VMOVNTPDmr : VPDI<0x2B, MRMDestMem, (outs), + (ins f128mem:$dst, VR128:$src), + "movntpd\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore (v2f64 VR128:$src), + addr:$dst)]>, VEX; + def VMOVNTDQ_64mr : VPDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f32 VR128:$src), + [(alignednontemporalstore (v2f64 VR128:$src), addr:$dst)]>, VEX; + let ExeDomain = SSEPackedInt in + def VMOVNTDQmr : VPDI<0xE7, MRMDestMem, (outs), + (ins f128mem:$dst, VR128:$src), + "movntdq\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore (v4f32 VR128:$src), + addr:$dst)]>, VEX; - def VMOVNTPSYmr : VPSI<0x2B, MRMDestMem, (outs), - (ins f256mem:$dst, VR256:$src), - "movntps\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v8f32 VR256:$src), - addr:$dst)]>, VEX; - def VMOVNTPDYmr : VPDI<0x2B, MRMDestMem, (outs), - (ins f256mem:$dst, VR256:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f64 VR256:$src), - addr:$dst)]>, VEX; - def VMOVNTDQY_64mr : VPDI<0xE7, MRMDestMem, (outs), - (ins f256mem:$dst, VR256:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v4f64 VR256:$src), - addr:$dst)]>, VEX; - let ExeDomain = SSEPackedInt in - def VMOVNTDQYmr : VPDI<0xE7, MRMDestMem, (outs), + def VMOVNTPSYmr : VPSI<0x2B, MRMDestMem, (outs), + (ins f256mem:$dst, VR256:$src), + "movntps\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore (v8f32 VR256:$src), + addr:$dst)]>, VEX; + def VMOVNTPDYmr : VPDI<0x2B, MRMDestMem, (outs), + (ins f256mem:$dst, VR256:$src), + "movntpd\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore (v4f64 VR256:$src), + addr:$dst)]>, VEX; + def VMOVNTDQY_64mr : VPDI<0xE7, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src), "movntdq\t{$src, $dst|$dst, $src}", - [(alignednontemporalstore (v8f32 VR256:$src), + [(alignednontemporalstore (v4f64 VR256:$src), addr:$dst)]>, VEX; - } + let ExeDomain = SSEPackedInt in + def VMOVNTDQYmr : VPDI<0xE7, MRMDestMem, (outs), + (ins f256mem:$dst, VR256:$src), + "movntdq\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore (v8f32 VR256:$src), + addr:$dst)]>, VEX; } def : Pat<(int_x86_avx_movnt_dq_256 addr:$dst, VR256:$src), @@ -2138,12 +2056,10 @@ def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))), // SSE 1 & 2 - Load/Store XCSR register //===----------------------------------------------------------------------===// -let isAsmParserOnly = 1 in { - def VLDMXCSR : VPSI<0xAE, MRM2m, (outs), (ins i32mem:$src), - "ldmxcsr\t$src", [(int_x86_sse_ldmxcsr addr:$src)]>, VEX; - def VSTMXCSR : VPSI<0xAE, MRM3m, (outs), (ins i32mem:$dst), - "stmxcsr\t$dst", [(int_x86_sse_stmxcsr addr:$dst)]>, VEX; -} +def VLDMXCSR : VPSI<0xAE, MRM2m, (outs), (ins i32mem:$src), + "ldmxcsr\t$src", [(int_x86_sse_ldmxcsr addr:$src)]>, VEX; +def VSTMXCSR : VPSI<0xAE, MRM3m, (outs), (ins i32mem:$dst), + "stmxcsr\t$dst", [(int_x86_sse_stmxcsr addr:$dst)]>, VEX; def LDMXCSR : PSI<0xAE, MRM2m, (outs), (ins i32mem:$src), "ldmxcsr\t$src", [(int_x86_sse_ldmxcsr addr:$src)]>; @@ -2156,45 +2072,43 @@ def STMXCSR : PSI<0xAE, MRM3m, (outs), (ins i32mem:$dst), let ExeDomain = SSEPackedInt in { // SSE integer instructions -let isAsmParserOnly = 1 in { - let neverHasSideEffects = 1 in { - def VMOVDQArr : VPDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; - def VMOVDQAYrr : VPDI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; - } - def VMOVDQUrr : VPDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, XS, VEX; - def VMOVDQUYrr : VPDI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), - "movdqu\t{$src, $dst|$dst, $src}", []>, XS, VEX; +let neverHasSideEffects = 1 in { +def VMOVDQArr : VPDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; +def VMOVDQAYrr : VPDI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), + "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; +} +def VMOVDQUrr : VPDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), + "movdqu\t{$src, $dst|$dst, $src}", []>, XS, VEX; +def VMOVDQUYrr : VPDI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src), + "movdqu\t{$src, $dst|$dst, $src}", []>, XS, VEX; - let canFoldAsLoad = 1, mayLoad = 1 in { - def VMOVDQArm : VPDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; - def VMOVDQAYrm : VPDI<0x6F, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; - let Predicates = [HasAVX] in { - def VMOVDQUrm : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vmovdqu\t{$src, $dst|$dst, $src}",[]>, XS, VEX; - def VMOVDQUYrm : I<0x6F, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), - "vmovdqu\t{$src, $dst|$dst, $src}",[]>, XS, VEX; - } - } +let canFoldAsLoad = 1, mayLoad = 1 in { +def VMOVDQArm : VPDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; +def VMOVDQAYrm : VPDI<0x6F, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), + "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; +let Predicates = [HasAVX] in { + def VMOVDQUrm : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "vmovdqu\t{$src, $dst|$dst, $src}",[]>, XS, VEX; + def VMOVDQUYrm : I<0x6F, MRMSrcMem, (outs VR256:$dst), (ins i256mem:$src), + "vmovdqu\t{$src, $dst|$dst, $src}",[]>, XS, VEX; +} +} - let mayStore = 1 in { - def VMOVDQAmr : VPDI<0x7F, MRMDestMem, (outs), - (ins i128mem:$dst, VR128:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; - def VMOVDQAYmr : VPDI<0x7F, MRMDestMem, (outs), - (ins i256mem:$dst, VR256:$src), - "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; - let Predicates = [HasAVX] in { - def VMOVDQUmr : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), - "vmovdqu\t{$src, $dst|$dst, $src}",[]>, XS, VEX; - def VMOVDQUYmr : I<0x7F, MRMDestMem, (outs), (ins i256mem:$dst, VR256:$src), - "vmovdqu\t{$src, $dst|$dst, $src}",[]>, XS, VEX; - } - } +let mayStore = 1 in { +def VMOVDQAmr : VPDI<0x7F, MRMDestMem, (outs), + (ins i128mem:$dst, VR128:$src), + "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; +def VMOVDQAYmr : VPDI<0x7F, MRMDestMem, (outs), + (ins i256mem:$dst, VR256:$src), + "movdqa\t{$src, $dst|$dst, $src}", []>, VEX; +let Predicates = [HasAVX] in { +def VMOVDQUmr : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), + "vmovdqu\t{$src, $dst|$dst, $src}",[]>, XS, VEX; +def VMOVDQUYmr : I<0x7F, MRMDestMem, (outs), (ins i256mem:$dst, VR256:$src), + "vmovdqu\t{$src, $dst|$dst, $src}",[]>, XS, VEX; +} } let neverHasSideEffects = 1 in @@ -2226,23 +2140,11 @@ def MOVDQUmr : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), } // Intrinsic forms of MOVDQU load and store -let isAsmParserOnly = 1 in { -let canFoldAsLoad = 1 in -def VMOVDQUrm_Int : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vmovdqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>, - XS, VEX, Requires<[HasAVX]>; def VMOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), "vmovdqu\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>, XS, VEX, Requires<[HasAVX]>; -} -let canFoldAsLoad = 1 in -def MOVDQUrm_Int : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>, - XS, Requires<[HasSSE2]>; def MOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), "movdqu\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>, @@ -2347,7 +2249,7 @@ multiclass PDI_binop_rm_v2i64 opc, string OpcodeStr, SDNode OpNode, // 128-bit Integer Arithmetic -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPADDB : PDI_binop_rm<0xFC, "vpaddb", add, v16i8, 1, 0 /*3addr*/>, VEX_4V; defm VPADDW : PDI_binop_rm<0xFD, "vpaddw", add, v8i16, 1, 0>, VEX_4V; defm VPADDD : PDI_binop_rm<0xFE, "vpaddd", add, v4i32, 1, 0>, VEX_4V; @@ -2437,7 +2339,7 @@ defm PSADBW : PDI_binop_rm_int<0xF6, "psadbw", int_x86_sse2_psad_bw, 1>; // SSE2 - Packed Integer Logical Instructions //===---------------------------------------------------------------------===// -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPSLLW : PDI_binop_rmi_int<0xF1, 0x71, MRM6r, "vpsllw", int_x86_sse2_psll_w, int_x86_sse2_pslli_w, 0>, VEX_4V; @@ -2584,7 +2486,7 @@ let Predicates = [HasSSE2] in { // SSE2 - Packed Integer Comparison Instructions //===---------------------------------------------------------------------===// -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPCMPEQB : PDI_binop_rm_int<0x74, "vpcmpeqb", int_x86_sse2_pcmpeq_b, 1, 0>, VEX_4V; defm VPCMPEQW : PDI_binop_rm_int<0x75, "vpcmpeqw", int_x86_sse2_pcmpeq_w, 1, @@ -2638,7 +2540,7 @@ def : Pat<(v4i32 (X86pcmpgtd VR128:$src1, (memop addr:$src2))), // SSE2 - Packed Integer Pack Instructions //===---------------------------------------------------------------------===// -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPACKSSWB : PDI_binop_rm_int<0x63, "vpacksswb", int_x86_sse2_packsswb_128, 0, 0>, VEX_4V; defm VPACKSSDW : PDI_binop_rm_int<0x6B, "vpackssdw", int_x86_sse2_packssdw_128, @@ -2676,7 +2578,7 @@ def mi : Ii8<0x70, MRMSrcMem, } } // ExeDomain = SSEPackedInt -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { let AddedComplexity = 5 in defm VPSHUFD : sse2_pshuffle<"vpshufd", v4i32, pshufd, bc_v4i32>, OpSize, VEX; @@ -2724,7 +2626,7 @@ multiclass sse2_unpack opc, string OpcodeStr, ValueType vt, addr:$src2))))]>; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPUNPCKLBW : sse2_unpack<0x60, "vpunpcklbw", v16i8, unpckl, bc_v16i8, 0>, VEX_4V; defm VPUNPCKLWD : sse2_unpack<0x61, "vpunpcklwd", v8i16, unpckl, bc_v8i16, @@ -2834,7 +2736,7 @@ multiclass sse2_pinsrw { } // Extract -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in def VPEXTRWri : Ii8<0xC5, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src1, i32i8imm:$src2), "vpextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", @@ -2847,7 +2749,7 @@ def PEXTRWri : PDIi8<0xC5, MRMSrcReg, imm:$src2))]>; // Insert -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPINSRW : sse2_pinsrw<0>, OpSize, VEX_4V; def VPINSRWrr64i : Ii8<0xC4, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, GR64:$src2, i32i8imm:$src3), @@ -2866,13 +2768,11 @@ let Constraints = "$src1 = $dst" in let ExeDomain = SSEPackedInt in { -let isAsmParserOnly = 1 in { def VPMOVMSKBrr : VPDI<0xD7, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), "pmovmskb\t{$src, $dst|$dst, $src}", [(set GR32:$dst, (int_x86_sse2_pmovmskb_128 VR128:$src))]>, VEX; def VPMOVMSKBr64r : VPDI<0xD7, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src), "pmovmskb\t{$src, $dst|$dst, $src}", []>, VEX; -} def PMOVMSKBrr : PDI<0xD7, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), "pmovmskb\t{$src, $dst|$dst, $src}", [(set GR32:$dst, (int_x86_sse2_pmovmskb_128 VR128:$src))]>; @@ -2885,7 +2785,6 @@ def PMOVMSKBrr : PDI<0xD7, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), let ExeDomain = SSEPackedInt in { -let isAsmParserOnly = 1 in { let Uses = [EDI] in def VMASKMOVDQU : VPDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), @@ -2896,7 +2795,6 @@ def VMASKMOVDQU64 : VPDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), "maskmovdqu\t{$mask, $src|$src, $mask}", [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, RDI)]>, VEX; -} let Uses = [EDI] in def MASKMOVDQU : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), @@ -2914,7 +2812,6 @@ def MASKMOVDQU64 : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), //===---------------------------------------------------------------------===// // Move Int Doubleword to Packed Double Int -let isAsmParserOnly = 1 in { def VMOVDI2PDIrr : VPDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), "movd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, @@ -2924,7 +2821,6 @@ def VMOVDI2PDIrm : VPDI<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src), [(set VR128:$dst, (v4i32 (scalar_to_vector (loadi32 addr:$src))))]>, VEX; -} def MOVDI2PDIrr : PDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), "movd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, @@ -2943,7 +2839,6 @@ def MOV64toSDrr : RPDI<0x6E, MRMSrcReg, (outs FR64:$dst), (ins GR64:$src), // Move Int Doubleword to Single Scalar -let isAsmParserOnly = 1 in { def VMOVDI2SSrr : VPDI<0x6E, MRMSrcReg, (outs FR32:$dst), (ins GR32:$src), "movd\t{$src, $dst|$dst, $src}", [(set FR32:$dst, (bitconvert GR32:$src))]>, VEX; @@ -2952,7 +2847,6 @@ def VMOVDI2SSrm : VPDI<0x6E, MRMSrcMem, (outs FR32:$dst), (ins i32mem:$src), "movd\t{$src, $dst|$dst, $src}", [(set FR32:$dst, (bitconvert (loadi32 addr:$src)))]>, VEX; -} def MOVDI2SSrr : PDI<0x6E, MRMSrcReg, (outs FR32:$dst), (ins GR32:$src), "movd\t{$src, $dst|$dst, $src}", [(set FR32:$dst, (bitconvert GR32:$src))]>; @@ -2962,7 +2856,6 @@ def MOVDI2SSrm : PDI<0x6E, MRMSrcMem, (outs FR32:$dst), (ins i32mem:$src), [(set FR32:$dst, (bitconvert (loadi32 addr:$src)))]>; // Move Packed Doubleword Int to Packed Double Int -let isAsmParserOnly = 1 in { def VMOVPDI2DIrr : VPDI<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128:$src), "movd\t{$src, $dst|$dst, $src}", [(set GR32:$dst, (vector_extract (v4i32 VR128:$src), @@ -2972,7 +2865,6 @@ def VMOVPDI2DImr : VPDI<0x7E, MRMDestMem, (outs), "movd\t{$src, $dst|$dst, $src}", [(store (i32 (vector_extract (v4i32 VR128:$src), (iPTR 0))), addr:$dst)]>, VEX; -} def MOVPDI2DIrr : PDI<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128:$src), "movd\t{$src, $dst|$dst, $src}", [(set GR32:$dst, (vector_extract (v4i32 VR128:$src), @@ -2998,14 +2890,12 @@ def MOVSDto64mr : RPDI<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64:$src), [(store (i64 (bitconvert FR64:$src)), addr:$dst)]>; // Move Scalar Single to Double Int -let isAsmParserOnly = 1 in { def VMOVSS2DIrr : VPDI<0x7E, MRMDestReg, (outs GR32:$dst), (ins FR32:$src), "movd\t{$src, $dst|$dst, $src}", [(set GR32:$dst, (bitconvert FR32:$src))]>, VEX; def VMOVSS2DImr : VPDI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, FR32:$src), "movd\t{$src, $dst|$dst, $src}", [(store (i32 (bitconvert FR32:$src)), addr:$dst)]>, VEX; -} def MOVSS2DIrr : PDI<0x7E, MRMDestReg, (outs GR32:$dst), (ins FR32:$src), "movd\t{$src, $dst|$dst, $src}", [(set GR32:$dst, (bitconvert FR32:$src))]>; @@ -3014,7 +2904,7 @@ def MOVSS2DImr : PDI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, FR32:$src), [(store (i32 (bitconvert FR32:$src)), addr:$dst)]>; // movd / movq to XMM register zero-extends -let AddedComplexity = 15, isAsmParserOnly = 1 in { +let AddedComplexity = 15 in { def VMOVZDI2PDIrr : VPDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), "movd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (v4i32 (X86vzmovl @@ -3038,7 +2928,6 @@ def MOVZQI2PQIrr : RPDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR64:$src), } let AddedComplexity = 20 in { -let isAsmParserOnly = 1 in def VMOVZDI2PDIrm : VPDI<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src), "movd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, @@ -3064,7 +2953,6 @@ def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))), //===---------------------------------------------------------------------===// // Move Quadword Int to Packed Quadword Int -let isAsmParserOnly = 1 in def VMOVQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), "vmovq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, @@ -3077,7 +2965,6 @@ def MOVQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), Requires<[HasSSE2]>; // SSE2 instruction with XS Prefix // Move Packed Quadword Int to Quadword Int -let isAsmParserOnly = 1 in def VMOVPQI2QImr : VPDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), "movq\t{$src, $dst|$dst, $src}", [(store (i64 (vector_extract (v2i64 VR128:$src), @@ -3091,7 +2978,6 @@ def : Pat<(f64 (vector_extract (v2f64 VR128:$src), (iPTR 0))), (f64 (EXTRACT_SUBREG (v2f64 VR128:$src), sub_sd))>; // Store / copy lower 64-bits of a XMM register. -let isAsmParserOnly = 1 in def VMOVLQ128mr : VPDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), "movq\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storel_dq addr:$dst, VR128:$src)]>, VEX; @@ -3099,7 +2985,7 @@ def MOVLQ128mr : PDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), "movq\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storel_dq addr:$dst, VR128:$src)]>; -let AddedComplexity = 20, isAsmParserOnly = 1 in +let AddedComplexity = 20 in def VMOVZQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src), "vmovq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, @@ -3124,7 +3010,7 @@ def : Pat<(v2i64 (X86vzload addr:$src)), (MOVZQI2PQIrm addr:$src)>; // Moving from XMM to XMM and clear upper 64 bits. Note, there is a bug in // IA32 document. movq xmm1, xmm2 does clear the high bits. -let isAsmParserOnly = 1, AddedComplexity = 15 in +let AddedComplexity = 15 in def VMOVZPQILo2PQIrr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "vmovq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (v2i64 (X86vzmovl (v2i64 VR128:$src))))]>, @@ -3135,7 +3021,7 @@ def MOVZPQILo2PQIrr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), [(set VR128:$dst, (v2i64 (X86vzmovl (v2i64 VR128:$src))))]>, XS, Requires<[HasSSE2]>; -let AddedComplexity = 20, isAsmParserOnly = 1 in +let AddedComplexity = 20 in def VMOVZPQILo2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), "vmovq\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (v2i64 (X86vzmovl @@ -3153,7 +3039,6 @@ def : Pat<(v2i64 (X86vzmovl (bc_v2i64 (loadv4i32 addr:$src)))), } // Instructions to match in the assembler -let isAsmParserOnly = 1 in { def VMOVQs64rr : VPDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR64:$src), "movq\t{$src, $dst|$dst, $src}", []>, VEX, VEX_W; def VMOVQd64rr : VPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src), @@ -3161,13 +3046,12 @@ def VMOVQd64rr : VPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src), // Recognize "movd" with GR64 destination, but encode as a "movq" def VMOVQd64rr_alt : VPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src), "movd\t{$src, $dst|$dst, $src}", []>, VEX, VEX_W; -} // Instructions for the disassembler // xr = XMM register // xm = mem64 -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in def VMOVQxrxr: I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "vmovq\t{$src, $dst|$dst, $src}", []>, VEX, XS; def MOVQxrxr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), @@ -3209,7 +3093,7 @@ let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, //===---------------------------------------------------------------------===// // Convert Packed Double FP to Packed DW Integers -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { // The assembler can recognize rr 256-bit instructions by seeing a ymm // register, but the same isn't true when using memory operands instead. // Provide other assembly rr and rm forms to address this explicitly. @@ -3237,7 +3121,7 @@ def CVTPD2DQrr : S3DI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtpd2dq\t{$src, $dst|$dst, $src}", []>; // Convert Packed DW Integers to Packed Double FP -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { def VCVTDQ2PDrm : S3SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "vcvtdq2pd\t{$src, $dst|$dst, $src}", []>, VEX; def VCVTDQ2PDrr : S3SI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), @@ -3288,7 +3172,7 @@ def rm : S3SI; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { // FIXME: Merge above classes when we have patterns for the ymm version defm VMOVSHDUP : sse3_replicate_sfp<0x16, movshdup, "vmovshdup">, VEX; defm VMOVSLDUP : sse3_replicate_sfp<0x12, movsldup, "vmovsldup">, VEX; @@ -3319,7 +3203,7 @@ def rm : S3DI<0x12, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src), []>; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { // FIXME: Merge above classes when we have patterns for the ymm version defm VMOVDDUP : sse3_replicate_dfp<"vmovddup">, VEX; defm VMOVDDUPY : sse3_replicate_dfp_y<"vmovddup">, VEX; @@ -3327,7 +3211,7 @@ let isAsmParserOnly = 1, Predicates = [HasAVX] in { defm MOVDDUP : sse3_replicate_dfp<"movddup">; // Move Unaligned Integer -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { def VLDDQUrm : S3DI<0xF0, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), "vlddqu\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse3_ldu_dq addr:$src))]>, VEX; @@ -3391,21 +3275,21 @@ multiclass sse3_addsub; } -let isAsmParserOnly = 1, Predicates = [HasAVX], +let Predicates = [HasAVX], ExeDomain = SSEPackedDouble in { defm VADDSUBPS : sse3_addsub, XD, VEX_4V; + f128mem, 0>, TB, XD, VEX_4V; defm VADDSUBPD : sse3_addsub, OpSize, VEX_4V; + f128mem, 0>, TB, OpSize, VEX_4V; defm VADDSUBPSY : sse3_addsub, XD, VEX_4V; + f256mem, 0>, TB, XD, VEX_4V; defm VADDSUBPDY : sse3_addsub, OpSize, VEX_4V; + f256mem, 0>, TB, OpSize, VEX_4V; } let Constraints = "$src1 = $dst", Predicates = [HasSSE3], ExeDomain = SSEPackedDouble in { defm ADDSUBPS : sse3_addsub, XD; + f128mem>, TB, XD; defm ADDSUBPD : sse3_addsub, TB, OpSize; } @@ -3444,7 +3328,7 @@ multiclass S3_Int o, string OpcodeStr, ValueType vt, RegisterClass RC, [(set RC:$dst, (vt (IntId RC:$src1, (memop addr:$src2))))]>; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VHADDPS : S3D_Int<0x7C, "vhaddps", v4f32, VR128, f128mem, int_x86_sse3_hadd_ps, 0>, VEX_4V; defm VHADDPD : S3_Int <0x7C, "vhaddpd", v2f64, VR128, f128mem, @@ -3496,7 +3380,7 @@ multiclass SS3I_unop_rm_int opc, string OpcodeStr, (bitconvert (mem_frag128 addr:$src))))]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPABSB : SS3I_unop_rm_int<0x1C, "vpabsb", memopv16i8, int_x86_ssse3_pabs_b_128>, VEX; defm VPABSW : SS3I_unop_rm_int<0x1D, "vpabsw", memopv8i16, @@ -3538,7 +3422,7 @@ multiclass SS3I_binop_rm_int opc, string OpcodeStr, (bitconvert (memopv16i8 addr:$src2))))]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { let isCommutable = 0 in { defm VPHADDW : SS3I_binop_rm_int<0x01, "vphaddw", memopv8i16, int_x86_ssse3_phadd_w_128, 0>, VEX_4V; @@ -3630,7 +3514,7 @@ multiclass ssse3_palign { []>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPALIGN : ssse3_palign<"vpalignr", 0>, VEX_4V; let Constraints = "$src1 = $dst" in defm PALIGN : ssse3_palign<"palignr">; @@ -3985,7 +3869,7 @@ multiclass SS41I_binop_rm_int8 opc, string OpcodeStr, Intrinsic IntId> { OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPMOVSXBW : SS41I_binop_rm_int8<0x20, "vpmovsxbw", int_x86_sse41_pmovsxbw>, VEX; defm VPMOVSXWD : SS41I_binop_rm_int8<0x23, "vpmovsxwd", int_x86_sse41_pmovsxwd>, @@ -4051,7 +3935,7 @@ multiclass SS41I_binop_rm_int4 opc, string OpcodeStr, Intrinsic IntId> { OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPMOVSXBD : SS41I_binop_rm_int4<0x21, "vpmovsxbd", int_x86_sse41_pmovsxbd>, VEX; defm VPMOVSXWQ : SS41I_binop_rm_int4<0x24, "vpmovsxwq", int_x86_sse41_pmovsxwq>, @@ -4092,7 +3976,7 @@ multiclass SS41I_binop_rm_int2 opc, string OpcodeStr, Intrinsic IntId> { OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPMOVSXBQ : SS41I_binop_rm_int2<0x22, "vpmovsxbq", int_x86_sse41_pmovsxbq>, VEX; defm VPMOVZXBQ : SS41I_binop_rm_int2<0x32, "vpmovzxbq", int_x86_sse41_pmovzxbq>, @@ -4134,7 +4018,7 @@ multiclass SS41I_extract8 opc, string OpcodeStr> { // (store (i8 (trunc (X86pextrb (v16i8 VR128:$src1), imm:$src2))), addr:$dst) } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPEXTRB : SS41I_extract8<0x14, "vpextrb">, VEX; def VPEXTRBrr64 : SS4AIi8<0x14, MRMDestReg, (outs GR64:$dst), (ins VR128:$src1, i32i8imm:$src2), @@ -4156,7 +4040,7 @@ multiclass SS41I_extract16 opc, string OpcodeStr> { // (store (i16 (trunc (X86pextrw (v16i8 VR128:$src1), imm:$src2))), addr:$dst) } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPEXTRW : SS41I_extract16<0x15, "vpextrw">, VEX; defm PEXTRW : SS41I_extract16<0x15, "pextrw">; @@ -4178,7 +4062,7 @@ multiclass SS41I_extract32 opc, string OpcodeStr> { addr:$dst)]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPEXTRD : SS41I_extract32<0x16, "vpextrd">, VEX; defm PEXTRD : SS41I_extract32<0x16, "pextrd">; @@ -4199,7 +4083,7 @@ multiclass SS41I_extract64 opc, string OpcodeStr> { addr:$dst)]>, OpSize, REX_W; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPEXTRQ : SS41I_extract64<0x16, "vpextrq">, VEX, VEX_W; defm PEXTRQ : SS41I_extract64<0x16, "pextrq">; @@ -4222,7 +4106,7 @@ multiclass SS41I_extractf32 opc, string OpcodeStr> { addr:$dst)]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VEXTRACTPS : SS41I_extractf32<0x17, "vextractps">, VEX; def VEXTRACTPSrr64 : SS4AIi8<0x17, MRMDestReg, (outs GR64:$dst), (ins VR128:$src1, i32i8imm:$src2), @@ -4262,7 +4146,7 @@ multiclass SS41I_insert8 opc, string asm, bit Is2Addr = 1> { imm:$src3))]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPINSRB : SS41I_insert8<0x20, "vpinsrb", 0>, VEX_4V; let Constraints = "$src1 = $dst" in defm PINSRB : SS41I_insert8<0x20, "pinsrb">; @@ -4288,7 +4172,7 @@ multiclass SS41I_insert32 opc, string asm, bit Is2Addr = 1> { imm:$src3)))]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPINSRD : SS41I_insert32<0x22, "vpinsrd", 0>, VEX_4V; let Constraints = "$src1 = $dst" in defm PINSRD : SS41I_insert32<0x22, "pinsrd">; @@ -4314,7 +4198,7 @@ multiclass SS41I_insert64 opc, string asm, bit Is2Addr = 1> { imm:$src3)))]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPINSRQ : SS41I_insert64<0x22, "vpinsrq", 0>, VEX_4V, VEX_W; let Constraints = "$src1 = $dst" in defm PINSRQ : SS41I_insert64<0x22, "pinsrq">, REX_W; @@ -4347,7 +4231,7 @@ multiclass SS41I_insertf32 opc, string asm, bit Is2Addr = 1> { let Constraints = "$src1 = $dst" in defm INSERTPS : SS41I_insertf32<0x21, "insertps">; -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VINSERTPS : SS41I_insertf32<0x21, "vinsertps", 0>, VEX_4V; def : Pat<(int_x86_sse41_insertps VR128:$src1, VR128:$src2, imm:$src3), @@ -4517,7 +4401,7 @@ multiclass sse41_fp_binop_rm_avx_s opcss, bits<8> opcsd, } // FP round - roundss, roundps, roundsd, roundpd -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { // Intrinsic form defm VROUND : sse41_fp_unop_rm<0x08, 0x09, "vround", f128mem, VR128, memopv4f32, memopv2f64, @@ -4552,7 +4436,7 @@ defm ROUND : sse41_fp_binop_rm<0x0A, 0x0B, "round", // ptest instruction we'll lower to this in X86ISelLowering primarily from // the intel intrinsic that corresponds to this. -let Defs = [EFLAGS], isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Defs = [EFLAGS], Predicates = [HasAVX] in { def VPTESTrr : SS48I<0x17, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2), "vptest\t{$src2, $src1|$src1, $src2}", [(set EFLAGS, (X86ptest VR128:$src1, (v4f32 VR128:$src2)))]>, @@ -4595,7 +4479,7 @@ multiclass avx_bittest opc, string OpcodeStr, RegisterClass RC, OpSize, VEX; } -let Defs = [EFLAGS], isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Defs = [EFLAGS], Predicates = [HasAVX] in { defm VTESTPS : avx_bittest<0x0E, "vtestps", VR128, f128mem, memopv4f32, v4f32>; defm VTESTPSY : avx_bittest<0x0E, "vtestps", VR256, f256mem, memopv8f32, v8f32>; defm VTESTPD : avx_bittest<0x0F, "vtestpd", VR128, f128mem, memopv2f64, v2f64>; @@ -4644,7 +4528,7 @@ multiclass SS41I_unop_rm_int_v16 opc, string OpcodeStr, (bitconvert (memopv8i16 addr:$src))))]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPHMINPOSUW : SS41I_unop_rm_int_v16 <0x41, "vphminposuw", int_x86_sse41_phminposuw>, VEX; defm PHMINPOSUW : SS41I_unop_rm_int_v16 <0x41, "phminposuw", @@ -4670,7 +4554,7 @@ multiclass SS41I_binop_rm_int opc, string OpcodeStr, (bitconvert (memopv16i8 addr:$src2))))]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { let isCommutable = 0 in defm VPACKUSDW : SS41I_binop_rm_int<0x2B, "vpackusdw", int_x86_sse41_packusdw, 0>, VEX_4V; @@ -4737,7 +4621,7 @@ multiclass SS48I_binop_rm opc, string OpcodeStr, SDNode OpNode, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPMULLD : SS48I_binop_rm<0x40, "vpmulld", mul, v4i32, 0>, VEX_4V; let Constraints = "$src1 = $dst" in defm PMULLD : SS48I_binop_rm<0x40, "pmulld", mul, v4i32>; @@ -4769,7 +4653,7 @@ multiclass SS41I_binop_rmi_int opc, string OpcodeStr, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { let isCommutable = 0 in { defm VBLENDPS : SS41I_binop_rmi_int<0x0C, "vblendps", int_x86_sse41_blendps, VR128, memopv16i8, i128mem, 0>, VEX_4V; @@ -4810,7 +4694,7 @@ let Constraints = "$src1 = $dst" in { } /// SS41I_quaternary_int_avx - AVX SSE 4.1 with 4 operators -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { multiclass SS41I_quaternary_int_avx opc, string OpcodeStr, RegisterClass RC, X86MemOperand x86memop, PatFrag mem_frag, Intrinsic IntId> { @@ -4870,7 +4754,7 @@ defm PBLENDVB : SS41I_ternary_int<0x10, "pblendvb", int_x86_sse41_pblendvb>; def : Pat<(X86pblendv VR128:$src1, VR128:$src2, XMM0), (PBLENDVBrr0 VR128:$src1, VR128:$src2)>; -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in def VMOVNTDQArm : SS48I<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), "vmovntdqa\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse41_movntdqa addr:$src))]>, @@ -4904,7 +4788,7 @@ multiclass SS42I_binop_rm_int opc, string OpcodeStr, (bitconvert (memopv16i8 addr:$src2))))]>, OpSize; } -let isAsmParserOnly = 1, Predicates = [HasAVX] in +let Predicates = [HasAVX] in defm VPCMPGTQ : SS42I_binop_rm_int<0x37, "vpcmpgtq", int_x86_sse42_pcmpgtq, 0>, VEX_4V; let Constraints = "$src1 = $dst" in @@ -4936,8 +4820,7 @@ let Defs = [EFLAGS], usesCustomInserter = 1 in { defm VPCMPISTRM128 : pseudo_pcmpistrm<"#VPCMPISTRM128">, Requires<[HasAVX]>; } -let Defs = [XMM0, EFLAGS], isAsmParserOnly = 1, - Predicates = [HasAVX] in { +let Defs = [XMM0, EFLAGS], Predicates = [HasAVX] in { def VPCMPISTRM128rr : SS42AI<0x62, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2, i8imm:$src3), "vpcmpistrm\t{$src3, $src2, $src1|$src1, $src2, $src3}", []>, OpSize, VEX; @@ -4972,7 +4855,7 @@ let Defs = [EFLAGS], Uses = [EAX, EDX], usesCustomInserter = 1 in { defm VPCMPESTRM128 : pseudo_pcmpestrm<"#VPCMPESTRM128">, Requires<[HasAVX]>; } -let isAsmParserOnly = 1, Predicates = [HasAVX], +let Predicates = [HasAVX], Defs = [XMM0, EFLAGS], Uses = [EAX, EDX] in { def VPCMPESTRM128rr : SS42AI<0x60, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src3, i8imm:$src5), @@ -5007,7 +4890,7 @@ let Defs = [ECX, EFLAGS] in { } } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPCMPISTRI : SS42AI_pcmpistri, VEX; defm VPCMPISTRIA : SS42AI_pcmpistri, @@ -5046,7 +4929,7 @@ let Defs = [ECX, EFLAGS], Uses = [EAX, EDX] in { } } -let isAsmParserOnly = 1, Predicates = [HasAVX] in { +let Predicates = [HasAVX] in { defm VPCMPESTRI : SS42AI_pcmpestri, VEX; defm VPCMPESTRIA : SS42AI_pcmpestri, @@ -5165,7 +5048,7 @@ multiclass AESI_binop_rm_int opc, string OpcodeStr, } // Perform One Round of an AES Encryption/Decryption Flow -let isAsmParserOnly = 1, Predicates = [HasAVX, HasAES] in { +let Predicates = [HasAVX, HasAES] in { defm VAESENC : AESI_binop_rm_int<0xDC, "vaesenc", int_x86_aesni_aesenc, 0>, VEX_4V; defm VAESENCLAST : AESI_binop_rm_int<0xDD, "vaesenclast", @@ -5205,7 +5088,7 @@ def : Pat<(v2i64 (int_x86_aesni_aesdeclast VR128:$src1, (memop addr:$src2))), (AESDECLASTrm VR128:$src1, addr:$src2)>; // Perform the AES InvMixColumn Transformation -let isAsmParserOnly = 1, Predicates = [HasAVX, HasAES] in { +let Predicates = [HasAVX, HasAES] in { def VAESIMCrr : AES8I<0xDB, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1), "vaesimc\t{$src1, $dst|$dst, $src1}", @@ -5233,7 +5116,7 @@ def AESIMCrm : AES8I<0xDB, MRMSrcMem, (outs VR128:$dst), OpSize; // AES Round Key Generation Assist -let isAsmParserOnly = 1, Predicates = [HasAVX, HasAES] in { +let Predicates = [HasAVX, HasAES] in { def VAESKEYGENASSIST128rr : AESAI<0xDF, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, i8imm:$src2), "vaeskeygenassist\t{$src2, $src1, $dst|$dst, $src1, $src2}", @@ -5269,7 +5152,6 @@ def AESKEYGENASSIST128rm : AESAI<0xDF, MRMSrcMem, (outs VR128:$dst), // Only the AVX version of CLMUL instructions are described here. // Carry-less Multiplication instructions -let isAsmParserOnly = 1 in { def VPCLMULQDQrr : CLMULIi8<0x44, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2, i8imm:$src3), "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", @@ -5295,13 +5177,10 @@ defm VPCLMULHQLQDQ : avx_vpclmul<"vpclmulhqlqdq">; defm VPCLMULLQHQDQ : avx_vpclmul<"vpclmullqhqdq">; defm VPCLMULLQLQDQ : avx_vpclmul<"vpclmullqlqdq">; -} // isAsmParserOnly - //===----------------------------------------------------------------------===// // AVX Instructions //===----------------------------------------------------------------------===// -let isAsmParserOnly = 1 in { // Load from memory and broadcast to all elements of the destination operand class avx_broadcast opc, string OpcodeStr, RegisterClass RC, @@ -5435,8 +5314,6 @@ def VZEROALL : I<0x77, RawFrm, (outs), (ins), "vzeroall", def VZEROUPPER : I<0x77, RawFrm, (outs), (ins), "vzeroupper", [(int_x86_avx_vzeroupper)]>, VEX, Requires<[HasAVX]>; -} // isAsmParserOnly - def : Pat<(int_x86_avx_vinsertf128_pd_256 VR256:$src1, VR128:$src2, imm:$src3), (VINSERTF128rr VR256:$src1, VR128:$src2, imm:$src3)>; def : Pat<(int_x86_avx_vinsertf128_ps_256 VR256:$src1, VR128:$src2, imm:$src3), @@ -5622,11 +5499,15 @@ def : Pat<(X86Movddup (bc_v2f64 // Shuffle with UNPCKLPS def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))), (VUNPCKLPSrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>; +def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, (memopv8f32 addr:$src2))), + (VUNPCKLPSYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))), (UNPCKLPSrm VR128:$src1, addr:$src2)>; def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)), (VUNPCKLPSrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>; +def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, VR256:$src2)), + (VUNPCKLPSYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)), (UNPCKLPSrr VR128:$src1, VR128:$src2)>; @@ -5644,11 +5525,15 @@ def : Pat<(v4f32 (X86Unpckhps VR128:$src1, VR128:$src2)), // Shuffle with UNPCKLPD def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))), (VUNPCKLPDrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>; +def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, (memopv4f64 addr:$src2))), + (VUNPCKLPDYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))), (UNPCKLPDrm VR128:$src1, addr:$src2)>; def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)), (VUNPCKLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>; +def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, VR256:$src2)), + (VUNPCKLPDYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)), (UNPCKLPDrr VR128:$src1, VR128:$src2)>; diff --git a/contrib/llvm/lib/Target/X86/X86InstrSystem.td b/contrib/llvm/lib/Target/X86/X86InstrSystem.td index 6a24d145c696..f73cff39e86d 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrSystem.td +++ b/contrib/llvm/lib/Target/X86/X86InstrSystem.td @@ -34,9 +34,16 @@ let Uses = [EFLAGS] in def INTO : I<0xce, RawFrm, (outs), (ins), "into", []>; def INT3 : I<0xcc, RawFrm, (outs), (ins), "int3", [(int_x86_int (i8 3))]>; + +// The long form of "int $3" turns into int3 as a size optimization. +// FIXME: This doesn't work because InstAlias can't match immediate constants. +//def : InstAlias<"int\t$3", (INT3)>; + + def INT : Ii8<0xcd, RawFrm, (outs), (ins i8imm:$trap), "int\t$trap", [(int_x86_int imm:$trap)]>; + def SYSCALL : I<0x05, RawFrm, (outs), (ins), "syscall", []>, TB; def SYSRETL : I<0x07, RawFrm, (outs), (ins), "sysretl", []>, TB; def SYSRETQ :RI<0x07, RawFrm, (outs), (ins), "sysretq", []>, TB, @@ -207,10 +214,15 @@ def LSL64rr : RI<0x03, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), def INVLPG : I<0x01, MRM7m, (outs), (ins i8mem:$addr), "invlpg\t$addr", []>, TB; -def STRr : I<0x00, MRM1r, (outs GR16:$dst), (ins), - "str{w}\t{$dst}", []>, TB; -def STRm : I<0x00, MRM1m, (outs i16mem:$dst), (ins), - "str{w}\t{$dst}", []>, TB; +def STR16r : I<0x00, MRM1r, (outs GR16:$dst), (ins), + "str{w}\t{$dst}", []>, TB, OpSize; +def STR32r : I<0x00, MRM1r, (outs GR32:$dst), (ins), + "str{l}\t{$dst}", []>, TB; +def STR64r : RI<0x00, MRM1r, (outs GR64:$dst), (ins), + "str{q}\t{$dst}", []>, TB; +def STRm : I<0x00, MRM1m, (outs i16mem:$dst), (ins), + "str{w}\t{$dst}", []>, TB; + def LTRr : I<0x00, MRM3r, (outs), (ins GR16:$src), "ltr{w}\t{$src}", []>, TB; def LTRm : I<0x00, MRM3m, (outs), (ins i16mem:$src), @@ -393,3 +405,23 @@ let Defs = [RDX, RAX], Uses = [RCX] in let Uses = [RDX, RAX, RCX] in def XSETBV : I<0x01, MRM_D1, (outs), (ins), "xsetbv", []>, TB; + +//===----------------------------------------------------------------------===// +// VIA PadLock crypto instructions +let Defs = [RAX, RDI], Uses = [RDX, RDI] in + def XSTORE : I<0xc0, RawFrm, (outs), (ins), "xstore", []>, A7; + +let Defs = [RSI, RDI], Uses = [RBX, RDX, RSI, RDI] in { + def XCRYPTECB : I<0xc8, RawFrm, (outs), (ins), "xcryptecb", []>, A7; + def XCRYPTCBC : I<0xd0, RawFrm, (outs), (ins), "xcryptcbc", []>, A7; + def XCRYPTCTR : I<0xd8, RawFrm, (outs), (ins), "xcryptctr", []>, A7; + def XCRYPTCFB : I<0xe0, RawFrm, (outs), (ins), "xcryptcfb", []>, A7; + def XCRYPTOFB : I<0xe8, RawFrm, (outs), (ins), "xcryptofb", []>, A7; +} + +let Defs = [RAX, RSI, RDI], Uses = [RAX, RSI, RDI] in { + def XSHA1 : I<0xc8, RawFrm, (outs), (ins), "xsha1", []>, A6; + def XSHA256 : I<0xd0, RawFrm, (outs), (ins), "xsha256", []>, A6; +} +let Defs = [RAX, RDX, RSI], Uses = [RAX, RSI] in + def MONTMUL : I<0xc0, RawFrm, (outs), (ins), "montmul", []>, A6; diff --git a/contrib/llvm/lib/Target/X86/X86MCAsmInfo.cpp b/contrib/llvm/lib/Target/X86/X86MCAsmInfo.cpp index 6686214e06f5..83bba529a689 100644 --- a/contrib/llvm/lib/Target/X86/X86MCAsmInfo.cpp +++ b/contrib/llvm/lib/Target/X86/X86MCAsmInfo.cpp @@ -15,7 +15,9 @@ #include "X86TargetMachine.h" #include "llvm/ADT/Triple.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ELF.h" using namespace llvm; @@ -69,7 +71,22 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &Triple) { DwarfUsesInlineInfoSection = true; // Exceptions handling - ExceptionsType = ExceptionHandling::DwarfTable; + ExceptionsType = ExceptionHandling::DwarfCFI; +} + +const MCExpr * +X86_64MCAsmInfoDarwin::getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const { + MCContext &Context = Streamer.getContext(); + const MCExpr *Res = + MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Context); + const MCExpr *Four = MCConstantExpr::Create(4, Context); + return MCBinaryExpr::CreateAdd(Res, Four, Context); +} + +X86_64MCAsmInfoDarwin::X86_64MCAsmInfoDarwin(const Triple &Triple) + : X86MCAsmInfoDarwin(Triple) { } X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) { @@ -89,7 +106,9 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) { SupportsDebugInformation = true; // Exceptions handling - ExceptionsType = ExceptionHandling::DwarfTable; + ExceptionsType = ExceptionHandling::DwarfCFI; + + DwarfRequiresFrameSection = false; // OpenBSD has buggy support for .quad in 32-bit mode, just split into two // .words. diff --git a/contrib/llvm/lib/Target/X86/X86MCAsmInfo.h b/contrib/llvm/lib/Target/X86/X86MCAsmInfo.h index 581522567d09..2cd4c8eb30ec 100644 --- a/contrib/llvm/lib/Target/X86/X86MCAsmInfo.h +++ b/contrib/llvm/lib/Target/X86/X86MCAsmInfo.h @@ -25,6 +25,14 @@ namespace llvm { explicit X86MCAsmInfoDarwin(const Triple &Triple); }; + struct X86_64MCAsmInfoDarwin : public X86MCAsmInfoDarwin { + explicit X86_64MCAsmInfoDarwin(const Triple &Triple); + virtual const MCExpr * + getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; + }; + struct X86ELFMCAsmInfo : public MCAsmInfo { explicit X86ELFMCAsmInfo(const Triple &Triple); virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const; diff --git a/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp b/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp index 0e3b5711f2b5..f195a67a3040 100644 --- a/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp @@ -382,7 +382,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, const TargetInstrDesc &Desc, raw_ostream &OS) const { bool HasVEX_4V = false; - if ((TSFlags >> 32) & X86II::VEX_4V) + if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V) HasVEX_4V = true; // VEX_R: opcode externsion equivalent to REX.R in @@ -446,10 +446,10 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, if (TSFlags & X86II::OpSize) VEX_PP = 0x01; - if ((TSFlags >> 32) & X86II::VEX_W) + if ((TSFlags >> X86II::VEXShift) & X86II::VEX_W) VEX_W = 1; - if ((TSFlags >> 32) & X86II::VEX_L) + if ((TSFlags >> X86II::VEXShift) & X86II::VEX_L) VEX_L = 1; switch (TSFlags & X86II::Op0Mask) { @@ -470,6 +470,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, case X86II::XD: // F2 0F VEX_PP = 0x3; break; + case X86II::A6: // Bypass: Not used by VEX + case X86II::A7: // Bypass: Not used by VEX case X86II::TB: // Bypass: Not used by VEX case 0: break; // No prefix! @@ -512,13 +514,13 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, } // To only check operands before the memory address ones, start - // the search from the begining + // the search from the beginning if (IsDestMem) CurOp = 0; // If the last register should be encoded in the immediate field // do not use any bit from VEX prefix to this register, ignore it - if ((TSFlags >> 32) & X86II::VEX_I8IMM) + if ((TSFlags >> X86II::VEXShift) & X86II::VEX_I8IMM) NumOps--; for (; CurOp != NumOps; ++CurOp) { @@ -742,6 +744,8 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, case X86II::TB: // Two-byte opcode prefix case X86II::T8: // 0F 38 case X86II::TA: // 0F 3A + case X86II::A6: // 0F A6 + case X86II::A7: // 0F A7 Need0FPrefix = true; break; case X86II::TF: // F2 0F 38 @@ -786,6 +790,12 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, case X86II::TA: // 0F 3A EmitByte(0x3A, CurByte, OS); break; + case X86II::A6: // 0F A6 + EmitByte(0xA6, CurByte, OS); + break; + case X86II::A7: // 0F A7 + EmitByte(0xA7, CurByte, OS); + break; } } @@ -819,9 +829,9 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, // It uses the VEX.VVVV field? bool HasVEX_4V = false; - if ((TSFlags >> 32) & X86II::VEX) + if ((TSFlags >> X86II::VEXShift) & X86II::VEX) HasVEXPrefix = true; - if ((TSFlags >> 32) & X86II::VEX_4V) + if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V) HasVEX_4V = true; @@ -837,7 +847,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, unsigned char BaseOpcode = X86II::getBaseOpcodeFor(TSFlags); - if ((TSFlags >> 32) & X86II::Has3DNow0F0FOpcode) + if ((TSFlags >> X86II::VEXShift) & X86II::Has3DNow0F0FOpcode) BaseOpcode = 0x0F; // Weird 3DNow! encoding. unsigned SrcRegNum = 0; @@ -994,7 +1004,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, if (CurOp != NumOps) { // The last source register of a 4 operand instruction in AVX is encoded // in bits[7:4] of a immediate byte, and bits[3:0] are ignored. - if ((TSFlags >> 32) & X86II::VEX_I8IMM) { + if ((TSFlags >> X86II::VEXShift) & X86II::VEX_I8IMM) { const MCOperand &MO = MI.getOperand(CurOp++); bool IsExtReg = X86InstrInfo::isX86_64ExtendedReg(MO.getReg()); @@ -1017,7 +1027,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, } } - if ((TSFlags >> 32) & X86II::Has3DNow0F0FOpcode) + if ((TSFlags >> X86II::VEXShift) & X86II::Has3DNow0F0FOpcode) EmitByte(X86II::getBaseOpcodeFor(TSFlags), CurByte, OS); diff --git a/contrib/llvm/lib/Target/X86/X86RegisterInfo.cpp b/contrib/llvm/lib/Target/X86/X86RegisterInfo.cpp index 2f6bd88c6526..37fb0fe56948 100644 --- a/contrib/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/contrib/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -308,6 +308,33 @@ X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A, return 0; } +const TargetRegisterClass* +X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) const{ + const TargetRegisterClass *Super = RC; + TargetRegisterClass::sc_iterator I = RC->superclasses_begin(); + do { + switch (Super->getID()) { + case X86::GR8RegClassID: + case X86::GR16RegClassID: + case X86::GR32RegClassID: + case X86::GR64RegClassID: + case X86::FR32RegClassID: + case X86::FR64RegClassID: + case X86::RFP32RegClassID: + case X86::RFP64RegClassID: + case X86::RFP80RegClassID: + case X86::VR128RegClassID: + case X86::VR256RegClassID: + // Don't return a super-class that would shrink the spill size. + // That can happen with the vector and float classes. + if (Super->getSize() == RC->getSize()) + return Super; + } + Super = *I++; + } while (Super); + return RC; +} + const TargetRegisterClass * X86RegisterInfo::getPointerRegClass(unsigned Kind) const { switch (Kind) { @@ -337,7 +364,27 @@ X86RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { else return &X86::GR32RegClass; } - return NULL; + return RC; +} + +unsigned +X86RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, + MachineFunction &MF) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + unsigned FPDiff = TFI->hasFP(MF) ? 1 : 0; + switch (RC->getID()) { + default: + return 0; + case X86::GR32RegClassID: + return 4 - FPDiff; + case X86::GR64RegClassID: + return 12 - FPDiff; + case X86::VR128RegClassID: + return TM.getSubtarget().is64Bit() ? 10 : 4; + case X86::VR64RegClassID: + return 4; + } } const unsigned * @@ -450,7 +497,7 @@ bool X86RegisterInfo::needsStackRealignment(const MachineFunction &MF) const { // FIXME: It's more complicated than this... if (0 && requiresRealignment && MFI->hasVarSizedObjects()) report_fatal_error( - "Stack realignment in presense of dynamic allocas is not supported"); + "Stack realignment in presence of dynamic allocas is not supported"); // If we've requested that we force align the stack do so now. if (ForceStackAlign) diff --git a/contrib/llvm/lib/Target/X86/X86RegisterInfo.h b/contrib/llvm/lib/Target/X86/X86RegisterInfo.h index 064be64f4916..9970c52c3e72 100644 --- a/contrib/llvm/lib/Target/X86/X86RegisterInfo.h +++ b/contrib/llvm/lib/Target/X86/X86RegisterInfo.h @@ -91,6 +91,9 @@ class X86RegisterInfo : public X86GenRegisterInfo { getMatchingSuperRegClass(const TargetRegisterClass *A, const TargetRegisterClass *B, unsigned Idx) const; + const TargetRegisterClass* + getLargestLegalSuperClass(const TargetRegisterClass *RC) const; + /// getPointerRegClass - Returns a TargetRegisterClass used for pointer /// values. const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const; @@ -101,6 +104,9 @@ class X86RegisterInfo : public X86GenRegisterInfo { const TargetRegisterClass * getCrossCopyRegClass(const TargetRegisterClass *RC) const; + unsigned getRegPressureLimit(const TargetRegisterClass *RC, + MachineFunction &MF) const; + /// getCalleeSavedRegs - Return a null-terminated list of all of the /// callee-save registers on this target. const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; diff --git a/contrib/llvm/lib/Target/X86/X86RegisterInfo.td b/contrib/llvm/lib/Target/X86/X86RegisterInfo.td index 612fac2f3be5..fd7a247adcb6 100644 --- a/contrib/llvm/lib/Target/X86/X86RegisterInfo.td +++ b/contrib/llvm/lib/Target/X86/X86RegisterInfo.td @@ -46,7 +46,8 @@ let Namespace = "X86" in { def CL : Register<"cl">, DwarfRegNum<[2, 1, 1]>; def BL : Register<"bl">, DwarfRegNum<[3, 3, 3]>; - // X86-64 only + // X86-64 only, requires REX. + let CostPerUse = 1 in { def SIL : Register<"sil">, DwarfRegNum<[4, 6, 6]>; def DIL : Register<"dil">, DwarfRegNum<[5, 7, 7]>; def BPL : Register<"bpl">, DwarfRegNum<[6, 4, 5]>; @@ -59,6 +60,7 @@ let Namespace = "X86" in { def R13B : Register<"r13b">, DwarfRegNum<[13, -2, -2]>; def R14B : Register<"r14b">, DwarfRegNum<[14, -2, -2]>; def R15B : Register<"r15b">, DwarfRegNum<[15, -2, -2]>; + } // High registers. On x86-64, these cannot be used in any instruction // with a REX prefix. @@ -82,8 +84,8 @@ let Namespace = "X86" in { } def IP : Register<"ip">, DwarfRegNum<[16]>; - // X86-64 only - let SubRegIndices = [sub_8bit] in { + // X86-64 only, requires REX. + let SubRegIndices = [sub_8bit], CostPerUse = 1 in { def R8W : RegisterWithSubRegs<"r8w", [R8B]>, DwarfRegNum<[8, -2, -2]>; def R9W : RegisterWithSubRegs<"r9w", [R9B]>, DwarfRegNum<[9, -2, -2]>; def R10W : RegisterWithSubRegs<"r10w", [R10B]>, DwarfRegNum<[10, -2, -2]>; @@ -105,7 +107,8 @@ let Namespace = "X86" in { def ESP : RegisterWithSubRegs<"esp", [SP]>, DwarfRegNum<[7, 5, 4]>; def EIP : RegisterWithSubRegs<"eip", [IP]>, DwarfRegNum<[16, 8, 8]>; - // X86-64 only + // X86-64 only, requires REX + let CostPerUse = 1 in { def R8D : RegisterWithSubRegs<"r8d", [R8W]>, DwarfRegNum<[8, -2, -2]>; def R9D : RegisterWithSubRegs<"r9d", [R9W]>, DwarfRegNum<[9, -2, -2]>; def R10D : RegisterWithSubRegs<"r10d", [R10W]>, DwarfRegNum<[10, -2, -2]>; @@ -114,7 +117,7 @@ let Namespace = "X86" in { def R13D : RegisterWithSubRegs<"r13d", [R13W]>, DwarfRegNum<[13, -2, -2]>; def R14D : RegisterWithSubRegs<"r14d", [R14W]>, DwarfRegNum<[14, -2, -2]>; def R15D : RegisterWithSubRegs<"r15d", [R15W]>, DwarfRegNum<[15, -2, -2]>; - } + }} // 64-bit registers, X86-64 only let SubRegIndices = [sub_32bit] in { @@ -127,6 +130,8 @@ let Namespace = "X86" in { def RBP : RegisterWithSubRegs<"rbp", [EBP]>, DwarfRegNum<[6, -2, -2]>; def RSP : RegisterWithSubRegs<"rsp", [ESP]>, DwarfRegNum<[7, -2, -2]>; + // These also require REX. + let CostPerUse = 1 in { def R8 : RegisterWithSubRegs<"r8", [R8D]>, DwarfRegNum<[8, -2, -2]>; def R9 : RegisterWithSubRegs<"r9", [R9D]>, DwarfRegNum<[9, -2, -2]>; def R10 : RegisterWithSubRegs<"r10", [R10D]>, DwarfRegNum<[10, -2, -2]>; @@ -136,7 +141,7 @@ let Namespace = "X86" in { def R14 : RegisterWithSubRegs<"r14", [R14D]>, DwarfRegNum<[14, -2, -2]>; def R15 : RegisterWithSubRegs<"r15", [R15D]>, DwarfRegNum<[15, -2, -2]>; def RIP : RegisterWithSubRegs<"rip", [EIP]>, DwarfRegNum<[16, -2, -2]>; - } + }} // MMX Registers. These are actually aliased to ST0 .. ST7 def MM0 : Register<"mm0">, DwarfRegNum<[41, 29, 29]>; @@ -170,6 +175,7 @@ let Namespace = "X86" in { def XMM7: Register<"xmm7">, DwarfRegNum<[24, 28, 28]>; // X86-64 only + let CostPerUse = 1 in { def XMM8: Register<"xmm8">, DwarfRegNum<[25, -2, -2]>; def XMM9: Register<"xmm9">, DwarfRegNum<[26, -2, -2]>; def XMM10: Register<"xmm10">, DwarfRegNum<[27, -2, -2]>; @@ -178,7 +184,7 @@ let Namespace = "X86" in { def XMM13: Register<"xmm13">, DwarfRegNum<[30, -2, -2]>; def XMM14: Register<"xmm14">, DwarfRegNum<[31, -2, -2]>; def XMM15: Register<"xmm15">, DwarfRegNum<[32, -2, -2]>; - } + }} // YMM Registers, used by AVX instructions let SubRegIndices = [sub_xmm] in { diff --git a/contrib/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp b/contrib/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp index 42e819343b5b..02754f9ae503 100644 --- a/contrib/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp +++ b/contrib/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp @@ -178,7 +178,7 @@ X86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const { - // This requires the copy size to be a constant, preferrably + // This requires the copy size to be a constant, preferably // within a subtarget-specific limit. ConstantSDNode *ConstantSize = dyn_cast(Size); if (!ConstantSize) diff --git a/contrib/llvm/lib/Target/X86/X86Subtarget.cpp b/contrib/llvm/lib/Target/X86/X86Subtarget.cpp index 1ee73123bbc6..ba5864ef0e0a 100644 --- a/contrib/llvm/lib/Target/X86/X86Subtarget.cpp +++ b/contrib/llvm/lib/Target/X86/X86Subtarget.cpp @@ -144,7 +144,8 @@ ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { /// passed as the second argument. Otherwise it returns null. const char *X86Subtarget::getBZeroEntry() const { // Darwin 10 has a __bzero entry point for this purpose. - if (getDarwinVers() >= 10) + if (getTargetTriple().isMacOSX() && + !getTargetTriple().isMacOSXVersionLT(10, 6)) return "__bzero"; return 0; diff --git a/contrib/llvm/lib/Target/X86/X86Subtarget.h b/contrib/llvm/lib/Target/X86/X86Subtarget.h index 0a62a029554c..286a7982a699 100644 --- a/contrib/llvm/lib/Target/X86/X86Subtarget.h +++ b/contrib/llvm/lib/Target/X86/X86Subtarget.h @@ -165,9 +165,15 @@ class X86Subtarget : public TargetSubtarget { bool isUnalignedMemAccessFast() const { return IsUAMemFast; } bool hasVectorUAMem() const { return HasVectorUAMem; } - bool isTargetDarwin() const { return TargetTriple.getOS() == Triple::Darwin; } - bool isTargetFreeBSD() const { return TargetTriple.getOS() == Triple::FreeBSD; } - bool isTargetSolaris() const { return TargetTriple.getOS() == Triple::Solaris; } + const Triple &getTargetTriple() const { return TargetTriple; } + + bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } + bool isTargetFreeBSD() const { + return TargetTriple.getOS() == Triple::FreeBSD; + } + bool isTargetSolaris() const { + return TargetTriple.getOS() == Triple::Solaris; + } // ELF is a reasonably sane default and the only other X86 targets we // support are Darwin and Windows. Just use "not those". @@ -215,13 +221,6 @@ class X86Subtarget : public TargetSubtarget { return PICStyle == PICStyles::StubDynamicNoPIC || PICStyle == PICStyles::StubPIC; } - /// getDarwinVers - Return the darwin version number, 8 = Tiger, 9 = Leopard, - /// 10 = Snow Leopard, etc. - unsigned getDarwinVers() const { - if (isTargetDarwin()) return TargetTriple.getDarwinMajorNumber(); - return 0; - } - /// ClassifyGlobalReference - Classify a global variable reference for the /// current subtarget according to how we should reference it in a non-pcrel /// context. diff --git a/contrib/llvm/lib/Target/X86/X86TargetMachine.cpp b/contrib/llvm/lib/Target/X86/X86TargetMachine.cpp index 889c824b0e11..74833291dc7a 100644 --- a/contrib/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/contrib/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -26,19 +26,18 @@ using namespace llvm; static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { Triple TheTriple(TT); - switch (TheTriple.getOS()) { - case Triple::Darwin: - return new X86MCAsmInfoDarwin(TheTriple); - case Triple::MinGW32: - case Triple::Cygwin: - case Triple::Win32: - if (TheTriple.getEnvironment() == Triple::MachO) - return new X86MCAsmInfoDarwin(TheTriple); + + if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) { + if (TheTriple.getArch() == Triple::x86_64) + return new X86_64MCAsmInfoDarwin(TheTriple); else - return new X86MCAsmInfoCOFF(TheTriple); - default: - return new X86ELFMCAsmInfo(TheTriple); + return new X86MCAsmInfoDarwin(TheTriple); } + + if (TheTriple.isOSWindows()) + return new X86MCAsmInfoCOFF(TheTriple); + + return new X86ELFMCAsmInfo(TheTriple); } static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, @@ -48,19 +47,14 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, bool RelaxAll, bool NoExecStack) { Triple TheTriple(TT); - switch (TheTriple.getOS()) { - case Triple::Darwin: + + if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) return createMachOStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll); - case Triple::MinGW32: - case Triple::Cygwin: - case Triple::Win32: - if (TheTriple.getEnvironment() == Triple::MachO) - return createMachOStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll); - else - return createWinCOFFStreamer(Ctx, TAB, *_Emitter, _OS, RelaxAll); - default: - return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, NoExecStack); - } + + if (TheTriple.isOSWindows()) + return createWinCOFFStreamer(Ctx, TAB, *_Emitter, _OS, RelaxAll); + + return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, NoExecStack); } extern "C" void LLVMInitializeX86Target() { @@ -96,11 +90,11 @@ X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT, const std::string &FS) : X86TargetMachine(T, TT, FS, false), DataLayout(getSubtargetImpl()->isTargetDarwin() ? - "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-n8:16:32" : + "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-f128:128:128-n8:16:32" : (getSubtargetImpl()->isTargetCygMing() || getSubtargetImpl()->isTargetWindows()) ? - "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32" : - "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"), + "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-f128:128:128-n8:16:32" : + "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-f128:128:128-n8:16:32"), InstrInfo(*this), TSInfo(*this), TLInfo(*this), @@ -111,7 +105,7 @@ X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT, X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT, const std::string &FS) : X86TargetMachine(T, TT, FS, true), - DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-n8:16:32:64"), + DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-f128:128:128-n8:16:32:64"), InstrInfo(*this), TSInfo(*this), TLInfo(*this), diff --git a/contrib/llvm/lib/Target/X86/X86TargetObjectFile.cpp b/contrib/llvm/lib/Target/X86/X86TargetObjectFile.cpp index c15dfbb1c8ec..1231798297ac 100644 --- a/contrib/llvm/lib/Target/X86/X86TargetObjectFile.cpp +++ b/contrib/llvm/lib/Target/X86/X86TargetObjectFile.cpp @@ -38,6 +38,12 @@ getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, Streamer); } +MCSymbol *X8664_MachoTargetObjectFile:: +getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI) const { + return Mang->getSymbol(GV); +} + unsigned X8632_ELFTargetObjectFile::getPersonalityEncoding() const { if (TM.getRelocationModel() == Reloc::PIC_) return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; @@ -52,7 +58,7 @@ unsigned X8632_ELFTargetObjectFile::getLSDAEncoding() const { return DW_EH_PE_absptr; } -unsigned X8632_ELFTargetObjectFile::getFDEEncoding() const { +unsigned X8632_ELFTargetObjectFile::getFDEEncoding(bool FDE) const { if (TM.getRelocationModel() == Reloc::PIC_) return DW_EH_PE_pcrel | DW_EH_PE_sdata4; else @@ -91,17 +97,14 @@ unsigned X8664_ELFTargetObjectFile::getLSDAEncoding() const { return DW_EH_PE_absptr; } -unsigned X8664_ELFTargetObjectFile::getFDEEncoding() const { - CodeModel::Model Model = TM.getCodeModel(); +unsigned X8664_ELFTargetObjectFile::getFDEEncoding(bool CFI) const { + if (CFI) + return DW_EH_PE_pcrel | DW_EH_PE_sdata4; + if (TM.getRelocationModel() == Reloc::PIC_) - return DW_EH_PE_pcrel | (Model == CodeModel::Small || - Model == CodeModel::Medium ? - DW_EH_PE_sdata4 : DW_EH_PE_sdata8); + return DW_EH_PE_pcrel | DW_EH_PE_sdata4; - if (Model == CodeModel::Small || Model == CodeModel::Medium) - return DW_EH_PE_udata4; - - return DW_EH_PE_absptr; + return DW_EH_PE_udata4; } unsigned X8664_ELFTargetObjectFile::getTTypeEncoding() const { diff --git a/contrib/llvm/lib/Target/X86/X86TargetObjectFile.h b/contrib/llvm/lib/Target/X86/X86TargetObjectFile.h index f2fd49caca38..e21b5bffd059 100644 --- a/contrib/llvm/lib/Target/X86/X86TargetObjectFile.h +++ b/contrib/llvm/lib/Target/X86/X86TargetObjectFile.h @@ -25,6 +25,12 @@ namespace llvm { getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, MachineModuleInfo *MMI, unsigned Encoding, MCStreamer &Streamer) const; + + // getCFIPersonalitySymbol - The symbol that gets passed to + // .cfi_personality. + virtual MCSymbol * + getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI) const; }; class X8632_ELFTargetObjectFile : public TargetLoweringObjectFileELF { @@ -34,7 +40,7 @@ namespace llvm { :TM(tm) { } virtual unsigned getPersonalityEncoding() const; virtual unsigned getLSDAEncoding() const; - virtual unsigned getFDEEncoding() const; + virtual unsigned getFDEEncoding(bool CFI) const; virtual unsigned getTTypeEncoding() const; }; @@ -45,7 +51,7 @@ namespace llvm { :TM(tm) { } virtual unsigned getPersonalityEncoding() const; virtual unsigned getLSDAEncoding() const; - virtual unsigned getFDEEncoding() const; + virtual unsigned getFDEEncoding(bool CFI) const; virtual unsigned getTTypeEncoding() const; }; diff --git a/contrib/llvm/lib/Target/XCore/XCoreISelDAGToDAG.cpp b/contrib/llvm/lib/Target/XCore/XCoreISelDAGToDAG.cpp index fc8a07aad73b..6bec9f91944a 100644 --- a/contrib/llvm/lib/Target/XCore/XCoreISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/XCore/XCoreISelDAGToDAG.cpp @@ -30,8 +30,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include -#include using namespace llvm; /// XCoreDAGToDAGISel - XCore specific code to select XCore machine @@ -49,7 +47,8 @@ namespace { Subtarget(*TM.getSubtargetImpl()) { } SDNode *Select(SDNode *N); - + SDNode *SelectBRIND(SDNode *N); + /// getI32Imm - Return a target constant with the specified value, of type /// i32. inline SDValue getI32Imm(unsigned Imm) { @@ -154,62 +153,133 @@ bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Addr, SDValue &Base, SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { DebugLoc dl = N->getDebugLoc(); - EVT NVT = N->getValueType(0); - if (NVT == MVT::i32) { - switch (N->getOpcode()) { - default: break; - case ISD::Constant: { - uint64_t Val = cast(N)->getZExtValue(); - if (immMskBitp(N)) { - // Transformation function: get the size of a mask - // Look for the first non-zero bit - SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(Val)); - return CurDAG->getMachineNode(XCore::MKMSK_rus, dl, - MVT::i32, MskSize); - } - else if (!isUInt<16>(Val)) { - SDValue CPIdx = - CurDAG->getTargetConstantPool(ConstantInt::get( - Type::getInt32Ty(*CurDAG->getContext()), Val), - TLI.getPointerTy()); - return CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, - MVT::Other, CPIdx, - CurDAG->getEntryNode()); - } - break; - } - case XCoreISD::LADD: { - SDValue Ops[] = { N->getOperand(0), N->getOperand(1), - N->getOperand(2) }; - return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32, - Ops, 3); - } - case XCoreISD::LSUB: { - SDValue Ops[] = { N->getOperand(0), N->getOperand(1), - N->getOperand(2) }; - return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32, - Ops, 3); - } - case XCoreISD::MACCU: { - SDValue Ops[] = { N->getOperand(0), N->getOperand(1), - N->getOperand(2), N->getOperand(3) }; - return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32, - Ops, 4); - } - case XCoreISD::MACCS: { - SDValue Ops[] = { N->getOperand(0), N->getOperand(1), - N->getOperand(2), N->getOperand(3) }; - return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32, - Ops, 4); - } - case XCoreISD::LMUL: { - SDValue Ops[] = { N->getOperand(0), N->getOperand(1), - N->getOperand(2), N->getOperand(3) }; - return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32, - Ops, 4); - } - // Other cases are autogenerated. + switch (N->getOpcode()) { + default: break; + case ISD::Constant: { + uint64_t Val = cast(N)->getZExtValue(); + if (immMskBitp(N)) { + // Transformation function: get the size of a mask + // Look for the first non-zero bit + SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(Val)); + return CurDAG->getMachineNode(XCore::MKMSK_rus, dl, + MVT::i32, MskSize); } + else if (!isUInt<16>(Val)) { + SDValue CPIdx = + CurDAG->getTargetConstantPool(ConstantInt::get( + Type::getInt32Ty(*CurDAG->getContext()), Val), + TLI.getPointerTy()); + return CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, + MVT::Other, CPIdx, + CurDAG->getEntryNode()); + } + break; + } + case XCoreISD::LADD: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2) }; + return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32, + Ops, 3); + } + case XCoreISD::LSUB: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2) }; + return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32, + Ops, 3); + } + case XCoreISD::MACCU: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2), N->getOperand(3) }; + return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32, + Ops, 4); + } + case XCoreISD::MACCS: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2), N->getOperand(3) }; + return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32, + Ops, 4); + } + case XCoreISD::LMUL: { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + N->getOperand(2), N->getOperand(3) }; + return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32, + Ops, 4); + } + case ISD::BRIND: + if (SDNode *ResNode = SelectBRIND(N)) + return ResNode; + break; + // Other cases are autogenerated. } return SelectCode(N); } + +/// Given a chain return a new chain where any appearance of Old is replaced +/// by New. There must be at most one instruction between Old and Chain and +/// this instruction must be a TokenFactor. Returns an empty SDValue if +/// these conditions don't hold. +static SDValue +replaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New) +{ + if (Chain == Old) + return New; + if (Chain->getOpcode() != ISD::TokenFactor) + return SDValue(); + SmallVector Ops; + bool found = false; + for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) { + if (Chain->getOperand(i) == Old) { + Ops.push_back(New); + found = true; + } else { + Ops.push_back(Chain->getOperand(i)); + } + } + if (!found) + return SDValue(); + return CurDAG->getNode(ISD::TokenFactor, Chain->getDebugLoc(), MVT::Other, + &Ops[0], Ops.size()); +} + +SDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + // (brind (int_xcore_checkevent (addr))) + SDValue Chain = N->getOperand(0); + SDValue Addr = N->getOperand(1); + if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN) + return 0; + unsigned IntNo = cast(Addr->getOperand(1))->getZExtValue(); + if (IntNo != Intrinsic::xcore_checkevent) + return 0; + SDValue nextAddr = Addr->getOperand(2); + SDValue CheckEventChainOut(Addr.getNode(), 1); + if (!CheckEventChainOut.use_empty()) { + // If the chain out of the checkevent intrinsic is an operand of the + // indirect branch or used in a TokenFactor which is the operand of the + // indirect branch then build a new chain which uses the chain coming into + // the checkevent intrinsic instead. + SDValue CheckEventChainIn = Addr->getOperand(0); + SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut, + CheckEventChainIn); + if (!NewChain.getNode()) + return 0; + Chain = NewChain; + } + // Enable events on the thread using setsr 1 and then disable them immediately + // after with clrsr 1. If any resources owned by the thread are ready an event + // will be taken. If no resource is ready we branch to the address which was + // the operand to the checkevent intrinsic. + SDValue constOne = getI32Imm(1); + SDValue Glue = + SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue, + constOne, Chain), 0); + Glue = + SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue, + constOne, Glue), 0); + if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper && + nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) { + return CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other, + nextAddr->getOperand(0), Glue); + } + return CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue); +} diff --git a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp index 4817787d7515..5987e8be9a16 100644 --- a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp +++ b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp @@ -37,8 +37,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/VectorExtras.h" -#include -#include using namespace llvm; const char *XCoreTargetLowering:: @@ -967,7 +965,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. - // The InFlag in necessary since all emited instructions must be + // The InFlag in necessary since all emitted instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { diff --git a/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td b/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td index ecdd4cb63000..789546ed304b 100644 --- a/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td +++ b/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td @@ -308,6 +308,16 @@ multiclass FU6_LU6 { !strconcat(OpcStr, " $b"), [(OpNode immU16:$b)]>; } +multiclass FU6_LU6_int { + def _u6: _FU6< + (outs), (ins i32imm:$b), + !strconcat(OpcStr, " $b"), + [(Int immU6:$b)]>; + def _lu6: _FLU6< + (outs), (ins i32imm:$b), + !strconcat(OpcStr, " $b"), + [(Int immU16:$b)]>; +} multiclass FU6_LU6_np { def _u6: _FU6< @@ -638,8 +648,8 @@ defm RETSP : FU6_LU6<"retsp", XCoreRetsp>; } } -// TODO extdp, kentsp, krestsp, blat, setsr -// clrsr, getsr, kalli +// TODO extdp, kentsp, krestsp, blat +// getsr, kalli let isBranch = 1, isTerminator = 1, isBarrier = 1 in { def BRBU_u6 : _FU6< (outs), @@ -678,6 +688,17 @@ def LDAWCP_lu6: _FLRU6< "ldaw r11, cp[$a]", [(set R11, ADDRcpii:$a)]>; +defm SETSR : FU6_LU6_int<"setsr", int_xcore_setsr>; + +defm CLRSR : FU6_LU6_int<"clrsr", int_xcore_clrsr>; + +// setsr may cause a branch if it is used to enable events. clrsr may +// branch if it is executed while events are enabled. +let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in { +defm SETSR_branch : FU6_LU6_np<"setsr">; +defm CLRSR_branch : FU6_LU6_np<"clrsr">; +} + // U10 // TODO ldwcpl, blacp @@ -718,7 +739,7 @@ def BL_lu10 : _FLU10< } // Two operand short -// TODO getr, getst +// TODO eet, eef, testwct, tsetmr, sext (reg), zext (reg) def NOT : _F2R<(outs GRRegs:$dst), (ins GRRegs:$b), "not $dst, $b", [(set GRRegs:$dst, (not GRRegs:$b))]>; @@ -727,8 +748,6 @@ def NEG : _F2R<(outs GRRegs:$dst), (ins GRRegs:$b), "neg $dst, $b", [(set GRRegs:$dst, (ineg GRRegs:$b))]>; -// TODO setd, eet, eef, testwct, tinitpc, tinitdp, -// tinitsp, tinitcp, tsetmr, sext (reg), zext (reg) let Constraints = "$src1 = $dst" in { let neverHasSideEffects = 1 in def SEXT_rus : _FRUS<(outs GRRegs:$dst), (ins GRRegs:$src1, i32imm:$src2), @@ -816,9 +835,29 @@ def SETD_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val), "setd res[$r], $val", [(int_xcore_setd GRRegs:$r, GRRegs:$val)]>; +def GETST_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r), + "getst $dst, res[$r]", + [(set GRRegs:$dst, (int_xcore_getst GRRegs:$r))]>; + +def INITSP_2r : _F2R<(outs), (ins GRRegs:$t, GRRegs:$src), + "init t[$t]:sp, $src", + [(int_xcore_initsp GRRegs:$t, GRRegs:$src)]>; + +def INITPC_2r : _F2R<(outs), (ins GRRegs:$t, GRRegs:$src), + "init t[$t]:pc, $src", + [(int_xcore_initpc GRRegs:$t, GRRegs:$src)]>; + +def INITCP_2r : _F2R<(outs), (ins GRRegs:$t, GRRegs:$src), + "init t[$t]:cp, $src", + [(int_xcore_initcp GRRegs:$t, GRRegs:$src)]>; + +def INITDP_2r : _F2R<(outs), (ins GRRegs:$t, GRRegs:$src), + "init t[$t]:dp, $src", + [(int_xcore_initdp GRRegs:$t, GRRegs:$src)]>; + // Two operand long -// TODO setclk, setrdy, setpsc, endin, peek, -// getd, testlcl, tinitlr, getps, setps +// TODO endin, peek, +// getd, testlcl def BITREV_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src), "bitrev $dst, $src", [(set GRRegs:$dst, (int_xcore_bitrev GRRegs:$src))]>; @@ -839,10 +878,41 @@ def SETTW_l2r : _FL2R<(outs), (ins GRRegs:$r, GRRegs:$val), "settw res[$r], $val", [(int_xcore_settw GRRegs:$r, GRRegs:$val)]>; +def GETPS_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src), + "get $dst, ps[$src]", + [(set GRRegs:$dst, (int_xcore_getps GRRegs:$src))]>; + +def SETPS_l2r : _FL2R<(outs), (ins GRRegs:$src1, GRRegs:$src2), + "set ps[$src1], $src2", + [(int_xcore_setps GRRegs:$src1, GRRegs:$src2)]>; + +def INITLR_l2r : _FL2R<(outs), (ins GRRegs:$t, GRRegs:$src), + "init t[$t]:lr, $src", + [(int_xcore_initlr GRRegs:$t, GRRegs:$src)]>; + +def SETCLK_l2r : _FL2R<(outs), (ins GRRegs:$src1, GRRegs:$src2), + "setclk res[$src1], $src2", + [(int_xcore_setclk GRRegs:$src1, GRRegs:$src2)]>; + +def SETRDY_l2r : _FL2R<(outs), (ins GRRegs:$src1, GRRegs:$src2), + "setrdy res[$src1], $src2", + [(int_xcore_setrdy GRRegs:$src1, GRRegs:$src2)]>; + +def SETPSC_l2r : _FL2R<(outs), (ins GRRegs:$src1, GRRegs:$src2), + "setpsc res[$src1], $src2", + [(int_xcore_setpsc GRRegs:$src1, GRRegs:$src2)]>; + // One operand short -// TODO edu, eeu, waitet, waitef, tstart, msync, mjoin, clrtp +// TODO edu, eeu, waitet, waitef, tstart, clrtp // setdp, setcp, setev, kcall // dgetreg +def MSYNC_1r : _F1R<(outs), (ins GRRegs:$i), + "msync res[$i]", + [(int_xcore_msync GRRegs:$i)]>; +def MJOIN_1r : _F1R<(outs), (ins GRRegs:$i), + "mjoin res[$i]", + [(int_xcore_mjoin GRRegs:$i)]>; + let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in def BAU_1r : _F1R<(outs), (ins GRRegs:$addr), "bau $addr", @@ -899,7 +969,7 @@ def EEU_1r : _F1R<(outs), (ins GRRegs:$r), [(int_xcore_eeu GRRegs:$r)]>; // Zero operand short -// TODO ssync, freet, ldspc, stspc, ldssr, stssr, ldsed, stsed, +// TODO freet, ldspc, stspc, ldssr, stssr, ldsed, stsed, // stet, geted, getet, getkep, getksp, setkep, getid, kret, dcall, dret, // dentsp, drestsp @@ -910,6 +980,10 @@ def GETID_0R : _F0R<(outs), (ins), "get r11, id", [(set R11, (int_xcore_getid))]>; +def SSYNC_0r : _F0R<(outs), (ins), + "ssync", + [(int_xcore_ssync)]>; + let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1, hasSideEffects = 1 in def WAITEU_0R : _F0R<(outs), (ins), diff --git a/contrib/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp b/contrib/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp index 56c0879cc8fc..0287a5135837 100644 --- a/contrib/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -104,6 +104,11 @@ XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { return TFI->hasFP(MF); } +bool +XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const { + return false; +} + // This function eliminates ADJCALLSTACKDOWN, // ADJCALLSTACKUP pseudo instructions void XCoreRegisterInfo:: diff --git a/contrib/llvm/lib/Target/XCore/XCoreRegisterInfo.h b/contrib/llvm/lib/Target/XCore/XCoreRegisterInfo.h index 218575581d4a..770483b68615 100644 --- a/contrib/llvm/lib/Target/XCore/XCoreRegisterInfo.h +++ b/contrib/llvm/lib/Target/XCore/XCoreRegisterInfo.h @@ -48,6 +48,8 @@ struct XCoreRegisterInfo : public XCoreGenRegisterInfo { bool requiresRegisterScavenging(const MachineFunction &MF) const; + bool useFPForScavengingIndex(const MachineFunction &MF) const; + void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; diff --git a/contrib/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/contrib/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp index 0c650cfe6440..54a7f679e01c 100644 --- a/contrib/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/contrib/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -771,8 +771,8 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F, // function empty. NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); - // Loop over the argument list, transfering uses of the old arguments over to - // the new arguments, also transfering over the names as well. + // Loop over the argument list, transferring uses of the old arguments over to + // the new arguments, also transferring over the names as well. // for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin(); I != E; ++I) { diff --git a/contrib/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/contrib/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp index b42322116a98..d4eaf0c4a3ec 100644 --- a/contrib/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/contrib/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -49,7 +49,7 @@ namespace { /// Struct that represents (part of) either a return value or a function /// argument. Used so that arguments and return values can be used - /// interchangably. + /// interchangeably. struct RetOrArg { RetOrArg(const Function *F, unsigned Idx, bool IsArg) : F(F), Idx(Idx), IsArg(IsArg) {} @@ -273,8 +273,8 @@ bool DAE::DeleteDeadVarargs(Function &Fn) { // function empty. NF->getBasicBlockList().splice(NF->begin(), Fn.getBasicBlockList()); - // Loop over the argument list, transfering uses of the old arguments over to - // the new arguments, also transfering over the names as well. While we're at + // Loop over the argument list, transferring uses of the old arguments over to + // the new arguments, also transferring over the names as well. While we're at // it, remove the dead arguments from the DeadArguments list. // for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(), @@ -294,7 +294,7 @@ bool DAE::DeleteDeadVarargs(Function &Fn) { /// instead. bool DAE::RemoveDeadArgumentsFromCallers(Function &Fn) { - if (Fn.isDeclaration()) + if (Fn.isDeclaration() || Fn.mayBeOverridden()) return false; // Functions with local linkage should already have been handled. @@ -379,7 +379,7 @@ DAE::Liveness DAE::SurveyUse(Value::const_use_iterator U, // The value is returned from a function. It's only live when the // function's return value is live. We use RetValNum here, for the case // that U is really a use of an insertvalue instruction that uses the - // orginal Use. + // original Use. RetOrArg Use = CreateRet(RI->getParent()->getParent(), RetValNum); // We might be live, depending on the liveness of Use. return MarkIfNotLive(Use, MaybeLiveUses); @@ -894,8 +894,8 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { // function empty. NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); - // Loop over the argument list, transfering uses of the old arguments over to - // the new arguments, also transfering over the names as well. + // Loop over the argument list, transferring uses of the old arguments over to + // the new arguments, also transferring over the names as well. i = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin(); I != E; ++I, ++i) diff --git a/contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp index d4cb71272f76..ded58aca75fc 100644 --- a/contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -21,6 +21,7 @@ #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" #include "llvm/Module.h" +#include "llvm/Operator.h" #include "llvm/Pass.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/MemoryBuiltins.h" @@ -54,6 +55,7 @@ STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated"); STATISTIC(NumNestRemoved , "Number of nest attributes removed"); STATISTIC(NumAliasesResolved, "Number of global aliases resolved"); STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated"); +STATISTIC(NumCXXDtorsRemoved, "Number of global C++ destructors removed"); namespace { struct GlobalStatus; @@ -77,6 +79,7 @@ namespace { bool ProcessInternalGlobal(GlobalVariable *GV,Module::global_iterator &GVI, const SmallPtrSet &PHIUsers, const GlobalStatus &GS); + bool OptimizeEmptyGlobalCXXDtors(Function *CXAAtExitFn); }; } @@ -1191,9 +1194,11 @@ static Value *GetHeapSROAValue(Value *V, unsigned FieldNo, const StructType *ST = cast(cast(PN->getType())->getElementType()); - Result = + PHINode *NewPN = PHINode::Create(PointerType::getUnqual(ST->getElementType(FieldNo)), + PN->getNumIncomingValues(), PN->getName()+".f"+Twine(FieldNo), PN); + Result = NewPN; PHIsToRewrite.push_back(std::make_pair(PN, FieldNo)); } else { llvm_unreachable("Unknown usable value"); @@ -1940,36 +1945,24 @@ bool GlobalOpt::OptimizeGlobalVars(Module &M) { return Changed; } -/// FindGlobalCtors - Find the llvm.globalctors list, verifying that all +/// FindGlobalCtors - Find the llvm.global_ctors list, verifying that all /// initializers have an init priority of 65535. GlobalVariable *GlobalOpt::FindGlobalCtors(Module &M) { GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors"); if (GV == 0) return 0; - // Found it, verify it's an array of { int, void()* }. - const ArrayType *ATy =dyn_cast(GV->getType()->getElementType()); - if (!ATy) return 0; - const StructType *STy = dyn_cast(ATy->getElementType()); - if (!STy || STy->getNumElements() != 2 || - !STy->getElementType(0)->isIntegerTy(32)) return 0; - const PointerType *PFTy = dyn_cast(STy->getElementType(1)); - if (!PFTy) return 0; - const FunctionType *FTy = dyn_cast(PFTy->getElementType()); - if (!FTy || !FTy->getReturnType()->isVoidTy() || - FTy->isVarArg() || FTy->getNumParams() != 0) - return 0; - // Verify that the initializer is simple enough for us to handle. We are // only allowed to optimize the initializer if it is unique. if (!GV->hasUniqueInitializer()) return 0; - - ConstantArray *CA = dyn_cast(GV->getInitializer()); - if (!CA) return 0; - + + if (isa(GV->getInitializer())) + return GV; + ConstantArray *CA = cast(GV->getInitializer()); + for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) { - ConstantStruct *CS = dyn_cast(*i); - if (CS == 0) return 0; - + if (isa(*i)) + continue; + ConstantStruct *CS = cast(*i); if (isa(CS->getOperand(1))) continue; @@ -1978,8 +1971,8 @@ GlobalVariable *GlobalOpt::FindGlobalCtors(Module &M) { return 0; // Init priority must be standard. - ConstantInt *CI = dyn_cast(CS->getOperand(0)); - if (!CI || CI->getZExtValue() != 65535) + ConstantInt *CI = cast(CS->getOperand(0)); + if (CI->getZExtValue() != 65535) return 0; } @@ -1989,6 +1982,8 @@ GlobalVariable *GlobalOpt::FindGlobalCtors(Module &M) { /// ParseGlobalCtors - Given a llvm.global_ctors list that we can understand, /// return a list of the functions and null terminator as a vector. static std::vector ParseGlobalCtors(GlobalVariable *GV) { + if (GV->getInitializer()->isNullValue()) + return std::vector(); ConstantArray *CA = cast(GV->getInitializer()); std::vector Result; Result.reserve(CA->getNumOperands()); @@ -2019,7 +2014,7 @@ static GlobalVariable *InstallGlobalCtors(GlobalVariable *GCL, const PointerType *PFTy = PointerType::getUnqual(FTy); CSVals[1] = Constant::getNullValue(PFTy); CSVals[0] = ConstantInt::get(Type::getInt32Ty(GCL->getContext()), - 2147483647); + 0x7fffffff); } CAList.push_back(ConstantStruct::get(GCL->getContext(), CSVals, false)); } @@ -2696,12 +2691,126 @@ bool GlobalOpt::OptimizeGlobalAliases(Module &M) { return Changed; } +static Function *FindCXAAtExit(Module &M) { + Function *Fn = M.getFunction("__cxa_atexit"); + + if (!Fn) + return 0; + + const FunctionType *FTy = Fn->getFunctionType(); + + // Checking that the function has the right return type, the right number of + // parameters and that they all have pointer types should be enough. + if (!FTy->getReturnType()->isIntegerTy() || + FTy->getNumParams() != 3 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) + return 0; + + return Fn; +} + +/// cxxDtorIsEmpty - Returns whether the given function is an empty C++ +/// destructor and can therefore be eliminated. +/// Note that we assume that other optimization passes have already simplified +/// the code so we only look for a function with a single basic block, where +/// the only allowed instructions are 'ret' or 'call' to empty C++ dtor. +static bool cxxDtorIsEmpty(const Function &Fn, + SmallPtrSet &CalledFunctions) { + // FIXME: We could eliminate C++ destructors if they're readonly/readnone and + // nounwind, but that doesn't seem worth doing. + if (Fn.isDeclaration()) + return false; + + if (++Fn.begin() != Fn.end()) + return false; + + const BasicBlock &EntryBlock = Fn.getEntryBlock(); + for (BasicBlock::const_iterator I = EntryBlock.begin(), E = EntryBlock.end(); + I != E; ++I) { + if (const CallInst *CI = dyn_cast(I)) { + // Ignore debug intrinsics. + if (isa(CI)) + continue; + + const Function *CalledFn = CI->getCalledFunction(); + + if (!CalledFn) + return false; + + SmallPtrSet NewCalledFunctions(CalledFunctions); + + // Don't treat recursive functions as empty. + if (!NewCalledFunctions.insert(CalledFn)) + return false; + + if (!cxxDtorIsEmpty(*CalledFn, NewCalledFunctions)) + return false; + } else if (isa(*I)) + return true; + else + return false; + } + + return false; +} + +bool GlobalOpt::OptimizeEmptyGlobalCXXDtors(Function *CXAAtExitFn) { + /// Itanium C++ ABI p3.3.5: + /// + /// After constructing a global (or local static) object, that will require + /// destruction on exit, a termination function is registered as follows: + /// + /// extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d ); + /// + /// This registration, e.g. __cxa_atexit(f,p,d), is intended to cause the + /// call f(p) when DSO d is unloaded, before all such termination calls + /// registered before this one. It returns zero if registration is + /// successful, nonzero on failure. + + // This pass will look for calls to __cxa_atexit where the function is trivial + // and remove them. + bool Changed = false; + + for (Function::use_iterator I = CXAAtExitFn->use_begin(), + E = CXAAtExitFn->use_end(); I != E;) { + // We're only interested in calls. Theoretically, we could handle invoke + // instructions as well, but neither llvm-gcc nor clang generate invokes + // to __cxa_atexit. + CallInst *CI = dyn_cast(*I++); + if (!CI) + continue; + + Function *DtorFn = + dyn_cast(CI->getArgOperand(0)->stripPointerCasts()); + if (!DtorFn) + continue; + + SmallPtrSet CalledFunctions; + if (!cxxDtorIsEmpty(*DtorFn, CalledFunctions)) + continue; + + // Just remove the call. + CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); + CI->eraseFromParent(); + + ++NumCXXDtorsRemoved; + + Changed |= true; + } + + return Changed; +} + bool GlobalOpt::runOnModule(Module &M) { bool Changed = false; // Try to find the llvm.globalctors list. GlobalVariable *GlobalCtors = FindGlobalCtors(M); + Function *CXAAtExitFn = FindCXAAtExit(M); + bool LocalChange = true; while (LocalChange) { LocalChange = false; @@ -2718,6 +2827,11 @@ bool GlobalOpt::runOnModule(Module &M) { // Resolve aliases, when possible. LocalChange |= OptimizeGlobalAliases(M); + + // Try to remove trivial global destructors. + if (CXAAtExitFn) + LocalChange |= OptimizeEmptyGlobalCXXDtors(CXAAtExitFn); + Changed |= LocalChange; } diff --git a/contrib/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp b/contrib/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp index c7c293987a58..25c01346642b 100644 --- a/contrib/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp +++ b/contrib/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp @@ -186,7 +186,7 @@ bool IPCP::PropagateConstantReturn(Function &F) { // Find the returned value Value *V; if (!STy) - V = RI->getOperand(i); + V = RI->getOperand(0); else V = FindInsertedValue(RI->getOperand(0), i); diff --git a/contrib/llvm/lib/Transforms/IPO/IPO.cpp b/contrib/llvm/lib/Transforms/IPO/IPO.cpp index fbe90ce67591..21dcb519d9c9 100644 --- a/contrib/llvm/lib/Transforms/IPO/IPO.cpp +++ b/contrib/llvm/lib/Transforms/IPO/IPO.cpp @@ -45,7 +45,6 @@ void llvm::initializeIPO(PassRegistry &Registry) { initializeStripDebugDeclarePass(Registry); initializeStripDeadDebugInfoPass(Registry); initializeStripNonDebugSymbolsPass(Registry); - initializeSRETPromotionPass(Registry); } void LLVMInitializeIPO(LLVMPassRegistryRef R) { diff --git a/contrib/llvm/lib/Transforms/IPO/Inliner.cpp b/contrib/llvm/lib/Transforms/IPO/Inliner.cpp index 37eafd723bf8..57f3e772b569 100644 --- a/contrib/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/contrib/llvm/lib/Transforms/IPO/Inliner.cpp @@ -29,7 +29,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" -#include using namespace llvm; STATISTIC(NumInlined, "Number of functions inlined"); diff --git a/contrib/llvm/lib/Transforms/IPO/Internalize.cpp b/contrib/llvm/lib/Transforms/IPO/Internalize.cpp index 9b9ebad47225..7cb1d18f933d 100644 --- a/contrib/llvm/lib/Transforms/IPO/Internalize.cpp +++ b/contrib/llvm/lib/Transforms/IPO/Internalize.cpp @@ -126,6 +126,8 @@ bool InternalizePass::runOnModule(Module &M) { // FIXME: maybe use private linkage? for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isDeclaration() && // Function must be defined here + // Available externally is really just a "declaration with a body". + !I->hasAvailableExternallyLinkage() && !I->hasLocalLinkage() && // Can't already have internal linkage !ExternalNames.count(I->getName())) {// Not marked to keep external? I->setLinkage(GlobalValue::InternalLinkage); @@ -144,9 +146,6 @@ bool InternalizePass::runOnModule(Module &M) { // Never internalize anchors used by the machine module info, else the info // won't find them. (see MachineModuleInfo.) - ExternalNames.insert("llvm.dbg.compile_units"); - ExternalNames.insert("llvm.dbg.global_variables"); - ExternalNames.insert("llvm.dbg.subprograms"); ExternalNames.insert("llvm.global_ctors"); ExternalNames.insert("llvm.global_dtors"); ExternalNames.insert("llvm.noinline"); diff --git a/contrib/llvm/lib/Transforms/IPO/LowerSetJmp.cpp b/contrib/llvm/lib/Transforms/IPO/LowerSetJmp.cpp index b545f0bb267d..52ecf17b8f9b 100644 --- a/contrib/llvm/lib/Transforms/IPO/LowerSetJmp.cpp +++ b/contrib/llvm/lib/Transforms/IPO/LowerSetJmp.cpp @@ -430,7 +430,7 @@ void LowerSetJmp::TransformSetJmpCall(CallInst* Inst) // This PHI node will be in the new block created from the // splitBasicBlock call. - PHINode* PHI = PHINode::Create(Type::getInt32Ty(Inst->getContext()), + PHINode* PHI = PHINode::Create(Type::getInt32Ty(Inst->getContext()), 2, "SetJmpReturn", Inst); // Coming from a call to setjmp, the return is 0. diff --git a/contrib/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/contrib/llvm/lib/Transforms/IPO/MergeFunctions.cpp index cccffca6e384..f74144338a61 100644 --- a/contrib/llvm/lib/Transforms/IPO/MergeFunctions.cpp +++ b/contrib/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -55,6 +55,7 @@ #include "llvm/Instructions.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" +#include "llvm/Operator.h" #include "llvm/Pass.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" @@ -125,7 +126,7 @@ class ComparableFunction { const ComparableFunction ComparableFunction::EmptyKey = ComparableFunction(0); const ComparableFunction ComparableFunction::TombstoneKey = ComparableFunction(1); -TargetData * const ComparableFunction::LookupOnly = (TargetData*)(-1); +TargetData *const ComparableFunction::LookupOnly = (TargetData*)(-1); } @@ -212,7 +213,7 @@ bool FunctionComparator::isEquivalentType(const Type *Ty1, return false; } - switch(Ty1->getTypeID()) { + switch (Ty1->getTypeID()) { default: llvm_unreachable("Unknown type!"); // Fall through in Release mode. diff --git a/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp b/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp index 2afd02985764..d9d1d106111e 100644 --- a/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp +++ b/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp @@ -95,7 +95,7 @@ Function* PartialInliner::unswitchFunction(Function* F) { PHINode* OldPhi = dyn_cast(I); if (!OldPhi) break; - PHINode* retPhi = PHINode::Create(OldPhi->getType(), "", Ins); + PHINode* retPhi = PHINode::Create(OldPhi->getType(), 2, "", Ins); OldPhi->replaceAllUsesWith(retPhi); Ins = newReturnBlock->getFirstNonPHI(); diff --git a/contrib/llvm/lib/Transforms/IPO/PruneEH.cpp b/contrib/llvm/lib/Transforms/IPO/PruneEH.cpp index d91c2c403aae..9470180c5657 100644 --- a/contrib/llvm/lib/Transforms/IPO/PruneEH.cpp +++ b/contrib/llvm/lib/Transforms/IPO/PruneEH.cpp @@ -27,7 +27,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/CFG.h" -#include #include using namespace llvm; diff --git a/contrib/llvm/lib/Transforms/IPO/StructRetPromotion.cpp b/contrib/llvm/lib/Transforms/IPO/StructRetPromotion.cpp deleted file mode 100644 index 584deacaff1b..000000000000 --- a/contrib/llvm/lib/Transforms/IPO/StructRetPromotion.cpp +++ /dev/null @@ -1,357 +0,0 @@ -//===-- StructRetPromotion.cpp - Promote sret arguments -------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass finds functions that return a struct (using a pointer to the struct -// as the first argument of the function, marked with the 'sret' attribute) and -// replaces them with a new function that simply returns each of the elements of -// that struct (using multiple return values). -// -// This pass works under a number of conditions: -// 1. The returned struct must not contain other structs -// 2. The returned struct must only be used to load values from -// 3. The placeholder struct passed in is the result of an alloca -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "sretpromotion" -#include "llvm/Transforms/IPO.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/CallGraphSCCPass.h" -#include "llvm/Instructions.h" -#include "llvm/Analysis/CallGraph.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/CFG.h" -#include "llvm/Support/Debug.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -STATISTIC(NumRejectedSRETUses , "Number of sret rejected due to unexpected uses"); -STATISTIC(NumSRET , "Number of sret promoted"); -namespace { - /// SRETPromotion - This pass removes sret parameter and updates - /// function to use multiple return value. - /// - struct SRETPromotion : public CallGraphSCCPass { - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - CallGraphSCCPass::getAnalysisUsage(AU); - } - - virtual bool runOnSCC(CallGraphSCC &SCC); - static char ID; // Pass identification, replacement for typeid - SRETPromotion() : CallGraphSCCPass(ID) { - initializeSRETPromotionPass(*PassRegistry::getPassRegistry()); - } - - private: - CallGraphNode *PromoteReturn(CallGraphNode *CGN); - bool isSafeToUpdateAllCallers(Function *F); - Function *cloneFunctionBody(Function *F, const StructType *STy); - CallGraphNode *updateCallSites(Function *F, Function *NF); - }; -} - -char SRETPromotion::ID = 0; -INITIALIZE_PASS_BEGIN(SRETPromotion, "sretpromotion", - "Promote sret arguments to multiple ret values", false, false) -INITIALIZE_AG_DEPENDENCY(CallGraph) -INITIALIZE_PASS_END(SRETPromotion, "sretpromotion", - "Promote sret arguments to multiple ret values", false, false) - -Pass *llvm::createStructRetPromotionPass() { - return new SRETPromotion(); -} - -bool SRETPromotion::runOnSCC(CallGraphSCC &SCC) { - bool Changed = false; - - for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) - if (CallGraphNode *NewNode = PromoteReturn(*I)) { - SCC.ReplaceNode(*I, NewNode); - Changed = true; - } - - return Changed; -} - -/// PromoteReturn - This method promotes function that uses StructRet paramater -/// into a function that uses multiple return values. -CallGraphNode *SRETPromotion::PromoteReturn(CallGraphNode *CGN) { - Function *F = CGN->getFunction(); - - if (!F || F->isDeclaration() || !F->hasLocalLinkage()) - return 0; - - // Make sure that function returns struct. - if (F->arg_size() == 0 || !F->hasStructRetAttr() || F->doesNotReturn()) - return 0; - - DEBUG(dbgs() << "SretPromotion: Looking at sret function " - << F->getName() << "\n"); - - assert(F->getReturnType()->isVoidTy() && "Invalid function return type"); - Function::arg_iterator AI = F->arg_begin(); - const llvm::PointerType *FArgType = dyn_cast(AI->getType()); - assert(FArgType && "Invalid sret parameter type"); - const llvm::StructType *STy = - dyn_cast(FArgType->getElementType()); - assert(STy && "Invalid sret parameter element type"); - - // Check if it is ok to perform this promotion. - if (isSafeToUpdateAllCallers(F) == false) { - DEBUG(dbgs() << "SretPromotion: Not all callers can be updated\n"); - ++NumRejectedSRETUses; - return 0; - } - - DEBUG(dbgs() << "SretPromotion: sret argument will be promoted\n"); - ++NumSRET; - // [1] Replace use of sret parameter - AllocaInst *TheAlloca = new AllocaInst(STy, NULL, "mrv", - F->getEntryBlock().begin()); - Value *NFirstArg = F->arg_begin(); - NFirstArg->replaceAllUsesWith(TheAlloca); - - // [2] Find and replace ret instructions - for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) - for(BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) { - Instruction *I = BI; - ++BI; - if (isa(I)) { - Value *NV = new LoadInst(TheAlloca, "mrv.ld", I); - ReturnInst *NR = ReturnInst::Create(F->getContext(), NV, I); - I->replaceAllUsesWith(NR); - I->eraseFromParent(); - } - } - - // [3] Create the new function body and insert it into the module. - Function *NF = cloneFunctionBody(F, STy); - - // [4] Update all call sites to use new function - CallGraphNode *NF_CFN = updateCallSites(F, NF); - - CallGraph &CG = getAnalysis(); - NF_CFN->stealCalledFunctionsFrom(CG[F]); - - delete CG.removeFunctionFromModule(F); - return NF_CFN; -} - -// Check if it is ok to perform this promotion. -bool SRETPromotion::isSafeToUpdateAllCallers(Function *F) { - - if (F->use_empty()) - // No users. OK to modify signature. - return true; - - for (Value::use_iterator FnUseI = F->use_begin(), FnUseE = F->use_end(); - FnUseI != FnUseE; ++FnUseI) { - // The function is passed in as an argument to (possibly) another function, - // we can't change it! - CallSite CS(*FnUseI); - Instruction *Call = CS.getInstruction(); - // The function is used by something else than a call or invoke instruction, - // we can't change it! - if (!Call || !CS.isCallee(FnUseI)) - return false; - CallSite::arg_iterator AI = CS.arg_begin(); - Value *FirstArg = *AI; - - if (!isa(FirstArg)) - return false; - - // Check FirstArg's users. - for (Value::use_iterator ArgI = FirstArg->use_begin(), - ArgE = FirstArg->use_end(); ArgI != ArgE; ++ArgI) { - User *U = *ArgI; - // If FirstArg user is a CallInst that does not correspond to current - // call site then this function F is not suitable for sret promotion. - if (CallInst *CI = dyn_cast(U)) { - if (CI != Call) - return false; - } - // If FirstArg user is a GEP whose all users are not LoadInst then - // this function F is not suitable for sret promotion. - else if (GetElementPtrInst *GEP = dyn_cast(U)) { - // TODO : Use dom info and insert PHINodes to collect get results - // from multiple call sites for this GEP. - if (GEP->getParent() != Call->getParent()) - return false; - for (Value::use_iterator GEPI = GEP->use_begin(), GEPE = GEP->use_end(); - GEPI != GEPE; ++GEPI) - if (!isa(*GEPI)) - return false; - } - // Any other FirstArg users make this function unsuitable for sret - // promotion. - else - return false; - } - } - - return true; -} - -/// cloneFunctionBody - Create a new function based on F and -/// insert it into module. Remove first argument. Use STy as -/// the return type for new function. -Function *SRETPromotion::cloneFunctionBody(Function *F, - const StructType *STy) { - - const FunctionType *FTy = F->getFunctionType(); - std::vector Params; - - // Attributes - Keep track of the parameter attributes for the arguments. - SmallVector AttributesVec; - const AttrListPtr &PAL = F->getAttributes(); - - // Add any return attributes. - if (Attributes attrs = PAL.getRetAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); - - // Skip first argument. - Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); - ++I; - // 0th parameter attribute is reserved for return type. - // 1th parameter attribute is for first 1st sret argument. - unsigned ParamIndex = 2; - while (I != E) { - Params.push_back(I->getType()); - if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) - AttributesVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); - ++I; - ++ParamIndex; - } - - // Add any fn attributes. - if (Attributes attrs = PAL.getFnAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); - - - FunctionType *NFTy = FunctionType::get(STy, Params, FTy->isVarArg()); - Function *NF = Function::Create(NFTy, F->getLinkage()); - NF->takeName(F); - NF->copyAttributesFrom(F); - NF->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); - F->getParent()->getFunctionList().insert(F, NF); - NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); - - // Replace arguments - I = F->arg_begin(); - E = F->arg_end(); - Function::arg_iterator NI = NF->arg_begin(); - ++I; - while (I != E) { - I->replaceAllUsesWith(NI); - NI->takeName(I); - ++I; - ++NI; - } - - return NF; -} - -/// updateCallSites - Update all sites that call F to use NF. -CallGraphNode *SRETPromotion::updateCallSites(Function *F, Function *NF) { - CallGraph &CG = getAnalysis(); - SmallVector Args; - - // Attributes - Keep track of the parameter attributes for the arguments. - SmallVector ArgAttrsVec; - - // Get a new callgraph node for NF. - CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF); - - while (!F->use_empty()) { - CallSite CS(*F->use_begin()); - Instruction *Call = CS.getInstruction(); - - const AttrListPtr &PAL = F->getAttributes(); - // Add any return attributes. - if (Attributes attrs = PAL.getRetAttributes()) - ArgAttrsVec.push_back(AttributeWithIndex::get(0, attrs)); - - // Copy arguments, however skip first one. - CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); - Value *FirstCArg = *AI; - ++AI; - // 0th parameter attribute is reserved for return type. - // 1th parameter attribute is for first 1st sret argument. - unsigned ParamIndex = 2; - while (AI != AE) { - Args.push_back(*AI); - if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) - ArgAttrsVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); - ++ParamIndex; - ++AI; - } - - // Add any function attributes. - if (Attributes attrs = PAL.getFnAttributes()) - ArgAttrsVec.push_back(AttributeWithIndex::get(~0, attrs)); - - AttrListPtr NewPAL = AttrListPtr::get(ArgAttrsVec.begin(), ArgAttrsVec.end()); - - // Build new call instruction. - Instruction *New; - if (InvokeInst *II = dyn_cast(Call)) { - New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), - Args.begin(), Args.end(), "", Call); - cast(New)->setCallingConv(CS.getCallingConv()); - cast(New)->setAttributes(NewPAL); - } else { - New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); - cast(New)->setCallingConv(CS.getCallingConv()); - cast(New)->setAttributes(NewPAL); - if (cast(Call)->isTailCall()) - cast(New)->setTailCall(); - } - Args.clear(); - ArgAttrsVec.clear(); - New->takeName(Call); - - // Update the callgraph to know that the callsite has been transformed. - CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()]; - CalleeNode->removeCallEdgeFor(Call); - CalleeNode->addCalledFunction(New, NF_CGN); - - // Update all users of sret parameter to extract value using extractvalue. - for (Value::use_iterator UI = FirstCArg->use_begin(), - UE = FirstCArg->use_end(); UI != UE; ) { - User *U2 = *UI++; - CallInst *C2 = dyn_cast(U2); - if (C2 && (C2 == Call)) - continue; - - GetElementPtrInst *UGEP = cast(U2); - ConstantInt *Idx = cast(UGEP->getOperand(2)); - Value *GR = ExtractValueInst::Create(New, Idx->getZExtValue(), - "evi", UGEP); - while(!UGEP->use_empty()) { - // isSafeToUpdateAllCallers has checked that all GEP uses are - // LoadInsts - LoadInst *L = cast(*UGEP->use_begin()); - L->replaceAllUsesWith(GR); - L->eraseFromParent(); - } - UGEP->eraseFromParent(); - continue; - } - Call->eraseFromParent(); - } - - return NF_CGN; -} - diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombine.h b/contrib/llvm/lib/Transforms/InstCombine/InstCombine.h index 9c2969c7ab22..9c70cf89e48c 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombine.h +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombine.h @@ -11,6 +11,7 @@ #define INSTCOMBINE_INSTCOMBINE_H #include "InstCombineWorklist.h" +#include "llvm/Operator.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/IRBuilder.h" @@ -69,7 +70,6 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner : public FunctionPass, public InstVisitor { TargetData *TD; - bool MustPreserveLCSSA; bool MadeIRChange; public: /// Worklist - All of the instructions that need to be simplified. @@ -217,8 +217,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner Instruction *transformCallThroughTrampoline(CallSite CS); Instruction *transformZExtICmp(ICmpInst *ICI, Instruction &CI, bool DoXform = true); + Instruction *transformSExtICmp(ICmpInst *ICI, Instruction &CI); bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS); - DbgDeclareInst *hasOneUsePlusDeclare(Value *V); Value *EmitGEPOffset(User *GEP); public: @@ -247,7 +247,10 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner // segment of unreachable code, so just clobber the instruction. if (&I == V) V = UndefValue::get(I.getType()); - + + DEBUG(errs() << "IC: Replacing " << I << "\n" + " with " << *V << '\n'); + I.replaceAllUsesWith(V); return &I; } diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 7986d1aca762..a08446e5d519 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -14,6 +14,7 @@ #include "InstCombine.h" #include "llvm/Intrinsics.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Support/ConstantRange.h" #include "llvm/Support/PatternMatch.h" using namespace llvm; using namespace PatternMatch; @@ -330,7 +331,7 @@ Instruction *InstCombiner::OptAndOp(Instruction *Op, /// InsertRangeTest - Emit a computation of: (V >= Lo && V < Hi) if Inside is -/// true, otherwise (V < Lo || V >= Hi). In pratice, we emit the more efficient +/// true, otherwise (V < Lo || V >= Hi). In practice, we emit the more efficient /// (V-Lo) CreateOr(Val, Val2); return Builder->CreateICmp(LHSCC, NewOr, LHSCst); } + + // (icmp slt A, 0) & (icmp slt B, 0) --> (icmp slt (A&B), 0) + if (LHSCC == ICmpInst::ICMP_SLT && LHSCst->isZero()) { + Value *NewAnd = Builder->CreateAnd(Val, Val2); + return Builder->CreateICmp(LHSCC, NewAnd, LHSCst); + } + + // (icmp sgt A, -1) & (icmp sgt B, -1) --> (icmp sgt (A|B), -1) + if (LHSCC == ICmpInst::ICMP_SGT && LHSCst->isAllOnesValue()) { + Value *NewOr = Builder->CreateOr(Val, Val2); + return Builder->CreateICmp(LHSCC, NewOr, LHSCst); + } + } + + // (trunc x) == C1 & (and x, CA) == C2 -> (and x, CA|CMAX) == C1|C2 + // where CMAX is the all ones value for the truncated type, + // iff the lower bits of C2 and CA are zero. + if (LHSCC == RHSCC && ICmpInst::isEquality(LHSCC) && + LHS->hasOneUse() && RHS->hasOneUse()) { + Value *V; + ConstantInt *AndCst, *SmallCst = 0, *BigCst = 0; + + // (trunc x) == C1 & (and x, CA) == C2 + if (match(Val2, m_Trunc(m_Value(V))) && + match(Val, m_And(m_Specific(V), m_ConstantInt(AndCst)))) { + SmallCst = RHSCst; + BigCst = LHSCst; + } + // (and x, CA) == C2 & (trunc x) == C1 + else if (match(Val, m_Trunc(m_Value(V))) && + match(Val2, m_And(m_Specific(V), m_ConstantInt(AndCst)))) { + SmallCst = LHSCst; + BigCst = RHSCst; + } + + if (SmallCst && BigCst) { + unsigned BigBitSize = BigCst->getType()->getBitWidth(); + unsigned SmallBitSize = SmallCst->getType()->getBitWidth(); + + // Check that the low bits are zero. + APInt Low = APInt::getLowBitsSet(BigBitSize, SmallBitSize); + if ((Low & AndCst->getValue()) == 0 && (Low & BigCst->getValue()) == 0) { + Value *NewAnd = Builder->CreateAnd(V, Low | AndCst->getValue()); + APInt N = SmallCst->getValue().zext(BigBitSize) | BigCst->getValue(); + Value *NewVal = ConstantInt::get(AndCst->getType()->getContext(), N); + return Builder->CreateICmp(LHSCC, NewAnd, NewVal); + } + } } // From here on, we only handle: @@ -767,7 +816,17 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) { LHSCC == ICmpInst::ICMP_SGE || LHSCC == ICmpInst::ICMP_SLE || RHSCC == ICmpInst::ICMP_SGE || RHSCC == ICmpInst::ICMP_SLE) return 0; - + + // Make a constant range that's the intersection of the two icmp ranges. + // If the intersection is empty, we know that the result is false. + ConstantRange LHSRange = + ConstantRange::makeICmpRegion(LHSCC, LHSCst->getValue()); + ConstantRange RHSRange = + ConstantRange::makeICmpRegion(RHSCC, RHSCst->getValue()); + + if (LHSRange.intersectWith(RHSRange).isEmptySet()) + return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0); + // We can't fold (ugt x, C) & (sgt x, C2). if (!PredicatesFoldable(LHSCC, RHSCC)) return 0; @@ -800,10 +859,6 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) { case ICmpInst::ICMP_EQ: switch (RHSCC) { default: llvm_unreachable("Unknown integer condition code!"); - case ICmpInst::ICMP_EQ: // (X == 13 & X == 15) -> false - case ICmpInst::ICMP_UGT: // (X == 13 & X > 15) -> false - case ICmpInst::ICMP_SGT: // (X == 13 & X > 15) -> false - return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0); case ICmpInst::ICMP_NE: // (X == 13 & X != 15) -> X == 13 case ICmpInst::ICMP_ULT: // (X == 13 & X < 15) -> X == 13 case ICmpInst::ICMP_SLT: // (X == 13 & X < 15) -> X == 13 @@ -851,9 +906,6 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) { case ICmpInst::ICMP_SLT: switch (RHSCC) { default: llvm_unreachable("Unknown integer condition code!"); - case ICmpInst::ICMP_EQ: // (X s< 13 & X == 15) -> false - case ICmpInst::ICMP_SGT: // (X s< 13 & X s> 15) -> false - return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0); case ICmpInst::ICMP_UGT: // (X s< 13 & X u> 15) -> no change break; case ICmpInst::ICMP_NE: // (X s< 13 & X != 15) -> X < 13 @@ -1438,6 +1490,18 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS) { Value *NewOr = Builder->CreateOr(Val, Val2); return Builder->CreateICmp(LHSCC, NewOr, LHSCst); } + + // (icmp slt A, 0) | (icmp slt B, 0) --> (icmp slt (A|B), 0) + if (LHSCC == ICmpInst::ICMP_SLT && LHSCst->isZero()) { + Value *NewOr = Builder->CreateOr(Val, Val2); + return Builder->CreateICmp(LHSCC, NewOr, LHSCst); + } + + // (icmp sgt A, -1) | (icmp sgt B, -1) --> (icmp sgt (A&B), -1) + if (LHSCC == ICmpInst::ICMP_SGT && LHSCst->isAllOnesValue()) { + Value *NewAnd = Builder->CreateAnd(Val, Val2); + return Builder->CreateICmp(LHSCC, NewAnd, LHSCst); + } } // (icmp ult (X + CA), C1) | (icmp eq X, C2) -> (icmp ule (X + CA), C1) @@ -1975,7 +2039,14 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { } } } - + + // or(sext(A), B) -> A ? -1 : B where A is an i1 + // or(A, sext(B)) -> B ? -1 : A where B is an i1 + if (match(Op0, m_SExt(m_Value(A))) && A->getType()->isIntegerTy(1)) + return SelectInst::Create(A, ConstantInt::getSigned(I.getType(), -1), Op1); + if (match(Op1, m_SExt(m_Value(A))) && A->getType()->isIntegerTy(1)) + return SelectInst::Create(A, ConstantInt::getSigned(I.getType(), -1), Op0); + // Note: If we've gotten to the point of visiting the outer OR, then the // inner one couldn't be simplified. If it was a constant, then it won't // be simplified by a later pass either, so we try swapping the inner/outer diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 0e464507a7e4..726105f75d6f 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -475,7 +475,36 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { } } break; - case Intrinsic::umul_with_overflow: + case Intrinsic::umul_with_overflow: { + Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1); + unsigned BitWidth = cast(LHS->getType())->getBitWidth(); + APInt Mask = APInt::getAllOnesValue(BitWidth); + + APInt LHSKnownZero(BitWidth, 0); + APInt LHSKnownOne(BitWidth, 0); + ComputeMaskedBits(LHS, Mask, LHSKnownZero, LHSKnownOne); + APInt RHSKnownZero(BitWidth, 0); + APInt RHSKnownOne(BitWidth, 0); + ComputeMaskedBits(RHS, Mask, RHSKnownZero, RHSKnownOne); + + // Get the largest possible values for each operand. + APInt LHSMax = ~LHSKnownZero; + APInt RHSMax = ~RHSKnownZero; + + // If multiplying the maximum values does not overflow then we can turn + // this into a plain NUW mul. + bool Overflow; + LHSMax.umul_ov(RHSMax, Overflow); + if (!Overflow) { + Value *Mul = Builder->CreateNUWMul(LHS, RHS, "umul_with_overflow"); + Constant *V[] = { + UndefValue::get(LHS->getType()), + Builder->getFalse() + }; + Constant *Struct = ConstantStruct::get(II->getContext(), V, 2, false); + return InsertValueInst::Create(Struct, Mul, 0); + } + } // FALL THROUGH case Intrinsic::smul_with_overflow: // Canonicalize constants into the RHS. if (isa(II->getArgOperand(0)) && @@ -508,11 +537,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { break; case Intrinsic::ppc_altivec_lvx: case Intrinsic::ppc_altivec_lvxl: - case Intrinsic::x86_sse_loadu_ps: - case Intrinsic::x86_sse2_loadu_pd: - case Intrinsic::x86_sse2_loadu_dq: - // Turn PPC lvx -> load if the pointer is known aligned. - // Turn X86 loadups -> load if the pointer is known aligned. + // Turn PPC lvx -> load if the pointer is known aligned. if (getOrEnforceKnownAlignment(II->getArgOperand(0), 16, TD) >= 16) { Value *Ptr = Builder->CreateBitCast(II->getArgOperand(0), PointerType::getUnqual(II->getType())); @@ -731,9 +756,13 @@ class InstCombineFortifiedLibCalls : public SimplifyFortifiedLibCalls { dyn_cast(CI->getArgOperand(SizeCIOp))) { if (SizeCI->isAllOnesValue()) return true; - if (isString) - return SizeCI->getZExtValue() >= - GetStringLength(CI->getArgOperand(SizeArgOp)); + if (isString) { + uint64_t Len = GetStringLength(CI->getArgOperand(SizeArgOp)); + // If the length is 0 we don't know how long it is and so we can't + // remove the check. + if (Len == 0) return false; + return SizeCI->getZExtValue() >= Len; + } if (ConstantInt *Arg = dyn_cast( CI->getArgOperand(SizeArgOp))) return SizeCI->getZExtValue() >= Arg->getZExtValue(); diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index b432641a1403..6f70de865764 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -87,10 +87,8 @@ Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI, // If the allocation has multiple uses, only promote it if we are strictly // increasing the alignment of the resultant allocation. If we keep it the - // same, we open the door to infinite loops of various kinds. (A reference - // from a dbg.declare doesn't count as a use for this purpose.) - if (!AI.hasOneUse() && !hasOneUsePlusDeclare(&AI) && - CastElTyAlign == AllocElTyAlign) return 0; + // same, we open the door to infinite loops of various kinds. + if (!AI.hasOneUse() && CastElTyAlign == AllocElTyAlign) return 0; uint64_t AllocElTySize = TD->getTypeAllocSize(AllocElTy); uint64_t CastElTySize = TD->getTypeAllocSize(CastElTy); @@ -128,15 +126,10 @@ Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI, New->setAlignment(AI.getAlignment()); New->takeName(&AI); - // If the allocation has one real use plus a dbg.declare, just remove the - // declare. - if (DbgDeclareInst *DI = hasOneUsePlusDeclare(&AI)) { - EraseInstFromFunction(*(Instruction*)DI); - } // If the allocation has multiple real uses, insert a cast and change all // things that used it to use the new cast. This will also hack on CI, but it // will die soon. - else if (!AI.hasOneUse()) { + if (!AI.hasOneUse()) { // New is the allocation instruction, pointer typed. AI is the original // allocation instruction, also pointer typed. Thus, cast to use is BitCast. Value *NewCast = AllocaBuilder.CreateBitCast(New, AI.getType(), "tmpcast"); @@ -203,7 +196,7 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty, } case Instruction::PHI: { PHINode *OPN = cast(I); - PHINode *NPN = PHINode::Create(Ty); + PHINode *NPN = PHINode::Create(Ty, OPN->getNumIncomingValues()); for (unsigned i = 0, e = OPN->getNumIncomingValues(); i != e; ++i) { Value *V =EvaluateInDifferentType(OPN->getIncomingValue(i), Ty, isSigned); NPN->addIncoming(V, OPN->getIncomingBlock(i)); @@ -883,6 +876,102 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) { return 0; } +/// transformSExtICmp - Transform (sext icmp) to bitwise / integer operations +/// in order to eliminate the icmp. +Instruction *InstCombiner::transformSExtICmp(ICmpInst *ICI, Instruction &CI) { + Value *Op0 = ICI->getOperand(0), *Op1 = ICI->getOperand(1); + ICmpInst::Predicate Pred = ICI->getPredicate(); + + if (ConstantInt *Op1C = dyn_cast(Op1)) { + // (x ashr x, 31 -> all ones if negative + // (x >s -1) ? -1 : 0 -> not (ashr x, 31) -> all ones if positive + if ((Pred == ICmpInst::ICMP_SLT && Op1C->isZero()) || + (Pred == ICmpInst::ICMP_SGT && Op1C->isAllOnesValue())) { + + Value *Sh = ConstantInt::get(Op0->getType(), + Op0->getType()->getScalarSizeInBits()-1); + Value *In = Builder->CreateAShr(Op0, Sh, Op0->getName()+".lobit"); + if (In->getType() != CI.getType()) + In = Builder->CreateIntCast(In, CI.getType(), true/*SExt*/, "tmp"); + + if (Pred == ICmpInst::ICMP_SGT) + In = Builder->CreateNot(In, In->getName()+".not"); + return ReplaceInstUsesWith(CI, In); + } + + // If we know that only one bit of the LHS of the icmp can be set and we + // have an equality comparison with zero or a power of 2, we can transform + // the icmp and sext into bitwise/integer operations. + if (ICI->hasOneUse() && + ICI->isEquality() && (Op1C->isZero() || Op1C->getValue().isPowerOf2())){ + unsigned BitWidth = Op1C->getType()->getBitWidth(); + APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + APInt TypeMask(APInt::getAllOnesValue(BitWidth)); + ComputeMaskedBits(Op0, TypeMask, KnownZero, KnownOne); + + APInt KnownZeroMask(~KnownZero); + if (KnownZeroMask.isPowerOf2()) { + Value *In = ICI->getOperand(0); + + // If the icmp tests for a known zero bit we can constant fold it. + if (!Op1C->isZero() && Op1C->getValue() != KnownZeroMask) { + Value *V = Pred == ICmpInst::ICMP_NE ? + ConstantInt::getAllOnesValue(CI.getType()) : + ConstantInt::getNullValue(CI.getType()); + return ReplaceInstUsesWith(CI, V); + } + + if (!Op1C->isZero() == (Pred == ICmpInst::ICMP_NE)) { + // sext ((x & 2^n) == 0) -> (x >> n) - 1 + // sext ((x & 2^n) != 2^n) -> (x >> n) - 1 + unsigned ShiftAmt = KnownZeroMask.countTrailingZeros(); + // Perform a right shift to place the desired bit in the LSB. + if (ShiftAmt) + In = Builder->CreateLShr(In, + ConstantInt::get(In->getType(), ShiftAmt)); + + // At this point "In" is either 1 or 0. Subtract 1 to turn + // {1, 0} -> {0, -1}. + In = Builder->CreateAdd(In, + ConstantInt::getAllOnesValue(In->getType()), + "sext"); + } else { + // sext ((x & 2^n) != 0) -> (x << bitwidth-n) a>> bitwidth-1 + // sext ((x & 2^n) == 2^n) -> (x << bitwidth-n) a>> bitwidth-1 + unsigned ShiftAmt = KnownZeroMask.countLeadingZeros(); + // Perform a left shift to place the desired bit in the MSB. + if (ShiftAmt) + In = Builder->CreateShl(In, + ConstantInt::get(In->getType(), ShiftAmt)); + + // Distribute the bit over the whole bit width. + In = Builder->CreateAShr(In, ConstantInt::get(In->getType(), + BitWidth - 1), "sext"); + } + + if (CI.getType() == In->getType()) + return ReplaceInstUsesWith(CI, In); + return CastInst::CreateIntegerCast(In, CI.getType(), true/*SExt*/); + } + } + } + + // vector (x ashr x, 31 -> all ones if signed. + if (const VectorType *VTy = dyn_cast(CI.getType())) { + if (Pred == ICmpInst::ICMP_SLT && match(Op1, m_Zero()) && + Op0->getType() == CI.getType()) { + const Type *EltTy = VTy->getElementType(); + + // splat the shift constant to a constant vector. + Constant *VSh = ConstantInt::get(VTy, EltTy->getScalarSizeInBits()-1); + Value *In = Builder->CreateAShr(Op0, VSh, Op0->getName()+".lobit"); + return ReplaceInstUsesWith(CI, In); + } + } + + return 0; +} + /// CanEvaluateSExtd - Return true if we can take the specified value /// and return it as type Ty without inserting any new casts and without /// changing the value of the common low bits. This is used by code that tries @@ -1006,44 +1095,9 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) { Value *Res = Builder->CreateShl(TI->getOperand(0), ShAmt, "sext"); return BinaryOperator::CreateAShr(Res, ShAmt); } - - - // (x ashr x, 31 -> all ones if signed - // (x >s -1) ? -1 : 0 -> ashr x, 31 -> all ones if not signed - { - ICmpInst::Predicate Pred; Value *CmpLHS; ConstantInt *CmpRHS; - if (match(Src, m_ICmp(Pred, m_Value(CmpLHS), m_ConstantInt(CmpRHS)))) { - // sext (x x>>s31 true if signbit set. - // sext (x >s -1) to i32 --> (x>>s31)^-1 true if signbit clear. - if ((Pred == ICmpInst::ICMP_SLT && CmpRHS->isZero()) || - (Pred == ICmpInst::ICMP_SGT && CmpRHS->isAllOnesValue())) { - Value *Sh = ConstantInt::get(CmpLHS->getType(), - CmpLHS->getType()->getScalarSizeInBits()-1); - Value *In = Builder->CreateAShr(CmpLHS, Sh, CmpLHS->getName()+".lobit"); - if (In->getType() != CI.getType()) - In = Builder->CreateIntCast(In, CI.getType(), true/*SExt*/, "tmp"); - - if (Pred == ICmpInst::ICMP_SGT) - In = Builder->CreateNot(In, In->getName()+".not"); - return ReplaceInstUsesWith(CI, In); - } - } - } - // vector (x ashr x, 31 -> all ones if signed. - if (const VectorType *VTy = dyn_cast(DestTy)) { - ICmpInst::Predicate Pred; Value *CmpLHS; - if (match(Src, m_ICmp(Pred, m_Value(CmpLHS), m_Zero()))) { - if (Pred == ICmpInst::ICMP_SLT && CmpLHS->getType() == DestTy) { - const Type *EltTy = VTy->getElementType(); - - // splat the shift constant to a constant vector. - Constant *VSh = ConstantInt::get(VTy, EltTy->getScalarSizeInBits()-1); - Value *In = Builder->CreateAShr(CmpLHS, VSh,CmpLHS->getName()+".lobit"); - return ReplaceInstUsesWith(CI, In); - } - } - } + if (ICmpInst *ICI = dyn_cast(Src)) + return transformSExtICmp(ICI, CI); // If the input is a shl/ashr pair of a same constant, then this is a sign // extension from a smaller value. If we could trust arbitrary bitwidth diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 999de3409750..bb9b88bfe6a7 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -699,7 +699,7 @@ Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI, return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(X->getContext())); // From this point on, we know that (X+C <= X) --> (X+C < X) because C != 0, - // so the values can never be equal. Similiarly for all other "or equals" + // so the values can never be equal. Similarly for all other "or equals" // operators. // (X+1) X >u (MAXUINT-1) --> X == 255 @@ -1289,13 +1289,21 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, } case Instruction::LShr: // (icmp pred (shr X, ShAmt), CI) - case Instruction::AShr: - // Only handle equality comparisons of shift-by-constant. - if (ConstantInt *ShAmt = dyn_cast(LHSI->getOperand(1))) - if (Instruction *Res = FoldICmpShrCst(ICI, cast(LHSI), - ShAmt)) + case Instruction::AShr: { + // Handle equality comparisons of shift-by-constant. + BinaryOperator *BO = cast(LHSI); + if (ConstantInt *ShAmt = dyn_cast(LHSI->getOperand(1))) { + if (Instruction *Res = FoldICmpShrCst(ICI, BO, ShAmt)) return Res; + } + + // Handle exact shr's. + if (ICI.isEquality() && BO->isExact() && BO->hasOneUse()) { + if (RHSV.isMinValue()) + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), RHS); + } break; + } case Instruction::SDiv: case Instruction::UDiv: @@ -1376,9 +1384,9 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, if (Value *NegVal = dyn_castNegVal(BOp1)) return new ICmpInst(ICI.getPredicate(), BOp0, NegVal); - else if (Value *NegVal = dyn_castNegVal(BOp0)) + if (Value *NegVal = dyn_castNegVal(BOp0)) return new ICmpInst(ICI.getPredicate(), NegVal, BOp1); - else if (BO->hasOneUse()) { + if (BO->hasOneUse()) { Value *Neg = Builder->CreateNeg(BOp1); Neg->takeName(BO); return new ICmpInst(ICI.getPredicate(), BOp0, Neg); @@ -1855,11 +1863,11 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { return new ICmpInst(ICmpInst::ICMP_SLT, Op0, ConstantInt::get(CI->getContext(), CI->getValue()+1)); case ICmpInst::ICMP_UGE: - assert(!CI->isMinValue(false)); // A >=u MIN -> TRUE + assert(!CI->isMinValue(false)); // A >=u MIN -> TRUE return new ICmpInst(ICmpInst::ICMP_UGT, Op0, ConstantInt::get(CI->getContext(), CI->getValue()-1)); case ICmpInst::ICMP_SGE: - assert(!CI->isMinValue(true)); // A >=s MIN -> TRUE + assert(!CI->isMinValue(true)); // A >=s MIN -> TRUE return new ICmpInst(ICmpInst::ICMP_SGT, Op0, ConstantInt::get(CI->getContext(), CI->getValue()-1)); } @@ -1907,18 +1915,18 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { // that code below can assume that Min != Max. if (!isa(Op0) && Op0Min == Op0Max) return new ICmpInst(I.getPredicate(), - ConstantInt::get(I.getContext(), Op0Min), Op1); + ConstantInt::get(Op0->getType(), Op0Min), Op1); if (!isa(Op1) && Op1Min == Op1Max) return new ICmpInst(I.getPredicate(), Op0, - ConstantInt::get(I.getContext(), Op1Min)); + ConstantInt::get(Op1->getType(), Op1Min)); // Based on the range information we know about the LHS, see if we can - // simplify this comparison. For example, (x&4) < 8 is always true. + // simplify this comparison. For example, (x&4) < 8 is always true. switch (I.getPredicate()) { default: llvm_unreachable("Unknown icmp opcode!"); case ICmpInst::ICMP_EQ: { if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); // If all bits are known zero except for one, then we know at most one // bit is set. If the comparison is against zero, then this is a check @@ -1955,7 +1963,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { } case ICmpInst::ICMP_NE: { if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max)) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); // If all bits are known zero except for one, then we know at most one // bit is set. If the comparison is against zero, then this is a check @@ -1992,9 +2000,9 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { } case ICmpInst::ICMP_ULT: if (Op0Max.ult(Op1Min)) // A true if max(A) < min(B) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); if (Op0Min.uge(Op1Max)) // A false if min(A) >= max(B) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); if (Op1Min == Op0Max) // A A != B if max(A) == min(B) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); if (ConstantInt *CI = dyn_cast(Op1)) { @@ -2010,9 +2018,9 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { break; case ICmpInst::ICMP_UGT: if (Op0Min.ugt(Op1Max)) // A >u B -> true if min(A) > max(B) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); if (Op0Max.ule(Op1Min)) // A >u B -> false if max(A) <= max(B) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); if (Op1Max == Op0Min) // A >u B -> A != B if min(A) == max(B) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); @@ -2029,9 +2037,9 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { break; case ICmpInst::ICMP_SLT: if (Op0Max.slt(Op1Min)) // A true if max(A) < min(C) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); if (Op0Min.sge(Op1Max)) // A false if min(A) >= max(C) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); if (Op1Min == Op0Max) // A A != B if max(A) == min(B) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); if (ConstantInt *CI = dyn_cast(Op1)) { @@ -2042,9 +2050,9 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { break; case ICmpInst::ICMP_SGT: if (Op0Min.sgt(Op1Max)) // A >s B -> true if min(A) > max(B) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); if (Op0Max.sle(Op1Min)) // A >s B -> false if max(A) <= min(B) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); if (Op1Max == Op0Min) // A >s B -> A != B if min(A) == max(B) return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1); @@ -2057,30 +2065,30 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { case ICmpInst::ICMP_SGE: assert(!isa(Op1) && "ICMP_SGE with ConstantInt not folded!"); if (Op0Min.sge(Op1Max)) // A >=s B -> true if min(A) >= max(B) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); if (Op0Max.slt(Op1Min)) // A >=s B -> false if max(A) < min(B) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); break; case ICmpInst::ICMP_SLE: assert(!isa(Op1) && "ICMP_SLE with ConstantInt not folded!"); if (Op0Max.sle(Op1Min)) // A <=s B -> true if max(A) <= min(B) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); if (Op0Min.sgt(Op1Max)) // A <=s B -> false if min(A) > max(B) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); break; case ICmpInst::ICMP_UGE: assert(!isa(Op1) && "ICMP_UGE with ConstantInt not folded!"); if (Op0Min.uge(Op1Max)) // A >=u B -> true if min(A) >= max(B) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); if (Op0Max.ult(Op1Min)) // A >=u B -> false if max(A) < min(B) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); break; case ICmpInst::ICMP_ULE: assert(!isa(Op1) && "ICMP_ULE with ConstantInt not folded!"); if (Op0Max.ule(Op1Min)) // A <=u B -> true if max(A) <= min(B) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); if (Op0Min.ugt(Op1Max)) // A <=u B -> false if min(A) > max(B) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); break; } @@ -2306,6 +2314,35 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { BO0->hasOneUse() && BO1->hasOneUse()) return new ICmpInst(Pred, D, B); + BinaryOperator *SRem = NULL; + // icmp (srem X, Y), Y + if (BO0 && BO0->getOpcode() == Instruction::SRem && + Op1 == BO0->getOperand(1)) + SRem = BO0; + // icmp Y, (srem X, Y) + else if (BO1 && BO1->getOpcode() == Instruction::SRem && + Op0 == BO1->getOperand(1)) + SRem = BO1; + if (SRem) { + // We don't check hasOneUse to avoid increasing register pressure because + // the value we use is the same value this instruction was already using. + switch (SRem == BO0 ? ICmpInst::getSwappedPredicate(Pred) : Pred) { + default: break; + case ICmpInst::ICMP_EQ: + return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType())); + case ICmpInst::ICMP_NE: + return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType())); + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + return new ICmpInst(ICmpInst::ICMP_SGT, SRem->getOperand(1), + Constant::getAllOnesValue(SRem->getType())); + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + return new ICmpInst(ICmpInst::ICMP_SLT, SRem->getOperand(1), + Constant::getNullValue(SRem->getType())); + } + } + if (BO0 && BO1 && BO0->getOpcode() == BO1->getOpcode() && BO0->hasOneUse() && BO1->hasOneUse() && BO0->getOperand(1) == BO1->getOperand(1)) { @@ -2356,6 +2393,27 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { } } break; + case Instruction::UDiv: + case Instruction::LShr: + if (I.isSigned()) + break; + // fall-through + case Instruction::SDiv: + case Instruction::AShr: + if (!BO0->isExact() && !BO1->isExact()) + break; + return new ICmpInst(I.getPredicate(), BO0->getOperand(0), + BO1->getOperand(0)); + case Instruction::Shl: { + bool NUW = BO0->hasNoUnsignedWrap() && BO1->hasNoUnsignedWrap(); + bool NSW = BO0->hasNoSignedWrap() && BO1->hasNoSignedWrap(); + if (!NUW && !NSW) + break; + if (!NSW && I.isSigned()) + break; + return new ICmpInst(I.getPredicate(), BO0->getOperand(0), + BO1->getOperand(0)); + } } } } @@ -2425,9 +2483,8 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { } // (X&Z) == (Y&Z) -> (X^Y) & Z == 0 - if (Op0->hasOneUse() && Op1->hasOneUse() && - match(Op0, m_And(m_Value(A), m_Value(B))) && - match(Op1, m_And(m_Value(C), m_Value(D)))) { + if (match(Op0, m_OneUse(m_And(m_Value(A), m_Value(B)))) && + match(Op1, m_OneUse(m_And(m_Value(C), m_Value(D))))) { Value *X = 0, *Y = 0, *Z = 0; if (A == C) { @@ -2448,6 +2505,32 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { return &I; } } + + // Transform "icmp eq (trunc (lshr(X, cst1)), cst" to + // "icmp (and X, mask), cst" + uint64_t ShAmt = 0; + ConstantInt *Cst1; + if (Op0->hasOneUse() && + match(Op0, m_Trunc(m_OneUse(m_LShr(m_Value(A), + m_ConstantInt(ShAmt))))) && + match(Op1, m_ConstantInt(Cst1)) && + // Only do this when A has multiple uses. This is most important to do + // when it exposes other optimizations. + !A->hasOneUse()) { + unsigned ASize =cast(A->getType())->getPrimitiveSizeInBits(); + + if (ShAmt < ASize) { + APInt MaskV = + APInt::getLowBitsSet(ASize, Op0->getType()->getPrimitiveSizeInBits()); + MaskV <<= ShAmt; + + APInt CmpV = Cst1->getValue().zext(ASize); + CmpV <<= ShAmt; + + Value *Mask = Builder->CreateAnd(A, Builder->getInt(MaskV)); + return new ICmpInst(I.getPredicate(), Mask, Builder->getInt(CmpV)); + } + } } { @@ -2704,6 +2787,42 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) { if (Constant *RHSC = dyn_cast(Op1)) { if (Instruction *LHSI = dyn_cast(Op0)) switch (LHSI->getOpcode()) { + case Instruction::FPExt: { + // fcmp (fpext x), C -> fcmp x, (fptrunc C) if fptrunc is lossless + FPExtInst *LHSExt = cast(LHSI); + ConstantFP *RHSF = dyn_cast(RHSC); + if (!RHSF) + break; + + // We can't convert a PPC double double. + if (RHSF->getType()->isPPC_FP128Ty()) + break; + + const fltSemantics *Sem; + // FIXME: This shouldn't be here. + if (LHSExt->getSrcTy()->isFloatTy()) + Sem = &APFloat::IEEEsingle; + else if (LHSExt->getSrcTy()->isDoubleTy()) + Sem = &APFloat::IEEEdouble; + else if (LHSExt->getSrcTy()->isFP128Ty()) + Sem = &APFloat::IEEEquad; + else if (LHSExt->getSrcTy()->isX86_FP80Ty()) + Sem = &APFloat::x87DoubleExtended; + else + break; + + bool Lossy; + APFloat F = RHSF->getValueAPF(); + F.convert(*Sem, APFloat::rmNearestTiesToEven, &Lossy); + + // Avoid lossy conversions and denormals. + if (!Lossy && + F.compare(APFloat::getSmallestNormalized(*Sem)) != + APFloat::cmpLessThan) + return new FCmpInst(I.getPredicate(), LHSExt->getOperand(0), + ConstantFP::get(RHSC->getContext(), F)); + break; + } case Instruction::PHI: // Only fold fcmp into the PHI if the phi and fcmp are in the same // block. If in the same block, we're encouraging jump threading. If @@ -2742,6 +2861,14 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) { return SelectInst::Create(LHSI->getOperand(0), Op1, Op2); break; } + case Instruction::FSub: { + // fcmp pred (fneg x), C -> fcmp swap(pred) x, -C + Value *Op; + if (match(LHSI, m_FNeg(m_Value(Op)))) + return new FCmpInst(I.getSwappedPredicate(), Op, + ConstantExpr::getFNeg(RHSC)); + break; + } case Instruction::Load: if (GetElementPtrInst *GEP = dyn_cast(LHSI->getOperand(0))) { @@ -2755,5 +2882,17 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) { } } + // fcmp pred (fneg x), (fneg y) -> fcmp swap(pred) x, y + Value *X, *Y; + if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_FNeg(m_Value(Y)))) + return new FCmpInst(I.getSwappedPredicate(), X, Y); + + // fcmp (fpext x), (fpext y) -> fcmp x, y + if (FPExtInst *LHSExt = dyn_cast(Op0)) + if (FPExtInst *RHSExt = dyn_cast(Op1)) + if (LHSExt->getSrcTy() == RHSExt->getSrcTy()) + return new FCmpInst(I.getPredicate(), LHSExt->getOperand(0), + RHSExt->getOperand(0)); + return Changed ? &I : 0; } diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 78ff7346abe4..432adc9d046d 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -364,34 +364,12 @@ static bool equivalentAddressValues(Value *A, Value *B) { return false; } -// If this instruction has two uses, one of which is a llvm.dbg.declare, -// return the llvm.dbg.declare. -DbgDeclareInst *InstCombiner::hasOneUsePlusDeclare(Value *V) { - if (!V->hasNUses(2)) - return 0; - for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); - UI != E; ++UI) { - User *U = *UI; - if (DbgDeclareInst *DI = dyn_cast(U)) - return DI; - if (isa(U) && U->hasOneUse()) { - if (DbgDeclareInst *DI = dyn_cast(*U->use_begin())) - return DI; - } - } - return 0; -} - Instruction *InstCombiner::visitStoreInst(StoreInst &SI) { Value *Val = SI.getOperand(0); Value *Ptr = SI.getOperand(1); // If the RHS is an alloca with a single use, zapify the store, making the // alloca dead. - // If the RHS is an alloca with a two uses, the other one being a - // llvm.dbg.declare, zapify the store and the declare, making the - // alloca dead. We must do this to prevent declares from affecting - // codegen. if (!SI.isVolatile()) { if (Ptr->hasOneUse()) { if (isa(Ptr)) @@ -400,17 +378,9 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) { if (isa(GEP->getOperand(0))) { if (GEP->getOperand(0)->hasOneUse()) return EraseInstFromFunction(SI); - if (DbgDeclareInst *DI = hasOneUsePlusDeclare(GEP->getOperand(0))) { - EraseInstFromFunction(*DI); - return EraseInstFromFunction(SI); - } } } } - if (DbgDeclareInst *DI = hasOneUsePlusDeclare(Ptr)) { - EraseInstFromFunction(*DI); - return EraseInstFromFunction(SI); - } } // Attempt to improve the alignment. @@ -621,8 +591,7 @@ bool InstCombiner::SimplifyStoreAtEndOfBlock(StoreInst &SI) { // Insert a PHI node now if we need it. Value *MergedVal = OtherStore->getOperand(0); if (MergedVal != SI.getOperand(0)) { - PHINode *PN = PHINode::Create(MergedVal->getType(), "storemerge"); - PN->reserveOperandSpace(2); + PHINode *PN = PHINode::Create(MergedVal->getType(), 2, "storemerge"); PN->addIncoming(SI.getOperand(0), SI.getParent()); PN->addIncoming(OtherStore->getOperand(0), OtherBB); MergedVal = InsertNewInstBefore(PN, DestBB->front()); diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index d1a1fd6ddfac..57fb08aca266 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -320,6 +320,10 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { } } + // See if we can fold away this div instruction. + if (SimplifyDemandedInstructionBits(I)) + return &I; + // (X - (X rem Y)) / Y -> X / Y; usually originates as ((X / Y) * Y) / Y Value *X = 0, *Z = 0; if (match(Op0, m_Sub(m_Value(X), m_Value(Z)))) { // (X - Z) / Y; Y = Op1 @@ -332,6 +336,19 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { return 0; } +/// dyn_castZExtVal - Checks if V is a zext or constant that can +/// be truncated to Ty without losing bits. +static Value *dyn_castZExtVal(Value *V, const Type *Ty) { + if (ZExtInst *Z = dyn_cast(V)) { + if (Z->getSrcTy() == Ty) + return Z->getOperand(0); + } else if (ConstantInt *C = dyn_cast(V)) { + if (C->getValue().getActiveBits() <= cast(Ty)->getBitWidth()) + return ConstantExpr::getTrunc(C, Ty); + } + return 0; +} + Instruction *InstCombiner::visitUDiv(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); @@ -390,6 +407,14 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) { return SelectInst::Create(Cond, TSI, FSI); } } + + // (zext A) udiv (zext B) --> zext (A udiv B) + if (ZExtInst *ZOp0 = dyn_cast(Op0)) + if (Value *ZOp1 = dyn_castZExtVal(Op1, ZOp0->getSrcTy())) + return new ZExtInst(Builder->CreateUDiv(ZOp0->getOperand(0), ZOp1, "div", + I.isExact()), + I.getType()); + return 0; } @@ -452,27 +477,17 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) { if (Value *V = SimplifyFDivInst(Op0, Op1, TD)) return ReplaceInstUsesWith(I, V); - return 0; -} + if (ConstantFP *Op1C = dyn_cast(Op1)) { + const APFloat &Op1F = Op1C->getValueAPF(); -/// This function implements the transforms on rem instructions that work -/// regardless of the kind of rem instruction it is (urem, srem, or frem). It -/// is used by the visitors to those instructions. -/// @brief Transforms common to all three rem instructions -Instruction *InstCombiner::commonRemTransforms(BinaryOperator &I) { - Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - - if (isa(Op0)) { // undef % X -> 0 - if (I.getType()->isFPOrFPVectorTy()) - return ReplaceInstUsesWith(I, Op0); // X % undef -> undef (could be SNaN) - return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + // If the divisor has an exact multiplicative inverse we can turn the fdiv + // into a cheaper fmul. + APFloat Reciprocal(Op1F.getSemantics()); + if (Op1F.getExactInverse(&Reciprocal)) { + ConstantFP *RFP = ConstantFP::get(Builder->getContext(), Reciprocal); + return BinaryOperator::CreateFMul(Op0, RFP); + } } - if (isa(Op1)) - return ReplaceInstUsesWith(I, Op1); // X % undef -> undef - - // Handle cases involving: rem X, (select Cond, Y, Z) - if (isa(Op1) && SimplifyDivRemOfSelect(I)) - return &I; return 0; } @@ -484,26 +499,11 @@ Instruction *InstCombiner::commonRemTransforms(BinaryOperator &I) { Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - if (Instruction *common = commonRemTransforms(I)) - return common; - - // X % X == 0 - if (Op0 == Op1) - return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); - - // 0 % X == 0 for integer, we don't need to preserve faults! - if (Constant *LHS = dyn_cast(Op0)) - if (LHS->isNullValue()) - return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + // Handle cases involving: rem X, (select Cond, Y, Z) + if (isa(Op1) && SimplifyDivRemOfSelect(I)) + return &I; if (ConstantInt *RHS = dyn_cast(Op1)) { - // X % 0 == undef, we don't need to preserve faults! - if (RHS->equalsInt(0)) - return ReplaceInstUsesWith(I, UndefValue::get(I.getType())); - - if (RHS->equalsInt(1)) // X % 1 == 0 - return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); - if (Instruction *Op0I = dyn_cast(Op0)) { if (SelectInst *SI = dyn_cast(Op0I)) { if (Instruction *R = FoldOpIntoSelect(I, SI)) @@ -525,6 +525,9 @@ Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) { Instruction *InstCombiner::visitURem(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + if (Value *V = SimplifyURemInst(Op0, Op1, TD)) + return ReplaceInstUsesWith(I, V); + if (Instruction *common = commonIRemTransforms(I)) return common; @@ -552,13 +555,22 @@ Instruction *InstCombiner::visitURem(BinaryOperator &I) { return SelectInst::Create(Cond, TrueAnd, FalseAnd); } } - + + // (zext A) urem (zext B) --> zext (A urem B) + if (ZExtInst *ZOp0 = dyn_cast(Op0)) + if (Value *ZOp1 = dyn_castZExtVal(Op1, ZOp0->getSrcTy())) + return new ZExtInst(Builder->CreateURem(ZOp0->getOperand(0), ZOp1), + I.getType()); + return 0; } Instruction *InstCombiner::visitSRem(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + if (Value *V = SimplifySRemInst(Op0, Op1, TD)) + return ReplaceInstUsesWith(I, V); + // Handle the integer rem common cases if (Instruction *Common = commonIRemTransforms(I)) return Common; @@ -617,6 +629,14 @@ Instruction *InstCombiner::visitSRem(BinaryOperator &I) { } Instruction *InstCombiner::visitFRem(BinaryOperator &I) { - return commonRemTransforms(I); -} + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + if (Value *V = SimplifyFRemInst(Op0, Op1, TD)) + return ReplaceInstUsesWith(I, V); + + // Handle cases involving: rem X, (select Cond, Y, Z) + if (isa(Op1) && SimplifyDivRemOfSelect(I)) + return &I; + + return 0; +} diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp index 297a18c40a97..abf61bbaf3a6 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -80,18 +80,16 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) { Value *InRHS = FirstInst->getOperand(1); PHINode *NewLHS = 0, *NewRHS = 0; if (LHSVal == 0) { - NewLHS = PHINode::Create(LHSType, + NewLHS = PHINode::Create(LHSType, PN.getNumIncomingValues(), FirstInst->getOperand(0)->getName() + ".pn"); - NewLHS->reserveOperandSpace(PN.getNumOperands()/2); NewLHS->addIncoming(InLHS, PN.getIncomingBlock(0)); InsertNewInstBefore(NewLHS, PN); LHSVal = NewLHS; } if (RHSVal == 0) { - NewRHS = PHINode::Create(RHSType, + NewRHS = PHINode::Create(RHSType, PN.getNumIncomingValues(), FirstInst->getOperand(1)->getName() + ".pn"); - NewRHS->reserveOperandSpace(PN.getNumOperands()/2); NewRHS->addIncoming(InRHS, PN.getIncomingBlock(0)); InsertNewInstBefore(NewRHS, PN); RHSVal = NewRHS; @@ -202,11 +200,10 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) { for (unsigned i = 0, e = FixedOperands.size(); i != e; ++i) { if (FixedOperands[i]) continue; // operand doesn't need a phi. Value *FirstOp = FirstInst->getOperand(i); - PHINode *NewPN = PHINode::Create(FirstOp->getType(), + PHINode *NewPN = PHINode::Create(FirstOp->getType(), e, FirstOp->getName()+".pn"); InsertNewInstBefore(NewPN, PN); - NewPN->reserveOperandSpace(e); NewPN->addIncoming(FirstOp, PN.getIncomingBlock(0)); OperandPhis[i] = NewPN; FixedOperands[i] = NewPN; @@ -240,7 +237,7 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) { /// obvious the value of the load is not changed from the point of the load to /// the end of the block it is in. /// -/// Finally, it is safe, but not profitable, to sink a load targetting a +/// Finally, it is safe, but not profitable, to sink a load targeting a /// non-address-taken alloca. Doing so will cause us to not promote the alloca /// to a register. static bool isSafeAndProfitableToSinkLoad(LoadInst *L) { @@ -340,8 +337,8 @@ Instruction *InstCombiner::FoldPHIArgLoadIntoPHI(PHINode &PN) { // Okay, they are all the same operation. Create a new PHI node of the // correct type, and PHI together all of the LHS's of the instructions. PHINode *NewPN = PHINode::Create(FirstLI->getOperand(0)->getType(), + PN.getNumIncomingValues(), PN.getName()+".in"); - NewPN->reserveOperandSpace(PN.getNumOperands()/2); Value *InVal = FirstLI->getOperand(0); NewPN->addIncoming(InVal, PN.getIncomingBlock(0)); @@ -446,8 +443,8 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) { // Okay, they are all the same operation. Create a new PHI node of the // correct type, and PHI together all of the LHS's of the instructions. PHINode *NewPN = PHINode::Create(FirstInst->getOperand(0)->getType(), + PN.getNumIncomingValues(), PN.getName()+".in"); - NewPN->reserveOperandSpace(PN.getNumOperands()/2); Value *InVal = FirstInst->getOperand(0); NewPN->addIncoming(InVal, PN.getIncomingBlock(0)); @@ -699,7 +696,8 @@ Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) { if ((EltPHI = ExtractedVals[LoweredPHIRecord(PN, Offset, Ty)]) == 0) { // Otherwise, Create the new PHI node for this user. - EltPHI = PHINode::Create(Ty, PN->getName()+".off"+Twine(Offset), PN); + EltPHI = PHINode::Create(Ty, PN->getNumIncomingValues(), + PN->getName()+".off"+Twine(Offset), PN); assert(EltPHI->getType() != PN->getType() && "Truncate didn't shrink phi?"); @@ -776,9 +774,6 @@ Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) { // PHINode simplification // Instruction *InstCombiner::visitPHINode(PHINode &PN) { - // If LCSSA is around, don't mess with Phi nodes - if (MustPreserveLCSSA) return 0; - if (Value *V = SimplifyInstruction(&PN, TD)) return ReplaceInstUsesWith(PN, V); @@ -826,18 +821,18 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) { // quick check to see if the PHI node only contains a single non-phi value, if // so, scan to see if the phi cycle is actually equal to that value. { - unsigned InValNo = 0, NumOperandVals = PN.getNumIncomingValues(); + unsigned InValNo = 0, NumIncomingVals = PN.getNumIncomingValues(); // Scan for the first non-phi operand. - while (InValNo != NumOperandVals && + while (InValNo != NumIncomingVals && isa(PN.getIncomingValue(InValNo))) ++InValNo; - if (InValNo != NumOperandVals) { - Value *NonPhiInVal = PN.getOperand(InValNo); + if (InValNo != NumIncomingVals) { + Value *NonPhiInVal = PN.getIncomingValue(InValNo); // Scan the rest of the operands to see if there are any conflicts, if so // there is no need to recursively scan other phis. - for (++InValNo; InValNo != NumOperandVals; ++InValNo) { + for (++InValNo; InValNo != NumIncomingVals; ++InValNo) { Value *OpVal = PN.getIncomingValue(InValNo); if (OpVal != NonPhiInVal && !isa(OpVal)) break; @@ -846,7 +841,7 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) { // If we scanned over all operands, then we have one unique value plus // phi values. Scan PHI nodes to see if they all merge in each other or // the value. - if (InValNo == NumOperandVals) { + if (InValNo == NumIncomingVals) { SmallPtrSet ValueEqualPHIs; if (PHIsEqualValue(&PN, NonPhiInVal, ValueEqualPHIs)) return ReplaceInstUsesWith(PN, NonPhiInVal); diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 97abc769ae5f..61a433a9c00c 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -214,7 +214,7 @@ Instruction *InstCombiner::FoldSelectIntoOp(SelectInst &SI, Value *TrueVal, unsigned OpToFold = 0; if ((SFO & 1) && FalseVal == TVI->getOperand(0)) { OpToFold = 1; - } else if ((SFO & 2) && FalseVal == TVI->getOperand(1)) { + } else if ((SFO & 2) && FalseVal == TVI->getOperand(1)) { OpToFold = 2; } @@ -227,9 +227,16 @@ Instruction *InstCombiner::FoldSelectIntoOp(SelectInst &SI, Value *TrueVal, Instruction *NewSel = SelectInst::Create(SI.getCondition(), OOp, C); InsertNewInstBefore(NewSel, SI); NewSel->takeName(TVI); - if (BinaryOperator *BO = dyn_cast(TVI)) - return BinaryOperator::Create(BO->getOpcode(), FalseVal, NewSel); - llvm_unreachable("Unknown instruction!!"); + BinaryOperator *TVI_BO = cast(TVI); + BinaryOperator *BO = BinaryOperator::Create(TVI_BO->getOpcode(), + FalseVal, NewSel); + if (isa(BO)) + BO->setIsExact(TVI_BO->isExact()); + if (isa(BO)) { + BO->setHasNoUnsignedWrap(TVI_BO->hasNoUnsignedWrap()); + BO->setHasNoSignedWrap(TVI_BO->hasNoSignedWrap()); + } + return BO; } } } @@ -243,7 +250,7 @@ Instruction *InstCombiner::FoldSelectIntoOp(SelectInst &SI, Value *TrueVal, unsigned OpToFold = 0; if ((SFO & 1) && TrueVal == FVI->getOperand(0)) { OpToFold = 1; - } else if ((SFO & 2) && TrueVal == FVI->getOperand(1)) { + } else if ((SFO & 2) && TrueVal == FVI->getOperand(1)) { OpToFold = 2; } @@ -256,9 +263,16 @@ Instruction *InstCombiner::FoldSelectIntoOp(SelectInst &SI, Value *TrueVal, Instruction *NewSel = SelectInst::Create(SI.getCondition(), C, OOp); InsertNewInstBefore(NewSel, SI); NewSel->takeName(FVI); - if (BinaryOperator *BO = dyn_cast(FVI)) - return BinaryOperator::Create(BO->getOpcode(), TrueVal, NewSel); - llvm_unreachable("Unknown instruction!!"); + BinaryOperator *FVI_BO = cast(FVI); + BinaryOperator *BO = BinaryOperator::Create(FVI_BO->getOpcode(), + TrueVal, NewSel); + if (isa(BO)) + BO->setIsExact(FVI_BO->isExact()); + if (isa(BO)) { + BO->setHasNoUnsignedWrap(FVI_BO->hasNoUnsignedWrap()); + BO->setHasNoSignedWrap(FVI_BO->hasNoSignedWrap()); + } + return BO; } } } @@ -424,6 +438,19 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI, return ReplaceInstUsesWith(SI, TrueVal); /// NOTE: if we wanted to, this is where to detect integer MIN/MAX } + + if (isa(CmpRHS)) { + if (CmpLHS == TrueVal && Pred == ICmpInst::ICMP_EQ) { + // Transform (X == C) ? X : Y -> (X == C) ? C : Y + SI.setOperand(1, CmpRHS); + Changed = true; + } else if (CmpLHS == FalseVal && Pred == ICmpInst::ICMP_NE) { + // Transform (X != C) ? Y : X -> (X != C) ? Y : C + SI.setOperand(2, CmpRHS); + Changed = true; + } + } + return Changed ? &SI : 0; } @@ -503,9 +530,8 @@ static Value *foldSelectICmpAnd(const SelectInst &SI, ConstantInt *TrueVal, if (!IC || !IC->isEquality()) return 0; - if (ConstantInt *C = dyn_cast(IC->getOperand(1))) - if (!C->isZero()) - return 0; + if (!match(IC->getOperand(1), m_Zero())) + return 0; ConstantInt *AndRHS; Value *LHS = IC->getOperand(0); diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp index a7f800587bb6..811f94976f68 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -644,7 +644,14 @@ Instruction *InstCombiner::visitShl(BinaryOperator &I) { return &I; } } - + + // (C1 << A) << C2 -> (C1 << C2) << A + Constant *C1, *C2; + Value *A; + if (match(I.getOperand(0), m_OneUse(m_Shl(m_Constant(C1), m_Value(A)))) && + match(I.getOperand(1), m_Constant(C2))) + return BinaryOperator::CreateShl(ConstantExpr::getShl(C1, C2), A); + return 0; } diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index bda8cea4e41f..6e727ce6e35c 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -684,6 +684,10 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, break; case Instruction::SRem: if (ConstantInt *Rem = dyn_cast(I->getOperand(1))) { + // X % -1 demands all the bits because we don't want to introduce + // INT_MIN % -1 (== undef) by accident. + if (Rem->isAllOnesValue()) + break; APInt RA = Rem->getValue().abs(); if (RA.isPowerOf2()) { if (DemandedMask.ult(RA)) // srem won't affect demanded bits @@ -712,6 +716,18 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, assert(!(KnownZero & KnownOne) && "Bits known to be one AND zero?"); } } + + // The sign bit is the LHS's sign bit, except when the result of the + // remainder is zero. + if (DemandedMask.isNegative() && KnownZero.isNonNegative()) { + APInt Mask2 = APInt::getSignBit(BitWidth); + APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0); + ComputeMaskedBits(I->getOperand(0), Mask2, LHSKnownZero, LHSKnownOne, + Depth+1); + // If it's known zero, our sign bit is also zero. + if (LHSKnownZero.isNegative()) + KnownZero |= LHSKnownZero; + } break; case Instruction::URem: { APInt KnownZero2(BitWidth, 0), KnownOne2(BitWidth, 0); diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index 5caa12dfdfa5..ad6a8d054ee7 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -230,8 +230,16 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) { ConstantInt::get(Int32Ty, SrcIdx, false)); } + } else if (CastInst *CI = dyn_cast(I)) { + // Canonicalize extractelement(cast) -> cast(extractelement) + // bitcasts can change the number of vector elements and they cost nothing + if (CI->hasOneUse() && EI.hasOneUse() && + (CI->getOpcode() != Instruction::BitCast)) { + Value *EE = Builder->CreateExtractElement(CI->getOperand(0), + EI.getIndexOperand()); + return CastInst::Create(CI->getOpcode(), EE, EI.getType()); + } } - // FIXME: Canonicalize extractelement(bitcast) -> bitcast(extractelement) } return 0; } diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineWorklist.h b/contrib/llvm/lib/Transforms/InstCombine/InstCombineWorklist.h index 9100a851f16e..32009c39ec25 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineWorklist.h +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineWorklist.h @@ -53,6 +53,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombineWorklist { void AddInitialGroup(Instruction *const *List, unsigned NumEntries) { assert(Worklist.empty() && "Worklist must be empty to add initial group"); Worklist.reserve(NumEntries+16); + WorklistMap.resize(NumEntries); DEBUG(errs() << "IC: ADDING: " << NumEntries << " instrs to worklist\n"); for (; NumEntries; --NumEntries) { Instruction *I = List[NumEntries-1]; diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 37123d0621eb..7a84598c3a0d 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -76,7 +76,6 @@ INITIALIZE_PASS(InstCombiner, "instcombine", "Combine redundant instructions", false, false) void InstCombiner::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addPreservedID(LCSSAID); AU.setPreservesCFG(); } @@ -600,8 +599,7 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) { } // Okay, we can do the transformation: create the new PHI node. - PHINode *NewPN = PHINode::Create(I.getType(), ""); - NewPN->reserveOperandSpace(PN->getNumOperands()/2); + PHINode *NewPN = PHINode::Create(I.getType(), PN->getNumIncomingValues(), ""); InsertNewInstBefore(NewPN, *PN); NewPN->takeName(PN); @@ -850,22 +848,23 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { GetElementPtrInst::Create(Src->getOperand(0), Indices.begin(), Indices.end(), GEP.getName()); } - + // Handle gep(bitcast x) and gep(gep x, 0, 0, 0). Value *StrippedPtr = PtrOp->stripPointerCasts(); - if (StrippedPtr != PtrOp) { - const PointerType *StrippedPtrTy =cast(StrippedPtr->getType()); + const PointerType *StrippedPtrTy =cast(StrippedPtr->getType()); + if (StrippedPtr != PtrOp && + StrippedPtrTy->getAddressSpace() == GEP.getPointerAddressSpace()) { bool HasZeroPointerIndex = false; if (ConstantInt *C = dyn_cast(GEP.getOperand(1))) HasZeroPointerIndex = C->isZero(); - + // Transform: GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ... // into : GEP [10 x i8]* X, i32 0, ... // // Likewise, transform: GEP (bitcast i8* X to [0 x i8]*), i32 0, ... // into : GEP i8* X, ... - // + // // This occurs when the program declares an array extern like "int X[];" if (HasZeroPointerIndex) { const PointerType *CPTy = cast(PtrOp->getType()); @@ -976,7 +975,7 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { } } } - + /// See if we can simplify: /// X = bitcast A* to B* /// Y = gep X, <...constant indices...> @@ -984,12 +983,14 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { /// analysis of unions. If "A" is also a bitcast, wait for A/X to be merged. if (BitCastInst *BCI = dyn_cast(PtrOp)) { if (TD && - !isa(BCI->getOperand(0)) && GEP.hasAllConstantIndices()) { + !isa(BCI->getOperand(0)) && GEP.hasAllConstantIndices() && + StrippedPtrTy->getAddressSpace() == GEP.getPointerAddressSpace()) { + // Determine how much the GEP moves the pointer. We are guaranteed to get // a constant back from EmitGEPOffset. ConstantInt *OffsetV = cast(EmitGEPOffset(&GEP)); int64_t Offset = OffsetV->getSExtValue(); - + // If this GEP instruction doesn't move the pointer, just replace the GEP // with a bitcast of the real input to the dest type. if (Offset == 0) { @@ -1635,7 +1636,6 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) { bool InstCombiner::runOnFunction(Function &F) { - MustPreserveLCSSA = mustPreserveAnalysisID(LCSSAID); TD = getAnalysisIfAvailable(); @@ -1648,6 +1648,10 @@ bool InstCombiner::runOnFunction(Function &F) { bool EverMadeChange = false; + // Lower dbg.declare intrinsics otherwise their value may be clobbered + // by instcombiner. + EverMadeChange = LowerDbgDeclare(F); + // Iterate while there is work to do. unsigned Iteration = 0; while (DoOneIteration(F, Iteration++)) diff --git a/contrib/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/contrib/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp new file mode 100644 index 000000000000..2425342f7e6c --- /dev/null +++ b/contrib/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -0,0 +1,638 @@ +//===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass implements GCOV-style profiling. When this pass is run it emits +// "gcno" files next to the existing source, and instruments the code that runs +// to records the edges between blocks that run and emit a complementary "gcda" +// file on exit. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "insert-gcov-profiling" + +#include "ProfilingUtils.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Instructions.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/PathV2.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/UniqueVector.h" +#include +#include +using namespace llvm; + +namespace { + class GCOVProfiler : public ModulePass { + bool runOnModule(Module &M); + public: + static char ID; + GCOVProfiler() + : ModulePass(ID), EmitNotes(true), EmitData(true) { + initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); + } + GCOVProfiler(bool EmitNotes, bool EmitData) + : ModulePass(ID), EmitNotes(EmitNotes), EmitData(EmitData) { + assert((EmitNotes || EmitData) && "GCOVProfiler asked to do nothing?"); + initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); + } + virtual const char *getPassName() const { + return "GCOV Profiler"; + } + + private: + // Create the GCNO files for the Module based on DebugInfo. + void emitGCNO(DebugInfoFinder &DIF); + + // Modify the program to track transitions along edges and call into the + // profiling runtime to emit .gcda files when run. + bool emitProfileArcs(DebugInfoFinder &DIF); + + // Get pointers to the functions in the runtime library. + Constant *getStartFileFunc(); + Constant *getIncrementIndirectCounterFunc(); + Constant *getEmitFunctionFunc(); + Constant *getEmitArcsFunc(); + Constant *getEndFileFunc(); + + // Create or retrieve an i32 state value that is used to represent the + // pred block number for certain non-trivial edges. + GlobalVariable *getEdgeStateValue(); + + // Produce a table of pointers to counters, by predecessor and successor + // block number. + GlobalVariable *buildEdgeLookupTable(Function *F, + GlobalVariable *Counter, + const UniqueVector &Preds, + const UniqueVector &Succs); + + // Add the function to write out all our counters to the global destructor + // list. + void insertCounterWriteout(DebugInfoFinder &, + SmallVector, 8> &); + + bool EmitNotes; + bool EmitData; + + Module *M; + LLVMContext *Ctx; + }; +} + +char GCOVProfiler::ID = 0; +INITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling", + "Insert instrumentation for GCOV profiling", false, false) + +ModulePass *llvm::createGCOVProfilerPass(bool EmitNotes, bool EmitData) { + return new GCOVProfiler(EmitNotes, EmitData); +} + +static DISubprogram findSubprogram(DIScope Scope) { + while (!Scope.isSubprogram()) { + assert(Scope.isLexicalBlock() && + "Debug location not lexical block or subprogram"); + Scope = DILexicalBlock(Scope).getContext(); + } + return DISubprogram(Scope); +} + +namespace { + class GCOVRecord { + protected: + static const char *LinesTag; + static const char *FunctionTag; + static const char *BlockTag; + static const char *EdgeTag; + + GCOVRecord() {} + + void writeBytes(const char *Bytes, int Size) { + os->write(Bytes, Size); + } + + void write(uint32_t i) { + writeBytes(reinterpret_cast(&i), 4); + } + + // Returns the length measured in 4-byte blocks that will be used to + // represent this string in a GCOV file + unsigned lengthOfGCOVString(StringRef s) { + // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs + // padding out to the next 4-byte word. The length is measured in 4-byte + // words including padding, not bytes of actual string. + return (s.size() + 5) / 4; + } + + void writeGCOVString(StringRef s) { + uint32_t Len = lengthOfGCOVString(s); + write(Len); + writeBytes(s.data(), s.size()); + + // Write 1 to 4 bytes of NUL padding. + assert((unsigned)(4 - (s.size() % 4)) > 0); + assert((unsigned)(4 - (s.size() % 4)) <= 4); + writeBytes("\0\0\0\0", 4 - (s.size() % 4)); + } + + raw_ostream *os; + }; + const char *GCOVRecord::LinesTag = "\0\0\x45\x01"; + const char *GCOVRecord::FunctionTag = "\0\0\0\1"; + const char *GCOVRecord::BlockTag = "\0\0\x41\x01"; + const char *GCOVRecord::EdgeTag = "\0\0\x43\x01"; + + class GCOVFunction; + class GCOVBlock; + + // Constructed only by requesting it from a GCOVBlock, this object stores a + // list of line numbers and a single filename, representing lines that belong + // to the block. + class GCOVLines : public GCOVRecord { + public: + void addLine(uint32_t Line) { + Lines.push_back(Line); + } + + uint32_t length() { + return lengthOfGCOVString(Filename) + 2 + Lines.size(); + } + + private: + friend class GCOVBlock; + + GCOVLines(std::string Filename, raw_ostream *os) + : Filename(Filename) { + this->os = os; + } + + std::string Filename; + SmallVector Lines; + }; + + // Represent a basic block in GCOV. Each block has a unique number in the + // function, number of lines belonging to each block, and a set of edges to + // other blocks. + class GCOVBlock : public GCOVRecord { + public: + GCOVLines &getFile(std::string Filename) { + GCOVLines *&Lines = LinesByFile[Filename]; + if (!Lines) { + Lines = new GCOVLines(Filename, os); + } + return *Lines; + } + + void addEdge(GCOVBlock &Successor) { + OutEdges.push_back(&Successor); + } + + void writeOut() { + uint32_t Len = 3; + for (StringMap::iterator I = LinesByFile.begin(), + E = LinesByFile.end(); I != E; ++I) { + Len += I->second->length(); + } + + writeBytes(LinesTag, 4); + write(Len); + write(Number); + for (StringMap::iterator I = LinesByFile.begin(), + E = LinesByFile.end(); I != E; ++I) { + write(0); + writeGCOVString(I->second->Filename); + for (int i = 0, e = I->second->Lines.size(); i != e; ++i) { + write(I->second->Lines[i]); + } + } + write(0); + write(0); + } + + ~GCOVBlock() { + DeleteContainerSeconds(LinesByFile); + } + + private: + friend class GCOVFunction; + + GCOVBlock(uint32_t Number, raw_ostream *os) + : Number(Number) { + this->os = os; + } + + uint32_t Number; + StringMap LinesByFile; + SmallVector OutEdges; + }; + + // A function has a unique identifier, a checksum (we leave as zero) and a + // set of blocks and a map of edges between blocks. This is the only GCOV + // object users can construct, the blocks and lines will be rooted here. + class GCOVFunction : public GCOVRecord { + public: + GCOVFunction(DISubprogram SP, raw_ostream *os) { + this->os = os; + + Function *F = SP.getFunction(); + uint32_t i = 0; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + Blocks[BB] = new GCOVBlock(i++, os); + } + ReturnBlock = new GCOVBlock(i++, os); + + writeBytes(FunctionTag, 4); + uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(SP.getName()) + + 1 + lengthOfGCOVString(SP.getFilename()) + 1; + write(BlockLen); + uint32_t Ident = reinterpret_cast((MDNode*)SP); + write(Ident); + write(0); // checksum + writeGCOVString(SP.getName()); + writeGCOVString(SP.getFilename()); + write(SP.getLineNumber()); + } + + ~GCOVFunction() { + DeleteContainerSeconds(Blocks); + delete ReturnBlock; + } + + GCOVBlock &getBlock(BasicBlock *BB) { + return *Blocks[BB]; + } + + GCOVBlock &getReturnBlock() { + return *ReturnBlock; + } + + void writeOut() { + // Emit count of blocks. + writeBytes(BlockTag, 4); + write(Blocks.size() + 1); + for (int i = 0, e = Blocks.size() + 1; i != e; ++i) { + write(0); // No flags on our blocks. + } + + // Emit edges between blocks. + for (DenseMap::iterator I = Blocks.begin(), + E = Blocks.end(); I != E; ++I) { + GCOVBlock &Block = *I->second; + if (Block.OutEdges.empty()) continue; + + writeBytes(EdgeTag, 4); + write(Block.OutEdges.size() * 2 + 1); + write(Block.Number); + for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) { + write(Block.OutEdges[i]->Number); + write(0); // no flags + } + } + + // Emit lines for each block. + for (DenseMap::iterator I = Blocks.begin(), + E = Blocks.end(); I != E; ++I) { + I->second->writeOut(); + } + } + + private: + DenseMap Blocks; + GCOVBlock *ReturnBlock; + }; +} + +// Replace the stem of a file, or add one if missing. +static std::string replaceStem(std::string OrigFilename, std::string NewStem) { + return (sys::path::stem(OrigFilename) + "." + NewStem).str(); +} + +bool GCOVProfiler::runOnModule(Module &M) { + this->M = &M; + Ctx = &M.getContext(); + + DebugInfoFinder DIF; + DIF.processModule(M); + + if (EmitNotes) emitGCNO(DIF); + if (EmitData) return emitProfileArcs(DIF); + return false; +} + +void GCOVProfiler::emitGCNO(DebugInfoFinder &DIF) { + DenseMap GcnoFiles; + for (DebugInfoFinder::iterator I = DIF.compile_unit_begin(), + E = DIF.compile_unit_end(); I != E; ++I) { + // Each compile unit gets its own .gcno file. This means that whether we run + // this pass over the original .o's as they're produced, or run it after + // LTO, we'll generate the same .gcno files. + + DICompileUnit CU(*I); + raw_fd_ostream *&out = GcnoFiles[CU]; + std::string ErrorInfo; + out = new raw_fd_ostream(replaceStem(CU.getFilename(), "gcno").c_str(), + ErrorInfo, raw_fd_ostream::F_Binary); + out->write("oncg*404MVLL", 12); + } + + for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(), + SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) { + DISubprogram SP(*SPI); + raw_fd_ostream *&os = GcnoFiles[SP.getCompileUnit()]; + + Function *F = SP.getFunction(); + if (!F) continue; + GCOVFunction Func(SP, os); + + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + GCOVBlock &Block = Func.getBlock(BB); + TerminatorInst *TI = BB->getTerminator(); + if (int successors = TI->getNumSuccessors()) { + for (int i = 0; i != successors; ++i) { + Block.addEdge(Func.getBlock(TI->getSuccessor(i))); + } + } else if (isa(TI)) { + Block.addEdge(Func.getReturnBlock()); + } + + uint32_t Line = 0; + for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) { + const DebugLoc &Loc = I->getDebugLoc(); + if (Loc.isUnknown()) continue; + if (Line == Loc.getLine()) continue; + Line = Loc.getLine(); + if (SP != findSubprogram(DIScope(Loc.getScope(*Ctx)))) continue; + + GCOVLines &Lines = Block.getFile(SP.getFilename()); + Lines.addLine(Loc.getLine()); + } + } + Func.writeOut(); + } + + for (DenseMap::iterator + I = GcnoFiles.begin(), E = GcnoFiles.end(); I != E; ++I) { + raw_fd_ostream *&out = I->second; + out->write("\0\0\0\0\0\0\0\0", 8); // EOF + out->close(); + delete out; + } +} + +bool GCOVProfiler::emitProfileArcs(DebugInfoFinder &DIF) { + if (DIF.subprogram_begin() == DIF.subprogram_end()) + return false; + + SmallVector, 8> CountersByIdent; + for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(), + SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) { + DISubprogram SP(*SPI); + Function *F = SP.getFunction(); + if (!F) continue; + + unsigned Edges = 0; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + TerminatorInst *TI = BB->getTerminator(); + if (isa(TI)) + ++Edges; + else + Edges += TI->getNumSuccessors(); + } + + const ArrayType *CounterTy = + ArrayType::get(Type::getInt64Ty(*Ctx), Edges); + GlobalVariable *Counters = + new GlobalVariable(*M, CounterTy, false, + GlobalValue::InternalLinkage, + Constant::getNullValue(CounterTy), + "__llvm_gcov_ctr", 0, false, 0); + CountersByIdent.push_back( + std::make_pair(Counters, reinterpret_cast((MDNode*)SP))); + + UniqueVector ComplexEdgePreds; + UniqueVector ComplexEdgeSuccs; + + unsigned Edge = 0; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + TerminatorInst *TI = BB->getTerminator(); + int Successors = isa(TI) ? 1 : TI->getNumSuccessors(); + if (Successors) { + IRBuilder<> Builder(TI); + + if (Successors == 1) { + Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, + Edge); + Value *Count = Builder.CreateLoad(Counter); + Count = Builder.CreateAdd(Count, + ConstantInt::get(Type::getInt64Ty(*Ctx),1)); + Builder.CreateStore(Count, Counter); + } else if (BranchInst *BI = dyn_cast(TI)) { + Value *Sel = Builder.CreateSelect( + BI->getCondition(), + ConstantInt::get(Type::getInt64Ty(*Ctx), Edge), + ConstantInt::get(Type::getInt64Ty(*Ctx), Edge + 1)); + SmallVector Idx; + Idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx))); + Idx.push_back(Sel); + Value *Counter = Builder.CreateInBoundsGEP(Counters, + Idx.begin(), Idx.end()); + Value *Count = Builder.CreateLoad(Counter); + Count = Builder.CreateAdd(Count, + ConstantInt::get(Type::getInt64Ty(*Ctx),1)); + Builder.CreateStore(Count, Counter); + } else { + ComplexEdgePreds.insert(BB); + for (int i = 0; i != Successors; ++i) + ComplexEdgeSuccs.insert(TI->getSuccessor(i)); + } + Edge += Successors; + } + } + + if (!ComplexEdgePreds.empty()) { + GlobalVariable *EdgeTable = + buildEdgeLookupTable(F, Counters, + ComplexEdgePreds, ComplexEdgeSuccs); + GlobalVariable *EdgeState = getEdgeStateValue(); + + const Type *Int32Ty = Type::getInt32Ty(*Ctx); + for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { + IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator()); + Builder.CreateStore(ConstantInt::get(Int32Ty, i), EdgeState); + } + for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) { + // call runtime to perform increment + IRBuilder<> Builder(ComplexEdgeSuccs[i+1]->getFirstNonPHI()); + Value *CounterPtrArray = + Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0, + i * ComplexEdgePreds.size()); + Builder.CreateCall2(getIncrementIndirectCounterFunc(), + EdgeState, CounterPtrArray); + // clear the predecessor number + Builder.CreateStore(ConstantInt::get(Int32Ty, 0xffffffff), EdgeState); + } + } + } + + insertCounterWriteout(DIF, CountersByIdent); + + return true; +} + +// All edges with successors that aren't branches are "complex", because it +// requires complex logic to pick which counter to update. +GlobalVariable *GCOVProfiler::buildEdgeLookupTable( + Function *F, + GlobalVariable *Counters, + const UniqueVector &Preds, + const UniqueVector &Succs) { + // TODO: support invoke, threads. We rely on the fact that nothing can modify + // the whole-Module pred edge# between the time we set it and the time we next + // read it. Threads and invoke make this untrue. + + // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]]. + const Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx); + const ArrayType *EdgeTableTy = ArrayType::get( + Int64PtrTy, Succs.size() * Preds.size()); + + Constant **EdgeTable = new Constant*[Succs.size() * Preds.size()]; + Constant *NullValue = Constant::getNullValue(Int64PtrTy); + for (int i = 0, ie = Succs.size() * Preds.size(); i != ie; ++i) + EdgeTable[i] = NullValue; + + unsigned Edge = 0; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + TerminatorInst *TI = BB->getTerminator(); + int Successors = isa(TI) ? 1 : TI->getNumSuccessors(); + if (Successors > 1 && !isa(TI) && !isa(TI)) { + for (int i = 0; i != Successors; ++i) { + BasicBlock *Succ = TI->getSuccessor(i); + IRBuilder<> builder(Succ); + Value *Counter = builder.CreateConstInBoundsGEP2_64(Counters, 0, + Edge + i); + EdgeTable[((Succs.idFor(Succ)-1) * Preds.size()) + + (Preds.idFor(BB)-1)] = cast(Counter); + } + } + Edge += Successors; + } + + GlobalVariable *EdgeTableGV = + new GlobalVariable( + *M, EdgeTableTy, true, GlobalValue::InternalLinkage, + ConstantArray::get(EdgeTableTy, + &EdgeTable[0], Succs.size() * Preds.size()), + "__llvm_gcda_edge_table"); + EdgeTableGV->setUnnamedAddr(true); + return EdgeTableGV; +} + +Constant *GCOVProfiler::getStartFileFunc() { + const Type *Args[] = { Type::getInt8PtrTy(*Ctx) }; + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), + Args, false); + return M->getOrInsertFunction("llvm_gcda_start_file", FTy); +} + +Constant *GCOVProfiler::getIncrementIndirectCounterFunc() { + const Type *Args[] = { + Type::getInt32PtrTy(*Ctx), // uint32_t *predecessor + Type::getInt64PtrTy(*Ctx)->getPointerTo(), // uint64_t **state_table_row + }; + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), + Args, false); + return M->getOrInsertFunction("llvm_gcda_increment_indirect_counter", FTy); +} + +Constant *GCOVProfiler::getEmitFunctionFunc() { + const Type *Args[] = { Type::getInt32Ty(*Ctx) }; + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), + Args, false); + return M->getOrInsertFunction("llvm_gcda_emit_function", FTy); +} + +Constant *GCOVProfiler::getEmitArcsFunc() { + const Type *Args[] = { + Type::getInt32Ty(*Ctx), // uint32_t num_counters + Type::getInt64PtrTy(*Ctx), // uint64_t *counters + }; + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), + Args, false); + return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy); +} + +Constant *GCOVProfiler::getEndFileFunc() { + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); + return M->getOrInsertFunction("llvm_gcda_end_file", FTy); +} + +GlobalVariable *GCOVProfiler::getEdgeStateValue() { + GlobalVariable *GV = M->getGlobalVariable("__llvm_gcov_global_state_pred"); + if (!GV) { + GV = new GlobalVariable(*M, Type::getInt32Ty(*Ctx), false, + GlobalValue::InternalLinkage, + ConstantInt::get(Type::getInt32Ty(*Ctx), + 0xffffffff), + "__llvm_gcov_global_state_pred"); + GV->setUnnamedAddr(true); + } + return GV; +} + +void GCOVProfiler::insertCounterWriteout( + DebugInfoFinder &DIF, + SmallVector, 8> &CountersByIdent) { + const FunctionType *WriteoutFTy = + FunctionType::get(Type::getVoidTy(*Ctx), false); + Function *WriteoutF = Function::Create(WriteoutFTy, + GlobalValue::InternalLinkage, + "__llvm_gcov_writeout", M); + WriteoutF->setUnnamedAddr(true); + BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF); + IRBuilder<> Builder(BB); + + Constant *StartFile = getStartFileFunc(); + Constant *EmitFunction = getEmitFunctionFunc(); + Constant *EmitArcs = getEmitArcsFunc(); + Constant *EndFile = getEndFileFunc(); + + for (DebugInfoFinder::iterator CUI = DIF.compile_unit_begin(), + CUE = DIF.compile_unit_end(); CUI != CUE; ++CUI) { + DICompileUnit compile_unit(*CUI); + std::string FilenameGcda = replaceStem(compile_unit.getFilename(), "gcda"); + Builder.CreateCall(StartFile, + Builder.CreateGlobalStringPtr(FilenameGcda)); + for (SmallVector, 8>::iterator + I = CountersByIdent.begin(), E = CountersByIdent.end(); + I != E; ++I) { + Builder.CreateCall(EmitFunction, ConstantInt::get(Type::getInt32Ty(*Ctx), + I->second)); + GlobalVariable *GV = I->first; + unsigned Arcs = + cast(GV->getType()->getElementType())->getNumElements(); + Builder.CreateCall2(EmitArcs, + ConstantInt::get(Type::getInt32Ty(*Ctx), Arcs), + Builder.CreateConstGEP2_64(GV, 0, 0)); + } + Builder.CreateCall(EndFile); + } + Builder.CreateRetVoid(); + + InsertProfilingShutdownCall(WriteoutF, M); +} diff --git a/contrib/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp b/contrib/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp index 96ed4fa5c0fe..71adc1ec6de0 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp +++ b/contrib/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp @@ -23,6 +23,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) { initializeEdgeProfilerPass(Registry); initializeOptimalEdgeProfilerPass(Registry); initializePathProfilerPass(Registry); + initializeGCOVProfilerPass(Registry); } /// LLVMInitializeInstrumentation - C binding for diff --git a/contrib/llvm/lib/Transforms/Instrumentation/MaximumSpanningTree.h b/contrib/llvm/lib/Transforms/Instrumentation/MaximumSpanningTree.h index 829da6b295de..f76c77e1bdbf 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/MaximumSpanningTree.h +++ b/contrib/llvm/lib/Transforms/Instrumentation/MaximumSpanningTree.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This module privides means for calculating a maximum spanning tree for a +// This module provides means for calculating a maximum spanning tree for a // given set of weighted edges. The type parameter T is the type of a node. // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp b/contrib/llvm/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp index c85a1a9391d4..e09f882aa323 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp +++ b/contrib/llvm/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "insert-optimal-edge-profiling" #include "ProfilingUtils.h" +#include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/Analysis/Passes.h" @@ -26,7 +27,6 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Statistic.h" #include "MaximumSpanningTree.h" -#include using namespace llvm; STATISTIC(NumEdgesInserted, "The # of edges inserted."); @@ -120,14 +120,14 @@ bool OptimalEdgeProfiler::runOnModule(Module &M) { NumEdgesInserted = 0; std::vector Initializer(NumEdges); - Constant* Zero = ConstantInt::get(Int32, 0); - Constant* Uncounted = ConstantInt::get(Int32, ProfileInfoLoader::Uncounted); + Constant *Zero = ConstantInt::get(Int32, 0); + Constant *Uncounted = ConstantInt::get(Int32, ProfileInfoLoader::Uncounted); // Instrument all of the edges not in MST... unsigned i = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; - DEBUG(dbgs()<<"Working on "<getNameStr()<<"\n"); + DEBUG(dbgs() << "Working on " << F->getNameStr() << "\n"); // Calculate a Maximum Spanning Tree with the edge weights determined by // ProfileEstimator. ProfileEstimator also assign weights to the virtual @@ -139,17 +139,17 @@ bool OptimalEdgeProfiler::runOnModule(Module &M) { ProfileInfo::EdgeWeights ECs = getAnalysis(*F).getEdgeWeights(F); std::vector EdgeVector(ECs.begin(), ECs.end()); - MaximumSpanningTree MST (EdgeVector); - std::stable_sort(MST.begin(),MST.end()); + MaximumSpanningTree MST(EdgeVector); + std::stable_sort(MST.begin(), MST.end()); // Check if (0,entry) not in the MST. If not, instrument edge // (IncrementCounterInBlock()) and set the counter initially to zero, if // the edge is in the MST the counter is initialised to -1. BasicBlock *entry = &(F->getEntryBlock()); - ProfileInfo::Edge edge = ProfileInfo::getEdge(0,entry); + ProfileInfo::Edge edge = ProfileInfo::getEdge(0, entry); if (!std::binary_search(MST.begin(), MST.end(), edge)) { - printEdgeCounter(edge,entry,i); + printEdgeCounter(edge, entry, i); IncrementCounterInBlock(entry, i, Counters); ++NumEdgesInserted; Initializer[i++] = (Zero); } else{ @@ -170,9 +170,9 @@ bool OptimalEdgeProfiler::runOnModule(Module &M) { // has no successors, the virtual edge (BB,0) is processed. TerminatorInst *TI = BB->getTerminator(); if (TI->getNumSuccessors() == 0) { - ProfileInfo::Edge edge = ProfileInfo::getEdge(BB,0); + ProfileInfo::Edge edge = ProfileInfo::getEdge(BB, 0); if (!std::binary_search(MST.begin(), MST.end(), edge)) { - printEdgeCounter(edge,BB,i); + printEdgeCounter(edge, BB, i); IncrementCounterInBlock(BB, i, Counters); ++NumEdgesInserted; Initializer[i++] = (Zero); } else{ @@ -195,11 +195,11 @@ bool OptimalEdgeProfiler::runOnModule(Module &M) { // otherwise insert it in the successor block. if (TI->getNumSuccessors() == 1) { // Insert counter at the start of the block - printEdgeCounter(edge,BB,i); + printEdgeCounter(edge, BB, i); IncrementCounterInBlock(BB, i, Counters); ++NumEdgesInserted; } else { // Insert counter at the start of the block - printEdgeCounter(edge,Succ,i); + printEdgeCounter(edge, Succ, i); IncrementCounterInBlock(Succ, i, Counters); ++NumEdgesInserted; } Initializer[i++] = (Zero); @@ -212,9 +212,9 @@ bool OptimalEdgeProfiler::runOnModule(Module &M) { // Check if the number of edges counted at first was the number of edges we // considered for instrumentation. - assert(i==NumEdges && "the number of edges in counting array is wrong"); + assert(i == NumEdges && "the number of edges in counting array is wrong"); - // Assing the now completely defined initialiser to the array. + // Assign the now completely defined initialiser to the array. Constant *init = ConstantArray::get(ATy, Initializer); Counters->setInitializer(init); diff --git a/contrib/llvm/lib/Transforms/Instrumentation/PathProfiling.cpp b/contrib/llvm/lib/Transforms/Instrumentation/PathProfiling.cpp index 6449b39cfc9d..6b3f12dcbc84 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/PathProfiling.cpp +++ b/contrib/llvm/lib/Transforms/Instrumentation/PathProfiling.cpp @@ -63,7 +63,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Instrumentation.h" -#include #include #define HASH_THRESHHOLD 100000 @@ -259,7 +258,7 @@ class BLInstrumentationDag : public BallLarusDag { }; // --------------------------------------------------------------------------- -// PathProfiler is a module pass which intruments path profiling instructions +// PathProfiler is a module pass which instruments path profiling instructions // --------------------------------------------------------------------------- class PathProfiler : public ModulePass { private: @@ -388,6 +387,9 @@ namespace llvm { ftEntryTypeBuilder; // BallLarusEdge << operator overloading + raw_ostream& operator<<(raw_ostream& os, + const BLInstrumentationEdge& edge) + LLVM_ATTRIBUTE_USED; raw_ostream& operator<<(raw_ostream& os, const BLInstrumentationEdge& edge) { os << "[" << edge.getSource()->getName() << " -> " @@ -929,14 +931,16 @@ BasicBlock::iterator PathProfiler::getInsertionPoint(BasicBlock* block, Value* void PathProfiler::preparePHI(BLInstrumentationNode* node) { BasicBlock* block = node->getBlock(); BasicBlock::iterator insertPoint = block->getFirstNonPHI(); - PHINode* phi = PHINode::Create(Type::getInt32Ty(*Context), "pathNumber", + pred_iterator PB = pred_begin(node->getBlock()), + PE = pred_end(node->getBlock()); + PHINode* phi = PHINode::Create(Type::getInt32Ty(*Context), + std::distance(PB, PE), "pathNumber", insertPoint ); node->setPathPHI(phi); node->setStartingPathNumber(phi); node->setEndingPathNumber(phi); - for(pred_iterator predIt = pred_begin(node->getBlock()), - end = pred_end(node->getBlock()); predIt != end; predIt++) { + for(pred_iterator predIt = PB; predIt != PE; predIt++) { BasicBlock* pred = (*predIt); if(pred != NULL) diff --git a/contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.cpp b/contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.cpp index b57bbf60a07a..7435bc37fbe1 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.cpp +++ b/contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.cpp @@ -110,7 +110,7 @@ void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, GlobalValue *CounterArray, bool beginning) { // Insert the increment after any alloca or PHI instructions... BasicBlock::iterator InsertPos = beginning ? BB->getFirstNonPHI() : - BB->getTerminator(); + BB->getTerminator(); while (isa(InsertPos)) ++InsertPos; @@ -121,8 +121,7 @@ void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, Indices[0] = Constant::getNullValue(Type::getInt32Ty(Context)); Indices[1] = ConstantInt::get(Type::getInt32Ty(Context), CounterNum); Constant *ElementPtr = - ConstantExpr::getGetElementPtr(CounterArray, &Indices[0], - Indices.size()); + ConstantExpr::getGetElementPtr(CounterArray, &Indices[0], Indices.size()); // Load, increment and store the value back. Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos); @@ -131,3 +130,41 @@ void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, "NewFuncCounter", InsertPos); new StoreInst(NewVal, ElementPtr, InsertPos); } + +void llvm::InsertProfilingShutdownCall(Function *Callee, Module *Mod) { + // llvm.global_dtors is an array of type { i32, void ()* }. Prepare those + // types. + const Type *GlobalDtorElems[2] = { + Type::getInt32Ty(Mod->getContext()), + FunctionType::get(Type::getVoidTy(Mod->getContext()), false)->getPointerTo() + }; + const StructType *GlobalDtorElemTy = + StructType::get(Mod->getContext(), GlobalDtorElems, false); + + // Construct the new element we'll be adding. + Constant *Elem[2] = { + ConstantInt::get(Type::getInt32Ty(Mod->getContext()), 65535), + ConstantExpr::getBitCast(Callee, GlobalDtorElems[1]) + }; + + // If llvm.global_dtors exists, make a copy of the things in its list and + // delete it, to replace it with one that has a larger array type. + std::vector dtors; + if (GlobalVariable *GlobalDtors = Mod->getNamedGlobal("llvm.global_dtors")) { + if (ConstantArray *InitList = + dyn_cast(GlobalDtors->getInitializer())) { + for (unsigned i = 0, e = InitList->getType()->getNumElements(); + i != e; ++i) + dtors.push_back(cast(InitList->getOperand(i))); + } + GlobalDtors->eraseFromParent(); + } + + // Build up llvm.global_dtors with our new item in it. + GlobalVariable *GlobalDtors = new GlobalVariable( + *Mod, ArrayType::get(GlobalDtorElemTy, 1), false, + GlobalValue::AppendingLinkage, NULL, "llvm.global_dtors"); + dtors.push_back(ConstantStruct::get(Mod->getContext(), Elem, 2, false)); + GlobalDtors->setInitializer(ConstantArray::get( + cast(GlobalDtors->getType()->getElementType()), dtors)); +} diff --git a/contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.h b/contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.h index a76e3576e1ca..09b22171ff04 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.h +++ b/contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.h @@ -18,9 +18,10 @@ #define PROFILINGUTILS_H namespace llvm { + class BasicBlock; class Function; class GlobalValue; - class BasicBlock; + class Module; class PointerType; void InsertProfilingInitCall(Function *MainFn, const char *FnName, @@ -29,6 +30,7 @@ namespace llvm { void IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, GlobalValue *CounterArray, bool beginning = true); + void InsertProfilingShutdownCall(Function *Callee, Module *Mod); } #endif diff --git a/contrib/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp b/contrib/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp index 9536939ba2d4..018439018553 100644 --- a/contrib/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -47,21 +47,21 @@ using namespace llvm; using namespace llvm::PatternMatch; STATISTIC(NumBlocksElim, "Number of blocks eliminated"); -STATISTIC(NumPHIsElim, "Number of trivial PHIs eliminated"); -STATISTIC(NumGEPsElim, "Number of GEPs converted to casts"); +STATISTIC(NumPHIsElim, "Number of trivial PHIs eliminated"); +STATISTIC(NumGEPsElim, "Number of GEPs converted to casts"); STATISTIC(NumCmpUses, "Number of uses of Cmp expressions replaced with uses of " "sunken Cmps"); STATISTIC(NumCastUses, "Number of uses of Cast expressions replaced with uses " "of sunken Casts"); STATISTIC(NumMemoryInsts, "Number of memory instructions whose address " "computations were sunk"); -STATISTIC(NumExtsMoved, "Number of [s|z]ext instructions combined with loads"); -STATISTIC(NumExtUses, "Number of uses of [s|z]ext instructions optimized"); +STATISTIC(NumExtsMoved, "Number of [s|z]ext instructions combined with loads"); +STATISTIC(NumExtUses, "Number of uses of [s|z]ext instructions optimized"); +STATISTIC(NumRetsDup, "Number of return instructions duplicated"); -static cl::opt -CriticalEdgeSplit("cgp-critical-edge-splitting", - cl::desc("Split critical edges during codegen prepare"), - cl::init(false), cl::Hidden); +static cl::opt DisableBranchOpts( + "disable-cgp-branch-opts", cl::Hidden, cl::init(false), + cl::desc("Disable branch optimizations in CodeGenPrepare")); namespace { class CodeGenPrepare : public FunctionPass { @@ -76,15 +76,15 @@ namespace { /// update it. BasicBlock::iterator CurInstIterator; - /// BackEdges - Keep a set of all the loop back edges. - /// - SmallSet, 8> BackEdges; - - // Keeps track of non-local addresses that have been sunk into a block. This - // allows us to avoid inserting duplicate code for blocks with multiple - // load/stores of the same address. + /// Keeps track of non-local addresses that have been sunk into a block. + /// This allows us to avoid inserting duplicate code for blocks with + /// multiple load/stores of the same address. DenseMap SunkAddrs; + /// ModifiedDT - If CFG is modified in anyway, dominator tree may need to + /// be updated. + bool ModifiedDT; + public: static char ID; // Pass identification, replacement for typeid explicit CodeGenPrepare(const TargetLowering *tli = 0) @@ -98,10 +98,6 @@ namespace { AU.addPreserved(); } - virtual void releaseMemory() { - BackEdges.clear(); - } - private: bool EliminateMostlyEmptyBlocks(Function &F); bool CanMergeBlocks(const BasicBlock *BB, const BasicBlock *DestBB) const; @@ -113,7 +109,7 @@ namespace { bool OptimizeCallInst(CallInst *CI); bool MoveExtToFormExtLoad(Instruction *I); bool OptimizeExtUses(Instruction *I); - void findLoopBackEdges(const Function &F); + bool DupRetToEnableTailCallOpts(ReturnInst *RI); }; } @@ -125,40 +121,42 @@ FunctionPass *llvm::createCodeGenPreparePass(const TargetLowering *TLI) { return new CodeGenPrepare(TLI); } -/// findLoopBackEdges - Do a DFS walk to find loop back edges. -/// -void CodeGenPrepare::findLoopBackEdges(const Function &F) { - SmallVector, 32> Edges; - FindFunctionBackedges(F, Edges); - - BackEdges.insert(Edges.begin(), Edges.end()); -} - - bool CodeGenPrepare::runOnFunction(Function &F) { bool EverMadeChange = false; + ModifiedDT = false; DT = getAnalysisIfAvailable(); PFI = getAnalysisIfAvailable(); + // First pass, eliminate blocks that contain only PHI nodes and an // unconditional branch. EverMadeChange |= EliminateMostlyEmptyBlocks(F); - // Now find loop back edges, but only if they are being used to decide which - // critical edges to split. - if (CriticalEdgeSplit) - findLoopBackEdges(F); - bool MadeChange = true; while (MadeChange) { MadeChange = false; - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (Function::iterator I = F.begin(), E = F.end(); I != E; ) { + BasicBlock *BB = I++; MadeChange |= OptimizeBlock(*BB); + } EverMadeChange |= MadeChange; } SunkAddrs.clear(); + if (!DisableBranchOpts) { + MadeChange = false; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + MadeChange |= ConstantFoldTerminator(BB); + + if (MadeChange) + ModifiedDT = true; + EverMadeChange |= MadeChange; + } + + if (ModifiedDT && DT) + DT->DT->recalculate(F); + return EverMadeChange; } @@ -333,7 +331,7 @@ void CodeGenPrepare::EliminateMostlyEmptyBlock(BasicBlock *BB) { // The PHIs are now updated, change everything that refers to BB to use // DestBB and remove BB. BB->replaceAllUsesWith(DestBB); - if (DT) { + if (DT && !ModifiedDT) { BasicBlock *BBIDom = DT->getNode(BB)->getIDom()->getBlock(); BasicBlock *DestBBIDom = DT->getNode(DestBB)->getIDom()->getBlock(); BasicBlock *NewIDom = DT->findNearestCommonDominator(BBIDom, DestBBIDom); @@ -350,110 +348,6 @@ void CodeGenPrepare::EliminateMostlyEmptyBlock(BasicBlock *BB) { DEBUG(dbgs() << "AFTER:\n" << *DestBB << "\n\n\n"); } -/// FindReusablePredBB - Check all of the predecessors of the block DestPHI -/// lives in to see if there is a block that we can reuse as a critical edge -/// from TIBB. -static BasicBlock *FindReusablePredBB(PHINode *DestPHI, BasicBlock *TIBB) { - BasicBlock *Dest = DestPHI->getParent(); - - /// TIPHIValues - This array is lazily computed to determine the values of - /// PHIs in Dest that TI would provide. - SmallVector TIPHIValues; - - /// TIBBEntryNo - This is a cache to speed up pred queries for TIBB. - unsigned TIBBEntryNo = 0; - - // Check to see if Dest has any blocks that can be used as a split edge for - // this terminator. - for (unsigned pi = 0, e = DestPHI->getNumIncomingValues(); pi != e; ++pi) { - BasicBlock *Pred = DestPHI->getIncomingBlock(pi); - // To be usable, the pred has to end with an uncond branch to the dest. - BranchInst *PredBr = dyn_cast(Pred->getTerminator()); - if (!PredBr || !PredBr->isUnconditional()) - continue; - // Must be empty other than the branch and debug info. - BasicBlock::iterator I = Pred->begin(); - while (isa(I)) - I++; - if (&*I != PredBr) - continue; - // Cannot be the entry block; its label does not get emitted. - if (Pred == &Dest->getParent()->getEntryBlock()) - continue; - - // Finally, since we know that Dest has phi nodes in it, we have to make - // sure that jumping to Pred will have the same effect as going to Dest in - // terms of PHI values. - PHINode *PN; - unsigned PHINo = 0; - unsigned PredEntryNo = pi; - - bool FoundMatch = true; - for (BasicBlock::iterator I = Dest->begin(); - (PN = dyn_cast(I)); ++I, ++PHINo) { - if (PHINo == TIPHIValues.size()) { - if (PN->getIncomingBlock(TIBBEntryNo) != TIBB) - TIBBEntryNo = PN->getBasicBlockIndex(TIBB); - TIPHIValues.push_back(PN->getIncomingValue(TIBBEntryNo)); - } - - // If the PHI entry doesn't work, we can't use this pred. - if (PN->getIncomingBlock(PredEntryNo) != Pred) - PredEntryNo = PN->getBasicBlockIndex(Pred); - - if (TIPHIValues[PHINo] != PN->getIncomingValue(PredEntryNo)) { - FoundMatch = false; - break; - } - } - - // If we found a workable predecessor, change TI to branch to Succ. - if (FoundMatch) - return Pred; - } - return 0; -} - - -/// SplitEdgeNicely - Split the critical edge from TI to its specified -/// successor if it will improve codegen. We only do this if the successor has -/// phi nodes (otherwise critical edges are ok). If there is already another -/// predecessor of the succ that is empty (and thus has no phi nodes), use it -/// instead of introducing a new block. -static void SplitEdgeNicely(TerminatorInst *TI, unsigned SuccNum, - SmallSet, 8> &BackEdges, - Pass *P) { - BasicBlock *TIBB = TI->getParent(); - BasicBlock *Dest = TI->getSuccessor(SuccNum); - assert(isa(Dest->begin()) && - "This should only be called if Dest has a PHI!"); - PHINode *DestPHI = cast(Dest->begin()); - - // Do not split edges to EH landing pads. - if (InvokeInst *Invoke = dyn_cast(TI)) - if (Invoke->getSuccessor(1) == Dest) - return; - - // As a hack, never split backedges of loops. Even though the copy for any - // PHIs inserted on the backedge would be dead for exits from the loop, we - // assume that the cost of *splitting* the backedge would be too high. - if (BackEdges.count(std::make_pair(TIBB, Dest))) - return; - - if (BasicBlock *ReuseBB = FindReusablePredBB(DestPHI, TIBB)) { - ProfileInfo *PFI = P->getAnalysisIfAvailable(); - if (PFI) - PFI->splitEdge(TIBB, Dest, ReuseBB); - Dest->removePredecessor(TIBB); - TI->setSuccessor(SuccNum, ReuseBB); - return; - } - - SplitCriticalEdge(TI, SuccNum, P, true); -} - - /// OptimizeNoopCopyExpression - If the specified cast instruction is a noop /// copy (e.g. it's casting from one pointer type to another, i32->i8 on PPC), /// sink it into user blocks to reduce the number of virtual @@ -640,7 +534,8 @@ bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) { // happens. WeakVH IterHandle(CurInstIterator); - ReplaceAndSimplifyAllUses(CI, RetVal, TLI ? TLI->getTargetData() : 0, DT); + ReplaceAndSimplifyAllUses(CI, RetVal, TLI ? TLI->getTargetData() : 0, + ModifiedDT ? 0 : DT); // If the iterator instruction was recursively deleted, start over at the // start of the block. @@ -666,6 +561,129 @@ bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) { return Simplifier.fold(CI, TD); } +/// DupRetToEnableTailCallOpts - Look for opportunities to duplicate return +/// instructions to the predecessor to enable tail call optimizations. The +/// case it is currently looking for is: +/// bb0: +/// %tmp0 = tail call i32 @f0() +/// br label %return +/// bb1: +/// %tmp1 = tail call i32 @f1() +/// br label %return +/// bb2: +/// %tmp2 = tail call i32 @f2() +/// br label %return +/// return: +/// %retval = phi i32 [ %tmp0, %bb0 ], [ %tmp1, %bb1 ], [ %tmp2, %bb2 ] +/// ret i32 %retval +/// +/// => +/// +/// bb0: +/// %tmp0 = tail call i32 @f0() +/// ret i32 %tmp0 +/// bb1: +/// %tmp1 = tail call i32 @f1() +/// ret i32 %tmp1 +/// bb2: +/// %tmp2 = tail call i32 @f2() +/// ret i32 %tmp2 +/// +bool CodeGenPrepare::DupRetToEnableTailCallOpts(ReturnInst *RI) { + if (!TLI) + return false; + + Value *V = RI->getReturnValue(); + PHINode *PN = V ? dyn_cast(V) : NULL; + if (V && !PN) + return false; + + BasicBlock *BB = RI->getParent(); + if (PN && PN->getParent() != BB) + return false; + + // It's not safe to eliminate the sign / zero extension of the return value. + // See llvm::isInTailCallPosition(). + const Function *F = BB->getParent(); + unsigned CallerRetAttr = F->getAttributes().getRetAttributes(); + if ((CallerRetAttr & Attribute::ZExt) || (CallerRetAttr & Attribute::SExt)) + return false; + + // Make sure there are no instructions between the PHI and return, or that the + // return is the first instruction in the block. + if (PN) { + BasicBlock::iterator BI = BB->begin(); + do { ++BI; } while (isa(BI)); + if (&*BI != RI) + return false; + } else { + BasicBlock::iterator BI = BB->begin(); + while (isa(BI)) ++BI; + if (&*BI != RI) + return false; + } + + /// Only dup the ReturnInst if the CallInst is likely to be emitted as a tail + /// call. + SmallVector TailCalls; + if (PN) { + for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I) { + CallInst *CI = dyn_cast(PN->getIncomingValue(I)); + // Make sure the phi value is indeed produced by the tail call. + if (CI && CI->hasOneUse() && CI->getParent() == PN->getIncomingBlock(I) && + TLI->mayBeEmittedAsTailCall(CI)) + TailCalls.push_back(CI); + } + } else { + SmallPtrSet VisitedBBs; + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) { + if (!VisitedBBs.insert(*PI)) + continue; + + BasicBlock::InstListType &InstList = (*PI)->getInstList(); + BasicBlock::InstListType::reverse_iterator RI = InstList.rbegin(); + BasicBlock::InstListType::reverse_iterator RE = InstList.rend(); + do { ++RI; } while (RI != RE && isa(&*RI)); + if (RI == RE) + continue; + + CallInst *CI = dyn_cast(&*RI); + if (CI && CI->use_empty() && TLI->mayBeEmittedAsTailCall(CI)) + TailCalls.push_back(CI); + } + } + + bool Changed = false; + for (unsigned i = 0, e = TailCalls.size(); i != e; ++i) { + CallInst *CI = TailCalls[i]; + CallSite CS(CI); + + // Conservatively require the attributes of the call to match those of the + // return. Ignore noalias because it doesn't affect the call sequence. + unsigned CalleeRetAttr = CS.getAttributes().getRetAttributes(); + if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias) + continue; + + // Make sure the call instruction is followed by an unconditional branch to + // the return block. + BasicBlock *CallBB = CI->getParent(); + BranchInst *BI = dyn_cast(CallBB->getTerminator()); + if (!BI || !BI->isUnconditional() || BI->getSuccessor(0) != BB) + continue; + + // Duplicate the return into CallBB. + (void)FoldReturnIntoUncondBranch(RI, BB, CallBB); + ModifiedDT = Changed = true; + ++NumRetsDup; + } + + // If we eliminated all predecessors of the block, delete the block now. + if (Changed && pred_begin(BB) == pred_end(BB)) + BB->eraseFromParent(); + + return Changed; +} + //===----------------------------------------------------------------------===// // Memory Optimization //===----------------------------------------------------------------------===// @@ -701,7 +719,8 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, // the addressing mode obtained from the non-PHI roots of the graph // are equivalent. Value *Consensus = 0; - unsigned NumUses = 0; + unsigned NumUsesConsensus = 0; + bool IsNumUsesConsensusValid = false; SmallVector AddrModeInsts; ExtAddrMode AddrMode; while (!worklist.empty()) { @@ -728,16 +747,31 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, ExtAddrMode NewAddrMode = AddressingModeMatcher::Match(V, AccessTy,MemoryInst, NewAddrModeInsts, *TLI); - - // Ensure that the obtained addressing mode is equivalent to that obtained - // for all other roots of the PHI traversal. Also, when choosing one - // such root as representative, select the one with the most uses in order - // to keep the cost modeling heuristics in AddressingModeMatcher applicable. - if (!Consensus || NewAddrMode == AddrMode) { - if (V->getNumUses() > NumUses) { + + // This check is broken into two cases with very similar code to avoid using + // getNumUses() as much as possible. Some values have a lot of uses, so + // calling getNumUses() unconditionally caused a significant compile-time + // regression. + if (!Consensus) { + Consensus = V; + AddrMode = NewAddrMode; + AddrModeInsts = NewAddrModeInsts; + continue; + } else if (NewAddrMode == AddrMode) { + if (!IsNumUsesConsensusValid) { + NumUsesConsensus = Consensus->getNumUses(); + IsNumUsesConsensusValid = true; + } + + // Ensure that the obtained addressing mode is equivalent to that obtained + // for all other roots of the PHI traversal. Also, when choosing one + // such root as representative, select the one with the most uses in order + // to keep the cost modeling heuristics in AddressingModeMatcher + // applicable. + unsigned NumUses = V->getNumUses(); + if (NumUses > NumUsesConsensus) { Consensus = V; - NumUses = V->getNumUses(); - AddrMode = NewAddrMode; + NumUsesConsensus = NumUses; AddrModeInsts = NewAddrModeInsts; } continue; @@ -855,11 +889,26 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, MemoryInst->replaceUsesOfWith(Repl, SunkAddr); + // If we have no uses, recursively delete the value and all dead instructions + // using it. if (Repl->use_empty()) { + // This can cause recursive deletion, which can invalidate our iterator. + // Use a WeakVH to hold onto it in case this happens. + WeakVH IterHandle(CurInstIterator); + BasicBlock *BB = CurInstIterator->getParent(); + RecursivelyDeleteTriviallyDeadInstructions(Repl); - // This address is now available for reassignment, so erase the table entry; - // we don't want to match some completely different instruction. - SunkAddrs[Addr] = 0; + + if (IterHandle != CurInstIterator) { + // If the iterator instruction was recursively deleted, start over at the + // start of the block. + CurInstIterator = BB->begin(); + SunkAddrs.clear(); + } else { + // This address is now available for reassignment, so erase the table + // entry; we don't want to match some completely different instruction. + SunkAddrs[Addr] = 0; + } } ++NumMemoryInsts; return true; @@ -1073,6 +1122,9 @@ bool CodeGenPrepare::OptimizeInst(Instruction *I) { if (CallInst *CI = dyn_cast(I)) return OptimizeCallInst(CI); + if (ReturnInst *RI = dyn_cast(I)) + return DupRetToEnableTailCallOpts(RI); + return false; } @@ -1080,21 +1132,8 @@ bool CodeGenPrepare::OptimizeInst(Instruction *I) { // across basic blocks and rewrite them to improve basic-block-at-a-time // selection. bool CodeGenPrepare::OptimizeBlock(BasicBlock &BB) { - bool MadeChange = false; - - // Split all critical edges where the dest block has a PHI. - if (CriticalEdgeSplit) { - TerminatorInst *BBTI = BB.getTerminator(); - if (BBTI->getNumSuccessors() > 1 && !isa(BBTI)) { - for (unsigned i = 0, e = BBTI->getNumSuccessors(); i != e; ++i) { - BasicBlock *SuccBB = BBTI->getSuccessor(i); - if (isa(SuccBB->begin()) && isCriticalEdge(BBTI, i, true)) - SplitEdgeNicely(BBTI, i, BackEdges, this); - } - } - } - SunkAddrs.clear(); + bool MadeChange = false; CurInstIterator = BB.begin(); for (BasicBlock::iterator E = BB.end(); CurInstIterator != E; ) diff --git a/contrib/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/contrib/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index be12973b645f..e275268fc4ea 100644 --- a/contrib/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -13,6 +13,7 @@ #define DEBUG_TYPE "correlated-value-propagation" #include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Pass.h" diff --git a/contrib/llvm/lib/Transforms/Scalar/DCE.cpp b/contrib/llvm/lib/Transforms/Scalar/DCE.cpp index dbb68f3e0bd1..8dbcc23d7ec8 100644 --- a/contrib/llvm/lib/Transforms/Scalar/DCE.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/DCE.cpp @@ -23,7 +23,6 @@ #include "llvm/Pass.h" #include "llvm/Support/InstIterator.h" #include "llvm/ADT/Statistic.h" -#include using namespace llvm; STATISTIC(DIEEliminated, "Number of insts removed by DIE pass"); diff --git a/contrib/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/contrib/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index 867a06ad202d..53e46400dca8 100644 --- a/contrib/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -340,24 +340,35 @@ static bool isCompleteOverwrite(const AliasAnalysis::Location &Later, // Okay, we have stores to two completely different pointers. Try to // decompose the pointer into a "base + constant_offset" form. If the base // pointers are equal, then we can reason about the two stores. - int64_t Off1 = 0, Off2 = 0; - const Value *BP1 = GetPointerBaseWithConstantOffset(P1, Off1, TD); - const Value *BP2 = GetPointerBaseWithConstantOffset(P2, Off2, TD); + int64_t EarlierOff = 0, LaterOff = 0; + const Value *BP1 = GetPointerBaseWithConstantOffset(P1, EarlierOff, TD); + const Value *BP2 = GetPointerBaseWithConstantOffset(P2, LaterOff, TD); // If the base pointers still differ, we have two completely different stores. if (BP1 != BP2) return false; - - // Otherwise, we might have a situation like: - // store i16 -> P + 1 Byte - // store i32 -> P - // In this case, we see if the later store completely overlaps all bytes - // stored by the previous store. - if (Off1 < Off2 || // Earlier starts before Later. - Off1+Earlier.Size > Off2+Later.Size) // Earlier goes beyond Later. - return false; - // Otherwise, we have complete overlap. - return true; + + // The later store completely overlaps the earlier store if: + // + // 1. Both start at the same offset and the later one's size is greater than + // or equal to the earlier one's, or + // + // |--earlier--| + // |-- later --| + // + // 2. The earlier store has an offset greater than the later offset, but which + // still lies completely within the later store. + // + // |--earlier--| + // |----- later ------| + // + // We have to be careful here as *Off is signed while *.Size is unsigned. + if (EarlierOff >= LaterOff && + uint64_t(EarlierOff - LaterOff) + Earlier.Size <= Later.Size) + return true; + + // Otherwise, they don't completely overlap. + return false; } /// isPossibleSelfRead - If 'Inst' might be a self read (i.e. a noop copy of a @@ -474,7 +485,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { // away the store and we bail out. However, if we depend on on something // that overwrites the memory location we *can* potentially optimize it. // - // Find out what memory location the dependant instruction stores. + // Find out what memory location the dependent instruction stores. Instruction *DepWrite = InstDep.getInst(); AliasAnalysis::Location DepLoc = getLocForWrite(DepWrite, *AA); // If we didn't get a useful location, or if it isn't a size, bail out. @@ -631,28 +642,15 @@ bool DSE::handleEndBlock(BasicBlock &BB) { if (AA->doesNotAccessMemory(CS)) continue; - unsigned NumModRef = 0, NumOther = 0; - // If the call might load from any of our allocas, then any store above // the call is live. SmallVector LiveAllocas; for (SmallPtrSet::iterator I = DeadStackObjects.begin(), E = DeadStackObjects.end(); I != E; ++I) { - // If we detect that our AA is imprecise, it's not worth it to scan the - // rest of the DeadPointers set. Just assume that the AA will return - // ModRef for everything, and go ahead and bail out. - if (NumModRef >= 16 && NumOther == 0) - return MadeChange; - // See if the call site touches it. AliasAnalysis::ModRefResult A = AA->getModRefInfo(CS, *I, getPointerSize(*I, *AA)); - if (A == AliasAnalysis::ModRef) - ++NumModRef; - else - ++NumOther; - if (A == AliasAnalysis::ModRef || A == AliasAnalysis::Ref) LiveAllocas.push_back(*I); } diff --git a/contrib/llvm/lib/Transforms/Scalar/GEPSplitter.cpp b/contrib/llvm/lib/Transforms/Scalar/GEPSplitter.cpp deleted file mode 100644 index 4c3d188a8afd..000000000000 --- a/contrib/llvm/lib/Transforms/Scalar/GEPSplitter.cpp +++ /dev/null @@ -1,83 +0,0 @@ -//===- GEPSplitter.cpp - Split complex GEPs into simple ones --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This function breaks GEPs with more than 2 non-zero operands into smaller -// GEPs each with no more than 2 non-zero operands. This exposes redundancy -// between GEPs with common initial operand sequences. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "split-geps" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Constants.h" -#include "llvm/Function.h" -#include "llvm/Instructions.h" -#include "llvm/Pass.h" -using namespace llvm; - -namespace { - class GEPSplitter : public FunctionPass { - virtual bool runOnFunction(Function &F); - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - public: - static char ID; // Pass identification, replacement for typeid - explicit GEPSplitter() : FunctionPass(ID) { - initializeGEPSplitterPass(*PassRegistry::getPassRegistry()); - } - }; -} - -char GEPSplitter::ID = 0; -INITIALIZE_PASS(GEPSplitter, "split-geps", - "split complex GEPs into simple GEPs", false, false) - -FunctionPass *llvm::createGEPSplitterPass() { - return new GEPSplitter(); -} - -bool GEPSplitter::runOnFunction(Function &F) { - bool Changed = false; - - // Visit each GEP instruction. - for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) - for (BasicBlock::iterator II = I->begin(), IE = I->end(); II != IE; ) - if (GetElementPtrInst *GEP = dyn_cast(II++)) { - unsigned NumOps = GEP->getNumOperands(); - // Ignore GEPs which are already simple. - if (NumOps <= 2) - continue; - bool FirstIndexIsZero = isa(GEP->getOperand(1)) && - cast(GEP->getOperand(1))->isZero(); - if (NumOps == 3 && FirstIndexIsZero) - continue; - // The first index is special and gets expanded with a 2-operand GEP - // (unless it's zero, in which case we can skip this). - Value *NewGEP = FirstIndexIsZero ? - GEP->getOperand(0) : - GetElementPtrInst::Create(GEP->getOperand(0), GEP->getOperand(1), - "tmp", GEP); - // All remaining indices get expanded with a 3-operand GEP with zero - // as the second operand. - Value *Idxs[2]; - Idxs[0] = ConstantInt::get(Type::getInt64Ty(F.getContext()), 0); - for (unsigned i = 2; i != NumOps; ++i) { - Idxs[1] = GEP->getOperand(i); - NewGEP = GetElementPtrInst::Create(NewGEP, Idxs, Idxs+2, "tmp", GEP); - } - GEP->replaceAllUsesWith(NewGEP); - GEP->eraseFromParent(); - Changed = true; - } - - return Changed; -} - -void GEPSplitter::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); -} diff --git a/contrib/llvm/lib/Transforms/Scalar/GVN.cpp b/contrib/llvm/lib/Transforms/Scalar/GVN.cpp index a0123f589816..efecb97de77d 100644 --- a/contrib/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/GVN.cpp @@ -63,50 +63,48 @@ static cl::opt EnableLoadPRE("enable-load-pre", cl::init(true)); namespace { struct Expression { uint32_t opcode; - const Type* type; + const Type *type; SmallVector varargs; - Expression() { } - Expression(uint32_t o) : opcode(o) { } + Expression(uint32_t o = ~2U) : opcode(o) { } bool operator==(const Expression &other) const { if (opcode != other.opcode) return false; - else if (opcode == ~0U || opcode == ~1U) + if (opcode == ~0U || opcode == ~1U) return true; - else if (type != other.type) + if (type != other.type) return false; - else if (varargs != other.varargs) + if (varargs != other.varargs) return false; return true; } }; class ValueTable { - private: - DenseMap valueNumbering; - DenseMap expressionNumbering; - AliasAnalysis* AA; - MemoryDependenceAnalysis* MD; - DominatorTree* DT; + DenseMap valueNumbering; + DenseMap expressionNumbering; + AliasAnalysis *AA; + MemoryDependenceAnalysis *MD; + DominatorTree *DT; - uint32_t nextValueNumber; + uint32_t nextValueNumber; - Expression create_expression(Instruction* I); - uint32_t lookup_or_add_call(CallInst* C); - public: - ValueTable() : nextValueNumber(1) { } - uint32_t lookup_or_add(Value *V); - uint32_t lookup(Value *V) const; - void add(Value *V, uint32_t num); - void clear(); - void erase(Value *v); - void setAliasAnalysis(AliasAnalysis* A) { AA = A; } - AliasAnalysis *getAliasAnalysis() const { return AA; } - void setMemDep(MemoryDependenceAnalysis* M) { MD = M; } - void setDomTree(DominatorTree* D) { DT = D; } - uint32_t getNextUnusedValueNumber() { return nextValueNumber; } - void verifyRemoved(const Value *) const; + Expression create_expression(Instruction* I); + uint32_t lookup_or_add_call(CallInst* C); + public: + ValueTable() : nextValueNumber(1) { } + uint32_t lookup_or_add(Value *V); + uint32_t lookup(Value *V) const; + void add(Value *V, uint32_t num); + void clear(); + void erase(Value *v); + void setAliasAnalysis(AliasAnalysis* A) { AA = A; } + AliasAnalysis *getAliasAnalysis() const { return AA; } + void setMemDep(MemoryDependenceAnalysis* M) { MD = M; } + void setDomTree(DominatorTree* D) { DT = D; } + uint32_t getNextUnusedValueNumber() { return nextValueNumber; } + void verifyRemoved(const Value *) const; }; } @@ -364,14 +362,14 @@ uint32_t ValueTable::lookup(Value *V) const { return VI->second; } -/// clear - Remove all entries from the ValueTable +/// clear - Remove all entries from the ValueTable. void ValueTable::clear() { valueNumbering.clear(); expressionNumbering.clear(); nextValueNumber = 1; } -/// erase - Remove a value from the value numbering +/// erase - Remove a value from the value numbering. void ValueTable::erase(Value *V) { valueNumbering.erase(V); } @@ -392,20 +390,11 @@ void ValueTable::verifyRemoved(const Value *V) const { namespace { class GVN : public FunctionPass { - bool runOnFunction(Function &F); - public: - static char ID; // Pass identification, replacement for typeid - explicit GVN(bool noloads = false) - : FunctionPass(ID), NoLoads(noloads), MD(0) { - initializeGVNPass(*PassRegistry::getPassRegistry()); - } - - private: bool NoLoads; MemoryDependenceAnalysis *MD; DominatorTree *DT; - const TargetData* TD; - + const TargetData *TD; + ValueTable VN; /// LeaderTable - A mapping from value numbers to lists of Value*'s that @@ -418,17 +407,39 @@ namespace { DenseMap LeaderTable; BumpPtrAllocator TableAllocator; + SmallVector InstrsToErase; + public: + static char ID; // Pass identification, replacement for typeid + explicit GVN(bool noloads = false) + : FunctionPass(ID), NoLoads(noloads), MD(0) { + initializeGVNPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F); + + /// markInstructionForDeletion - This removes the specified instruction from + /// our various maps and marks it for deletion. + void markInstructionForDeletion(Instruction *I) { + VN.erase(I); + InstrsToErase.push_back(I); + } + + const TargetData *getTargetData() const { return TD; } + DominatorTree &getDominatorTree() const { return *DT; } + AliasAnalysis *getAliasAnalysis() const { return VN.getAliasAnalysis(); } + MemoryDependenceAnalysis &getMemDep() const { return *MD; } + private: /// addToLeaderTable - Push a new Value to the LeaderTable onto the list for /// its value number. void addToLeaderTable(uint32_t N, Value *V, BasicBlock *BB) { - LeaderTableEntry& Curr = LeaderTable[N]; + LeaderTableEntry &Curr = LeaderTable[N]; if (!Curr.Val) { Curr.Val = V; Curr.BB = BB; return; } - LeaderTableEntry* Node = TableAllocator.Allocate(); + LeaderTableEntry *Node = TableAllocator.Allocate(); Node->Val = V; Node->BB = BB; Node->Next = Curr.Next; @@ -474,19 +485,17 @@ namespace { AU.addPreserved(); AU.addPreserved(); } + // Helper fuctions // FIXME: eliminate or document these better - bool processLoad(LoadInst* L, - SmallVectorImpl &toErase); - bool processInstruction(Instruction *I, - SmallVectorImpl &toErase); - bool processNonLocalLoad(LoadInst* L, - SmallVectorImpl &toErase); + bool processLoad(LoadInst *L); + bool processInstruction(Instruction *I); + bool processNonLocalLoad(LoadInst *L); bool processBlock(BasicBlock *BB); - void dump(DenseMap& d); + void dump(DenseMap &d); bool iterateOnFunction(Function &F); - bool performPRE(Function& F); + bool performPRE(Function &F); Value *findLeader(BasicBlock *BB, uint32_t num); void cleanupGlobalSets(); void verifyRemoved(const Instruction *I) const; @@ -629,17 +638,17 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, if (!CanCoerceMustAliasedValueToLoad(StoredVal, LoadedTy, TD)) return 0; + // If this is already the right type, just return it. const Type *StoredValTy = StoredVal->getType(); uint64_t StoreSize = TD.getTypeStoreSizeInBits(StoredValTy); - uint64_t LoadSize = TD.getTypeSizeInBits(LoadedTy); + uint64_t LoadSize = TD.getTypeStoreSizeInBits(LoadedTy); // If the store and reload are the same size, we can always reuse it. if (StoreSize == LoadSize) { - if (StoredValTy->isPointerTy() && LoadedTy->isPointerTy()) { - // Pointer to Pointer -> use bitcast. + // Pointer to Pointer -> use bitcast. + if (StoredValTy->isPointerTy() && LoadedTy->isPointerTy()) return new BitCastInst(StoredVal, LoadedTy, "", InsertPt); - } // Convert source pointers to integers, which can be bitcast. if (StoredValTy->isPointerTy()) { @@ -796,6 +805,36 @@ static int AnalyzeLoadFromClobberingStore(const Type *LoadTy, Value *LoadPtr, StorePtr, StoreSize, TD); } +/// AnalyzeLoadFromClobberingLoad - This function is called when we have a +/// memdep query of a load that ends up being clobbered by another load. See if +/// the other load can feed into the second load. +static int AnalyzeLoadFromClobberingLoad(const Type *LoadTy, Value *LoadPtr, + LoadInst *DepLI, const TargetData &TD){ + // Cannot handle reading from store of first-class aggregate yet. + if (DepLI->getType()->isStructTy() || DepLI->getType()->isArrayTy()) + return -1; + + Value *DepPtr = DepLI->getPointerOperand(); + uint64_t DepSize = TD.getTypeSizeInBits(DepLI->getType()); + int R = AnalyzeLoadFromClobberingWrite(LoadTy, LoadPtr, DepPtr, DepSize, TD); + if (R != -1) return R; + + // If we have a load/load clobber an DepLI can be widened to cover this load, + // then we should widen it! + int64_t LoadOffs = 0; + const Value *LoadBase = + GetPointerBaseWithConstantOffset(LoadPtr, LoadOffs, TD); + unsigned LoadSize = TD.getTypeStoreSize(LoadTy); + + unsigned Size = MemoryDependenceAnalysis:: + getLoadLoadClobberFullWidthSize(LoadBase, LoadOffs, LoadSize, DepLI, TD); + if (Size == 0) return -1; + + return AnalyzeLoadFromClobberingWrite(LoadTy, LoadPtr, DepPtr, Size*8, TD); +} + + + static int AnalyzeLoadFromClobberingMemInst(const Type *LoadTy, Value *LoadPtr, MemIntrinsic *MI, const TargetData &TD) { @@ -843,9 +882,9 @@ static int AnalyzeLoadFromClobberingMemInst(const Type *LoadTy, Value *LoadPtr, /// GetStoreValueForLoad - This function is called when we have a /// memdep query of a load that ends up being a clobbering store. This means -/// that the store *may* provide bits used by the load but we can't be sure -/// because the pointers don't mustalias. Check this case to see if there is -/// anything more we can do before we give up. +/// that the store provides bits used by the load but we the pointers don't +/// mustalias. Check this case to see if there is anything more we can do +/// before we give up. static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset, const Type *LoadTy, Instruction *InsertPt, const TargetData &TD){ @@ -881,6 +920,69 @@ static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset, return CoerceAvailableValueToLoadType(SrcVal, LoadTy, InsertPt, TD); } +/// GetStoreValueForLoad - This function is called when we have a +/// memdep query of a load that ends up being a clobbering load. This means +/// that the load *may* provide bits used by the load but we can't be sure +/// because the pointers don't mustalias. Check this case to see if there is +/// anything more we can do before we give up. +static Value *GetLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, + const Type *LoadTy, Instruction *InsertPt, + GVN &gvn) { + const TargetData &TD = *gvn.getTargetData(); + // If Offset+LoadTy exceeds the size of SrcVal, then we must be wanting to + // widen SrcVal out to a larger load. + unsigned SrcValSize = TD.getTypeStoreSize(SrcVal->getType()); + unsigned LoadSize = TD.getTypeStoreSize(LoadTy); + if (Offset+LoadSize > SrcValSize) { + assert(!SrcVal->isVolatile() && "Cannot widen volatile load!"); + assert(isa(SrcVal->getType())&&"Can't widen non-integer load"); + // If we have a load/load clobber an DepLI can be widened to cover this + // load, then we should widen it to the next power of 2 size big enough! + unsigned NewLoadSize = Offset+LoadSize; + if (!isPowerOf2_32(NewLoadSize)) + NewLoadSize = NextPowerOf2(NewLoadSize); + + Value *PtrVal = SrcVal->getPointerOperand(); + + // Insert the new load after the old load. This ensures that subsequent + // memdep queries will find the new load. We can't easily remove the old + // load completely because it is already in the value numbering table. + IRBuilder<> Builder(SrcVal->getParent(), ++BasicBlock::iterator(SrcVal)); + const Type *DestPTy = + IntegerType::get(LoadTy->getContext(), NewLoadSize*8); + DestPTy = PointerType::get(DestPTy, + cast(PtrVal->getType())->getAddressSpace()); + + PtrVal = Builder.CreateBitCast(PtrVal, DestPTy); + LoadInst *NewLoad = Builder.CreateLoad(PtrVal); + NewLoad->takeName(SrcVal); + NewLoad->setAlignment(SrcVal->getAlignment()); + + DEBUG(dbgs() << "GVN WIDENED LOAD: " << *SrcVal << "\n"); + DEBUG(dbgs() << "TO: " << *NewLoad << "\n"); + + // Replace uses of the original load with the wider load. On a big endian + // system, we need to shift down to get the relevant bits. + Value *RV = NewLoad; + if (TD.isBigEndian()) + RV = Builder.CreateLShr(RV, + NewLoadSize*8-SrcVal->getType()->getPrimitiveSizeInBits()); + RV = Builder.CreateTrunc(RV, SrcVal->getType()); + SrcVal->replaceAllUsesWith(RV); + + // We would like to use gvn.markInstructionForDeletion here, but we can't + // because the load is already memoized into the leader map table that GVN + // tracks. It is potentially possible to remove the load from the table, + // but then there all of the operations based on it would need to be + // rehashed. Just leave the dead load around. + gvn.getMemDep().removeInstruction(SrcVal); + SrcVal = NewLoad; + } + + return GetStoreValueForLoad(SrcVal, Offset, LoadTy, InsertPt, TD); +} + + /// GetMemInstValueForLoad - This function is called when we have a /// memdep query of a load that ends up being a clobbering mem intrinsic. static Value *GetMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, @@ -943,11 +1045,12 @@ struct AvailableValueInBlock { BasicBlock *BB; enum ValType { SimpleVal, // A simple offsetted value that is accessed. + LoadVal, // A value produced by a load. MemIntrin // A memory intrinsic which is loaded from. }; /// V - The value that is live out of the block. - PointerIntPair Val; + PointerIntPair Val; /// Offset - The byte offset in Val that is interesting for the load query. unsigned Offset; @@ -972,37 +1075,69 @@ struct AvailableValueInBlock { return Res; } + static AvailableValueInBlock getLoad(BasicBlock *BB, LoadInst *LI, + unsigned Offset = 0) { + AvailableValueInBlock Res; + Res.BB = BB; + Res.Val.setPointer(LI); + Res.Val.setInt(LoadVal); + Res.Offset = Offset; + return Res; + } + bool isSimpleValue() const { return Val.getInt() == SimpleVal; } + bool isCoercedLoadValue() const { return Val.getInt() == LoadVal; } + bool isMemIntrinValue() const { return Val.getInt() == MemIntrin; } + Value *getSimpleValue() const { assert(isSimpleValue() && "Wrong accessor"); return Val.getPointer(); } + LoadInst *getCoercedLoadValue() const { + assert(isCoercedLoadValue() && "Wrong accessor"); + return cast(Val.getPointer()); + } + MemIntrinsic *getMemIntrinValue() const { - assert(!isSimpleValue() && "Wrong accessor"); + assert(isMemIntrinValue() && "Wrong accessor"); return cast(Val.getPointer()); } /// MaterializeAdjustedValue - Emit code into this block to adjust the value /// defined here to the specified type. This handles various coercion cases. - Value *MaterializeAdjustedValue(const Type *LoadTy, - const TargetData *TD) const { + Value *MaterializeAdjustedValue(const Type *LoadTy, GVN &gvn) const { Value *Res; if (isSimpleValue()) { Res = getSimpleValue(); if (Res->getType() != LoadTy) { + const TargetData *TD = gvn.getTargetData(); assert(TD && "Need target data to handle type mismatch case"); Res = GetStoreValueForLoad(Res, Offset, LoadTy, BB->getTerminator(), *TD); - DEBUG(errs() << "GVN COERCED NONLOCAL VAL:\nOffset: " << Offset << " " + DEBUG(dbgs() << "GVN COERCED NONLOCAL VAL:\nOffset: " << Offset << " " << *getSimpleValue() << '\n' << *Res << '\n' << "\n\n\n"); } + } else if (isCoercedLoadValue()) { + LoadInst *Load = getCoercedLoadValue(); + if (Load->getType() == LoadTy && Offset == 0) { + Res = Load; + } else { + Res = GetLoadValueForLoad(Load, Offset, LoadTy, BB->getTerminator(), + gvn); + + DEBUG(dbgs() << "GVN COERCED NONLOCAL LOAD:\nOffset: " << Offset << " " + << *getCoercedLoadValue() << '\n' + << *Res << '\n' << "\n\n\n"); + } } else { + const TargetData *TD = gvn.getTargetData(); + assert(TD && "Need target data to handle type mismatch case"); Res = GetMemInstValueForLoad(getMemIntrinValue(), Offset, LoadTy, BB->getTerminator(), *TD); - DEBUG(errs() << "GVN COERCED NONLOCAL MEM INTRIN:\nOffset: " << Offset + DEBUG(dbgs() << "GVN COERCED NONLOCAL MEM INTRIN:\nOffset: " << Offset << " " << *getMemIntrinValue() << '\n' << *Res << '\n' << "\n\n\n"); } @@ -1010,21 +1145,20 @@ struct AvailableValueInBlock { } }; -} +} // end anonymous namespace /// ConstructSSAForLoadSet - Given a set of loads specified by ValuesPerBlock, /// construct SSA form, allowing us to eliminate LI. This returns the value /// that should be used at LI's definition site. static Value *ConstructSSAForLoadSet(LoadInst *LI, SmallVectorImpl &ValuesPerBlock, - const TargetData *TD, - const DominatorTree &DT, - AliasAnalysis *AA) { + GVN &gvn) { // Check for the fully redundant, dominating load case. In this case, we can // just use the dominating value directly. if (ValuesPerBlock.size() == 1 && - DT.properlyDominates(ValuesPerBlock[0].BB, LI->getParent())) - return ValuesPerBlock[0].MaterializeAdjustedValue(LI->getType(), TD); + gvn.getDominatorTree().properlyDominates(ValuesPerBlock[0].BB, + LI->getParent())) + return ValuesPerBlock[0].MaterializeAdjustedValue(LI->getType(), gvn); // Otherwise, we have to construct SSA form. SmallVector NewPHIs; @@ -1040,14 +1174,16 @@ static Value *ConstructSSAForLoadSet(LoadInst *LI, if (SSAUpdate.HasValueForBlock(BB)) continue; - SSAUpdate.AddAvailableValue(BB, AV.MaterializeAdjustedValue(LoadTy, TD)); + SSAUpdate.AddAvailableValue(BB, AV.MaterializeAdjustedValue(LoadTy, gvn)); } // Perform PHI construction. Value *V = SSAUpdate.GetValueInMiddleOfBlock(LI->getParent()); // If new PHI nodes were created, notify alias analysis. - if (V->getType()->isPointerTy()) + if (V->getType()->isPointerTy()) { + AliasAnalysis *AA = gvn.getAliasAnalysis(); + for (unsigned i = 0, e = NewPHIs.size(); i != e; ++i) AA->copyValue(LI, NewPHIs[i]); @@ -1059,6 +1195,7 @@ static Value *ConstructSSAForLoadSet(LoadInst *LI, for (unsigned ii = 0, ee = P->getNumIncomingValues(); ii != ee; ++ii) AA->addEscapingUse(P->getOperandUse(2*ii)); } + } return V; } @@ -1071,8 +1208,7 @@ static bool isLifetimeStart(const Instruction *Inst) { /// processNonLocalLoad - Attempt to eliminate a load whose dependencies are /// non-local by performing PHI construction. -bool GVN::processNonLocalLoad(LoadInst *LI, - SmallVectorImpl &toErase) { +bool GVN::processNonLocalLoad(LoadInst *LI) { // Find the non-local dependencies of the load. SmallVector Deps; AliasAnalysis::Location Loc = VN.getAliasAnalysis()->getLocation(LI); @@ -1088,7 +1224,8 @@ bool GVN::processNonLocalLoad(LoadInst *LI, // If we had a phi translation failure, we'll have a single entry which is a // clobber in the current block. Reject this early. - if (Deps.size() == 1 && Deps[0].getResult().isClobber()) { + if (Deps.size() == 1 && Deps[0].getResult().isClobber() && + Deps[0].getResult().getInst()->getParent() == LI->getParent()) { DEBUG( dbgs() << "GVN: non-local load "; WriteAsOperand(dbgs(), LI); @@ -1129,6 +1266,26 @@ bool GVN::processNonLocalLoad(LoadInst *LI, } } } + + // Check to see if we have something like this: + // load i32* P + // load i8* (P+1) + // if we have this, replace the later with an extraction from the former. + if (LoadInst *DepLI = dyn_cast(DepInfo.getInst())) { + // If this is a clobber and L is the first instruction in its block, then + // we have the first instruction in the entry block. + if (DepLI != LI && Address && TD) { + int Offset = AnalyzeLoadFromClobberingLoad(LI->getType(), + LI->getPointerOperand(), + DepLI, *TD); + + if (Offset != -1) { + ValuesPerBlock.push_back(AvailableValueInBlock::getLoad(DepBB,DepLI, + Offset)); + continue; + } + } + } // If the clobbering value is a memset/memcpy/memmove, see if we can // forward a value on from it. @@ -1187,7 +1344,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI, continue; } } - ValuesPerBlock.push_back(AvailableValueInBlock::get(DepBB, LD)); + ValuesPerBlock.push_back(AvailableValueInBlock::getLoad(DepBB, LD)); continue; } @@ -1206,16 +1363,14 @@ bool GVN::processNonLocalLoad(LoadInst *LI, DEBUG(dbgs() << "GVN REMOVING NONLOCAL LOAD: " << *LI << '\n'); // Perform PHI construction. - Value *V = ConstructSSAForLoadSet(LI, ValuesPerBlock, TD, *DT, - VN.getAliasAnalysis()); + Value *V = ConstructSSAForLoadSet(LI, ValuesPerBlock, *this); LI->replaceAllUsesWith(V); if (isa(V)) V->takeName(LI); if (V->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(V); - VN.erase(LI); - toErase.push_back(LI); + markInstructionForDeletion(LI); ++NumGVNLoad; return true; } @@ -1429,22 +1584,20 @@ bool GVN::processNonLocalLoad(LoadInst *LI, } // Perform PHI construction. - Value *V = ConstructSSAForLoadSet(LI, ValuesPerBlock, TD, *DT, - VN.getAliasAnalysis()); + Value *V = ConstructSSAForLoadSet(LI, ValuesPerBlock, *this); LI->replaceAllUsesWith(V); if (isa(V)) V->takeName(LI); if (V->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(V); - VN.erase(LI); - toErase.push_back(LI); + markInstructionForDeletion(LI); ++NumPRELoad; return true; } /// processLoad - Attempt to eliminate a load, first by eliminating it /// locally, and then attempting non-local elimination if that fails. -bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { +bool GVN::processLoad(LoadInst *L) { if (!MD) return false; @@ -1454,8 +1607,9 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // ... to a pointer that has been loaded from before... MemDepResult Dep = MD->getDependency(L); - // If the value isn't available, don't do anything! - if (Dep.isClobber()) { + // If we have a clobber and target data is around, see if this is a clobber + // that we can fix up through code synthesis. + if (Dep.isClobber() && TD) { // Check to see if we have something like this: // store i32 123, i32* %P // %A = bitcast i32* %P to i8* @@ -1467,26 +1621,40 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // completely covers this load. This sort of thing can happen in bitfield // access code. Value *AvailVal = 0; - if (StoreInst *DepSI = dyn_cast(Dep.getInst())) - if (TD) { - int Offset = AnalyzeLoadFromClobberingStore(L->getType(), - L->getPointerOperand(), - DepSI, *TD); - if (Offset != -1) - AvailVal = GetStoreValueForLoad(DepSI->getValueOperand(), Offset, - L->getType(), L, *TD); - } + if (StoreInst *DepSI = dyn_cast(Dep.getInst())) { + int Offset = AnalyzeLoadFromClobberingStore(L->getType(), + L->getPointerOperand(), + DepSI, *TD); + if (Offset != -1) + AvailVal = GetStoreValueForLoad(DepSI->getValueOperand(), Offset, + L->getType(), L, *TD); + } + + // Check to see if we have something like this: + // load i32* P + // load i8* (P+1) + // if we have this, replace the later with an extraction from the former. + if (LoadInst *DepLI = dyn_cast(Dep.getInst())) { + // If this is a clobber and L is the first instruction in its block, then + // we have the first instruction in the entry block. + if (DepLI == L) + return false; + + int Offset = AnalyzeLoadFromClobberingLoad(L->getType(), + L->getPointerOperand(), + DepLI, *TD); + if (Offset != -1) + AvailVal = GetLoadValueForLoad(DepLI, Offset, L->getType(), L, *this); + } // If the clobbering value is a memset/memcpy/memmove, see if we can forward // a value on from it. if (MemIntrinsic *DepMI = dyn_cast(Dep.getInst())) { - if (TD) { - int Offset = AnalyzeLoadFromClobberingMemInst(L->getType(), - L->getPointerOperand(), - DepMI, *TD); - if (Offset != -1) - AvailVal = GetMemInstValueForLoad(DepMI, Offset, L->getType(), L,*TD); - } + int Offset = AnalyzeLoadFromClobberingMemInst(L->getType(), + L->getPointerOperand(), + DepMI, *TD); + if (Offset != -1) + AvailVal = GetMemInstValueForLoad(DepMI, Offset, L->getType(), L, *TD); } if (AvailVal) { @@ -1497,14 +1665,16 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { L->replaceAllUsesWith(AvailVal); if (AvailVal->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(AvailVal); - VN.erase(L); - toErase.push_back(L); + markInstructionForDeletion(L); ++NumGVNLoad; return true; } - + } + + // If the value isn't available, don't do anything! + if (Dep.isClobber()) { DEBUG( - // fast print dep, using operator<< on instruction would be too slow + // fast print dep, using operator<< on instruction is too slow. dbgs() << "GVN: load "; WriteAsOperand(dbgs(), L); Instruction *I = Dep.getInst(); @@ -1515,7 +1685,7 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // If it is defined in another block, try harder. if (Dep.isNonLocal()) - return processNonLocalLoad(L, toErase); + return processNonLocalLoad(L); Instruction *DepInst = Dep.getInst(); if (StoreInst *DepSI = dyn_cast(DepInst)) { @@ -1542,8 +1712,7 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { L->replaceAllUsesWith(StoredVal); if (StoredVal->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(StoredVal); - VN.erase(L); - toErase.push_back(L); + markInstructionForDeletion(L); ++NumGVNLoad; return true; } @@ -1556,7 +1725,8 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // (depending on its type). if (DepLI->getType() != L->getType()) { if (TD) { - AvailableVal = CoerceAvailableValueToLoadType(DepLI, L->getType(), L,*TD); + AvailableVal = CoerceAvailableValueToLoadType(DepLI, L->getType(), + L, *TD); if (AvailableVal == 0) return false; @@ -1571,8 +1741,7 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { L->replaceAllUsesWith(AvailableVal); if (DepLI->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(DepLI); - VN.erase(L); - toErase.push_back(L); + markInstructionForDeletion(L); ++NumGVNLoad; return true; } @@ -1582,19 +1751,17 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // intervening stores, for example. if (isa(DepInst) || isMalloc(DepInst)) { L->replaceAllUsesWith(UndefValue::get(L->getType())); - VN.erase(L); - toErase.push_back(L); + markInstructionForDeletion(L); ++NumGVNLoad; return true; } // If this load occurs either right after a lifetime begin, // then the loaded value is undefined. - if (IntrinsicInst* II = dyn_cast(DepInst)) { + if (IntrinsicInst *II = dyn_cast(DepInst)) { if (II->getIntrinsicID() == Intrinsic::lifetime_start) { L->replaceAllUsesWith(UndefValue::get(L->getType())); - VN.erase(L); - toErase.push_back(L); + markInstructionForDeletion(L); ++NumGVNLoad; return true; } @@ -1634,8 +1801,7 @@ Value *GVN::findLeader(BasicBlock *BB, uint32_t num) { /// processInstruction - When calculating availability, handle an instruction /// by inserting it into the appropriate sets -bool GVN::processInstruction(Instruction *I, - SmallVectorImpl &toErase) { +bool GVN::processInstruction(Instruction *I) { // Ignore dbg info intrinsics. if (isa(I)) return false; @@ -1648,20 +1814,17 @@ bool GVN::processInstruction(Instruction *I, I->replaceAllUsesWith(V); if (MD && V->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(V); - VN.erase(I); - toErase.push_back(I); + markInstructionForDeletion(I); return true; } if (LoadInst *LI = dyn_cast(I)) { - bool Changed = processLoad(LI, toErase); + if (processLoad(LI)) + return true; - if (!Changed) { - unsigned Num = VN.lookup_or_add(LI); - addToLeaderTable(Num, LI, LI->getParent()); - } - - return Changed; + unsigned Num = VN.lookup_or_add(LI); + addToLeaderTable(Num, LI, LI->getParent()); + return false; } // For conditions branches, we can perform simple conditional propagation on @@ -1720,11 +1883,10 @@ bool GVN::processInstruction(Instruction *I, } // Remove it! - VN.erase(I); I->replaceAllUsesWith(repl); if (MD && repl->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(repl); - toErase.push_back(I); + markInstructionForDeletion(I); return true; } @@ -1781,35 +1943,36 @@ bool GVN::runOnFunction(Function& F) { bool GVN::processBlock(BasicBlock *BB) { - // FIXME: Kill off toErase by doing erasing eagerly in a helper function (and - // incrementing BI before processing an instruction). - SmallVector toErase; + // FIXME: Kill off InstrsToErase by doing erasing eagerly in a helper function + // (and incrementing BI before processing an instruction). + assert(InstrsToErase.empty() && + "We expect InstrsToErase to be empty across iterations"); bool ChangedFunction = false; for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { - ChangedFunction |= processInstruction(BI, toErase); - if (toErase.empty()) { + ChangedFunction |= processInstruction(BI); + if (InstrsToErase.empty()) { ++BI; continue; } // If we need some instructions deleted, do it now. - NumGVNInstr += toErase.size(); + NumGVNInstr += InstrsToErase.size(); // Avoid iterator invalidation. bool AtStart = BI == BB->begin(); if (!AtStart) --BI; - for (SmallVector::iterator I = toErase.begin(), - E = toErase.end(); I != E; ++I) { + for (SmallVector::iterator I = InstrsToErase.begin(), + E = InstrsToErase.end(); I != E; ++I) { DEBUG(dbgs() << "GVN removed: " << **I << '\n'); if (MD) MD->removeInstruction(*I); (*I)->eraseFromParent(); DEBUG(verifyRemoved(*I)); } - toErase.clear(); + InstrsToErase.clear(); if (AtStart) BI = BB->begin(); @@ -1944,11 +2107,11 @@ bool GVN::performPRE(Function &F) { addToLeaderTable(ValNo, PREInstr, PREPred); // Create a PHI to make the value available in this block. - PHINode* Phi = PHINode::Create(CurInst->getType(), + pred_iterator PB = pred_begin(CurrentBlock), PE = pred_end(CurrentBlock); + PHINode* Phi = PHINode::Create(CurInst->getType(), std::distance(PB, PE), CurInst->getName() + ".pre-phi", CurrentBlock->begin()); - for (pred_iterator PI = pred_begin(CurrentBlock), - PE = pred_end(CurrentBlock); PI != PE; ++PI) { + for (pred_iterator PI = PB; PI != PE; ++PI) { BasicBlock *P = *PI; Phi->addIncoming(predMap[P], P); } diff --git a/contrib/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/contrib/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index 0fb67982a3db..09d569a097dd 100644 --- a/contrib/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -73,6 +73,7 @@ namespace { LoopInfo *LI; ScalarEvolution *SE; DominatorTree *DT; + SmallVector DeadInsts; bool Changed; public: @@ -98,6 +99,7 @@ namespace { } private: + bool isValidRewrite(Value *FromVal, Value *ToVal); void EliminateIVComparisons(); void EliminateIVRemainders(); @@ -134,6 +136,53 @@ Pass *llvm::createIndVarSimplifyPass() { return new IndVarSimplify(); } +/// isValidRewrite - Return true if the SCEV expansion generated by the +/// rewriter can replace the original value. SCEV guarantees that it +/// produces the same value, but the way it is produced may be illegal IR. +/// Ideally, this function will only be called for verification. +bool IndVarSimplify::isValidRewrite(Value *FromVal, Value *ToVal) { + // If an SCEV expression subsumed multiple pointers, its expansion could + // reassociate the GEP changing the base pointer. This is illegal because the + // final address produced by a GEP chain must be inbounds relative to its + // underlying object. Otherwise basic alias analysis, among other things, + // could fail in a dangerous way. Ultimately, SCEV will be improved to avoid + // producing an expression involving multiple pointers. Until then, we must + // bail out here. + // + // Retrieve the pointer operand of the GEP. Don't use GetUnderlyingObject + // because it understands lcssa phis while SCEV does not. + Value *FromPtr = FromVal; + Value *ToPtr = ToVal; + if (GEPOperator *GEP = dyn_cast(FromVal)) { + FromPtr = GEP->getPointerOperand(); + } + if (GEPOperator *GEP = dyn_cast(ToVal)) { + ToPtr = GEP->getPointerOperand(); + } + if (FromPtr != FromVal || ToPtr != ToVal) { + // Quickly check the common case + if (FromPtr == ToPtr) + return true; + + // SCEV may have rewritten an expression that produces the GEP's pointer + // operand. That's ok as long as the pointer operand has the same base + // pointer. Unlike GetUnderlyingObject(), getPointerBase() will find the + // base of a recurrence. This handles the case in which SCEV expansion + // converts a pointer type recurrence into a nonrecurrent pointer base + // indexed by an integer recurrence. + const SCEV *FromBase = SE->getPointerBase(SE->getSCEV(FromPtr)); + const SCEV *ToBase = SE->getPointerBase(SE->getSCEV(ToPtr)); + if (FromBase == ToBase) + return true; + + DEBUG(dbgs() << "INDVARS: GEP rewrite bail out " + << *FromBase << " != " << *ToBase << "\n"); + + return false; + } + return true; +} + /// LinearFunctionTestReplace - This method rewrites the exit condition of the /// loop to be a canonical != comparison against the incremented loop induction /// variable. This pass is able to rewrite the exit tests of any loop where the @@ -226,7 +275,7 @@ ICmpInst *IndVarSimplify::LinearFunctionTestReplace(Loop *L, // update the branch to use the new comparison; in the common case this // will make old comparison dead. BI->setCondition(Cond); - RecursivelyDeleteTriviallyDeadInstructions(OrigCond); + DeadInsts.push_back(OrigCond); ++NumLFTR; Changed = true; @@ -304,14 +353,18 @@ void IndVarSimplify::RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter) { if (!SE->isLoopInvariant(ExitValue, L)) continue; - Changed = true; - ++NumReplaced; - Value *ExitVal = Rewriter.expandCodeFor(ExitValue, PN->getType(), Inst); DEBUG(dbgs() << "INDVARS: RLEV: AfterLoopVal = " << *ExitVal << '\n' << " LoopVal = " << *Inst << "\n"); + if (!isValidRewrite(Inst, ExitVal)) { + DeadInsts.push_back(ExitVal); + continue; + } + Changed = true; + ++NumReplaced; + PN->setIncomingValue(i, ExitVal); // If this instruction is dead now, delete it. @@ -366,8 +419,6 @@ void IndVarSimplify::RewriteNonIntegerIVs(Loop *L) { } void IndVarSimplify::EliminateIVComparisons() { - SmallVector DeadInsts; - // Look for ICmp users. for (IVUsers::iterator I = IU->begin(), E = IU->end(); I != E; ++I) { IVStrideUse &UI = *I; @@ -399,18 +450,9 @@ void IndVarSimplify::EliminateIVComparisons() { DEBUG(dbgs() << "INDVARS: Eliminated comparison: " << *ICmp << '\n'); DeadInsts.push_back(ICmp); } - - // Now that we're done iterating through lists, clean up any instructions - // which are now dead. - while (!DeadInsts.empty()) - if (Instruction *Inst = - dyn_cast_or_null(&*DeadInsts.pop_back_val())) - RecursivelyDeleteTriviallyDeadInstructions(Inst); } void IndVarSimplify::EliminateIVRemainders() { - SmallVector DeadInsts; - // Look for SRem and URem users. for (IVUsers::iterator I = IU->begin(), E = IU->end(); I != E; ++I) { IVStrideUse &UI = *I; @@ -466,13 +508,6 @@ void IndVarSimplify::EliminateIVRemainders() { DEBUG(dbgs() << "INDVARS: Simplified rem: " << *Rem << '\n'); DeadInsts.push_back(Rem); } - - // Now that we're done iterating through lists, clean up any instructions - // which are now dead. - while (!DeadInsts.empty()) - if (Instruction *Inst = - dyn_cast_or_null(&*DeadInsts.pop_back_val())) - RecursivelyDeleteTriviallyDeadInstructions(Inst); } bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { @@ -491,6 +526,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { LI = &getAnalysis(); SE = &getAnalysis(); DT = &getAnalysis(); + DeadInsts.clear(); Changed = false; // If there are any floating-point recurrences, attempt to @@ -589,9 +625,21 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { ExitingBlock, BI, Rewriter); } - // Rewrite IV-derived expressions. Clears the rewriter cache. + // Rewrite IV-derived expressions. RewriteIVExpressions(L, Rewriter); + // Clear the rewriter cache, because values that are in the rewriter's cache + // can be deleted in the loop below, causing the AssertingVH in the cache to + // trigger. + Rewriter.clear(); + + // Now that we're done iterating through lists, clean up any instructions + // which are now dead. + while (!DeadInsts.empty()) + if (Instruction *Inst = + dyn_cast_or_null(&*DeadInsts.pop_back_val())) + RecursivelyDeleteTriviallyDeadInstructions(Inst); + // The Rewriter may not be used from this point on. // Loop-invariant instructions in the preheader that aren't used in the @@ -632,7 +680,7 @@ static bool isSafe(const SCEV *S, const Loop *L, ScalarEvolution *SE) { if (!isSafe(*I, L, SE)) return false; return true; } - + // A cast is safe if its operand is. if (const SCEVCastExpr *C = dyn_cast(S)) return isSafe(C->getOperand(), L, SE); @@ -651,8 +699,6 @@ static bool isSafe(const SCEV *S, const Loop *L, ScalarEvolution *SE) { } void IndVarSimplify::RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter) { - SmallVector DeadInsts; - // Rewrite all induction variable expressions in terms of the canonical // induction variable. // @@ -705,6 +751,13 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter) { // Now expand it into actual Instructions and patch it into place. Value *NewVal = Rewriter.expandCodeFor(AR, UseTy, InsertPt); + DEBUG(dbgs() << "INDVARS: Rewrote IV '" << *AR << "' " << *Op << '\n' + << " into = " << *NewVal << "\n"); + + if (!isValidRewrite(Op, NewVal)) { + DeadInsts.push_back(NewVal); + continue; + } // Inform ScalarEvolution that this value is changing. The change doesn't // affect its value, but it does potentially affect which use lists the // value will be on after the replacement, which affects ScalarEvolution's @@ -717,25 +770,13 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter) { NewVal->takeName(Op); User->replaceUsesOfWith(Op, NewVal); UI->setOperandValToReplace(NewVal); - DEBUG(dbgs() << "INDVARS: Rewrote IV '" << *AR << "' " << *Op << '\n' - << " into = " << *NewVal << "\n"); + ++NumRemoved; Changed = true; // The old value may be dead now. DeadInsts.push_back(Op); } - - // Clear the rewriter cache, because values that are in the rewriter's cache - // can be deleted in the loop below, causing the AssertingVH in the cache to - // trigger. - Rewriter.clear(); - // Now that we're done iterating through lists, clean up any instructions - // which are now dead. - while (!DeadInsts.empty()) - if (Instruction *Inst = - dyn_cast_or_null(&*DeadInsts.pop_back_val())) - RecursivelyDeleteTriviallyDeadInstructions(Inst); } /// If there's a single exit block, sink any loop-invariant values that @@ -859,7 +900,7 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) { BinaryOperator *Incr = dyn_cast(PN->getIncomingValue(BackEdge)); if (Incr == 0 || Incr->getOpcode() != Instruction::FAdd) return; - + // If this is not an add of the PHI with a constantfp, or if the constant fp // is not an integer, bail out. ConstantFP *IncValueVal = dyn_cast(Incr->getOperand(1)); @@ -884,7 +925,7 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) { if (Compare == 0 || !Compare->hasOneUse() || !isa(Compare->use_back())) return; - + BranchInst *TheBr = cast(Compare->use_back()); // We need to verify that the branch actually controls the iteration count @@ -896,8 +937,8 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) { (L->contains(TheBr->getSuccessor(0)) && L->contains(TheBr->getSuccessor(1)))) return; - - + + // If it isn't a comparison with an integer-as-fp (the exit value), we can't // transform it. ConstantFP *ExitValueVal = dyn_cast(Compare->getOperand(1)); @@ -905,7 +946,7 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) { if (ExitValueVal == 0 || !ConvertToSInt(ExitValueVal->getValueAPF(), ExitValue)) return; - + // Find new predicate for integer comparison. CmpInst::Predicate NewPred = CmpInst::BAD_ICMP_PREDICATE; switch (Compare->getPredicate()) { @@ -923,13 +964,13 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) { case CmpInst::FCMP_OLE: case CmpInst::FCMP_ULE: NewPred = CmpInst::ICMP_SLE; break; } - + // We convert the floating point induction variable to a signed i32 value if // we can. This is only safe if the comparison will not overflow in a way // that won't be trapped by the integer equivalent operations. Check for this // now. // TODO: We could use i64 if it is native and the range requires it. - + // The start/stride/exit values must all fit in signed i32. if (!isInt<32>(InitValue) || !isInt<32>(IncValue) || !isInt<32>(ExitValue)) return; @@ -945,59 +986,59 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) { if (InitValue >= ExitValue || NewPred == CmpInst::ICMP_SGT || NewPred == CmpInst::ICMP_SGE) return; - + uint32_t Range = uint32_t(ExitValue-InitValue); if (NewPred == CmpInst::ICMP_SLE) { // Normalize SLE -> SLT, check for infinite loop. if (++Range == 0) return; // Range overflows. } - + unsigned Leftover = Range % uint32_t(IncValue); - + // If this is an equality comparison, we require that the strided value // exactly land on the exit value, otherwise the IV condition will wrap // around and do things the fp IV wouldn't. if ((NewPred == CmpInst::ICMP_EQ || NewPred == CmpInst::ICMP_NE) && Leftover != 0) return; - + // If the stride would wrap around the i32 before exiting, we can't // transform the IV. if (Leftover != 0 && int32_t(ExitValue+IncValue) < ExitValue) return; - + } else { // If we have a negative stride, we require the init to be greater than the // exit value and an equality or greater than comparison. if (InitValue >= ExitValue || NewPred == CmpInst::ICMP_SLT || NewPred == CmpInst::ICMP_SLE) return; - + uint32_t Range = uint32_t(InitValue-ExitValue); if (NewPred == CmpInst::ICMP_SGE) { // Normalize SGE -> SGT, check for infinite loop. if (++Range == 0) return; // Range overflows. } - + unsigned Leftover = Range % uint32_t(-IncValue); - + // If this is an equality comparison, we require that the strided value // exactly land on the exit value, otherwise the IV condition will wrap // around and do things the fp IV wouldn't. if ((NewPred == CmpInst::ICMP_EQ || NewPred == CmpInst::ICMP_NE) && Leftover != 0) return; - + // If the stride would wrap around the i32 before exiting, we can't // transform the IV. if (Leftover != 0 && int32_t(ExitValue+IncValue) > ExitValue) return; } - + const IntegerType *Int32Ty = Type::getInt32Ty(PN->getContext()); // Insert new integer induction variable. - PHINode *NewPHI = PHINode::Create(Int32Ty, PN->getName()+".int", PN); + PHINode *NewPHI = PHINode::Create(Int32Ty, 2, PN->getName()+".int", PN); NewPHI->addIncoming(ConstantInt::get(Int32Ty, InitValue), PN->getIncomingBlock(IncomingEdge)); diff --git a/contrib/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/contrib/llvm/lib/Transforms/Scalar/JumpThreading.cpp index 90094a8da257..7168177a76b4 100644 --- a/contrib/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -16,6 +16,7 @@ #include "llvm/IntrinsicInst.h" #include "llvm/LLVMContext.h" #include "llvm/Pass.h" +#include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/LazyValueInfo.h" #include "llvm/Analysis/Loads.h" @@ -170,9 +171,9 @@ bool JumpThreading::runOnFunction(Function &F) { Changed = true; continue; } - + BranchInst *BI = dyn_cast(BB->getTerminator()); - + // Can't thread an unconditional jump, but if the block is "almost // empty", we can replace uses of it with uses of the successor and make // this dead. @@ -608,7 +609,7 @@ static unsigned GetBestDestForJumpOnUndef(BasicBlock *BB) { static bool hasAddressTakenAndUsed(BasicBlock *BB) { if (!BB->hasAddressTaken()) return false; - + // If the block has its address taken, it may be a tree of dead constants // hanging off of it. These shouldn't keep the block alive. BlockAddress *BA = BlockAddress::get(BB); @@ -668,6 +669,17 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) { return false; // Must be an invoke. } + // Run constant folding to see if we can reduce the condition to a simple + // constant. + if (Instruction *I = dyn_cast(Condition)) { + Value *SimpleVal = ConstantFoldInstruction(I, TD); + if (SimpleVal) { + I->replaceAllUsesWith(SimpleVal); + I->eraseFromParent(); + Condition = SimpleVal; + } + } + // If the terminator is branching on an undef, we can pick any of the // successors to branch to. Let GetBestDestForJumpOnUndef decide. if (isa(Condition)) { @@ -928,13 +940,14 @@ bool JumpThreading::SimplifyPartiallyRedundantLoad(LoadInst *LI) { array_pod_sort(AvailablePreds.begin(), AvailablePreds.end()); // Create a PHI node at the start of the block for the PRE'd load value. - PHINode *PN = PHINode::Create(LI->getType(), "", LoadBB->begin()); + pred_iterator PB = pred_begin(LoadBB), PE = pred_end(LoadBB); + PHINode *PN = PHINode::Create(LI->getType(), std::distance(PB, PE), "", + LoadBB->begin()); PN->takeName(LI); // Insert new entries into the PHI for each predecessor. A single block may // have multiple entries here. - for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB); PI != E; - ++PI) { + for (pred_iterator PI = PB; PI != PE; ++PI) { BasicBlock *P = *PI; AvailablePredsTy::iterator I = std::lower_bound(AvailablePreds.begin(), AvailablePreds.end(), diff --git a/contrib/llvm/lib/Transforms/Scalar/LICM.cpp b/contrib/llvm/lib/Transforms/Scalar/LICM.cpp index 07867933d08c..93de9cf002eb 100644 --- a/contrib/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/LICM.cpp @@ -445,7 +445,8 @@ void LICM::sink(Instruction &I) { // enough that we handle it as a special (more efficient) case. It is more // efficient to handle because there are no PHI nodes that need to be placed. if (ExitBlocks.size() == 1) { - if (!DT->dominates(I.getParent(), ExitBlocks[0])) { + if (!isa(I) && + !DT->dominates(I.getParent(), ExitBlocks[0])) { // Instruction is not used, just delete it. CurAST->deleteValue(&I); // If I has users in unreachable blocks, eliminate. @@ -742,30 +743,13 @@ void LICM::PromoteAliasSet(AliasSet &AS) { Preheader->getTerminator()); SSA.AddAvailableValue(Preheader, PreheaderLoad); - // Copy any value stored to or loaded from a must-alias of the pointer. - if (PreheaderLoad->getType()->isPointerTy()) { - Value *SomeValue; - if (LoadInst *LI = dyn_cast(LoopUses[0])) - SomeValue = LI; - else - SomeValue = cast(LoopUses[0])->getValueOperand(); - - CurAST->copyValue(SomeValue, PreheaderLoad); - } - // Rewrite all the loads in the loop and remember all the definitions from // stores in the loop. Promoter.run(LoopUses); - - // If the preheader load is itself a pointer, we need to tell alias analysis - // about the new pointer we created in the preheader block and about any PHI - // nodes that just got inserted. - if (PreheaderLoad->getType()->isPointerTy()) { - for (unsigned i = 0, e = NewPHIs.size(); i != e; ++i) - CurAST->copyValue(PreheaderLoad, NewPHIs[i]); - } - - // fwew, we're done! + + // If the SSAUpdater didn't use the load in the preheader, just zap it now. + if (PreheaderLoad->use_empty()) + PreheaderLoad->eraseFromParent(); } diff --git a/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index f8ce214750ac..1366231e9a1a 100644 --- a/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -81,7 +81,7 @@ namespace { bool processLoopStore(StoreInst *SI, const SCEV *BECount); bool processLoopMemSet(MemSetInst *MSI, const SCEV *BECount); - + bool processLoopStridedStore(Value *DestPtr, unsigned StoreSize, unsigned StoreAlignment, Value *SplatValue, Instruction *TheStore, @@ -91,7 +91,7 @@ namespace { const SCEVAddRecExpr *StoreEv, const SCEVAddRecExpr *LoadEv, const SCEV *BECount); - + /// This transformation requires natural loop information & requires that /// loop preheaders be inserted into the CFG. /// @@ -134,50 +134,50 @@ Pass *llvm::createLoopIdiomPass() { return new LoopIdiomRecognize(); } /// static void DeleteDeadInstruction(Instruction *I, ScalarEvolution &SE) { SmallVector NowDeadInsts; - + NowDeadInsts.push_back(I); - + // Before we touch this instruction, remove it from SE! do { Instruction *DeadInst = NowDeadInsts.pop_back_val(); - + // This instruction is dead, zap it, in stages. Start by removing it from // SCEV. SE.forgetValue(DeadInst); - + for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) { Value *Op = DeadInst->getOperand(op); DeadInst->setOperand(op, 0); - + // If this operand just became dead, add it to the NowDeadInsts list. if (!Op->use_empty()) continue; - + if (Instruction *OpI = dyn_cast(Op)) if (isInstructionTriviallyDead(OpI)) NowDeadInsts.push_back(OpI); } - + DeadInst->eraseFromParent(); - + } while (!NowDeadInsts.empty()); } bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) { CurLoop = L; - + // The trip count of the loop must be analyzable. SE = &getAnalysis(); if (!SE->hasLoopInvariantBackedgeTakenCount(L)) return false; const SCEV *BECount = SE->getBackedgeTakenCount(L); if (isa(BECount)) return false; - + // If this loop executes exactly one time, then it should be peeled, not // optimized by this pass. if (const SCEVConstant *BECst = dyn_cast(BECount)) if (BECst->getValue()->getValue() == 0) return false; - + // We require target data for now. TD = getAnalysisIfAvailable(); if (TD == 0) return false; @@ -185,14 +185,14 @@ bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) { DT = &getAnalysis(); LoopInfo &LI = getAnalysis(); TLI = &getAnalysis(); - + SmallVector ExitBlocks; CurLoop->getUniqueExitBlocks(ExitBlocks); DEBUG(dbgs() << "loop-idiom Scanning: F[" << L->getHeader()->getParent()->getName() << "] Loop %" << L->getHeader()->getName() << "\n"); - + bool MadeChange = false; // Scan all the blocks in the loop that are not in subloops. for (Loop::block_iterator BI = L->block_begin(), E = L->block_end(); BI != E; @@ -200,7 +200,7 @@ bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) { // Ignore blocks in subloops. if (LI.getLoopFor(*BI) != CurLoop) continue; - + MadeChange |= runOnLoopBlock(*BI, BECount, ExitBlocks); } return MadeChange; @@ -217,7 +217,7 @@ bool LoopIdiomRecognize::runOnLoopBlock(BasicBlock *BB, const SCEV *BECount, for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) if (!DT->dominates(BB, ExitBlocks[i])) return false; - + bool MadeChange = false; for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { Instruction *Inst = I++; @@ -226,20 +226,20 @@ bool LoopIdiomRecognize::runOnLoopBlock(BasicBlock *BB, const SCEV *BECount, WeakVH InstPtr(I); if (!processLoopStore(SI, BECount)) continue; MadeChange = true; - + // If processing the store invalidated our iterator, start over from the // top of the block. if (InstPtr == 0) I = BB->begin(); continue; } - + // Look for memset instructions, which may be optimized to a larger memset. if (MemSetInst *MSI = dyn_cast(Inst)) { WeakVH InstPtr(I); if (!processLoopMemSet(MSI, BECount)) continue; MadeChange = true; - + // If processing the memset invalidated our iterator, start over from the // top of the block. if (InstPtr == 0) @@ -247,7 +247,7 @@ bool LoopIdiomRecognize::runOnLoopBlock(BasicBlock *BB, const SCEV *BECount, continue; } } - + return MadeChange; } @@ -258,12 +258,12 @@ bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) { Value *StoredVal = SI->getValueOperand(); Value *StorePtr = SI->getPointerOperand(); - + // Reject stores that are so large that they overflow an unsigned. uint64_t SizeInBits = TD->getTypeSizeInBits(StoredVal->getType()); if ((SizeInBits & 7) || (SizeInBits >> 32) != 0) return false; - + // See if the pointer expression is an AddRec like {base,+,1} on the current // loop, which indicates a strided store. If we have something else, it's a // random store we can't handle. @@ -274,9 +274,9 @@ bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) { // Check to see if the stride matches the size of the store. If so, then we // know that every byte is touched in the loop. - unsigned StoreSize = (unsigned)SizeInBits >> 3; + unsigned StoreSize = (unsigned)SizeInBits >> 3; const SCEVConstant *Stride = dyn_cast(StoreEv->getOperand(1)); - + if (Stride == 0 || StoreSize != Stride->getValue()->getValue()) { // TODO: Could also handle negative stride here someday, that will require // the validity check in mayLoopAccessLocation to be updated though. @@ -285,7 +285,7 @@ bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) { dbgs() << "NEGATIVE STRIDE: " << *SI << "\n"; dbgs() << "BB: " << *SI->getParent(); } - + return false; } @@ -319,9 +319,9 @@ processLoopMemSet(MemSetInst *MSI, const SCEV *BECount) { // If we're not allowed to hack on memset, we fail. if (!TLI->has(LibFunc::memset)) return false; - + Value *Pointer = MSI->getDest(); - + // See if the pointer expression is an AddRec like {base,+,1} on the current // loop, which indicates a strided store. If we have something else, it's a // random store we can't handle. @@ -333,16 +333,16 @@ processLoopMemSet(MemSetInst *MSI, const SCEV *BECount) { uint64_t SizeInBytes = cast(MSI->getLength())->getZExtValue(); if ((SizeInBytes >> 32) != 0) return false; - + // Check to see if the stride matches the size of the memset. If so, then we // know that every byte is touched in the loop. const SCEVConstant *Stride = dyn_cast(Ev->getOperand(1)); - + // TODO: Could also handle negative stride here someday, that will require the // validity check in mayLoopAccessLocation to be updated though. if (Stride == 0 || MSI->getLength() != Stride->getValue()) return false; - + return processLoopStridedStore(Pointer, (unsigned)SizeInBytes, MSI->getAlignment(), MSI->getValue(), MSI, Ev, BECount); @@ -365,7 +365,7 @@ static bool mayLoopAccessLocation(Value *Ptr,AliasAnalysis::ModRefResult Access, // to be exactly the size of the memset, which is (BECount+1)*StoreSize if (const SCEVConstant *BECst = dyn_cast(BECount)) AccessSize = (BECst->getValue()->getZExtValue()+1)*StoreSize; - + // TODO: For this to be really effective, we have to dive into the pointer // operand in the store. Store to &A[i] of 100 will always return may alias // with store of &A[100], we need to StoreLoc to be "A" with size of 100, @@ -394,12 +394,12 @@ static Constant *getMemSetPatternValue(Value *V, const TargetData &TD) { // that doesn't seem worthwhile. Constant *C = dyn_cast(V); if (C == 0) return 0; - + // Only handle simple values that are a power of two bytes in size. uint64_t Size = TD.getTypeSizeInBits(V->getType()); if (Size == 0 || (Size & 7) || (Size & (Size-1))) return 0; - + // Don't care enough about darwin/ppc to implement this. if (TD.isBigEndian()) return 0; @@ -410,7 +410,7 @@ static Constant *getMemSetPatternValue(Value *V, const TargetData &TD) { // TODO: If CI is larger than 16-bytes, we can try slicing it in half to see // if the top and bottom are the same (e.g. for vectors and large integers). if (Size > 16) return 0; - + // If the constant is exactly 16 bytes, just use it. if (Size == 16) return C; @@ -428,14 +428,14 @@ processLoopStridedStore(Value *DestPtr, unsigned StoreSize, unsigned StoreAlignment, Value *StoredVal, Instruction *TheStore, const SCEVAddRecExpr *Ev, const SCEV *BECount) { - + // If the stored value is a byte-wise value (like i32 -1), then it may be // turned into a memset of i8 -1, assuming that all the consecutive bytes // are stored. A store of i32 0x01020304 can never be turned into a memset, // but it can be turned into memset_pattern if the target supports it. Value *SplatValue = isBytewiseValue(StoredVal); Constant *PatternValue = 0; - + // If we're allowed to form a memset, and the stored value would be acceptable // for memset, use it. if (SplatValue && TLI->has(LibFunc::memset) && @@ -453,8 +453,8 @@ processLoopStridedStore(Value *DestPtr, unsigned StoreSize, // do anything with a 3-byte store, for example. return false; } - - + + // Okay, we have a strided store "p[i]" of a splattable value. We can turn // this into a memset in the loop preheader now if we want. However, this // would be unsafe to do if there is anything else in the loop that may read @@ -463,47 +463,47 @@ processLoopStridedStore(Value *DestPtr, unsigned StoreSize, CurLoop, BECount, StoreSize, getAnalysis(), TheStore)) return false; - + // Okay, everything looks good, insert the memset. BasicBlock *Preheader = CurLoop->getLoopPreheader(); - + IRBuilder<> Builder(Preheader->getTerminator()); - + // The trip count of the loop and the base pointer of the addrec SCEV is // guaranteed to be loop invariant, which means that it should dominate the // header. Just insert code for it in the preheader. SCEVExpander Expander(*SE); - + unsigned AddrSpace = cast(DestPtr->getType())->getAddressSpace(); - Value *BasePtr = + Value *BasePtr = Expander.expandCodeFor(Ev->getStart(), Builder.getInt8PtrTy(AddrSpace), Preheader->getTerminator()); - + // The # stored bytes is (BECount+1)*Size. Expand the trip count out to // pointer size if it isn't already. const Type *IntPtr = TD->getIntPtrType(DestPtr->getContext()); BECount = SE->getTruncateOrZeroExtend(BECount, IntPtr); - + const SCEV *NumBytesS = SE->getAddExpr(BECount, SE->getConstant(IntPtr, 1), - true /*no unsigned overflow*/); + SCEV::FlagNUW); if (StoreSize != 1) NumBytesS = SE->getMulExpr(NumBytesS, SE->getConstant(IntPtr, StoreSize), - true /*no unsigned overflow*/); - - Value *NumBytes = + SCEV::FlagNUW); + + Value *NumBytes = Expander.expandCodeFor(NumBytesS, IntPtr, Preheader->getTerminator()); - - Value *NewCall; + + CallInst *NewCall; if (SplatValue) NewCall = Builder.CreateMemSet(BasePtr, SplatValue,NumBytes,StoreAlignment); else { Module *M = TheStore->getParent()->getParent()->getParent(); Value *MSP = M->getOrInsertFunction("memset_pattern16", Builder.getVoidTy(), - Builder.getInt8PtrTy(), + Builder.getInt8PtrTy(), Builder.getInt8PtrTy(), IntPtr, (void*)0); - + // Otherwise we should form a memset_pattern16. PatternValue is known to be // an constant array of 16-bytes. Plop the value into a mergable global. GlobalVariable *GV = new GlobalVariable(*M, PatternValue->getType(), true, @@ -514,11 +514,11 @@ processLoopStridedStore(Value *DestPtr, unsigned StoreSize, Value *PatternPtr = ConstantExpr::getBitCast(GV, Builder.getInt8PtrTy()); NewCall = Builder.CreateCall3(MSP, BasePtr, PatternPtr, NumBytes); } - + DEBUG(dbgs() << " Formed memset: " << *NewCall << "\n" << " from store to: " << *Ev << " at: " << *TheStore << "\n"); - (void)NewCall; - + NewCall->setDebugLoc(TheStore->getDebugLoc()); + // Okay, the memset has been formed. Zap the original store and anything that // feeds into it. DeleteDeadInstruction(TheStore, *SE); @@ -536,9 +536,9 @@ processLoopStoreOfLoopLoad(StoreInst *SI, unsigned StoreSize, // If we're not allowed to form memcpy, we fail. if (!TLI->has(LibFunc::memcpy)) return false; - + LoadInst *LI = cast(SI->getValueOperand()); - + // Okay, we have a strided store "p[i]" of a loaded value. We can turn // this into a memcpy in the loop preheader now if we want. However, this // would be unsafe to do if there is anything else in the loop that may read @@ -555,49 +555,49 @@ processLoopStoreOfLoopLoad(StoreInst *SI, unsigned StoreSize, CurLoop, BECount, StoreSize, getAnalysis(), SI)) return false; - + // Okay, everything looks good, insert the memcpy. BasicBlock *Preheader = CurLoop->getLoopPreheader(); - + IRBuilder<> Builder(Preheader->getTerminator()); - + // The trip count of the loop and the base pointer of the addrec SCEV is // guaranteed to be loop invariant, which means that it should dominate the // header. Just insert code for it in the preheader. SCEVExpander Expander(*SE); - Value *LoadBasePtr = + Value *LoadBasePtr = Expander.expandCodeFor(LoadEv->getStart(), Builder.getInt8PtrTy(LI->getPointerAddressSpace()), Preheader->getTerminator()); - Value *StoreBasePtr = + Value *StoreBasePtr = Expander.expandCodeFor(StoreEv->getStart(), Builder.getInt8PtrTy(SI->getPointerAddressSpace()), Preheader->getTerminator()); - + // The # stored bytes is (BECount+1)*Size. Expand the trip count out to // pointer size if it isn't already. const Type *IntPtr = TD->getIntPtrType(SI->getContext()); BECount = SE->getTruncateOrZeroExtend(BECount, IntPtr); - + const SCEV *NumBytesS = SE->getAddExpr(BECount, SE->getConstant(IntPtr, 1), - true /*no unsigned overflow*/); + SCEV::FlagNUW); if (StoreSize != 1) NumBytesS = SE->getMulExpr(NumBytesS, SE->getConstant(IntPtr, StoreSize), - true /*no unsigned overflow*/); - + SCEV::FlagNUW); + Value *NumBytes = Expander.expandCodeFor(NumBytesS, IntPtr, Preheader->getTerminator()); - + Value *NewCall = Builder.CreateMemCpy(StoreBasePtr, LoadBasePtr, NumBytes, std::min(SI->getAlignment(), LI->getAlignment())); - + DEBUG(dbgs() << " Formed memcpy: " << *NewCall << "\n" << " from load ptr=" << *LoadEv << " at: " << *LI << "\n" << " from store ptr=" << *StoreEv << " at: " << *SI << "\n"); (void)NewCall; - + // Okay, the memset has been formed. Zap the original store and anything that // feeds into it. DeleteDeadInstruction(SI, *SE); diff --git a/contrib/llvm/lib/Transforms/Scalar/LoopRotation.cpp b/contrib/llvm/lib/Transforms/Scalar/LoopRotation.cpp index 95e15784df2c..47dced37c3a4 100644 --- a/contrib/llvm/lib/Transforms/Scalar/LoopRotation.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/LoopRotation.cpp @@ -184,7 +184,11 @@ bool LoopRotate::rotateLoop(Loop *L) { // Now, this loop is suitable for rotation. BasicBlock *OrigPreheader = L->getLoopPreheader(); BasicBlock *OrigLatch = L->getLoopLatch(); - assert(OrigPreheader && OrigLatch && "Loop not in canonical form?"); + + // If the loop could not be converted to canonical form, it must have an + // indirectbr in it, just give up. + if (OrigPreheader == 0 || OrigLatch == 0) + return false; // Anything ScalarEvolution may know about this loop or the PHI nodes // in its header will soon be invalidated. @@ -322,7 +326,8 @@ bool LoopRotate::rotateLoop(Loop *L) { // We can fold the conditional branch in the preheader, this makes things // simpler. The first step is to remove the extra edge to the Exit block. Exit->removePredecessor(OrigPreheader, true /*preserve LCSSA*/); - BranchInst::Create(NewHeader, PHBI); + BranchInst *NewBI = BranchInst::Create(NewHeader, PHBI); + NewBI->setDebugLoc(PHBI->getDebugLoc()); PHBI->eraseFromParent(); // With our CFG finalized, update DomTree if it is available. diff --git a/contrib/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/contrib/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp index ac4aea2e404e..5abc79042390 100644 --- a/contrib/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -253,7 +253,8 @@ static void DoInitialMatch(const SCEV *S, Loop *L, DoInitialMatch(AR->getStart(), L, Good, Bad, SE); DoInitialMatch(SE.getAddRecExpr(SE.getConstant(AR->getType(), 0), AR->getStepRecurrence(SE), - AR->getLoop()), + // FIXME: AR->getNoWrapFlags() + AR->getLoop(), SCEV::FlagAnyWrap), L, Good, Bad, SE); return; } @@ -455,7 +456,10 @@ static const SCEV *getExactSDiv(const SCEV *LHS, const SCEV *RHS, const SCEV *Start = getExactSDiv(AR->getStart(), RHS, SE, IgnoreSignificantBits); if (!Start) return 0; - return SE.getAddRecExpr(Start, Step, AR->getLoop()); + // FlagNW is independent of the start value, step direction, and is + // preserved with smaller magnitude steps. + // FIXME: AR->getNoWrapFlags(SCEV::FlagNW) + return SE.getAddRecExpr(Start, Step, AR->getLoop(), SCEV::FlagAnyWrap); } return 0; } @@ -520,7 +524,9 @@ static int64_t ExtractImmediate(const SCEV *&S, ScalarEvolution &SE) { SmallVector NewOps(AR->op_begin(), AR->op_end()); int64_t Result = ExtractImmediate(NewOps.front(), SE); if (Result != 0) - S = SE.getAddRecExpr(NewOps, AR->getLoop()); + S = SE.getAddRecExpr(NewOps, AR->getLoop(), + // FIXME: AR->getNoWrapFlags(SCEV::FlagNW) + SCEV::FlagAnyWrap); return Result; } return 0; @@ -545,7 +551,9 @@ static GlobalValue *ExtractSymbol(const SCEV *&S, ScalarEvolution &SE) { SmallVector NewOps(AR->op_begin(), AR->op_end()); GlobalValue *Result = ExtractSymbol(NewOps.front(), SE); if (Result) - S = SE.getAddRecExpr(NewOps, AR->getLoop()); + S = SE.getAddRecExpr(NewOps, AR->getLoop(), + // FIXME: AR->getNoWrapFlags(SCEV::FlagNW) + SCEV::FlagAnyWrap); return Result; } return 0; @@ -564,9 +572,6 @@ static bool isAddressUse(Instruction *Inst, Value *OperandVal) { switch (II->getIntrinsicID()) { default: break; case Intrinsic::prefetch: - case Intrinsic::x86_sse2_loadu_dq: - case Intrinsic::x86_sse2_loadu_pd: - case Intrinsic::x86_sse_loadu_ps: case Intrinsic::x86_sse_storeu_ps: case Intrinsic::x86_sse2_storeu_pd: case Intrinsic::x86_sse2_storeu_dq: @@ -781,7 +786,7 @@ void Cost::RateFormula(const Formula &F, } } -/// Loose - Set this cost to a loosing value. +/// Loose - Set this cost to a losing value. void Cost::Loose() { NumRegs = ~0u; AddRecCost = ~0u; @@ -1483,7 +1488,7 @@ void LSRInstance::OptimizeShadowIV() { if (!C->getValue().isStrictlyPositive()) continue; /* Add new PHINode. */ - PHINode *NewPH = PHINode::Create(DestTy, "IV.S.", PH); + PHINode *NewPH = PHINode::Create(DestTy, 2, "IV.S.", PH); /* create new increment. '++d' in above example. */ Constant *CFP = ConstantFP::get(DestTy, C->getZExtValue()); @@ -1819,7 +1824,7 @@ LSRInstance::OptimizeLoopTermCond() { } } -/// reconcileNewOffset - Determine if the given use can accomodate a fixup +/// reconcileNewOffset - Determine if the given use can accommodate a fixup /// at the given offset and other details. If so, update the use and /// return true. bool @@ -2236,7 +2241,9 @@ static void CollectSubexprs(const SCEV *S, const SCEVConstant *C, if (!AR->getStart()->isZero()) { CollectSubexprs(SE.getAddRecExpr(SE.getConstant(AR->getType(), 0), AR->getStepRecurrence(SE), - AR->getLoop()), + AR->getLoop(), + //FIXME: AR->getNoWrapFlags(SCEV::FlagNW) + SCEV::FlagAnyWrap), C, Ops, L, SE); CollectSubexprs(AR->getStart(), C, Ops, L, SE); return; @@ -3047,7 +3054,7 @@ void LSRInstance::NarrowSearchSpaceByCollapsingUnrolledCode() { } } -/// NarrowSearchSpaceByRefilteringUndesirableDedicatedRegisters - Call +/// NarrowSearchSpaceByRefilteringUndesirableDedicatedRegisters - Call /// FilterOutUndesirableDedicatedRegisters again, if necessary, now that /// we've done more filtering, as it may be able to find more formulae to /// eliminate. diff --git a/contrib/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp b/contrib/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp index 80b263a30cb8..fef6bc31c7b6 100644 --- a/contrib/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -43,7 +43,13 @@ namespace { class LoopUnroll : public LoopPass { public: static char ID; // Pass ID, replacement for typeid - LoopUnroll() : LoopPass(ID) { + LoopUnroll(int T = -1, int C = -1, int P = -1) : LoopPass(ID) { + CurrentThreshold = (T == -1) ? UnrollThreshold : unsigned(T); + CurrentCount = (C == -1) ? UnrollCount : unsigned(C); + CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P; + + UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0); + initializeLoopUnrollPass(*PassRegistry::getPassRegistry()); } @@ -56,7 +62,10 @@ namespace { // explicit -unroll-threshold). static const unsigned OptSizeUnrollThreshold = 50; + unsigned CurrentCount; unsigned CurrentThreshold; + bool CurrentAllowPartial; + bool UserThreshold; // CurrentThreshold is user-specified. bool runOnLoop(Loop *L, LPPassManager &LPM); @@ -87,7 +96,9 @@ INITIALIZE_PASS_DEPENDENCY(LoopSimplify) INITIALIZE_PASS_DEPENDENCY(LCSSA) INITIALIZE_PASS_END(LoopUnroll, "loop-unroll", "Unroll loops", false, false) -Pass *llvm::createLoopUnrollPass() { return new LoopUnroll(); } +Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial) { + return new LoopUnroll(Threshold, Count, AllowPartial); +} /// ApproximateLoopSize - Approximate the size of the loop. static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls) { @@ -119,14 +130,14 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) { // from UnrollThreshold, it is overridden to a smaller value if the current // function is marked as optimize-for-size, and the unroll threshold was // not user specified. - CurrentThreshold = UnrollThreshold; - if (Header->getParent()->hasFnAttr(Attribute::OptimizeForSize) && - UnrollThreshold.getNumOccurrences() == 0) - CurrentThreshold = OptSizeUnrollThreshold; + unsigned Threshold = CurrentThreshold; + if (!UserThreshold && + Header->getParent()->hasFnAttr(Attribute::OptimizeForSize)) + Threshold = OptSizeUnrollThreshold; // Find trip count unsigned TripCount = L->getSmallConstantTripCount(); - unsigned Count = UnrollCount; + unsigned Count = CurrentCount; // Automatically select an unroll count. if (Count == 0) { @@ -140,7 +151,7 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) { } // Enforce the threshold. - if (CurrentThreshold != NoThreshold) { + if (Threshold != NoThreshold) { unsigned NumInlineCandidates; unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates); DEBUG(dbgs() << " Loop Size = " << LoopSize << "\n"); @@ -149,16 +160,16 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) { return false; } uint64_t Size = (uint64_t)LoopSize*Count; - if (TripCount != 1 && Size > CurrentThreshold) { + if (TripCount != 1 && Size > Threshold) { DEBUG(dbgs() << " Too large to fully unroll with count: " << Count - << " because size: " << Size << ">" << CurrentThreshold << "\n"); - if (!UnrollAllowPartial) { + << " because size: " << Size << ">" << Threshold << "\n"); + if (!CurrentAllowPartial) { DEBUG(dbgs() << " will not try to unroll partially because " << "-unroll-allow-partial not given\n"); return false; } // Reduce unroll count to be modulo of TripCount for partial unrolling - Count = CurrentThreshold / LoopSize; + Count = Threshold / LoopSize; while (Count != 0 && TripCount%Count != 0) { Count--; } diff --git a/contrib/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/contrib/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp index bde0e5316c3a..a3035cbfb0ee 100644 --- a/contrib/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -28,6 +28,7 @@ #include "llvm/Support/IRBuilder.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLibraryInfo.h" #include using namespace llvm; @@ -299,12 +300,15 @@ void MemsetRanges::addRange(int64_t Start, int64_t Size, Value *Ptr, namespace { class MemCpyOpt : public FunctionPass { MemoryDependenceAnalysis *MD; + TargetLibraryInfo *TLI; const TargetData *TD; public: static char ID; // Pass identification, replacement for typeid MemCpyOpt() : FunctionPass(ID) { initializeMemCpyOptPass(*PassRegistry::getPassRegistry()); MD = 0; + TLI = 0; + TD = 0; } bool runOnFunction(Function &F); @@ -316,6 +320,7 @@ namespace { AU.addRequired(); AU.addRequired(); AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); } @@ -346,6 +351,7 @@ INITIALIZE_PASS_BEGIN(MemCpyOpt, "memcpyopt", "MemCpy Optimization", false, false) INITIALIZE_PASS_DEPENDENCY(DominatorTree) INITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo) INITIALIZE_AG_DEPENDENCY(AliasAnalysis) INITIALIZE_PASS_END(MemCpyOpt, "memcpyopt", "MemCpy Optimization", false, false) @@ -688,7 +694,7 @@ bool MemCpyOpt::processMemCpyMemCpyDependence(MemCpyInst *M, MemCpyInst *MDep, if (M->getSource() == MDep->getSource()) return false; - // Second, the length of the memcpy's must be the same, or the preceeding one + // Second, the length of the memcpy's must be the same, or the preceding one // must be larger than the following one. ConstantInt *MDepLen = dyn_cast(MDep->getLength()); ConstantInt *MLen = dyn_cast(M->getLength()); @@ -804,6 +810,9 @@ bool MemCpyOpt::processMemCpy(MemCpyInst *M) { bool MemCpyOpt::processMemMove(MemMoveInst *M) { AliasAnalysis &AA = getAnalysis(); + if (!TLI->has(LibFunc::memmove)) + return false; + // See if the pointers alias. if (!AA.isNoAlias(AA.getLocationForDest(M), AA.getLocationForSource(M))) return false; @@ -935,6 +944,14 @@ bool MemCpyOpt::runOnFunction(Function &F) { bool MadeChange = false; MD = &getAnalysis(); TD = getAnalysisIfAvailable(); + TLI = &getAnalysis(); + + // If we don't have at least memset and memcpy, there is little point of doing + // anything here. These are required by a freestanding implementation, so if + // even they are disabled, there is no point in trying hard. + if (!TLI->has(LibFunc::memset) || !TLI->has(LibFunc::memcpy)) + return false; + while (1) { if (!iterateOnFunction(F)) break; diff --git a/contrib/llvm/lib/Transforms/Scalar/Reassociate.cpp b/contrib/llvm/lib/Transforms/Scalar/Reassociate.cpp index e093b52571af..c1dfe154ae3f 100644 --- a/contrib/llvm/lib/Transforms/Scalar/Reassociate.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -22,6 +22,7 @@ #define DEBUG_TYPE "reassociate" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" @@ -74,6 +75,8 @@ namespace { class Reassociate : public FunctionPass { DenseMap RankMap; DenseMap, unsigned> ValueRankMap; + SmallVector RedoInsts; + SmallVector DeadInsts; bool MadeChange; public: static char ID; // Pass identification, replacement for typeid @@ -98,7 +101,7 @@ namespace { void LinearizeExprTree(BinaryOperator *I, SmallVectorImpl &Ops); void LinearizeExpr(BinaryOperator *I); Value *RemoveFactorFromExpression(Value *V, Value *Factor); - void ReassociateBB(BasicBlock *BB); + void ReassociateInst(BasicBlock::iterator &BBI); void RemoveDeadBinaryOp(Value *V); }; @@ -113,13 +116,13 @@ FunctionPass *llvm::createReassociatePass() { return new Reassociate(); } void Reassociate::RemoveDeadBinaryOp(Value *V) { Instruction *Op = dyn_cast(V); - if (!Op || !isa(Op) || !Op->use_empty()) + if (!Op || !isa(Op)) return; Value *LHS = Op->getOperand(0), *RHS = Op->getOperand(1); ValueRankMap.erase(Op); - Op->eraseFromParent(); + DeadInsts.push_back(Op); RemoveDeadBinaryOp(LHS); RemoveDeadBinaryOp(RHS); } @@ -214,6 +217,7 @@ static Instruction *LowerNegateToMultiply(Instruction *Neg, ValueRankMap.erase(Neg); Res->takeName(Neg); Neg->replaceAllUsesWith(Res); + Res->setDebugLoc(Neg->getDebugLoc()); Neg->eraseFromParent(); return Res; } @@ -503,6 +507,7 @@ static Instruction *BreakUpSubtract(Instruction *Sub, // Everyone now refers to the add instruction. ValueRankMap.erase(Sub); Sub->replaceAllUsesWith(New); + New->setDebugLoc(Sub->getDebugLoc()); Sub->eraseFromParent(); DEBUG(dbgs() << "Negated: " << *New << '\n'); @@ -528,6 +533,7 @@ static Instruction *ConvertShiftToMul(Instruction *Shl, ValueRankMap.erase(Shl); Mul->takeName(Shl); Shl->replaceAllUsesWith(Mul); + Mul->setDebugLoc(Shl->getDebugLoc()); Shl->eraseFromParent(); return Mul; } @@ -603,7 +609,7 @@ Value *Reassociate::RemoveFactorFromExpression(Value *V, Value *Factor) { // remaining operand. if (Factors.size() == 1) { ValueRankMap.erase(BO); - BO->eraseFromParent(); + DeadInsts.push_back(BO); V = Factors[0].Op; } else { RewriteExprTree(BO, Factors); @@ -732,7 +738,7 @@ Value *Reassociate::OptimizeAdd(Instruction *I, // Now that we have inserted a multiply, optimize it. This allows us to // handle cases that require multiple factoring steps, such as this: // (X*2) + (X*2) + (X*2) -> (X*2)*3 -> X*6 - Mul = ReassociateExpression(cast(Mul)); + RedoInsts.push_back(Mul); // If every add operand was a duplicate, return the multiply. if (Ops.empty()) @@ -960,71 +966,69 @@ Value *Reassociate::OptimizeExpression(BinaryOperator *I, } -/// ReassociateBB - Inspect all of the instructions in this basic block, -/// reassociating them as we go. -void Reassociate::ReassociateBB(BasicBlock *BB) { - for (BasicBlock::iterator BBI = BB->begin(); BBI != BB->end(); ) { - Instruction *BI = BBI++; - if (BI->getOpcode() == Instruction::Shl && - isa(BI->getOperand(1))) - if (Instruction *NI = ConvertShiftToMul(BI, ValueRankMap)) { - MadeChange = true; - BI = NI; - } - - // Reject cases where it is pointless to do this. - if (!isa(BI) || BI->getType()->isFloatingPointTy() || - BI->getType()->isVectorTy()) - continue; // Floating point ops are not associative. - - // Do not reassociate boolean (i1) expressions. We want to preserve the - // original order of evaluation for short-circuited comparisons that - // SimplifyCFG has folded to AND/OR expressions. If the expression - // is not further optimized, it is likely to be transformed back to a - // short-circuited form for code gen, and the source order may have been - // optimized for the most likely conditions. - if (BI->getType()->isIntegerTy(1)) - continue; - - // If this is a subtract instruction which is not already in negate form, - // see if we can convert it to X+-Y. - if (BI->getOpcode() == Instruction::Sub) { - if (ShouldBreakUpSubtract(BI)) { - BI = BreakUpSubtract(BI, ValueRankMap); - // Reset the BBI iterator in case BreakUpSubtract changed the - // instruction it points to. - BBI = BI; - ++BBI; - MadeChange = true; - } else if (BinaryOperator::isNeg(BI)) { - // Otherwise, this is a negation. See if the operand is a multiply tree - // and if this is not an inner node of a multiply tree. - if (isReassociableOp(BI->getOperand(1), Instruction::Mul) && - (!BI->hasOneUse() || - !isReassociableOp(BI->use_back(), Instruction::Mul))) { - BI = LowerNegateToMultiply(BI, ValueRankMap); - MadeChange = true; - } - } +/// ReassociateInst - Inspect and reassociate the instruction at the +/// given position, post-incrementing the position. +void Reassociate::ReassociateInst(BasicBlock::iterator &BBI) { + Instruction *BI = BBI++; + if (BI->getOpcode() == Instruction::Shl && + isa(BI->getOperand(1))) + if (Instruction *NI = ConvertShiftToMul(BI, ValueRankMap)) { + MadeChange = true; + BI = NI; } - // If this instruction is a commutative binary operator, process it. - if (!BI->isAssociative()) continue; - BinaryOperator *I = cast(BI); + // Reject cases where it is pointless to do this. + if (!isa(BI) || BI->getType()->isFloatingPointTy() || + BI->getType()->isVectorTy()) + return; // Floating point ops are not associative. - // If this is an interior node of a reassociable tree, ignore it until we - // get to the root of the tree, to avoid N^2 analysis. - if (I->hasOneUse() && isReassociableOp(I->use_back(), I->getOpcode())) - continue; + // Do not reassociate boolean (i1) expressions. We want to preserve the + // original order of evaluation for short-circuited comparisons that + // SimplifyCFG has folded to AND/OR expressions. If the expression + // is not further optimized, it is likely to be transformed back to a + // short-circuited form for code gen, and the source order may have been + // optimized for the most likely conditions. + if (BI->getType()->isIntegerTy(1)) + return; - // If this is an add tree that is used by a sub instruction, ignore it - // until we process the subtract. - if (I->hasOneUse() && I->getOpcode() == Instruction::Add && - cast(I->use_back())->getOpcode() == Instruction::Sub) - continue; - - ReassociateExpression(I); + // If this is a subtract instruction which is not already in negate form, + // see if we can convert it to X+-Y. + if (BI->getOpcode() == Instruction::Sub) { + if (ShouldBreakUpSubtract(BI)) { + BI = BreakUpSubtract(BI, ValueRankMap); + // Reset the BBI iterator in case BreakUpSubtract changed the + // instruction it points to. + BBI = BI; + ++BBI; + MadeChange = true; + } else if (BinaryOperator::isNeg(BI)) { + // Otherwise, this is a negation. See if the operand is a multiply tree + // and if this is not an inner node of a multiply tree. + if (isReassociableOp(BI->getOperand(1), Instruction::Mul) && + (!BI->hasOneUse() || + !isReassociableOp(BI->use_back(), Instruction::Mul))) { + BI = LowerNegateToMultiply(BI, ValueRankMap); + MadeChange = true; + } + } } + + // If this instruction is a commutative binary operator, process it. + if (!BI->isAssociative()) return; + BinaryOperator *I = cast(BI); + + // If this is an interior node of a reassociable tree, ignore it until we + // get to the root of the tree, to avoid N^2 analysis. + if (I->hasOneUse() && isReassociableOp(I->use_back(), I->getOpcode())) + return; + + // If this is an add tree that is used by a sub instruction, ignore it + // until we process the subtract. + if (I->hasOneUse() && I->getOpcode() == Instruction::Add && + cast(I->use_back())->getOpcode() == Instruction::Sub) + return; + + ReassociateExpression(I); } Value *Reassociate::ReassociateExpression(BinaryOperator *I) { @@ -1051,6 +1055,8 @@ Value *Reassociate::ReassociateExpression(BinaryOperator *I) { // eliminate it. DEBUG(dbgs() << "Reassoc to scalar: " << *V << '\n'); I->replaceAllUsesWith(V); + if (Instruction *VI = dyn_cast(V)) + VI->setDebugLoc(I->getDebugLoc()); RemoveDeadBinaryOp(I); ++NumAnnihil; return V; @@ -1074,6 +1080,8 @@ Value *Reassociate::ReassociateExpression(BinaryOperator *I) { // This expression tree simplified to something that isn't a tree, // eliminate it. I->replaceAllUsesWith(Ops[0].Op); + if (Instruction *OI = dyn_cast(Ops[0].Op)) + OI->setDebugLoc(I->getDebugLoc()); RemoveDeadBinaryOp(I); return Ops[0].Op; } @@ -1091,7 +1099,21 @@ bool Reassociate::runOnFunction(Function &F) { MadeChange = false; for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) - ReassociateBB(FI); + for (BasicBlock::iterator BBI = FI->begin(); BBI != FI->end(); ) + ReassociateInst(BBI); + + // Now that we're done, revisit any instructions which are likely to + // have secondary reassociation opportunities. + while (!RedoInsts.empty()) + if (Value *V = RedoInsts.pop_back_val()) { + BasicBlock::iterator BBI = cast(V); + ReassociateInst(BBI); + } + + // Now that we're done, delete any instructions which are no longer used. + while (!DeadInsts.empty()) + if (Value *V = DeadInsts.pop_back_val()) + RecursivelyDeleteTriviallyDeadInstructions(V); // We are done with the rank map. RankMap.clear(); diff --git a/contrib/llvm/lib/Transforms/Scalar/Reg2Mem.cpp b/contrib/llvm/lib/Transforms/Scalar/Reg2Mem.cpp index 459bb0621f88..47afc770bb0c 100644 --- a/contrib/llvm/lib/Transforms/Scalar/Reg2Mem.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/Reg2Mem.cpp @@ -9,7 +9,7 @@ // // This file demotes all registers to memory references. It is intented to be // the inverse of PromoteMemoryToRegister. By converting to loads, the only -// values live accross basic blocks are allocas and loads before phi nodes. +// values live across basic blocks are allocas and loads before phi nodes. // It is intended that this should make CFG hacking much easier. // To make later hacking easier, the entry block is split into two, such that // all introduced allocas and nothing else are in the entry block. diff --git a/contrib/llvm/lib/Transforms/Scalar/SCCP.cpp b/contrib/llvm/lib/Transforms/Scalar/SCCP.cpp index c82e929b364e..db8eb850448f 100644 --- a/contrib/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -1989,7 +1989,7 @@ bool IPSCCP::runOnModule(Module &M) { ReturnsToZap[i]->setOperand(0, UndefValue::get(F->getReturnType())); } - // If we infered constant or undef values for globals variables, we can delete + // If we inferred constant or undef values for globals variables, we can delete // the global and any stores that remain to it. const DenseMap &TG = Solver.getTrackedGlobals(); for (DenseMap::const_iterator I = TG.begin(), diff --git a/contrib/llvm/lib/Transforms/Scalar/Scalar.cpp b/contrib/llvm/lib/Transforms/Scalar/Scalar.cpp index bf9ca6d803b6..32a050617432 100644 --- a/contrib/llvm/lib/Transforms/Scalar/Scalar.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/Scalar.cpp @@ -17,6 +17,7 @@ #include "llvm-c/Initialization.h" #include "llvm/InitializePasses.h" #include "llvm/PassManager.h" +#include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Target/TargetData.h" #include "llvm/Transforms/Scalar.h" @@ -34,7 +35,6 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) { initializeDCEPass(Registry); initializeDeadInstEliminationPass(Registry); initializeDSEPass(Registry); - initializeGEPSplitterPass(Registry); initializeGVNPass(Registry); initializeEarlyCSEPass(Registry); initializeIndVarSimplifyPass(Registry); @@ -56,7 +56,6 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) { initializeSROA_DTPass(Registry); initializeSROA_SSAUpPass(Registry); initializeCFGSimplifyPassPass(Registry); - initializeSimplifyHalfPowrLibCallsPass(Registry); initializeSimplifyLibCallsPass(Registry); initializeSinkingPass(Registry); initializeTailDupPass(Registry); @@ -103,6 +102,10 @@ void LLVMAddLoopDeletionPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createLoopDeletionPass()); } +void LLVMAddLoopIdiomPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createLoopIdiomPass()); +} + void LLVMAddLoopRotatePass(LLVMPassManagerRef PM) { unwrap(PM)->add(createLoopRotatePass()); } @@ -135,6 +138,10 @@ void LLVMAddScalarReplAggregatesPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createScalarReplAggregatesPass()); } +void LLVMAddScalarReplAggregatesPassSSA(LLVMPassManagerRef PM) { + unwrap(PM)->add(createScalarReplAggregatesPass(-1, false)); +} + void LLVMAddScalarReplAggregatesPassWithThreshold(LLVMPassManagerRef PM, int Threshold) { unwrap(PM)->add(createScalarReplAggregatesPass(Threshold)); @@ -159,3 +166,19 @@ void LLVMAddDemoteMemoryToRegisterPass(LLVMPassManagerRef PM) { void LLVMAddVerifierPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createVerifierPass()); } + +void LLVMAddCorrelatedValuePropagationPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createCorrelatedValuePropagationPass()); +} + +void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createEarlyCSEPass()); +} + +void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createTypeBasedAliasAnalysisPass()); +} + +void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createBasicAliasAnalysisPass()); +} diff --git a/contrib/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/contrib/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp index c3ca85280ee7..8178c2707599 100644 --- a/contrib/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -219,7 +219,7 @@ namespace { /// optimization, which scans the uses of an alloca and determines if it can /// rewrite it in terms of a single new alloca that can be mem2reg'd. class ConvertToScalarInfo { - /// AllocaSize - The size of the alloca being considered. + /// AllocaSize - The size of the alloca being considered in bytes. unsigned AllocaSize; const TargetData &TD; @@ -238,19 +238,22 @@ class ConvertToScalarInfo { /// also declared as a vector, we do want to promote to a vector. bool HadAVector; + /// HadNonMemTransferAccess - True if there is at least one access to the + /// alloca that is not a MemTransferInst. We don't want to turn structs into + /// large integers unless there is some potential for optimization. + bool HadNonMemTransferAccess; + public: explicit ConvertToScalarInfo(unsigned Size, const TargetData &td) - : AllocaSize(Size), TD(td) { - IsNotTrivial = false; - VectorTy = 0; - HadAVector = false; - } + : AllocaSize(Size), TD(td), IsNotTrivial(false), VectorTy(0), + HadAVector(false), HadNonMemTransferAccess(false) { } AllocaInst *TryConvert(AllocaInst *AI); private: bool CanConvertToScalar(Value *V, uint64_t Offset); - void MergeInType(const Type *In, uint64_t Offset); + void MergeInType(const Type *In, uint64_t Offset, bool IsLoadOrStore); + bool MergeInVectorType(const VectorType *VInTy, uint64_t Offset); void ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset); Value *ConvertScalar_ExtractValue(Value *NV, const Type *ToType, @@ -282,9 +285,14 @@ AllocaInst *ConvertToScalarInfo::TryConvert(AllocaInst *AI) { << *VectorTy << '\n'); NewTy = VectorTy; // Use the vector type. } else { + unsigned BitWidth = AllocaSize * 8; + if (!HadAVector && !HadNonMemTransferAccess && + !TD.fitsInLegalInteger(BitWidth)) + return 0; + DEBUG(dbgs() << "CONVERT TO SCALAR INTEGER: " << *AI << "\n"); // Create and insert the integer alloca. - NewTy = IntegerType::get(AI->getContext(), AllocaSize*8); + NewTy = IntegerType::get(AI->getContext(), BitWidth); } AllocaInst *NewAI = new AllocaInst(NewTy, 0, "", AI->getParent()->begin()); ConvertUsesToScalar(AI, NewAI, 0); @@ -294,16 +302,21 @@ AllocaInst *ConvertToScalarInfo::TryConvert(AllocaInst *AI) { /// MergeInType - Add the 'In' type to the accumulated vector type (VectorTy) /// so far at the offset specified by Offset (which is specified in bytes). /// -/// There are two cases we handle here: +/// There are three cases we handle here: /// 1) A union of vector types of the same size and potentially its elements. /// Here we turn element accesses into insert/extract element operations. /// This promotes a <4 x float> with a store of float to the third element /// into a <4 x float> that uses insert element. -/// 2) A fully general blob of memory, which we turn into some (potentially +/// 2) A union of vector types with power-of-2 size differences, e.g. a float, +/// <2 x float> and <4 x float>. Here we turn element accesses into insert +/// and extract element operations, and <2 x float> accesses into a cast to +/// <2 x double>, an extract, and a cast back to <2 x float>. +/// 3) A fully general blob of memory, which we turn into some (potentially /// large) integer type with extract and insert operations where the loads /// and stores would mutate the memory. We mark this by setting VectorTy /// to VoidTy. -void ConvertToScalarInfo::MergeInType(const Type *In, uint64_t Offset) { +void ConvertToScalarInfo::MergeInType(const Type *In, uint64_t Offset, + bool IsLoadOrStore) { // If we already decided to turn this into a blob of integer memory, there is // nothing to be done. if (VectorTy && VectorTy->isVoidTy()) @@ -314,33 +327,33 @@ void ConvertToScalarInfo::MergeInType(const Type *In, uint64_t Offset) { // If the In type is a vector that is the same size as the alloca, see if it // matches the existing VecTy. if (const VectorType *VInTy = dyn_cast(In)) { - // Remember if we saw a vector type. - HadAVector = true; - - if (VInTy->getBitWidth()/8 == AllocaSize && Offset == 0) { - // If we're storing/loading a vector of the right size, allow it as a - // vector. If this the first vector we see, remember the type so that - // we know the element size. If this is a subsequent access, ignore it - // even if it is a differing type but the same size. Worst case we can - // bitcast the resultant vectors. - if (VectorTy == 0) - VectorTy = VInTy; + if (MergeInVectorType(VInTy, Offset)) return; - } } else if (In->isFloatTy() || In->isDoubleTy() || (In->isIntegerTy() && In->getPrimitiveSizeInBits() >= 8 && isPowerOf2_32(In->getPrimitiveSizeInBits()))) { + // Full width accesses can be ignored, because they can always be turned + // into bitcasts. + unsigned EltSize = In->getPrimitiveSizeInBits()/8; + if (IsLoadOrStore && EltSize == AllocaSize) + return; + // If we're accessing something that could be an element of a vector, see // if the implied vector agrees with what we already have and if Offset is // compatible with it. - unsigned EltSize = In->getPrimitiveSizeInBits()/8; - if (Offset % EltSize == 0 && AllocaSize % EltSize == 0 && - (VectorTy == 0 || - cast(VectorTy)->getElementType() - ->getPrimitiveSizeInBits()/8 == EltSize)) { - if (VectorTy == 0) + if (Offset % EltSize == 0 && AllocaSize % EltSize == 0) { + if (!VectorTy) { VectorTy = VectorType::get(In, AllocaSize/EltSize); - return; + return; + } + + unsigned CurrentEltSize = cast(VectorTy)->getElementType() + ->getPrimitiveSizeInBits()/8; + if (EltSize == CurrentEltSize) + return; + + if (In->isIntegerTy() && isPowerOf2_32(AllocaSize / EltSize)) + return; } } @@ -349,6 +362,77 @@ void ConvertToScalarInfo::MergeInType(const Type *In, uint64_t Offset) { VectorTy = Type::getVoidTy(In->getContext()); } +/// MergeInVectorType - Handles the vector case of MergeInType, returning true +/// if the type was successfully merged and false otherwise. +bool ConvertToScalarInfo::MergeInVectorType(const VectorType *VInTy, + uint64_t Offset) { + // Remember if we saw a vector type. + HadAVector = true; + + // TODO: Support nonzero offsets? + if (Offset != 0) + return false; + + // Only allow vectors that are a power-of-2 away from the size of the alloca. + if (!isPowerOf2_64(AllocaSize / (VInTy->getBitWidth() / 8))) + return false; + + // If this the first vector we see, remember the type so that we know the + // element size. + if (!VectorTy) { + VectorTy = VInTy; + return true; + } + + unsigned BitWidth = cast(VectorTy)->getBitWidth(); + unsigned InBitWidth = VInTy->getBitWidth(); + + // Vectors of the same size can be converted using a simple bitcast. + if (InBitWidth == BitWidth && AllocaSize == (InBitWidth / 8)) + return true; + + const Type *ElementTy = cast(VectorTy)->getElementType(); + const Type *InElementTy = cast(VInTy)->getElementType(); + + // Do not allow mixed integer and floating-point accesses from vectors of + // different sizes. + if (ElementTy->isFloatingPointTy() != InElementTy->isFloatingPointTy()) + return false; + + if (ElementTy->isFloatingPointTy()) { + // Only allow floating-point vectors of different sizes if they have the + // same element type. + // TODO: This could be loosened a bit, but would anything benefit? + if (ElementTy != InElementTy) + return false; + + // There are no arbitrary-precision floating-point types, which limits the + // number of legal vector types with larger element types that we can form + // to bitcast and extract a subvector. + // TODO: We could support some more cases with mixed fp128 and double here. + if (!(BitWidth == 64 || BitWidth == 128) || + !(InBitWidth == 64 || InBitWidth == 128)) + return false; + } else { + assert(ElementTy->isIntegerTy() && "Vector elements must be either integer " + "or floating-point."); + unsigned BitWidth = ElementTy->getPrimitiveSizeInBits(); + unsigned InBitWidth = InElementTy->getPrimitiveSizeInBits(); + + // Do not allow integer types smaller than a byte or types whose widths are + // not a multiple of a byte. + if (BitWidth < 8 || InBitWidth < 8 || + BitWidth % 8 != 0 || InBitWidth % 8 != 0) + return false; + } + + // Pick the largest of the two vector types. + if (InBitWidth > BitWidth) + VectorTy = VInTy; + + return true; +} + /// CanConvertToScalar - V is a pointer. If we can convert the pointee and all /// its accesses to a single vector type, return true and set VecTy to /// the new type. If we could convert the alloca into a single promotable @@ -369,7 +453,8 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) { // Don't touch MMX operations. if (LI->getType()->isX86_MMXTy()) return false; - MergeInType(LI->getType(), Offset); + HadNonMemTransferAccess = true; + MergeInType(LI->getType(), Offset, true); continue; } @@ -379,7 +464,8 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) { // Don't touch MMX operations. if (SI->getOperand(0)->getType()->isX86_MMXTy()) return false; - MergeInType(SI->getOperand(0)->getType(), Offset); + HadNonMemTransferAccess = true; + MergeInType(SI->getOperand(0)->getType(), Offset, true); continue; } @@ -403,6 +489,7 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) { if (!CanConvertToScalar(GEP, Offset+GEPOffset)) return false; IsNotTrivial = true; // Can't be mem2reg'd. + HadNonMemTransferAccess = true; continue; } @@ -414,6 +501,7 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) { !isa(MSI->getLength())) return false; IsNotTrivial = true; // Can't be mem2reg'd. + HadNonMemTransferAccess = true; continue; } @@ -575,6 +663,63 @@ void ConvertToScalarInfo::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, } } +/// getScaledElementType - Gets a scaled element type for a partial vector +/// access of an alloca. The input types must be integer or floating-point +/// scalar or vector types, and the resulting type is an integer, float or +/// double. +static const Type *getScaledElementType(const Type *Ty1, const Type *Ty2, + unsigned NewBitWidth) { + bool IsFP1 = Ty1->isFloatingPointTy() || + (Ty1->isVectorTy() && + cast(Ty1)->getElementType()->isFloatingPointTy()); + bool IsFP2 = Ty2->isFloatingPointTy() || + (Ty2->isVectorTy() && + cast(Ty2)->getElementType()->isFloatingPointTy()); + + LLVMContext &Context = Ty1->getContext(); + + // Prefer floating-point types over integer types, as integer types may have + // been created by earlier scalar replacement. + if (IsFP1 || IsFP2) { + if (NewBitWidth == 32) + return Type::getFloatTy(Context); + if (NewBitWidth == 64) + return Type::getDoubleTy(Context); + } + + return Type::getIntNTy(Context, NewBitWidth); +} + +/// CreateShuffleVectorCast - Creates a shuffle vector to convert one vector +/// to another vector of the same element type which has the same allocation +/// size but different primitive sizes (e.g. <3 x i32> and <4 x i32>). +static Value *CreateShuffleVectorCast(Value *FromVal, const Type *ToType, + IRBuilder<> &Builder) { + const Type *FromType = FromVal->getType(); + const VectorType *FromVTy = cast(FromType); + const VectorType *ToVTy = cast(ToType); + assert((ToVTy->getElementType() == FromVTy->getElementType()) && + "Vectors must have the same element type"); + Value *UnV = UndefValue::get(FromType); + unsigned numEltsFrom = FromVTy->getNumElements(); + unsigned numEltsTo = ToVTy->getNumElements(); + + SmallVector Args; + const Type* Int32Ty = Builder.getInt32Ty(); + unsigned minNumElts = std::min(numEltsFrom, numEltsTo); + unsigned i; + for (i=0; i != minNumElts; ++i) + Args.push_back(ConstantInt::get(Int32Ty, i)); + + if (i < numEltsTo) { + Constant* UnC = UndefValue::get(Int32Ty); + for (; i != numEltsTo; ++i) + Args.push_back(UnC); + } + Constant *Mask = ConstantVector::get(Args); + return Builder.CreateShuffleVector(FromVal, UnV, Mask, "tmpV"); +} + /// ConvertScalar_ExtractValue - Extract a value of type ToType from an integer /// or vector value FromVal, extracting the bits from the offset specified by /// Offset. This returns the value, which is of type ToType. @@ -589,14 +734,46 @@ Value *ConvertToScalarInfo:: ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType, uint64_t Offset, IRBuilder<> &Builder) { // If the load is of the whole new alloca, no conversion is needed. - if (FromVal->getType() == ToType && Offset == 0) + const Type *FromType = FromVal->getType(); + if (FromType == ToType && Offset == 0) return FromVal; // If the result alloca is a vector type, this is either an element // access or a bitcast to another vector type of the same size. - if (const VectorType *VTy = dyn_cast(FromVal->getType())) { - if (ToType->isVectorTy()) - return Builder.CreateBitCast(FromVal, ToType, "tmp"); + if (const VectorType *VTy = dyn_cast(FromType)) { + unsigned ToTypeSize = TD.getTypeAllocSize(ToType); + if (ToTypeSize == AllocaSize) { + // If the two types have the same primitive size, use a bit cast. + // Otherwise, it is two vectors with the same element type that has + // the same allocation size but different number of elements so use + // a shuffle vector. + if (FromType->getPrimitiveSizeInBits() == + ToType->getPrimitiveSizeInBits()) + return Builder.CreateBitCast(FromVal, ToType, "tmp"); + else + return CreateShuffleVectorCast(FromVal, ToType, Builder); + } + + if (isPowerOf2_64(AllocaSize / ToTypeSize)) { + assert(!(ToType->isVectorTy() && Offset != 0) && "Can't extract a value " + "of a smaller vector type at a nonzero offset."); + + const Type *CastElementTy = getScaledElementType(FromType, ToType, + ToTypeSize * 8); + unsigned NumCastVectorElements = AllocaSize / ToTypeSize; + + LLVMContext &Context = FromVal->getContext(); + const Type *CastTy = VectorType::get(CastElementTy, + NumCastVectorElements); + Value *Cast = Builder.CreateBitCast(FromVal, CastTy, "tmp"); + + unsigned EltSize = TD.getTypeAllocSizeInBits(CastElementTy); + unsigned Elt = Offset/EltSize; + assert(EltSize*Elt == Offset && "Invalid modulus in validity checking"); + Value *Extract = Builder.CreateExtractElement(Cast, ConstantInt::get( + Type::getInt32Ty(Context), Elt), "tmp"); + return Builder.CreateBitCast(Extract, ToType, "tmp"); + } // Otherwise it must be an element access. unsigned Elt = 0; @@ -714,21 +891,49 @@ ConvertScalar_InsertValue(Value *SV, Value *Old, // Changing the whole vector with memset or with an access of a different // vector type? - if (ValSize == VecSize) - return Builder.CreateBitCast(SV, AllocaType, "tmp"); + if (ValSize == VecSize) { + // If the two types have the same primitive size, use a bit cast. + // Otherwise, it is two vectors with the same element type that has + // the same allocation size but different number of elements so use + // a shuffle vector. + if (VTy->getPrimitiveSizeInBits() == + SV->getType()->getPrimitiveSizeInBits()) + return Builder.CreateBitCast(SV, AllocaType, "tmp"); + else + return CreateShuffleVectorCast(SV, VTy, Builder); + } - uint64_t EltSize = TD.getTypeAllocSizeInBits(VTy->getElementType()); + if (isPowerOf2_64(VecSize / ValSize)) { + assert(!(SV->getType()->isVectorTy() && Offset != 0) && "Can't insert a " + "value of a smaller vector type at a nonzero offset."); + + const Type *CastElementTy = getScaledElementType(VTy, SV->getType(), + ValSize); + unsigned NumCastVectorElements = VecSize / ValSize; + + LLVMContext &Context = SV->getContext(); + const Type *OldCastTy = VectorType::get(CastElementTy, + NumCastVectorElements); + Value *OldCast = Builder.CreateBitCast(Old, OldCastTy, "tmp"); + + Value *SVCast = Builder.CreateBitCast(SV, CastElementTy, "tmp"); + + unsigned EltSize = TD.getTypeAllocSizeInBits(CastElementTy); + unsigned Elt = Offset/EltSize; + assert(EltSize*Elt == Offset && "Invalid modulus in validity checking"); + Value *Insert = + Builder.CreateInsertElement(OldCast, SVCast, ConstantInt::get( + Type::getInt32Ty(Context), Elt), "tmp"); + return Builder.CreateBitCast(Insert, AllocaType, "tmp"); + } // Must be an element insertion. + assert(SV->getType() == VTy->getElementType()); + uint64_t EltSize = TD.getTypeAllocSizeInBits(VTy->getElementType()); unsigned Elt = Offset/EltSize; - - if (SV->getType() != VTy->getElementType()) - SV = Builder.CreateBitCast(SV, VTy->getElementType(), "tmp"); - - SV = Builder.CreateInsertElement(Old, SV, + return Builder.CreateInsertElement(Old, SV, ConstantInt::get(Type::getInt32Ty(SV->getContext()), Elt), "tmp"); - return SV; } // If SV is a first-class aggregate value, insert each value recursively. @@ -1083,7 +1288,8 @@ static bool tryToMakeAllocaBePromotable(AllocaInst *AI, const TargetData *TD) { } const Type *LoadTy = cast(PN->getType())->getElementType(); - PHINode *NewPN = PHINode::Create(LoadTy, PN->getName()+".ld", PN); + PHINode *NewPN = PHINode::Create(LoadTy, PN->getNumIncomingValues(), + PN->getName()+".ld", PN); // Get the TBAA tag and alignment to use from one of the loads. It doesn't // matter which one we get and if any differ, it doesn't matter. diff --git a/contrib/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/contrib/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp index ce5dd73ace32..1137c2b23f96 100644 --- a/contrib/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -73,7 +73,8 @@ static void ChangeToUnreachable(Instruction *I, bool UseLLVMTrap) { if (UseLLVMTrap) { Function *TrapFn = Intrinsic::getDeclaration(BB->getParent()->getParent(), Intrinsic::trap); - CallInst::Create(TrapFn, "", I); + CallInst *CallTrap = CallInst::Create(TrapFn, "", I); + CallTrap->setDebugLoc(I->getDebugLoc()); } new UnreachableInst(I->getContext(), I); @@ -259,11 +260,12 @@ static bool MergeEmptyReturnBlocks(Function &F) { PHINode *RetBlockPHI = dyn_cast(RetBlock->begin()); if (RetBlockPHI == 0) { Value *InVal = cast(RetBlock->getTerminator())->getOperand(0); - RetBlockPHI = PHINode::Create(Ret->getOperand(0)->getType(), "merge", + pred_iterator PB = pred_begin(RetBlock), PE = pred_end(RetBlock); + RetBlockPHI = PHINode::Create(Ret->getOperand(0)->getType(), + std::distance(PB, PE), "merge", &RetBlock->front()); - for (pred_iterator PI = pred_begin(RetBlock), E = pred_end(RetBlock); - PI != E; ++PI) + for (pred_iterator PI = PB; PI != PE; ++PI) RetBlockPHI->addIncoming(InVal, *PI); RetBlock->getTerminator()->setOperand(0, RetBlockPHI); } diff --git a/contrib/llvm/lib/Transforms/Scalar/SimplifyHalfPowrLibCalls.cpp b/contrib/llvm/lib/Transforms/Scalar/SimplifyHalfPowrLibCalls.cpp deleted file mode 100644 index 70ff32e02310..000000000000 --- a/contrib/llvm/lib/Transforms/Scalar/SimplifyHalfPowrLibCalls.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//===- SimplifyHalfPowrLibCalls.cpp - Optimize specific half_powr calls ---===// -// -// 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 simple pass that applies an experimental -// transformation on calls to specific functions. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "simplify-libcalls-halfpowr" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Target/TargetData.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Debug.h" -using namespace llvm; - -namespace { - /// This pass optimizes well half_powr function calls. - /// - class SimplifyHalfPowrLibCalls : public FunctionPass { - const TargetData *TD; - public: - static char ID; // Pass identification - SimplifyHalfPowrLibCalls() : FunctionPass(ID) { - initializeSimplifyHalfPowrLibCallsPass(*PassRegistry::getPassRegistry()); - } - - bool runOnFunction(Function &F); - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - } - - Instruction * - InlineHalfPowrs(const std::vector &HalfPowrs, - Instruction *InsertPt); - }; - char SimplifyHalfPowrLibCalls::ID = 0; -} // end anonymous namespace. - -INITIALIZE_PASS(SimplifyHalfPowrLibCalls, "simplify-libcalls-halfpowr", - "Simplify half_powr library calls", false, false) - -// Public interface to the Simplify HalfPowr LibCalls pass. -FunctionPass *llvm::createSimplifyHalfPowrLibCallsPass() { - return new SimplifyHalfPowrLibCalls(); -} - -/// InlineHalfPowrs - Inline a sequence of adjacent half_powr calls, rearranging -/// their control flow to better facilitate subsequent optimization. -Instruction * -SimplifyHalfPowrLibCalls:: -InlineHalfPowrs(const std::vector &HalfPowrs, - Instruction *InsertPt) { - std::vector Bodies; - BasicBlock *NewBlock = 0; - - for (unsigned i = 0, e = HalfPowrs.size(); i != e; ++i) { - CallInst *Call = cast(HalfPowrs[i]); - Function *Callee = Call->getCalledFunction(); - - // Minimally sanity-check the CFG of half_powr to ensure that it contains - // the kind of code we expect. If we're running this pass, we have - // reason to believe it will be what we expect. - Function::iterator I = Callee->begin(); - BasicBlock *Prologue = I++; - if (I == Callee->end()) break; - BasicBlock *SubnormalHandling = I++; - if (I == Callee->end()) break; - BasicBlock *Body = I++; - if (I != Callee->end()) break; - if (SubnormalHandling->getSinglePredecessor() != Prologue) - break; - BranchInst *PBI = dyn_cast(Prologue->getTerminator()); - if (!PBI || !PBI->isConditional()) - break; - BranchInst *SNBI = dyn_cast(SubnormalHandling->getTerminator()); - if (!SNBI || SNBI->isConditional()) - break; - if (!isa(Body->getTerminator())) - break; - - Instruction *NextInst = llvm::next(BasicBlock::iterator(Call)); - - // Inline the call, taking care of what code ends up where. - NewBlock = SplitBlock(NextInst->getParent(), NextInst, this); - - InlineFunctionInfo IFI(0, TD); - bool B = InlineFunction(Call, IFI); - assert(B && "half_powr didn't inline?"); - (void)B; - - BasicBlock *NewBody = NewBlock->getSinglePredecessor(); - assert(NewBody); - Bodies.push_back(NewBody); - } - - if (!NewBlock) - return InsertPt; - - // Put the code for all the bodies into one block, to facilitate - // subsequent optimization. - (void)SplitEdge(NewBlock->getSinglePredecessor(), NewBlock, this); - for (unsigned i = 0, e = Bodies.size(); i != e; ++i) { - BasicBlock *Body = Bodies[i]; - Instruction *FNP = Body->getFirstNonPHI(); - // Splice the insts from body into NewBlock. - NewBlock->getInstList().splice(NewBlock->begin(), Body->getInstList(), - FNP, Body->getTerminator()); - } - - return NewBlock->begin(); -} - -/// runOnFunction - Top level algorithm. -/// -bool SimplifyHalfPowrLibCalls::runOnFunction(Function &F) { - TD = getAnalysisIfAvailable(); - - bool Changed = false; - std::vector HalfPowrs; - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { - // Look for calls. - bool IsHalfPowr = false; - if (CallInst *CI = dyn_cast(I)) { - // Look for direct calls and calls to non-external functions. - Function *Callee = CI->getCalledFunction(); - if (Callee && Callee->hasExternalLinkage()) { - // Look for calls with well-known names. - if (Callee->getName() == "__half_powrf4") - IsHalfPowr = true; - } - } - if (IsHalfPowr) - HalfPowrs.push_back(I); - // We're looking for sequences of up to three such calls, which we'll - // simplify as a group. - if ((!IsHalfPowr && !HalfPowrs.empty()) || HalfPowrs.size() == 3) { - I = InlineHalfPowrs(HalfPowrs, I); - E = I->getParent()->end(); - HalfPowrs.clear(); - Changed = true; - } - } - assert(HalfPowrs.empty() && "Block had no terminator!"); - } - - return Changed; -} diff --git a/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 9f136d4e3077..6247b0348f14 100644 --- a/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -49,6 +49,7 @@ class LibCallOptimization { protected: Function *Caller; const TargetData *TD; + const TargetLibraryInfo *TLI; LLVMContext* Context; public: LibCallOptimization() { } @@ -62,9 +63,11 @@ class LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) =0; - Value *OptimizeCall(CallInst *CI, const TargetData *TD, IRBuilder<> &B) { + Value *OptimizeCall(CallInst *CI, const TargetData *TD, + const TargetLibraryInfo *TLI, IRBuilder<> &B) { Caller = CI->getParent()->getParent(); this->TD = TD; + this->TLI = TLI; if (CI->getCalledFunction()) Context = &CI->getCalledFunction()->getContext(); @@ -97,6 +100,15 @@ static bool IsOnlyUsedInZeroEqualityComparison(Value *V) { } return true; } + +static bool CallHasFloatingPointArgument(const CallInst *CI) { + for (CallInst::const_op_iterator it = CI->op_begin(), e = CI->op_end(); + it != e; ++it) { + if ((*it)->getType()->isFloatingPointTy()) + return true; + } + return false; +} /// IsOnlyUsedInEqualityComparison - Return true if it is only used in equality /// comparisons with With. @@ -1075,14 +1087,8 @@ struct ToAsciiOpt : public LibCallOptimization { // 'printf' Optimizations struct PrintFOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - // Require one fixed pointer argument and an integer/void result. - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() || - !(FT->getReturnType()->isIntegerTy() || - FT->getReturnType()->isVoidTy())) - return 0; - + Value *OptimizeFixedFormatString(Function *Callee, CallInst *CI, + IRBuilder<> &B) { // Check for a fixed format string. std::string FormatStr; if (!GetConstantStringInfo(CI->getArgOperand(0), FormatStr)) @@ -1138,20 +1144,40 @@ struct PrintFOpt : public LibCallOptimization { } return 0; } + + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Require one fixed pointer argument and an integer/void result. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() || + !(FT->getReturnType()->isIntegerTy() || + FT->getReturnType()->isVoidTy())) + return 0; + + if (Value *V = OptimizeFixedFormatString(Callee, CI, B)) { + return V; + } + + // printf(format, ...) -> iprintf(format, ...) if no floating point + // arguments. + if (TLI->has(LibFunc::iprintf) && !CallHasFloatingPointArgument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Constant *IPrintFFn = + M->getOrInsertFunction("iprintf", FT, Callee->getAttributes()); + CallInst *New = cast(CI->clone()); + New->setCalledFunction(IPrintFFn); + B.Insert(New); + return New; + } + return 0; + } }; //===---------------------------------------===// // 'sprintf' Optimizations struct SPrintFOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - // Require two fixed pointer arguments and an integer result. - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isPointerTy() || - !FT->getReturnType()->isIntegerTy()) - return 0; - + Value *OptimizeFixedFormatString(Function *Callee, CallInst *CI, + IRBuilder<> &B) { // Check for a fixed format string. std::string FormatStr; if (!GetConstantStringInfo(CI->getArgOperand(1), FormatStr)) @@ -1212,6 +1238,32 @@ struct SPrintFOpt : public LibCallOptimization { } return 0; } + + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Require two fixed pointer arguments and an integer result. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy() || + !FT->getReturnType()->isIntegerTy()) + return 0; + + if (Value *V = OptimizeFixedFormatString(Callee, CI, B)) { + return V; + } + + // sprintf(str, format, ...) -> siprintf(str, format, ...) if no floating + // point arguments. + if (TLI->has(LibFunc::siprintf) && !CallHasFloatingPointArgument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Constant *SIPrintFFn = + M->getOrInsertFunction("siprintf", FT, Callee->getAttributes()); + CallInst *New = cast(CI->clone()); + New->setCalledFunction(SIPrintFFn); + B.Insert(New); + return New; + } + return 0; + } }; //===---------------------------------------===// @@ -1278,14 +1330,8 @@ struct FPutsOpt : public LibCallOptimization { // 'fprintf' Optimizations struct FPrintFOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - // Require two fixed paramters as pointers and integer result. - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() || - !FT->getParamType(1)->isPointerTy() || - !FT->getReturnType()->isIntegerTy()) - return 0; - + Value *OptimizeFixedFormatString(Function *Callee, CallInst *CI, + IRBuilder<> &B) { // All the optimizations depend on the format string. std::string FormatStr; if (!GetConstantStringInfo(CI->getArgOperand(1), FormatStr)) @@ -1330,6 +1376,32 @@ struct FPrintFOpt : public LibCallOptimization { } return 0; } + + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Require two fixed paramters as pointers and integer result. + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy() || + !FT->getReturnType()->isIntegerTy()) + return 0; + + if (Value *V = OptimizeFixedFormatString(Callee, CI, B)) { + return V; + } + + // fprintf(stream, format, ...) -> fiprintf(stream, format, ...) if no + // floating point arguments. + if (TLI->has(LibFunc::fiprintf) && !CallHasFloatingPointArgument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Constant *FIPrintFFn = + M->getOrInsertFunction("fiprintf", FT, Callee->getAttributes()); + CallInst *New = cast(CI->clone()); + New->setCalledFunction(FIPrintFFn); + B.Insert(New); + return New; + } + return 0; + } }; //===---------------------------------------===// @@ -1544,8 +1616,11 @@ bool SimplifyLibCalls::runOnFunction(Function &F) { // Set the builder to the instruction after the call. Builder.SetInsertPoint(BB, I); + // Use debug location of CI for all new instructions. + Builder.SetCurrentDebugLocation(CI->getDebugLoc()); + // Try to optimize this call. - Value *Result = LCO->OptimizeCall(CI, TD, Builder); + Value *Result = LCO->OptimizeCall(CI, TD, TLI, Builder); if (Result == 0) continue; DEBUG(dbgs() << "SimplifyLibCalls simplified: " << *CI; diff --git a/contrib/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/contrib/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp index 5b6bc04cc1c2..539cc6f0baf5 100644 --- a/contrib/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -36,7 +36,7 @@ // evaluated each time through the tail recursion. Safely keeping allocas // in the entry block requires analysis to proves that the tail-called // function does not read or write the stack object. -// 2. Tail recursion is only performed if the call immediately preceeds the +// 2. Tail recursion is only performed if the call immediately precedes the // return instruction. It's possible that there could be a jump between // the call and the return. // 3. There can be intervening operations between the call and the return that @@ -433,7 +433,7 @@ bool TailCallElim::EliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, if (CanMoveAboveCall(BBI, CI)) continue; // If we can't move the instruction above the call, it might be because it - // is an associative and commutative operation that could be tranformed + // is an associative and commutative operation that could be transformed // using accumulator recursion elimination. Check to see if this is the // case, and if so, remember the initial accumulator value for later. if ((AccumulatorRecursionEliminationInitVal = @@ -496,7 +496,7 @@ bool TailCallElim::EliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, Instruction *InsertPos = OldEntry->begin(); for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { - PHINode *PN = PHINode::Create(I->getType(), + PHINode *PN = PHINode::Create(I->getType(), 2, I->getName() + ".tr", InsertPos); I->replaceAllUsesWith(PN); // Everyone use the PHI node now! PN->addIncoming(I, NewEntry); @@ -527,8 +527,10 @@ bool TailCallElim::EliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, if (AccumulatorRecursionEliminationInitVal) { Instruction *AccRecInstr = AccumulatorRecursionInstr; // Start by inserting a new PHI node for the accumulator. + pred_iterator PB = pred_begin(OldEntry), PE = pred_end(OldEntry); PHINode *AccPN = PHINode::Create(AccumulatorRecursionEliminationInitVal->getType(), + std::distance(PB, PE) + 1, "accumulator.tr", OldEntry->begin()); // Loop over all of the predecessors of the tail recursion block. For the @@ -537,8 +539,7 @@ bool TailCallElim::EliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, // other tail recursions eliminated) the accumulator is not modified. // Because we haven't added the branch in the current block to OldEntry yet, // it will not show up as a predecessor. - for (pred_iterator PI = pred_begin(OldEntry), PE = pred_end(OldEntry); - PI != PE; ++PI) { + for (pred_iterator PI = PB; PI != PE; ++PI) { BasicBlock *P = *PI; if (P == &F->getEntryBlock()) AccPN->addIncoming(AccumulatorRecursionEliminationInitVal, P); @@ -572,7 +573,9 @@ bool TailCallElim::EliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, // Now that all of the PHI nodes are in place, remove the call and // ret instructions, replacing them with an unconditional branch. - BranchInst::Create(OldEntry, Ret); + BranchInst *NewBI = BranchInst::Create(OldEntry, Ret); + NewBI->setDebugLoc(CI->getDebugLoc()); + BB->getInstList().erase(Ret); // Remove return. BB->getInstList().erase(CI); // Remove call. ++NumEliminated; diff --git a/contrib/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/contrib/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp index acaea195e710..c705cc51094a 100644 --- a/contrib/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/contrib/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -447,7 +447,7 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB, // If the values coming into the block are not the same, we need a PHI. // Create the new PHI node, insert it into NewBB at the end of the block PHINode *NewPHI = - PHINode::Create(PN->getType(), PN->getName()+".ph", BI); + PHINode::Create(PN->getType(), NumPreds, PN->getName()+".ph", BI); if (AA) AA->copyValue(PN, NewPHI); // Move all of the PHI values for 'Preds' to the new PHI. @@ -538,3 +538,15 @@ ReturnInst *llvm::FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, UncondBranch->eraseFromParent(); return cast(NewRet); } + +/// GetFirstDebugLocInBasicBlock - Return first valid DebugLoc entry in a +/// given basic block. +DebugLoc llvm::GetFirstDebugLocInBasicBlock(const BasicBlock *BB) { + for (BasicBlock::const_iterator BI = BB->begin(), BE = BB->end(); + BI != BE; ++BI) { + DebugLoc DL = BI->getDebugLoc(); + if (!DL.isUnknown()) + return DL; + } + return DebugLoc(); +} diff --git a/contrib/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp b/contrib/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp index 616b066b5ab1..caf2aeb4d30a 100644 --- a/contrib/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ b/contrib/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -56,7 +56,7 @@ char BreakCriticalEdges::ID = 0; INITIALIZE_PASS(BreakCriticalEdges, "break-crit-edges", "Break critical edges in CFG", false, false) -// Publically exposed interface to pass... +// Publicly exposed interface to pass... char &llvm::BreakCriticalEdgesID = BreakCriticalEdges::ID; FunctionPass *llvm::createBreakCriticalEdgesPass() { return new BreakCriticalEdges(); @@ -140,7 +140,7 @@ static void CreatePHIsForSplitLoopExit(SmallVectorImpl &Preds, if (VP->getParent() == SplitBB) continue; // Otherwise a new PHI is needed. Create one and populate it. - PHINode *NewPN = PHINode::Create(PN->getType(), "split", + PHINode *NewPN = PHINode::Create(PN->getType(), Preds.size(), "split", SplitBB->getTerminator()); for (unsigned i = 0, e = Preds.size(); i != e; ++i) NewPN->addIncoming(V, Preds[i]); diff --git a/contrib/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/contrib/llvm/lib/Transforms/Utils/CodeExtractor.cpp index e6337722c8bd..8c133ea7f560 100644 --- a/contrib/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/contrib/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -104,7 +104,7 @@ namespace { /// region, we need to split the entry block of the region so that the PHI node /// is easier to deal with. void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) { - bool HasPredsFromRegion = false; + unsigned NumPredsFromRegion = 0; unsigned NumPredsOutsideRegion = 0; if (Header != &Header->getParent()->getEntryBlock()) { @@ -116,7 +116,7 @@ void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) { // header block into two. for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) if (BlocksToExtract.count(PN->getIncomingBlock(i))) - HasPredsFromRegion = true; + ++NumPredsFromRegion; else ++NumPredsOutsideRegion; @@ -147,7 +147,7 @@ void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) { // Okay, now we need to adjust the PHI nodes and any branches from within the // region to go to the new header block instead of the old header block. - if (HasPredsFromRegion) { + if (NumPredsFromRegion) { PHINode *PN = cast(OldPred->begin()); // Loop over all of the predecessors of OldPred that are in the region, // changing them to branch to NewBB instead. @@ -157,14 +157,14 @@ void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) { TI->replaceUsesOfWith(OldPred, NewBB); } - // Okay, everthing within the region is now branching to the right block, we + // Okay, everything within the region is now branching to the right block, we // just have to update the PHI nodes now, inserting PHI nodes into NewBB. for (AfterPHIs = OldPred->begin(); isa(AfterPHIs); ++AfterPHIs) { PHINode *PN = cast(AfterPHIs); // Create a new PHI node in the new region, which has an incoming value // from OldPred of PN. - PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName()+".ce", - NewBB->begin()); + PHINode *NewPN = PHINode::Create(PN->getType(), 1 + NumPredsFromRegion, + PN->getName()+".ce", NewBB->begin()); NewPN->addIncoming(PN, OldPred); // Loop over all of the incoming value in PN, moving them to NewPN if they diff --git a/contrib/llvm/lib/Transforms/Utils/InlineFunction.cpp b/contrib/llvm/lib/Transforms/Utils/InlineFunction.cpp index c1faf2411331..7d179092c063 100644 --- a/contrib/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/contrib/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -320,7 +320,7 @@ static Value *HandleByValArgument(Value *Arg, Instruction *TheCall, // // Note that this only does one level of inlining. For example, if the // instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now -// exists in the instruction stream. Similiarly this will inline a recursive +// exists in the instruction stream. Similarly this will inline a recursive // function by one level. // bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI) { @@ -624,7 +624,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI) { // The PHI node should go at the front of the new basic block to merge all // possible incoming values. if (!TheCall->use_empty()) { - PHI = PHINode::Create(RTy, TheCall->getName(), + PHI = PHINode::Create(RTy, Returns.size(), TheCall->getName(), AfterCallBB->begin()); // Anything that used the result of the function call should now use the // PHI node as their operand. diff --git a/contrib/llvm/lib/Transforms/Utils/LCSSA.cpp b/contrib/llvm/lib/Transforms/Utils/LCSSA.cpp index b2e5fa6d7e3a..b654111eba74 100644 --- a/contrib/llvm/lib/Transforms/Utils/LCSSA.cpp +++ b/contrib/llvm/lib/Transforms/Utils/LCSSA.cpp @@ -207,6 +207,8 @@ bool LCSSA::ProcessInstruction(Instruction *Inst, DomTreeNode *DomNode = DT->getNode(DomBB); + SmallVector AddedPHIs; + SSAUpdater SSAUpdate; SSAUpdate.Initialize(Inst->getType(), Inst->getName()); @@ -220,9 +222,10 @@ bool LCSSA::ProcessInstruction(Instruction *Inst, // If we already inserted something for this BB, don't reprocess it. if (SSAUpdate.HasValueForBlock(ExitBB)) continue; - PHINode *PN = PHINode::Create(Inst->getType(), Inst->getName()+".lcssa", + PHINode *PN = PHINode::Create(Inst->getType(), + PredCache.GetNumPreds(ExitBB), + Inst->getName()+".lcssa", ExitBB->begin()); - PN->reserveOperandSpace(PredCache.GetNumPreds(ExitBB)); // Add inputs from inside the loop for this PHI. for (BasicBlock **PI = PredCache.GetPreds(ExitBB); *PI; ++PI) { @@ -236,6 +239,8 @@ bool LCSSA::ProcessInstruction(Instruction *Inst, &PN->getOperandUse( PN->getOperandNumForIncomingValue(PN->getNumIncomingValues()-1))); } + + AddedPHIs.push_back(PN); // Remember that this phi makes the value alive in this block. SSAUpdate.AddAvailableValue(ExitBB, PN); @@ -262,6 +267,12 @@ bool LCSSA::ProcessInstruction(Instruction *Inst, // Otherwise, do full PHI insertion. SSAUpdate.RewriteUse(*UsesToRewrite[i]); } + + // Remove PHI nodes that did not have any uses rewritten. + for (unsigned i = 0, e = AddedPHIs.size(); i != e; ++i) { + if (AddedPHIs[i]->use_empty()) + AddedPHIs[i]->eraseFromParent(); + } return true; } diff --git a/contrib/llvm/lib/Transforms/Utils/Local.cpp b/contrib/llvm/lib/Transforms/Utils/Local.cpp index 3f789fa86589..4bca2fc1fb9d 100644 --- a/contrib/llvm/lib/Transforms/Utils/Local.cpp +++ b/contrib/llvm/lib/Transforms/Utils/Local.cpp @@ -20,8 +20,11 @@ #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/DIBuilder.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/InstructionSimplify.h" @@ -65,8 +68,7 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB) { // Let the basic block know that we are letting go of it. Based on this, // it will adjust it's PHI nodes. - assert(BI->getParent() && "Terminator not inserted in block!"); - OldDest->removePredecessor(BI->getParent()); + OldDest->removePredecessor(BB); // Replace the conditional branch with an unconditional one. BranchInst::Create(Destination, BI); @@ -209,8 +211,18 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB) { bool llvm::isInstructionTriviallyDead(Instruction *I) { if (!I->use_empty() || isa(I)) return false; - // We don't want debug info removed by anything this general. - if (isa(I)) return false; + // We don't want debug info removed by anything this general, unless + // debug info is empty. + if (DbgDeclareInst *DDI = dyn_cast(I)) { + if (DDI->getAddress()) + return false; + return true; + } + if (DbgValueInst *DVI = dyn_cast(I)) { + if (DVI->getValue()) + return false; + return true; + } if (!I->mayHaveSideEffects()) return true; @@ -320,8 +332,14 @@ bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD) { BI = BB->begin(); continue; } - + + if (Inst->isTerminator()) + break; + + WeakVH BIHandle(BI); MadeChange |= RecursivelyDeleteTriviallyDeadInstructions(Inst); + if (BIHandle != BI) + BI = BB->begin(); } return MadeChange; } @@ -632,6 +650,8 @@ bool llvm::EliminateDuplicatePHINodes(BasicBlock *BB) { Hash ^= reinterpret_cast(static_cast(*I)); Hash = (Hash << 7) | (Hash >> (sizeof(uintptr_t) * CHAR_BIT - 7)); } + // Avoid colliding with the DenseMap sentinels ~0 and ~0-1. + Hash >>= 1; // If we've never seen this hash value before, it's a unique PHI. std::pair::iterator, bool> Pair = HashMap.insert(std::make_pair(Hash, PN)); @@ -753,3 +773,83 @@ unsigned llvm::getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign, return Align; } +///===---------------------------------------------------------------------===// +/// Dbg Intrinsic utilities +/// + +/// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value +/// that has an associated llvm.dbg.decl intrinsic. +bool llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, + StoreInst *SI, DIBuilder &Builder) { + DIVariable DIVar(DDI->getVariable()); + if (!DIVar.Verify()) + return false; + + Instruction *DbgVal = + Builder.insertDbgValueIntrinsic(SI->getOperand(0), 0, + DIVar, SI); + + // Propagate any debug metadata from the store onto the dbg.value. + DebugLoc SIDL = SI->getDebugLoc(); + if (!SIDL.isUnknown()) + DbgVal->setDebugLoc(SIDL); + // Otherwise propagate debug metadata from dbg.declare. + else + DbgVal->setDebugLoc(DDI->getDebugLoc()); + return true; +} + +/// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value +/// that has an associated llvm.dbg.decl intrinsic. +bool llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, + LoadInst *LI, DIBuilder &Builder) { + DIVariable DIVar(DDI->getVariable()); + if (!DIVar.Verify()) + return false; + + Instruction *DbgVal = + Builder.insertDbgValueIntrinsic(LI->getOperand(0), 0, + DIVar, LI); + + // Propagate any debug metadata from the store onto the dbg.value. + DebugLoc LIDL = LI->getDebugLoc(); + if (!LIDL.isUnknown()) + DbgVal->setDebugLoc(LIDL); + // Otherwise propagate debug metadata from dbg.declare. + else + DbgVal->setDebugLoc(DDI->getDebugLoc()); + return true; +} + +/// LowerDbgDeclare - Lowers llvm.dbg.declare intrinsics into appropriate set +/// of llvm.dbg.value intrinsics. +bool llvm::LowerDbgDeclare(Function &F) { + DIBuilder DIB(*F.getParent()); + SmallVector Dbgs; + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { + if (DbgDeclareInst *DDI = dyn_cast(BI)) + Dbgs.push_back(DDI); + } + if (Dbgs.empty()) + return false; + + for (SmallVector::iterator I = Dbgs.begin(), + E = Dbgs.end(); I != E; ++I) { + DbgDeclareInst *DDI = *I; + if (AllocaInst *AI = dyn_cast_or_null(DDI->getAddress())) { + bool RemoveDDI = true; + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); + UI != E; ++UI) + if (StoreInst *SI = dyn_cast(*UI)) + ConvertDebugDeclareToDebugValue(DDI, SI, DIB); + else if (LoadInst *LI = dyn_cast(*UI)) + ConvertDebugDeclareToDebugValue(DDI, LI, DIB); + else + RemoveDDI = false; + if (RemoveDDI) + DDI->eraseFromParent(); + } + } + return true; +} diff --git a/contrib/llvm/lib/Transforms/Utils/LoopSimplify.cpp b/contrib/llvm/lib/Transforms/Utils/LoopSimplify.cpp index 246263026bb4..f02ffd20bca9 100644 --- a/contrib/llvm/lib/Transforms/Utils/LoopSimplify.cpp +++ b/contrib/llvm/lib/Transforms/Utils/LoopSimplify.cpp @@ -115,7 +115,7 @@ INITIALIZE_PASS_DEPENDENCY(LoopInfo) INITIALIZE_PASS_END(LoopSimplify, "loop-simplify", "Canonicalize natural loops", true, false) -// Publically exposed interface to pass... +// Publicly exposed interface to pass... char &llvm::LoopSimplifyID = LoopSimplify::ID; Pass *llvm::createLoopSimplifyPass() { return new LoopSimplify(); } @@ -648,9 +648,8 @@ LoopSimplify::InsertUniqueBackedgeBlock(Loop *L, BasicBlock *Preheader) { // the backedge block which correspond to any PHI nodes in the header block. for (BasicBlock::iterator I = Header->begin(); isa(I); ++I) { PHINode *PN = cast(I); - PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName()+".be", - BETerminator); - NewPN->reserveOperandSpace(BackedgeBlocks.size()); + PHINode *NewPN = PHINode::Create(PN->getType(), BackedgeBlocks.size(), + PN->getName()+".be", BETerminator); if (AA) AA->copyValue(PN, NewPN); // Loop over the PHI node, moving all entries except the one for the diff --git a/contrib/llvm/lib/Transforms/Utils/LowerSwitch.cpp b/contrib/llvm/lib/Transforms/Utils/LowerSwitch.cpp index 914a439718d4..ed733d393a11 100644 --- a/contrib/llvm/lib/Transforms/Utils/LowerSwitch.cpp +++ b/contrib/llvm/lib/Transforms/Utils/LowerSwitch.cpp @@ -84,7 +84,7 @@ char LowerSwitch::ID = 0; INITIALIZE_PASS(LowerSwitch, "lowerswitch", "Lower SwitchInst's to branches", false, false) -// Publically exposed interface to pass... +// Publicly exposed interface to pass... char &llvm::LowerSwitchID = LowerSwitch::ID; // createLowerSwitchPass - Interface to this file... FunctionPass *llvm::createLowerSwitchPass() { diff --git a/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index 778885723e66..50c9ae204a4c 100644 --- a/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -38,6 +38,7 @@ #include "llvm/Analysis/DIBuilder.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -45,7 +46,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/CFG.h" #include -#include #include using namespace llvm; @@ -103,7 +103,7 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) { /// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic describing the /// alloca 'V', if any. static DbgDeclareInst *FindAllocaDbgDeclare(Value *V) { - if (MDNode *DebugNode = MDNode::getIfExists(V->getContext(), &V, 1)) + if (MDNode *DebugNode = MDNode::getIfExists(V->getContext(), V)) for (Value::use_iterator UI = DebugNode->use_begin(), E = DebugNode->use_end(); UI != E; ++UI) if (DbgDeclareInst *DDI = dyn_cast(*UI)) @@ -273,8 +273,6 @@ namespace { LargeBlockInfo &LBI); void PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, LargeBlockInfo &LBI); - void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, StoreInst *SI); - void RenamePass(BasicBlock *BB, BasicBlock *Pred, RenamePassData::ValVector &IncVals, @@ -391,7 +389,9 @@ void PromoteMem2Reg::run() { if (Info.UsingBlocks.empty()) { // Record debuginfo for the store and remove the declaration's debuginfo. if (DbgDeclareInst *DDI = Info.DbgDeclare) { - ConvertDebugDeclareToDebugValue(DDI, Info.OnlyStore); + if (!DIB) + DIB = new DIBuilder(*DDI->getParent()->getParent()->getParent()); + ConvertDebugDeclareToDebugValue(DDI, Info.OnlyStore, *DIB); DDI->eraseFromParent(); } // Remove the (now dead) store and alloca. @@ -423,8 +423,11 @@ void PromoteMem2Reg::run() { while (!AI->use_empty()) { StoreInst *SI = cast(AI->use_back()); // Record debuginfo for the store before removing it. - if (DbgDeclareInst *DDI = Info.DbgDeclare) - ConvertDebugDeclareToDebugValue(DDI, SI); + if (DbgDeclareInst *DDI = Info.DbgDeclare) { + if (!DIB) + DIB = new DIBuilder(*SI->getParent()->getParent()->getParent()); + ConvertDebugDeclareToDebugValue(DDI, SI, *DIB); + } SI->eraseFromParent(); LBI.deleteValue(SI); } @@ -944,28 +947,6 @@ void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, } } -// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value -// that has an associated llvm.dbg.decl intrinsic. -void PromoteMem2Reg::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, - StoreInst *SI) { - DIVariable DIVar(DDI->getVariable()); - if (!DIVar.Verify()) - return; - - if (!DIB) - DIB = new DIBuilder(*SI->getParent()->getParent()->getParent()); - Instruction *DbgVal = DIB->insertDbgValueIntrinsic(SI->getOperand(0), 0, - DIVar, SI); - - // Propagate any debug metadata from the store onto the dbg.value. - DebugLoc SIDL = SI->getDebugLoc(); - if (!SIDL.isUnknown()) - DbgVal->setDebugLoc(SIDL); - // Otherwise propagate debug metadata from dbg.declare. - else - DbgVal->setDebugLoc(DDI->getDebugLoc()); -} - // QueuePhiNode - queues a phi-node to be added to a basic-block for a specific // Alloca returns true if there wasn't already a phi-node for that variable // @@ -979,12 +960,11 @@ bool PromoteMem2Reg::QueuePhiNode(BasicBlock *BB, unsigned AllocaNo, // Create a PhiNode using the dereferenced type... and add the phi-node to the // BasicBlock. - PN = PHINode::Create(Allocas[AllocaNo]->getAllocatedType(), + PN = PHINode::Create(Allocas[AllocaNo]->getAllocatedType(), getNumPreds(BB), Allocas[AllocaNo]->getName() + "." + Twine(Version++), BB->begin()); ++NumPHIInsert; PhiToAllocaMap[PN] = AllocaNo; - PN->reserveOperandSpace(getNumPreds(BB)); if (AST && PN->getType()->isPointerTy()) AST->copyValue(PointerAllocaValues[AllocaNo], PN); @@ -1076,8 +1056,11 @@ void PromoteMem2Reg::RenamePass(BasicBlock *BB, BasicBlock *Pred, // what value were we writing? IncomingVals[ai->second] = SI->getOperand(0); // Record debuginfo for the store before removing it. - if (DbgDeclareInst *DDI = AllocaDbgDeclares[ai->second]) - ConvertDebugDeclareToDebugValue(DDI, SI); + if (DbgDeclareInst *DDI = AllocaDbgDeclares[ai->second]) { + if (!DIB) + DIB = new DIBuilder(*SI->getParent()->getParent()->getParent()); + ConvertDebugDeclareToDebugValue(DDI, SI, *DIB); + } BB->getInstList().erase(SI); } } diff --git a/contrib/llvm/lib/Transforms/Utils/SSAUpdater.cpp b/contrib/llvm/lib/Transforms/Utils/SSAUpdater.cpp index 3896d9851b26..2860c3e511a6 100644 --- a/contrib/llvm/lib/Transforms/Utils/SSAUpdater.cpp +++ b/contrib/llvm/lib/Transforms/Utils/SSAUpdater.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "ssaupdater" +#include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Analysis/InstructionSimplify.h" @@ -20,8 +21,10 @@ #include "llvm/Support/CFG.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/SSAUpdater.h" #include "llvm/Transforms/Utils/SSAUpdaterImpl.h" + using namespace llvm; typedef DenseMap AvailableValsTy; @@ -170,8 +173,8 @@ Value *SSAUpdater::GetValueInMiddleOfBlock(BasicBlock *BB) { } // Ok, we have no way out, insert a new one now. - PHINode *InsertedPHI = PHINode::Create(ProtoType, ProtoName, &BB->front()); - InsertedPHI->reserveOperandSpace(PredValues.size()); + PHINode *InsertedPHI = PHINode::Create(ProtoType, PredValues.size(), + ProtoName, &BB->front()); // Fill in all the predecessors of the PHI. for (unsigned i = 0, e = PredValues.size(); i != e; ++i) @@ -184,6 +187,9 @@ Value *SSAUpdater::GetValueInMiddleOfBlock(BasicBlock *BB) { return V; } + // Set DebugLoc. + InsertedPHI->setDebugLoc(GetFirstDebugLocInBasicBlock(BB)); + // If the client wants to know about all new instructions, tell it. if (InsertedPHIs) InsertedPHIs->push_back(InsertedPHI); @@ -289,9 +295,8 @@ class SSAUpdaterTraits { /// Reserve space for the operands but do not fill them in yet. static Value *CreateEmptyPHI(BasicBlock *BB, unsigned NumPreds, SSAUpdater *Updater) { - PHINode *PHI = PHINode::Create(Updater->ProtoType, Updater->ProtoName, - &BB->front()); - PHI->reserveOperandSpace(NumPreds); + PHINode *PHI = PHINode::Create(Updater->ProtoType, NumPreds, + Updater->ProtoName, &BB->front()); return PHI; } diff --git a/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index c6708857cb56..18b857308e34 100644 --- a/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -37,6 +37,10 @@ #include using namespace llvm; +static cl::opt +PHINodeFoldingThreshold("phi-node-folding-threshold", cl::Hidden, cl::init(1), + cl::desc("Control the amount of phi node folding to perform (default = 1)")); + static cl::opt DupRet("simplifycfg-dup-ret", cl::Hidden, cl::init(false), cl::desc("Duplicate return instructions into unconditional branches")); @@ -201,11 +205,20 @@ static Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue, /// which works well enough for us. /// /// If AggressiveInsts is non-null, and if V does not dominate BB, we check to -/// see if V (which must be an instruction) is cheap to compute and is -/// non-trapping. If both are true, the instruction is inserted into the set -/// and true is returned. +/// see if V (which must be an instruction) and its recursive operands +/// that do not dominate BB have a combined cost lower than CostRemaining and +/// are non-trapping. If both are true, the instruction is inserted into the +/// set and true is returned. +/// +/// The cost for most non-trapping instructions is defined as 1 except for +/// Select whose cost is 2. +/// +/// After this function returns, CostRemaining is decreased by the cost of +/// V plus its non-dominating operands. If that cost is greater than +/// CostRemaining, false is returned and CostRemaining is undefined. static bool DominatesMergePoint(Value *V, BasicBlock *BB, - SmallPtrSet *AggressiveInsts) { + SmallPtrSet *AggressiveInsts, + unsigned &CostRemaining) { Instruction *I = dyn_cast(V); if (!I) { // Non-instructions all dominate instructions, but not all constantexprs @@ -232,12 +245,17 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB, // instructions in the 'if region'. if (AggressiveInsts == 0) return false; + // If we have seen this instruction before, don't count it again. + if (AggressiveInsts->count(I)) return true; + // Okay, it looks like the instruction IS in the "condition". Check to // see if it's a cheap instruction to unconditionally compute, and if it // only uses stuff defined outside of the condition. If so, hoist it out. if (!I->isSafeToSpeculativelyExecute()) return false; + unsigned Cost = 0; + switch (I->getOpcode()) { default: return false; // Cannot hoist this out safely. case Instruction::Load: @@ -246,11 +264,13 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB, // predecessor. if (PBB->getFirstNonPHIOrDbg() != I) return false; + Cost = 1; break; case Instruction::GetElementPtr: // GEPs are cheap if all indices are constant. if (!cast(I)->hasAllConstantIndices()) return false; + Cost = 1; break; case Instruction::Add: case Instruction::Sub: @@ -261,13 +281,26 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB, case Instruction::LShr: case Instruction::AShr: case Instruction::ICmp: + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + Cost = 1; break; // These are all cheap and non-trapping instructions. + + case Instruction::Select: + Cost = 2; + break; } - // Okay, we can only really hoist these out if their operands are not - // defined in the conditional region. + if (Cost > CostRemaining) + return false; + + CostRemaining -= Cost; + + // Okay, we can only really hoist these out if their operands do + // not take us over the cost threshold. for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) - if (!DominatesMergePoint(*i, BB, 0)) + if (!DominatesMergePoint(*i, BB, AggressiveInsts, CostRemaining)) return false; // Okay, it's safe to do this! Remember this instruction. AggressiveInsts->insert(I); @@ -807,12 +840,16 @@ static bool HoistThenElseCodeToIf(BranchInst *BI) { BasicBlock::iterator BB2_Itr = BB2->begin(); Instruction *I1 = BB1_Itr++, *I2 = BB2_Itr++; - while (isa(I1)) - I1 = BB1_Itr++; - while (isa(I2)) - I2 = BB2_Itr++; - if (I1->getOpcode() != I2->getOpcode() || isa(I1) || - !I1->isIdenticalToWhenDefined(I2) || + // Skip debug info if it is not identical. + DbgInfoIntrinsic *DBI1 = dyn_cast(I1); + DbgInfoIntrinsic *DBI2 = dyn_cast(I2); + if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { + while (isa(I1)) + I1 = BB1_Itr++; + while (isa(I2)) + I2 = BB2_Itr++; + } + if (isa(I1) || !I1->isIdenticalToWhenDefined(I2) || (isa(I1) && !isSafeToHoistInvoke(BB1, BB2, I1, I2))) return false; @@ -835,13 +872,17 @@ static bool HoistThenElseCodeToIf(BranchInst *BI) { I2->eraseFromParent(); I1 = BB1_Itr++; - while (isa(I1)) - I1 = BB1_Itr++; I2 = BB2_Itr++; - while (isa(I2)) - I2 = BB2_Itr++; - } while (I1->getOpcode() == I2->getOpcode() && - I1->isIdenticalToWhenDefined(I2)); + // Skip debug info if it is not identical. + DbgInfoIntrinsic *DBI1 = dyn_cast(I1); + DbgInfoIntrinsic *DBI2 = dyn_cast(I2); + if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { + while (isa(I1)) + I1 = BB1_Itr++; + while (isa(I2)) + I2 = BB2_Itr++; + } + } while (I1->isIdenticalToWhenDefined(I2)); return true; @@ -1209,6 +1250,8 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetData *TD) { // instructions. While we are at it, keep track of the instructions // that need to be moved to the dominating block. SmallPtrSet AggressiveInsts; + unsigned MaxCostVal0 = PHINodeFoldingThreshold, + MaxCostVal1 = PHINodeFoldingThreshold; for (BasicBlock::iterator II = BB->begin(); isa(II);) { PHINode *PN = cast(II++); @@ -1218,8 +1261,10 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetData *TD) { continue; } - if (!DominatesMergePoint(PN->getIncomingValue(0), BB, &AggressiveInsts) || - !DominatesMergePoint(PN->getIncomingValue(1), BB, &AggressiveInsts)) + if (!DominatesMergePoint(PN->getIncomingValue(0), BB, &AggressiveInsts, + MaxCostVal0) || + !DominatesMergePoint(PN->getIncomingValue(1), BB, &AggressiveInsts, + MaxCostVal1)) return false; } @@ -1393,24 +1438,23 @@ static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) { return true; } -/// 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 -/// setcc into the predecessor and use logical operations to pick the right -/// destination. +/// FoldBranchToCommonDest - If this basic block is simple enough, and if a +/// predecessor branches to us and one of our successors, fold the block into +/// the predecessor and use logical operations to pick the right destination. bool llvm::FoldBranchToCommonDest(BranchInst *BI) { BasicBlock *BB = BI->getParent(); Instruction *Cond = dyn_cast(BI->getCondition()); if (Cond == 0 || (!isa(Cond) && !isa(Cond)) || Cond->getParent() != BB || !Cond->hasOneUse()) return false; - + // Only allow this if the condition is a simple instruction that can be // executed unconditionally. It must be in the same block as the branch, and // must be at the front of the block. BasicBlock::iterator FrontIt = BB->front(); + // Ignore dbg intrinsics. - while (isa(FrontIt)) - ++FrontIt; + while (isa(FrontIt)) ++FrontIt; // Allow a single instruction to be hoisted in addition to the compare // that feeds the branch. We later ensure that any values that _it_ uses @@ -1422,21 +1466,23 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) { FrontIt->isSafeToSpeculativelyExecute()) { BonusInst = &*FrontIt; ++FrontIt; + + // Ignore dbg intrinsics. + while (isa(FrontIt)) ++FrontIt; } - + // Only a single bonus inst is allowed. if (&*FrontIt != Cond) return false; // Make sure the instruction after the condition is the cond branch. BasicBlock::iterator CondIt = Cond; ++CondIt; + // Ingore dbg intrinsics. - while(isa(CondIt)) - ++CondIt; - if (&*CondIt != BI) { - assert (!isa(CondIt) && "Hey do not forget debug info!"); + while (isa(CondIt)) ++CondIt; + + if (&*CondIt != BI) return false; - } // Cond is known to be a compare or binary operator. Check to make sure that // neither operand is a potentially-trapping constant expression. @@ -1447,13 +1493,12 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) { if (CE->canTrap()) return false; - // Finally, don't infinitely unroll conditional loops. BasicBlock *TrueDest = BI->getSuccessor(0); BasicBlock *FalseDest = BI->getSuccessor(1); if (TrueDest == BB || FalseDest == BB) return false; - + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { BasicBlock *PredBlock = *PI; BranchInst *PBI = dyn_cast(PredBlock->getTerminator()); @@ -1461,10 +1506,24 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) { // Check that we have two conditional branches. If there is a PHI node in // the common successor, verify that the same value flows in from both // blocks. - if (PBI == 0 || PBI->isUnconditional() || - !SafeToMergeTerminators(BI, PBI)) + if (PBI == 0 || PBI->isUnconditional() || !SafeToMergeTerminators(BI, PBI)) continue; + // Determine if the two branches share a common destination. + Instruction::BinaryOps Opc; + bool InvertPredCond = false; + + if (PBI->getSuccessor(0) == TrueDest) + Opc = Instruction::Or; + else if (PBI->getSuccessor(1) == FalseDest) + Opc = Instruction::And; + else if (PBI->getSuccessor(0) == FalseDest) + Opc = Instruction::And, InvertPredCond = true; + else if (PBI->getSuccessor(1) == TrueDest) + Opc = Instruction::Or, InvertPredCond = true; + else + continue; + // Ensure that any values used in the bonus instruction are also used // by the terminator of the predecessor. This means that those values // must already have been resolved, so we won't be inhibiting the @@ -1502,20 +1561,6 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) { if (!UsedValues.empty()) return false; } - - Instruction::BinaryOps Opc; - bool InvertPredCond = false; - - if (PBI->getSuccessor(0) == TrueDest) - Opc = Instruction::Or; - else if (PBI->getSuccessor(1) == FalseDest) - Opc = Instruction::And; - else if (PBI->getSuccessor(0) == FalseDest) - Opc = Instruction::And, InvertPredCond = true; - else if (PBI->getSuccessor(1) == TrueDest) - Opc = Instruction::Or, InvertPredCond = true; - else - continue; DEBUG(dbgs() << "FOLDING BRANCH TO COMMON DEST:\n" << *PBI << *BB); @@ -1566,6 +1611,12 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) { AddPredecessorToBlock(FalseDest, PredBlock, BB); PBI->setSuccessor(1, FalseDest); } + + // Copy any debug value intrinsics into the end of PredBlock. + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (isa(*I)) + I->clone()->insertBefore(PBI); + return true; } return false; @@ -1598,13 +1649,15 @@ static bool SimplifyCondBranchToCondBranch(BranchInst *PBI, BranchInst *BI) { // in the constant and simplify the block result. Subsequent passes of // simplifycfg will thread the block. if (BlockIsSimpleEnoughToThreadThrough(BB)) { + pred_iterator PB = pred_begin(BB), PE = pred_end(BB); PHINode *NewPN = PHINode::Create(Type::getInt1Ty(BB->getContext()), + std::distance(PB, PE), BI->getCondition()->getName() + ".pr", BB->begin()); // Okay, we're going to insert the PHI node. Since PBI is not the only // predecessor, compute the PHI'd conditional value for all of the preds. // Any predecessor where the condition is not computable we keep symbolic. - for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + for (pred_iterator PI = PB; PI != PE; ++PI) { BasicBlock *P = *PI; if ((PBI = dyn_cast(P->getTerminator())) && PBI != BI && PBI->isConditional() && @@ -1800,6 +1853,26 @@ static bool SimplifyTerminatorOnSelect(TerminatorInst *OldTerm, Value *Cond, return true; } +// SimplifySwitchOnSelect - Replaces +// (switch (select cond, X, Y)) on constant X, Y +// with a branch - conditional if X and Y lead to distinct BBs, +// unconditional otherwise. +static bool SimplifySwitchOnSelect(SwitchInst *SI, SelectInst *Select) { + // Check for constant integer values in the select. + ConstantInt *TrueVal = dyn_cast(Select->getTrueValue()); + ConstantInt *FalseVal = dyn_cast(Select->getFalseValue()); + if (!TrueVal || !FalseVal) + return false; + + // Find the relevant condition and destinations. + Value *Condition = Select->getCondition(); + BasicBlock *TrueBB = SI->getSuccessor(SI->findCaseValue(TrueVal)); + BasicBlock *FalseBB = SI->getSuccessor(SI->findCaseValue(FalseVal)); + + // Perform the actual simplification. + return SimplifyTerminatorOnSelect(SI, Condition, TrueBB, FalseBB); +} + // SimplifyIndirectBrOnSelect - Replaces // (indirectbr (select cond, blockaddress(@fn, BlockA), // blockaddress(@fn, BlockB))) @@ -2148,7 +2221,9 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) { if (LI->isVolatile()) break; - // Delete this instruction + // Delete this instruction (any uses are guaranteed to be dead) + if (!BBI->use_empty()) + BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); BBI->eraseFromParent(); Changed = true; } @@ -2189,17 +2264,28 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) { // If the default value is unreachable, figure out the most popular // destination and make it the default. if (SI->getSuccessor(0) == BB) { - std::map Popularity; - for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) - Popularity[SI->getSuccessor(i)]++; - + std::map > Popularity; + for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) { + std::pair& entry = + Popularity[SI->getSuccessor(i)]; + if (entry.first == 0) { + entry.first = 1; + entry.second = i; + } else { + entry.first++; + } + } + // Find the most popular block. unsigned MaxPop = 0; + unsigned MaxIndex = 0; BasicBlock *MaxBlock = 0; - for (std::map::iterator + for (std::map >::iterator I = Popularity.begin(), E = Popularity.end(); I != E; ++I) { - if (I->second > MaxPop) { - MaxPop = I->second; + if (I->second.first > MaxPop || + (I->second.first == MaxPop && MaxIndex > I->second.second)) { + MaxPop = I->second.first; + MaxIndex = I->second.second; MaxBlock = I->first; } } @@ -2309,7 +2395,12 @@ bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI) { if (BasicBlock *OnlyPred = BB->getSinglePredecessor()) if (SimplifyEqualityComparisonWithOnlyPredecessor(SI, OnlyPred)) return SimplifyCFG(BB) | true; - + + Value *Cond = SI->getCondition(); + if (SelectInst *Select = dyn_cast(Cond)) + if (SimplifySwitchOnSelect(SI, Select)) + return SimplifyCFG(BB) | true; + // If the block only contains the switch, see if we can fold the block // away into any preds. BasicBlock::iterator BBI = BB->begin(); diff --git a/contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp index ccb8287d7969..46d4adaaa154 100644 --- a/contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +++ b/contrib/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp @@ -116,7 +116,8 @@ bool UnifyFunctionExitNodes::runOnFunction(Function &F) { ReturnInst::Create(F.getContext(), NULL, NewRetBlock); } else { // If the function doesn't return void... add a PHI node to the block... - PN = PHINode::Create(F.getReturnType(), "UnifiedRetVal"); + PN = PHINode::Create(F.getReturnType(), ReturningBlocks.size(), + "UnifiedRetVal"); NewRetBlock->getInstList().push_back(PN); ReturnInst::Create(F.getContext(), PN, NewRetBlock); } diff --git a/contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp b/contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp index f5481d31eb8a..a73bf0449813 100644 --- a/contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp +++ b/contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -39,7 +39,7 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, return VM[V] = const_cast(V); // Create a dummy node in case we have a metadata cycle. - MDNode *Dummy = MDNode::getTemporary(V->getContext(), 0, 0); + MDNode *Dummy = MDNode::getTemporary(V->getContext(), ArrayRef()); VM[V] = Dummy; // Check all operands to see if any need to be remapped. @@ -54,7 +54,7 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, Value *Op = MD->getOperand(i); Elts.push_back(Op ? MapValue(Op, VM, Flags) : 0); } - MDNode *NewMD = MDNode::get(V->getContext(), Elts.data(), Elts.size()); + MDNode *NewMD = MDNode::get(V->getContext(), Elts); Dummy->replaceAllUsesWith(NewMD); VM[V] = NewMD; MDNode::deleteTemporary(Dummy); diff --git a/contrib/llvm/lib/VMCore/AsmWriter.cpp b/contrib/llvm/lib/VMCore/AsmWriter.cpp index cbc874a53f63..844284d09c72 100644 --- a/contrib/llvm/lib/VMCore/AsmWriter.cpp +++ b/contrib/llvm/lib/VMCore/AsmWriter.cpp @@ -32,6 +32,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" @@ -39,9 +40,13 @@ #include "llvm/Support/FormattedStream.h" #include #include -#include using namespace llvm; +static cl::opt +EnableDebugInfoComment("enable-debug-info-comment", cl::Hidden, + cl::desc("Enable debug info comments")); + + // Make virtual table appear in this compilation unit. AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {} @@ -89,7 +94,7 @@ enum PrefixType { /// prefixed with % (if the string only contains simple characters) or is /// surrounded with ""'s (if it has special chars in it). Print it out. static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) { - assert(Name.data() && "Cannot get empty name!"); + assert(!Name.empty() && "Cannot get empty name!"); switch (Prefix) { default: llvm_unreachable("Bad prefix!"); case NoPrefix: break; @@ -1075,7 +1080,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, } if (CE->hasIndices()) { - const SmallVector &Indices = CE->getIndices(); + ArrayRef Indices = CE->getIndices(); for (unsigned i = 0, e = Indices.size(); i != e; ++i) Out << ", " << Indices[i]; } @@ -1338,9 +1343,12 @@ void AssemblyWriter::printModule(const Module *M) { CurPos = NewLine+1; NewLine = Asm.find_first_of('\n', CurPos); } - Out << "module asm \""; - PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.end()), Out); - Out << "\"\n"; + std::string rest(Asm.begin()+CurPos, Asm.end()); + if (!rest.empty()) { + Out << "module asm \""; + PrintEscapedString(rest, Out); + Out << "\"\n"; + } } // Loop over the dependent libraries and emit them. @@ -1581,8 +1589,8 @@ void AssemblyWriter::printFunction(const Function *F) { case CallingConv::ARM_AAPCS: Out << "arm_aapcscc "; break; case CallingConv::ARM_AAPCS_VFP:Out << "arm_aapcs_vfpcc "; break; case CallingConv::MSP430_INTR: Out << "msp430_intrcc "; break; - case CallingConv::PTX_Kernel: Out << "ptx_kernel"; break; - case CallingConv::PTX_Device: Out << "ptx_device"; break; + case CallingConv::PTX_Kernel: Out << "ptx_kernel "; break; + case CallingConv::PTX_Device: Out << "ptx_device "; break; default: Out << "cc" << F->getCallingConv() << " "; break; } @@ -1727,6 +1735,18 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { if (AnnotationWriter) AnnotationWriter->emitBasicBlockEndAnnot(BB, Out); } +/// printDebugLoc - Print DebugLoc. +static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { + OS << DL.getLine() << ":" << DL.getCol(); + if (MDNode *N = DL.getInlinedAt(getGlobalContext())) { + DebugLoc IDL = DebugLoc::getFromDILocation(N); + if (!IDL.isUnknown()) { + OS << "@"; + printDebugLoc(IDL,OS); + } + } +} + /// printInfoComment - Print a little comment after the instruction indicating /// which slot it occupies. /// @@ -1734,6 +1754,43 @@ void AssemblyWriter::printInfoComment(const Value &V) { if (AnnotationWriter) { AnnotationWriter->printInfoComment(V, Out); return; + } else if (EnableDebugInfoComment) { + bool Padded = false; + if (const Instruction *I = dyn_cast(&V)) { + const DebugLoc &DL = I->getDebugLoc(); + if (!DL.isUnknown()) { + if (!Padded) { + Out.PadToColumn(50); + Padded = true; + Out << ";"; + } + Out << " [debug line = "; + printDebugLoc(DL,Out); + Out << "]"; + } + if (const DbgDeclareInst *DDI = dyn_cast(I)) { + const MDNode *Var = DDI->getVariable(); + if (!Padded) { + Out.PadToColumn(50); + Padded = true; + Out << ";"; + } + if (Var && Var->getNumOperands() >= 2) + if (MDString *MDS = dyn_cast_or_null(Var->getOperand(2))) + Out << " [debug variable = " << MDS->getString() << "]"; + } + else if (const DbgValueInst *DVI = dyn_cast(I)) { + const MDNode *Var = DVI->getVariable(); + if (!Padded) { + Out.PadToColumn(50); + Padded = true; + Out << ";"; + } + if (Var && Var->getNumOperands() >= 2) + if (MDString *MDS = dyn_cast_or_null(Var->getOperand(2))) + Out << " [debug variable = " << MDS->getString() << "]"; + } + } } } diff --git a/contrib/llvm/lib/VMCore/AutoUpgrade.cpp b/contrib/llvm/lib/VMCore/AutoUpgrade.cpp index b32354035644..4541f381ed4a 100644 --- a/contrib/llvm/lib/VMCore/AutoUpgrade.cpp +++ b/contrib/llvm/lib/VMCore/AutoUpgrade.cpp @@ -84,7 +84,6 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { Name.compare(14, 5, "vsubl", 5) == 0 || Name.compare(14, 5, "vaddw", 5) == 0 || Name.compare(14, 5, "vsubw", 5) == 0 || - Name.compare(14, 5, "vmull", 5) == 0 || Name.compare(14, 5, "vmlal", 5) == 0 || Name.compare(14, 5, "vmlsl", 5) == 0 || Name.compare(14, 5, "vabdl", 5) == 0 || @@ -528,6 +527,12 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { // or 0. NewFn = 0; return true; + } else if (Name.compare(5, 16, "x86.sse.loadu.ps", 16) == 0 || + Name.compare(5, 17, "x86.sse2.loadu.dq", 17) == 0 || + Name.compare(5, 17, "x86.sse2.loadu.pd", 17) == 0) { + // Calls to these instructions are transformed into unaligned loads. + NewFn = 0; + return true; } else if (Name.compare(5, 17, "x86.ssse3.pshuf.w", 17) == 0) { // This is an SSE/MMX instruction. const Type *X86_MMXTy = VectorType::getX86_MMXTy(FTy->getContext()); @@ -947,7 +952,29 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { // Remove upgraded instruction. CI->eraseFromParent(); - + + } else if (F->getName() == "llvm.x86.sse.loadu.ps" || + F->getName() == "llvm.x86.sse2.loadu.dq" || + F->getName() == "llvm.x86.sse2.loadu.pd") { + // Convert to a native, unaligned load. + const Type *VecTy = CI->getType(); + const Type *IntTy = IntegerType::get(C, 128); + IRBuilder<> Builder(C); + Builder.SetInsertPoint(CI->getParent(), CI); + + Value *BC = Builder.CreateBitCast(CI->getArgOperand(0), + PointerType::getUnqual(IntTy), + "cast"); + LoadInst *LI = Builder.CreateLoad(BC, CI->getName()); + LI->setAlignment(1); // Unaligned load. + BC = Builder.CreateBitCast(LI, VecTy, "new.cast"); + + // Fix up all the uses with our new load. + if (!CI->use_empty()) + CI->replaceAllUsesWith(BC); + + // Remove intrinsic. + CI->eraseFromParent(); } else { llvm_unreachable("Unknown function for CallInst upgrade."); } @@ -1180,74 +1207,6 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { break; } -#if 0 - case Intrinsic::x86_mmx_cvtsi32_si64: { - // The return type needs to be changed. - Value *Operands[1]; - Operands[0] = CI->getArgOperand(0); - ConstructNewCallInst(NewFn, CI, Operands, 1); - break; - } - case Intrinsic::x86_mmx_cvtsi64_si32: { - Value *Operands[1]; - - // Cast the operand to the X86 MMX type. - Operands[0] = new BitCastInst(CI->getArgOperand(0), - NewFn->getFunctionType()->getParamType(0), - "upgraded.", CI); - - ConstructNewCallInst(NewFn, CI, Operands, 1); - break; - } - case Intrinsic::x86_mmx_vec_init_b: - case Intrinsic::x86_mmx_vec_init_w: - case Intrinsic::x86_mmx_vec_init_d: { - // The return type needs to be changed. - Value *Operands[8]; - unsigned NumOps = 0; - - switch (NewFn->getIntrinsicID()) { - default: break; - case Intrinsic::x86_mmx_vec_init_b: NumOps = 8; break; - case Intrinsic::x86_mmx_vec_init_w: NumOps = 4; break; - case Intrinsic::x86_mmx_vec_init_d: NumOps = 2; break; - } - - switch (NewFn->getIntrinsicID()) { - default: break; - case Intrinsic::x86_mmx_vec_init_b: - Operands[7] = CI->getArgOperand(7); - Operands[6] = CI->getArgOperand(6); - Operands[5] = CI->getArgOperand(5); - Operands[4] = CI->getArgOperand(4); - // FALLTHRU - case Intrinsic::x86_mmx_vec_init_w: - Operands[3] = CI->getArgOperand(3); - Operands[2] = CI->getArgOperand(2); - // FALLTHRU - case Intrinsic::x86_mmx_vec_init_d: - Operands[1] = CI->getArgOperand(1); - Operands[0] = CI->getArgOperand(0); - break; - } - - ConstructNewCallInst(NewFn, CI, Operands, NumOps); - break; - } - case Intrinsic::x86_mmx_vec_ext_d: { - Value *Operands[2]; - - // Cast the operand to the X86 MMX type. - Operands[0] = new BitCastInst(CI->getArgOperand(0), - NewFn->getFunctionType()->getParamType(0), - "upgraded.", CI); - Operands[1] = CI->getArgOperand(1); - - ConstructNewCallInst(NewFn, CI, Operands, 2); - break; - } -#endif - case Intrinsic::ctlz: case Intrinsic::ctpop: case Intrinsic::cttz: { diff --git a/contrib/llvm/lib/VMCore/ConstantFold.cpp b/contrib/llvm/lib/VMCore/ConstantFold.cpp index 573efb7e5731..9985adaf576e 100644 --- a/contrib/llvm/lib/VMCore/ConstantFold.cpp +++ b/contrib/llvm/lib/VMCore/ConstantFold.cpp @@ -24,6 +24,7 @@ #include "llvm/Function.h" #include "llvm/GlobalAlias.h" #include "llvm/GlobalVariable.h" +#include "llvm/Operator.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -1735,7 +1736,7 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, // with a single zero index, it must be nonzero. assert(CE1->getNumOperands() == 2 && !CE1->getOperand(1)->isNullValue() && - "Suprising getelementptr!"); + "Surprising getelementptr!"); return isSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; } else { // If they are different globals, we don't know what the value is, diff --git a/contrib/llvm/lib/VMCore/Constants.cpp b/contrib/llvm/lib/VMCore/Constants.cpp index 246fde1569ae..15d7793d5893 100644 --- a/contrib/llvm/lib/VMCore/Constants.cpp +++ b/contrib/llvm/lib/VMCore/Constants.cpp @@ -32,7 +32,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include -#include +#include using namespace llvm; //===----------------------------------------------------------------------===// @@ -325,27 +325,53 @@ ConstantInt::ConstantInt(const IntegerType *Ty, const APInt& V) assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type"); } -ConstantInt* ConstantInt::getTrue(LLVMContext &Context) { +ConstantInt *ConstantInt::getTrue(LLVMContext &Context) { LLVMContextImpl *pImpl = Context.pImpl; if (!pImpl->TheTrueVal) pImpl->TheTrueVal = ConstantInt::get(Type::getInt1Ty(Context), 1); return pImpl->TheTrueVal; } -ConstantInt* ConstantInt::getFalse(LLVMContext &Context) { +ConstantInt *ConstantInt::getFalse(LLVMContext &Context) { LLVMContextImpl *pImpl = Context.pImpl; if (!pImpl->TheFalseVal) pImpl->TheFalseVal = ConstantInt::get(Type::getInt1Ty(Context), 0); return pImpl->TheFalseVal; } +Constant *ConstantInt::getTrue(const Type *Ty) { + const VectorType *VTy = dyn_cast(Ty); + if (!VTy) { + assert(Ty->isIntegerTy(1) && "True must be i1 or vector of i1."); + return ConstantInt::getTrue(Ty->getContext()); + } + assert(VTy->getElementType()->isIntegerTy(1) && + "True must be vector of i1 or i1."); + SmallVector Splat(VTy->getNumElements(), + ConstantInt::getTrue(Ty->getContext())); + return ConstantVector::get(Splat); +} + +Constant *ConstantInt::getFalse(const Type *Ty) { + const VectorType *VTy = dyn_cast(Ty); + if (!VTy) { + assert(Ty->isIntegerTy(1) && "False must be i1 or vector of i1."); + return ConstantInt::getFalse(Ty->getContext()); + } + assert(VTy->getElementType()->isIntegerTy(1) && + "False must be vector of i1 or i1."); + SmallVector Splat(VTy->getNumElements(), + ConstantInt::getFalse(Ty->getContext())); + return ConstantVector::get(Splat); +} + // Get a ConstantInt from an APInt. Note that the value stored in the DenseMap // as the key, is a DenseMapAPIntKeyInfo::KeyTy which has provided the // operator== and operator!= to ensure that the DenseMap doesn't attempt to // compare APInt's of different widths, which would violate an APInt class // invariant which generates an assertion. -ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt& V) { +ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt &V) { // Get the corresponding integer type for the bit width of the value. const IntegerType *ITy = IntegerType::get(Context, V.getBitWidth()); // get an existing value or the insertion position @@ -355,9 +381,8 @@ ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt& V) { return Slot; } -Constant *ConstantInt::get(const Type* Ty, uint64_t V, bool isSigned) { - Constant *C = get(cast(Ty->getScalarType()), - V, isSigned); +Constant *ConstantInt::get(const Type *Ty, uint64_t V, bool isSigned) { + Constant *C = get(cast(Ty->getScalarType()), V, isSigned); // For vectors, broadcast the value. if (const VectorType *VTy = dyn_cast(Ty)) @@ -596,8 +621,6 @@ Constant *ConstantArray::get(LLVMContext &Context, StringRef Str, return get(ATy, ElementVals); } - - ConstantStruct::ConstantStruct(const StructType *T, const std::vector &V) : Constant(T, ConstantStructVal, @@ -644,6 +667,19 @@ Constant *ConstantStruct::get(LLVMContext &Context, return get(Context, std::vector(Vals, Vals+NumVals), Packed); } +Constant* ConstantStruct::get(LLVMContext &Context, bool Packed, + Constant * Val, ...) { + va_list ap; + std::vector Values; + va_start(ap, Val); + while (Val) { + Values.push_back(Val); + Val = va_arg(ap, llvm::Constant*); + } + va_end(ap); + return get(Context, Values, Packed); +} + ConstantVector::ConstantVector(const VectorType *T, const std::vector &V) : Constant(T, ConstantVectorVal, @@ -734,7 +770,7 @@ bool ConstantExpr::hasIndices() const { getOpcode() == Instruction::InsertValue; } -const SmallVector &ConstantExpr::getIndices() const { +ArrayRef ConstantExpr::getIndices() const { if (const ExtractValueConstantExpr *EVCE = dyn_cast(this)) return EVCE->Indices; @@ -818,10 +854,10 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const { /// operands replaced with the specified values. The specified operands must /// match count and type with the existing ones. Constant *ConstantExpr:: -getWithOperands(Constant *const *Ops, unsigned NumOps) const { - assert(NumOps == getNumOperands() && "Operand count mismatch!"); +getWithOperands(ArrayRef Ops) const { + assert(Ops.size() == getNumOperands() && "Operand count mismatch!"); bool AnyChange = false; - for (unsigned i = 0; i != NumOps; ++i) { + for (unsigned i = 0; i != Ops.size(); ++i) { assert(Ops[i]->getType() == getOperand(i)->getType() && "Operand type mismatch!"); AnyChange |= Ops[i] != getOperand(i); @@ -853,8 +889,8 @@ getWithOperands(Constant *const *Ops, unsigned NumOps) const { return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); case Instruction::GetElementPtr: return cast(this)->isInBounds() ? - ConstantExpr::getInBoundsGetElementPtr(Ops[0], &Ops[1], NumOps-1) : - ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], NumOps-1); + ConstantExpr::getInBoundsGetElementPtr(Ops[0], &Ops[1], Ops.size()-1) : + ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], Ops.size()-1); case Instruction::ICmp: case Instruction::FCmp: return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]); @@ -2114,7 +2150,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, Constant *Agg = getOperand(0); if (Agg == From) Agg = To; - const SmallVector &Indices = getIndices(); + ArrayRef Indices = getIndices(); Replacement = ConstantExpr::getExtractValue(Agg, &Indices[0], Indices.size()); } else if (getOpcode() == Instruction::InsertValue) { @@ -2123,7 +2159,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, if (Agg == From) Agg = To; if (Val == From) Val = To; - const SmallVector &Indices = getIndices(); + ArrayRef Indices = getIndices(); Replacement = ConstantExpr::getInsertValue(Agg, Val, &Indices[0], Indices.size()); } else if (isCast()) { diff --git a/contrib/llvm/lib/VMCore/ConstantsContext.h b/contrib/llvm/lib/VMCore/ConstantsContext.h index ffc673fac0da..13957545786d 100644 --- a/contrib/llvm/lib/VMCore/ConstantsContext.h +++ b/contrib/llvm/lib/VMCore/ConstantsContext.h @@ -301,20 +301,18 @@ struct OperandTraits : DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value) struct ExprMapKeyType { - typedef SmallVector IndexList; - ExprMapKeyType(unsigned opc, - const std::vector &ops, + ArrayRef ops, unsigned short flags = 0, unsigned short optionalflags = 0, - const IndexList &inds = IndexList()) + ArrayRef inds = ArrayRef()) : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags), - operands(ops), indices(inds) {} + operands(ops.begin(), ops.end()), indices(inds.begin(), inds.end()) {} uint8_t opcode; uint8_t subclassoptionaldata; uint16_t subclassdata; std::vector operands; - IndexList indices; + SmallVector indices; bool operator==(const ExprMapKeyType& that) const { return this->opcode == that.opcode && this->subclassdata == that.subclassdata && @@ -465,7 +463,7 @@ struct ConstantKeyData { CE->isCompare() ? CE->getPredicate() : 0, CE->getRawSubclassOptionalData(), CE->hasIndices() ? - CE->getIndices() : SmallVector()); + CE->getIndices() : ArrayRef()); } }; diff --git a/contrib/llvm/lib/VMCore/Core.cpp b/contrib/llvm/lib/VMCore/Core.cpp index 35c3a2e92587..92f944027a7c 100644 --- a/contrib/llvm/lib/VMCore/Core.cpp +++ b/contrib/llvm/lib/VMCore/Core.cpp @@ -335,7 +335,7 @@ unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy) { void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest) { StructType *Ty = unwrap(StructTy); - for (FunctionType::param_iterator I = Ty->element_begin(), + for (StructType::element_iterator I = Ty->element_begin(), E = Ty->element_end(); I != E; ++I) *Dest++ = wrap(*I); } @@ -543,7 +543,8 @@ LLVMValueRef LLVMMDString(const char *Str, unsigned SLen) { LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals, unsigned Count) { - return wrap(MDNode::get(*unwrap(C), unwrap(Vals, Count), Count)); + return wrap(MDNode::get(*unwrap(C), + ArrayRef(unwrap(Vals, Count), Count))); } LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count) { @@ -2082,7 +2083,7 @@ LLVMValueRef LLVMBuildFCmp(LLVMBuilderRef B, LLVMRealPredicate Op, /*--.. Miscellaneous instructions ..........................................--*/ LLVMValueRef LLVMBuildPhi(LLVMBuilderRef B, LLVMTypeRef Ty, const char *Name) { - return wrap(unwrap(B)->CreatePHI(unwrap(Ty), Name)); + return wrap(unwrap(B)->CreatePHI(unwrap(Ty), 0, Name)); } LLVMValueRef LLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, diff --git a/contrib/llvm/lib/VMCore/DebugInfoProbe.cpp b/contrib/llvm/lib/VMCore/DebugInfoProbe.cpp new file mode 100644 index 000000000000..334c3d815d67 --- /dev/null +++ b/contrib/llvm/lib/VMCore/DebugInfoProbe.cpp @@ -0,0 +1,258 @@ +//===-- DebugInfoProbe.cpp - DebugInfo Probe ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements DebugInfoProbe. This probe can be used by a pass +// manager to analyze how optimizer is treating debugging information. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "debuginfoprobe" +#include "llvm/DebugInfoProbe.h" +#include "llvm/Function.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Metadata.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringRef.h" +#include +#include + +using namespace llvm; + +static cl::opt +EnableDebugInfoProbe("enable-debug-info-probe", cl::Hidden, + cl::desc("Enable debug info probe")); + +// CreateInfoOutputFile - Return a file stream to print our output on. +namespace llvm { extern raw_ostream *CreateInfoOutputFile(); } + +//===----------------------------------------------------------------------===// +// DebugInfoProbeImpl - This class implements a interface to monitor +// how an optimization pass is preserving debugging information. + +namespace llvm { + + class DebugInfoProbeImpl { + public: + DebugInfoProbeImpl() : NumDbgLineLost(0),NumDbgValueLost(0) {} + void initialize(StringRef PName, Function &F); + void finalize(Function &F); + void report(); + private: + unsigned NumDbgLineLost, NumDbgValueLost; + std::string PassName; + Function *TheFn; + std::set LineNos; + std::set DbgVariables; + std::set MissingDebugLoc; + }; +} + +//===----------------------------------------------------------------------===// +// DebugInfoProbeImpl + +static void collect(Function &F, std::set &Lines) { + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); + BI != BE; ++BI) { + const DebugLoc &DL = BI->getDebugLoc(); + unsigned LineNo = 0; + if (!DL.isUnknown()) { + if (MDNode *N = DL.getInlinedAt(F.getContext())) + LineNo = DebugLoc::getFromDILocation(N).getLine(); + else + LineNo = DL.getLine(); + + Lines.insert(LineNo); + } + } +} + +/// initialize - Collect information before running an optimization pass. +void DebugInfoProbeImpl::initialize(StringRef PName, Function &F) { + if (!EnableDebugInfoProbe) return; + PassName = PName; + + LineNos.clear(); + DbgVariables.clear(); + TheFn = &F; + collect(F, LineNos); + + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); + BI != BE; ++BI) { + if (BI->getDebugLoc().isUnknown()) + MissingDebugLoc.insert(BI); + if (!isa(BI)) continue; + Value *Addr = NULL; + MDNode *Node = NULL; + if (DbgDeclareInst *DDI = dyn_cast(BI)) { + Addr = DDI->getAddress(); + Node = DDI->getVariable(); + } else if (DbgValueInst *DVI = dyn_cast(BI)) { + Addr = DVI->getValue(); + Node = DVI->getVariable(); + } + if (Addr) + DbgVariables.insert(Node); + } +} + +/// report - Report findings. This should be invoked after finalize. +void DebugInfoProbeImpl::report() { + if (!EnableDebugInfoProbe) return; + if (NumDbgLineLost || NumDbgValueLost) { + raw_ostream *OutStream = CreateInfoOutputFile(); + if (NumDbgLineLost) + *OutStream << NumDbgLineLost + << "\t times line number info lost by " + << PassName << "\n"; + if (NumDbgValueLost) + *OutStream << NumDbgValueLost + << "\t times variable info lost by " + << PassName << "\n"; + delete OutStream; + } + NumDbgLineLost = 0; + NumDbgValueLost = 0; +} + +/// finalize - Collect information after running an optimization pass. This +/// must be used after initialization. +void DebugInfoProbeImpl::finalize(Function &F) { + if (!EnableDebugInfoProbe) return; + std::set LineNos2; + collect(F, LineNos2); + assert (TheFn == &F && "Invalid function to measure!"); + + for (std::set::iterator I = LineNos.begin(), + E = LineNos.end(); I != E; ++I) { + unsigned LineNo = *I; + if (LineNos2.count(LineNo) == 0) { + DEBUG(dbgs() + << "DebugInfoProbe(" + << PassName + << "): Losing dbg info for source line " + << LineNo << "\n"); + ++NumDbgLineLost; + } + } + + std::setDbgVariables2; + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); + BI != BE; ++BI) { + if (BI->getDebugLoc().isUnknown() && + MissingDebugLoc.count(BI) == 0) { + DEBUG(dbgs() << "DebugInfoProbe(" << PassName << "): --- "); + DEBUG(BI->print(dbgs())); + DEBUG(dbgs() << "\n"); + } + if (!isa(BI)) continue; + Value *Addr = NULL; + MDNode *Node = NULL; + if (DbgDeclareInst *DDI = dyn_cast(BI)) { + Addr = DDI->getAddress(); + Node = DDI->getVariable(); + } else if (DbgValueInst *DVI = dyn_cast(BI)) { + Addr = DVI->getValue(); + Node = DVI->getVariable(); + } + if (Addr) + DbgVariables2.insert(Node); + } + + for (std::set::iterator I = DbgVariables.begin(), + E = DbgVariables.end(); I != E; ++I) { + if (DbgVariables2.count(*I) == 0 && (*I)->getNumOperands() >= 2) { + DEBUG(dbgs() + << "DebugInfoProbe(" + << PassName + << "): Losing dbg info for variable: "; + if (MDString *MDS = dyn_cast_or_null( + (*I)->getOperand(2))) + dbgs() << MDS->getString(); + else + dbgs() << "..."; + dbgs() << "\n"); + ++NumDbgValueLost; + } + } +} + +//===----------------------------------------------------------------------===// +// DebugInfoProbe + +DebugInfoProbe::DebugInfoProbe() { + pImpl = new DebugInfoProbeImpl(); +} + +DebugInfoProbe::~DebugInfoProbe() { + delete pImpl; +} + +/// initialize - Collect information before running an optimization pass. +void DebugInfoProbe::initialize(StringRef PName, Function &F) { + pImpl->initialize(PName, F); +} + +/// finalize - Collect information after running an optimization pass. This +/// must be used after initialization. +void DebugInfoProbe::finalize(Function &F) { + pImpl->finalize(F); +} + +/// report - Report findings. This should be invoked after finalize. +void DebugInfoProbe::report() { + pImpl->report(); +} + +//===----------------------------------------------------------------------===// +// DebugInfoProbeInfo + +/// ~DebugInfoProbeInfo - Report data collected by all probes before deleting +/// them. +DebugInfoProbeInfo::~DebugInfoProbeInfo() { + if (!EnableDebugInfoProbe) return; + for (StringMap::iterator I = Probes.begin(), + E = Probes.end(); I != E; ++I) { + I->second->report(); + delete I->second; + } + } + +/// initialize - Collect information before running an optimization pass. +void DebugInfoProbeInfo::initialize(Pass *P, Function &F) { + if (!EnableDebugInfoProbe) return; + if (P->getAsPMDataManager()) + return; + + StringMapEntry &Entry = + Probes.GetOrCreateValue(P->getPassName()); + DebugInfoProbe *&Probe = Entry.getValue(); + if (!Probe) + Probe = new DebugInfoProbe(); + Probe->initialize(P->getPassName(), F); +} + +/// finalize - Collect information after running an optimization pass. This +/// must be used after initialization. +void DebugInfoProbeInfo::finalize(Pass *P, Function &F) { + if (!EnableDebugInfoProbe) return; + if (P->getAsPMDataManager()) + return; + StringMapEntry &Entry = + Probes.GetOrCreateValue(P->getPassName()); + DebugInfoProbe *&Probe = Entry.getValue(); + assert (Probe && "DebugInfoProbe is not initialized!"); + Probe->finalize(F); +} diff --git a/contrib/llvm/lib/VMCore/DebugLoc.cpp b/contrib/llvm/lib/VMCore/DebugLoc.cpp index f8b45eed0d5e..520333cbbcf2 100644 --- a/contrib/llvm/lib/VMCore/DebugLoc.cpp +++ b/contrib/llvm/lib/VMCore/DebugLoc.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/DebugLoc.h" +#include "llvm/ADT/DenseMapInfo.h" #include "LLVMContextImpl.h" using namespace llvm; @@ -108,7 +109,7 @@ MDNode *DebugLoc::getAsMDNode(const LLVMContext &Ctx) const { ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()), Scope, IA }; - return MDNode::get(Ctx2, &Elts[0], 4); + return MDNode::get(Ctx2, Elts); } /// getFromDILocation - Translate the DILocation quad into a DebugLoc. @@ -127,6 +128,29 @@ DebugLoc DebugLoc::getFromDILocation(MDNode *N) { return get(LineNo, ColNo, Scope, dyn_cast_or_null(N->getOperand(3))); } +//===----------------------------------------------------------------------===// +// DenseMap specialization +//===----------------------------------------------------------------------===// + +DebugLoc DenseMapInfo::getEmptyKey() { + return DebugLoc::getEmptyKey(); +} + +DebugLoc DenseMapInfo::getTombstoneKey() { + return DebugLoc::getTombstoneKey(); +} + +unsigned DenseMapInfo::getHashValue(const DebugLoc &Key) { + FoldingSetNodeID ID; + ID.AddInteger(Key.LineCol); + ID.AddInteger(Key.ScopeIdx); + return ID.ComputeHash(); +} + +bool DenseMapInfo::isEqual(const DebugLoc &LHS, const DebugLoc &RHS) { + return LHS == RHS; +} + //===----------------------------------------------------------------------===// // LLVMContextImpl Implementation //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/VMCore/Dominators.cpp b/contrib/llvm/lib/VMCore/Dominators.cpp index c374b067d72c..08b845ef9d6b 100644 --- a/contrib/llvm/lib/VMCore/Dominators.cpp +++ b/contrib/llvm/lib/VMCore/Dominators.cpp @@ -68,9 +68,8 @@ void DominatorTree::verifyAnalysis() const { DominatorTree OtherDT; OtherDT.getBase().recalculate(F); if (compare(OtherDT)) { - errs() << "DominatorTree is not up to date! Computed:\n"; + errs() << "DominatorTree is not up to date!\nComputed:\n"; print(errs()); - errs() << "\nActual:\n"; OtherDT.print(errs()); abort(); diff --git a/contrib/llvm/lib/VMCore/Function.cpp b/contrib/llvm/lib/VMCore/Function.cpp index 00d1d7873247..013c4587c9fc 100644 --- a/contrib/llvm/lib/VMCore/Function.cpp +++ b/contrib/llvm/lib/VMCore/Function.cpp @@ -328,7 +328,7 @@ unsigned Function::getIntrinsicID() const { std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) { assert(id < num_intrinsics && "Invalid intrinsic ID!"); - const char * const Table[] = { + static const char * const Table[] = { "not_intrinsic", #define GET_INTRINSIC_NAME_TABLE #include "llvm/Intrinsics.gen" @@ -363,7 +363,7 @@ const FunctionType *Intrinsic::getType(LLVMContext &Context, } bool Intrinsic::isOverloaded(ID id) { - const bool OTable[] = { + static const bool OTable[] = { false, #define GET_INTRINSIC_OVERLOAD_TABLE #include "llvm/Intrinsics.gen" diff --git a/contrib/llvm/lib/VMCore/IRBuilder.cpp b/contrib/llvm/lib/VMCore/IRBuilder.cpp index 595dea470bc3..21491557d4df 100644 --- a/contrib/llvm/lib/VMCore/IRBuilder.cpp +++ b/contrib/llvm/lib/VMCore/IRBuilder.cpp @@ -23,13 +23,14 @@ using namespace llvm; /// has array of i8 type filled in with the nul terminated string value /// specified. If Name is specified, it is the name of the global variable /// created. -Value *IRBuilderBase::CreateGlobalString(const char *Str, const Twine &Name) { +Value *IRBuilderBase::CreateGlobalString(StringRef Str, const Twine &Name) { Constant *StrConstant = ConstantArray::get(Context, Str, true); Module &M = *BB->getParent()->getParent(); GlobalVariable *GV = new GlobalVariable(M, StrConstant->getType(), true, GlobalValue::InternalLinkage, StrConstant, "", 0, false); GV->setName(Name); + GV->setUnnamedAddr(true); return GV; } diff --git a/contrib/llvm/lib/VMCore/Instructions.cpp b/contrib/llvm/lib/VMCore/Instructions.cpp index d1290281cb1a..61da9b6b8e0c 100644 --- a/contrib/llvm/lib/VMCore/Instructions.cpp +++ b/contrib/llvm/lib/VMCore/Instructions.cpp @@ -131,26 +131,15 @@ Value *PHINode::removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty) { return Removed; } -/// resizeOperands - resize operands - This adjusts the length of the operands -/// list according to the following behavior: -/// 1. If NumOps == 0, grow the operand list in response to a push_back style -/// of operation. This grows the number of ops by 1.5 times. -/// 2. If NumOps > NumOperands, reserve space for NumOps operands. -/// 3. If NumOps == NumOperands, trim the reserved space. +/// growOperands - grow operands - This grows the operand list in response +/// to a push_back style of operation. This grows the number of ops by 1.5 +/// times. /// -void PHINode::resizeOperands(unsigned NumOps) { +void PHINode::growOperands() { unsigned e = getNumOperands(); - if (NumOps == 0) { - NumOps = e*3/2; - if (NumOps < 4) NumOps = 4; // 4 op PHI nodes are VERY common. - } else if (NumOps*2 > NumOperands) { - // No resize needed. - if (ReservedSpace >= NumOps) return; - } else if (NumOps == NumOperands) { - if (ReservedSpace == NumOps) return; - } else { - return; - } + // Multiply by 1.5 and round down so the result is still even. + unsigned NumOps = e + e / 4 * 2; + if (NumOps < 4) NumOps = 4; // 4 op PHI nodes are VERY common. ReservedSpace = NumOps; Use *OldOps = OperandList; @@ -2297,8 +2286,12 @@ bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) { if (const VectorType *SrcPTy = dyn_cast(SrcTy)) { // Casting from vector return DestPTy->getBitWidth() == SrcPTy->getBitWidth(); - } else { // Casting from something else - return DestPTy->getBitWidth() == SrcBits; + } else if (DestPTy->getBitWidth() == SrcBits) { + return true; // float/int -> vector + } else if (SrcTy->isX86_MMXTy()) { + return DestPTy->getBitWidth() == 64; // MMX to 64-bit vector + } else { + return false; } } else if (DestTy->isPointerTy()) { // Casting to pointer if (SrcTy->isPointerTy()) { // Casting from pointer @@ -2308,8 +2301,12 @@ bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) { } else { // Casting from something else return false; } - } else if (DestTy->isX86_MMXTy()) { - return SrcBits == 64; + } else if (DestTy->isX86_MMXTy()) { + if (const VectorType *SrcPTy = dyn_cast(SrcTy)) { + return SrcPTy->getBitWidth() == 64; // 64-bit vector to MMX + } else { + return false; + } } else { // Casting to something else return false; } @@ -2990,7 +2987,7 @@ SwitchInst::~SwitchInst() { void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) { unsigned OpNo = NumOperands; if (OpNo+2 > ReservedSpace) - resizeOperands(0); // Get more space! + growOperands(); // Get more space! // Initialize some new operands. assert(OpNo+1 < ReservedSpace && "Growing didn't work!"); NumOperands = OpNo+2; @@ -3021,25 +3018,12 @@ void SwitchInst::removeCase(unsigned idx) { NumOperands = NumOps-2; } -/// resizeOperands - resize operands - This adjusts the length of the operands -/// list according to the following behavior: -/// 1. If NumOps == 0, grow the operand list in response to a push_back style -/// of operation. This grows the number of ops by 3 times. -/// 2. If NumOps > NumOperands, reserve space for NumOps operands. -/// 3. If NumOps == NumOperands, trim the reserved space. +/// growOperands - grow operands - This grows the operand list in response +/// to a push_back style of operation. This grows the number of ops by 3 times. /// -void SwitchInst::resizeOperands(unsigned NumOps) { +void SwitchInst::growOperands() { unsigned e = getNumOperands(); - if (NumOps == 0) { - NumOps = e*3; - } else if (NumOps*2 > NumOperands) { - // No resize needed. - if (ReservedSpace >= NumOps) return; - } else if (NumOps == NumOperands) { - if (ReservedSpace == NumOps) return; - } else { - return; - } + unsigned NumOps = e*3; ReservedSpace = NumOps; Use *NewOps = allocHungoffUses(NumOps); @@ -3077,25 +3061,12 @@ void IndirectBrInst::init(Value *Address, unsigned NumDests) { } -/// resizeOperands - resize operands - This adjusts the length of the operands -/// list according to the following behavior: -/// 1. If NumOps == 0, grow the operand list in response to a push_back style -/// of operation. This grows the number of ops by 2 times. -/// 2. If NumOps > NumOperands, reserve space for NumOps operands. -/// 3. If NumOps == NumOperands, trim the reserved space. +/// growOperands - grow operands - This grows the operand list in response +/// to a push_back style of operation. This grows the number of ops by 2 times. /// -void IndirectBrInst::resizeOperands(unsigned NumOps) { +void IndirectBrInst::growOperands() { unsigned e = getNumOperands(); - if (NumOps == 0) { - NumOps = e*2; - } else if (NumOps*2 > NumOperands) { - // No resize needed. - if (ReservedSpace >= NumOps) return; - } else if (NumOps == NumOperands) { - if (ReservedSpace == NumOps) return; - } else { - return; - } + unsigned NumOps = e*2; ReservedSpace = NumOps; Use *NewOps = allocHungoffUses(NumOps); @@ -3139,7 +3110,7 @@ IndirectBrInst::~IndirectBrInst() { void IndirectBrInst::addDestination(BasicBlock *DestBB) { unsigned OpNo = NumOperands; if (OpNo+1 > ReservedSpace) - resizeOperands(0); // Get more space! + growOperands(); // Get more space! // Initialize some new operands. assert(OpNo < ReservedSpace && "Growing didn't work!"); NumOperands = OpNo+1; diff --git a/contrib/llvm/lib/VMCore/LLVMContextImpl.h b/contrib/llvm/lib/VMCore/LLVMContextImpl.h index 23971aafa74d..6ea4b48e79b7 100644 --- a/contrib/llvm/lib/VMCore/LLVMContextImpl.h +++ b/contrib/llvm/lib/VMCore/LLVMContextImpl.h @@ -184,7 +184,7 @@ class LLVMContextImpl { // Concrete/Abstract TypeDescriptions - We lazily calculate type descriptions // for types as they are needed. Because resolution of types must invalidate - // all of the abstract type descriptions, we keep them in a seperate map to + // all of the abstract type descriptions, we keep them in a separate map to // make this easy. TypePrinting ConcreteTypeDescriptions; TypePrinting AbstractTypeDescriptions; diff --git a/contrib/llvm/lib/VMCore/Metadata.cpp b/contrib/llvm/lib/VMCore/Metadata.cpp index 0b8e8dfa8b36..eb719e54b289 100644 --- a/contrib/llvm/lib/VMCore/Metadata.cpp +++ b/contrib/llvm/lib/VMCore/Metadata.cpp @@ -84,18 +84,18 @@ static MDNodeOperand *getOperandPtr(MDNode *N, unsigned Op) { return reinterpret_cast(N+1)+Op; } -MDNode::MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, - bool isFunctionLocal) +MDNode::MDNode(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal) : Value(Type::getMetadataTy(C), Value::MDNodeVal) { - NumOperands = NumVals; + NumOperands = Vals.size(); if (isFunctionLocal) setValueSubclassData(getSubclassDataFromValue() | FunctionLocalBit); // Initialize the operand list, which is co-allocated on the end of the node. + unsigned i = 0; for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op+NumOperands; - Op != E; ++Op, ++Vals) - new (Op) MDNodeOperand(*Vals, this); + Op != E; ++Op, ++i) + new (Op) MDNodeOperand(Vals[i], this); } @@ -183,9 +183,8 @@ static bool isFunctionLocalValue(Value *V) { (isa(V) && cast(V)->isFunctionLocal()); } -MDNode *MDNode::getMDNode(LLVMContext &Context, Value *const *Vals, - unsigned NumVals, FunctionLocalness FL, - bool Insert) { +MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef Vals, + FunctionLocalness FL, bool Insert) { LLVMContextImpl *pImpl = Context.pImpl; // Add all the operand pointers. Note that we don't have to add the @@ -193,7 +192,7 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, Value *const *Vals, // Note that if the operands are later nulled out, the node will be // removed from the uniquing map. FoldingSetNodeID ID; - for (unsigned i = 0; i != NumVals; ++i) + for (unsigned i = 0; i != Vals.size(); ++i) ID.AddPointer(Vals[i]); void *InsertPoint; @@ -205,7 +204,7 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, Value *const *Vals, bool isFunctionLocal = false; switch (FL) { case FL_Unknown: - for (unsigned i = 0; i != NumVals; ++i) { + for (unsigned i = 0; i != Vals.size(); ++i) { Value *V = Vals[i]; if (!V) continue; if (isFunctionLocalValue(V)) { @@ -223,8 +222,8 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, Value *const *Vals, } // Coallocate space for the node and Operands together, then placement new. - void *Ptr = malloc(sizeof(MDNode)+NumVals*sizeof(MDNodeOperand)); - N = new (Ptr) MDNode(Context, Vals, NumVals, isFunctionLocal); + void *Ptr = malloc(sizeof(MDNode)+Vals.size()*sizeof(MDNodeOperand)); + N = new (Ptr) MDNode(Context, Vals, isFunctionLocal); // InsertPoint will have been set by the FindNodeOrInsertPos call. pImpl->MDNodeSet.InsertNode(N, InsertPoint); @@ -232,24 +231,24 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, Value *const *Vals, return N; } -MDNode *MDNode::get(LLVMContext &Context, Value*const* Vals, unsigned NumVals) { - return getMDNode(Context, Vals, NumVals, FL_Unknown); +MDNode *MDNode::get(LLVMContext &Context, ArrayRef Vals) { + return getMDNode(Context, Vals, FL_Unknown); } -MDNode *MDNode::getWhenValsUnresolved(LLVMContext &Context, Value *const *Vals, - unsigned NumVals, bool isFunctionLocal) { - return getMDNode(Context, Vals, NumVals, isFunctionLocal ? FL_Yes : FL_No); +MDNode *MDNode::getWhenValsUnresolved(LLVMContext &Context, + ArrayRef Vals, + bool isFunctionLocal) { + return getMDNode(Context, Vals, isFunctionLocal ? FL_Yes : FL_No); } -MDNode *MDNode::getIfExists(LLVMContext &Context, Value *const *Vals, - unsigned NumVals) { - return getMDNode(Context, Vals, NumVals, FL_Unknown, false); +MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef Vals) { + return getMDNode(Context, Vals, FL_Unknown, false); } -MDNode *MDNode::getTemporary(LLVMContext &Context, Value *const *Vals, - unsigned NumVals) { - MDNode *N = (MDNode *)malloc(sizeof(MDNode)+NumVals*sizeof(MDNodeOperand)); - N = new (N) MDNode(Context, Vals, NumVals, FL_No); +MDNode *MDNode::getTemporary(LLVMContext &Context, ArrayRef Vals) { + MDNode *N = + (MDNode *)malloc(sizeof(MDNode)+Vals.size()*sizeof(MDNodeOperand)); + N = new (N) MDNode(Context, Vals, FL_No); N->setValueSubclassData(N->getSubclassDataFromValue() | NotUniquedBit); LeakDetector::addGarbageObject(N); diff --git a/contrib/llvm/lib/VMCore/PassManager.cpp b/contrib/llvm/lib/VMCore/PassManager.cpp index 8bfef9855ca2..637fa79195c9 100644 --- a/contrib/llvm/lib/VMCore/PassManager.cpp +++ b/contrib/llvm/lib/VMCore/PassManager.cpp @@ -14,6 +14,7 @@ #include "llvm/PassManagers.h" #include "llvm/PassManager.h" +#include "llvm/DebugInfoProbe.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Assembly/Writer.h" #include "llvm/Support/CommandLine.h" @@ -25,6 +26,7 @@ #include "llvm/Support/PassNameParser.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Mutex.h" +#include "llvm/ADT/StringMap.h" #include #include #include @@ -63,11 +65,13 @@ PassOptionList; // Print IR out before/after specified passes. static PassOptionList PrintBefore("print-before", - llvm::cl::desc("Print IR before specified passes")); + llvm::cl::desc("Print IR before specified passes"), + cl::Hidden); static PassOptionList PrintAfter("print-after", - llvm::cl::desc("Print IR after specified passes")); + llvm::cl::desc("Print IR after specified passes"), + cl::Hidden); static cl::opt PrintBeforeAll("print-before-all", @@ -439,6 +443,20 @@ char PassManagerImpl::ID = 0; namespace { +//===----------------------------------------------------------------------===// +// DebugInfoProbe + +static DebugInfoProbeInfo *TheDebugProbe; +static void createDebugInfoProbe() { + if (TheDebugProbe) return; + + // Constructed the first time this is called. This guarantees that the + // object will be constructed, if -enable-debug-info-probe is set, + // before static globals, thus it will be destroyed before them. + static ManagedStatic DIP; + TheDebugProbe = &*DIP; +} + //===----------------------------------------------------------------------===// /// TimingInfo Class - This class is used to calculate information about the /// amount of time each pass takes to execute. This only happens when @@ -964,7 +982,7 @@ void PMDataManager::add(Pass *P, bool ProcessAnalysis) { // Keep track of higher level analysis used by this manager. HigherLevelAnalysis.push_back(PRequired); } else - llvm_unreachable("Unable to accomodate Required Pass"); + llvm_unreachable("Unable to accommodate Required Pass"); } // Set P as P's last user until someone starts using P. @@ -1428,6 +1446,7 @@ void FunctionPassManagerImpl::releaseMemoryOnTheFly() { bool FunctionPassManagerImpl::run(Function &F) { bool Changed = false; TimingInfo::createTheTimeInfo(); + createDebugInfoProbe(); initializeAllAnalysisInfo(); for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) @@ -1475,13 +1494,16 @@ bool FPPassManager::runOnFunction(Function &F) { dumpRequiredSet(FP); initializeAnalysisImpl(FP); - + if (TheDebugProbe) + TheDebugProbe->initialize(FP, F); { PassManagerPrettyStackEntry X(FP, F); TimeRegion PassTimer(getPassTimer(FP)); LocalChanged |= FP->runOnFunction(F); } + if (TheDebugProbe) + TheDebugProbe->finalize(FP, F); Changed |= LocalChanged; if (LocalChanged) @@ -1629,6 +1651,7 @@ Pass* MPPassManager::getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F){ bool PassManagerImpl::run(Module &M) { bool Changed = false; TimingInfo::createTheTimeInfo(); + createDebugInfoProbe(); dumpArguments(); dumpPasses(); diff --git a/contrib/llvm/lib/VMCore/PassRegistry.cpp b/contrib/llvm/lib/VMCore/PassRegistry.cpp index c97a170f501f..fa92620b288e 100644 --- a/contrib/llvm/lib/VMCore/PassRegistry.cpp +++ b/contrib/llvm/lib/VMCore/PassRegistry.cpp @@ -26,7 +26,7 @@ using namespace llvm; // FIXME: We use ManagedStatic to erase the pass registrar on shutdown. // Unfortunately, passes are registered with static ctors, and having -// llvm_shutdown clear this map prevents successful ressurection after +// llvm_shutdown clear this map prevents successful resurrection after // llvm_shutdown is run. Ideally we should find a solution so that we don't // leak the map, AND can still resurrect after shutdown. static ManagedStatic PassRegistryObj; diff --git a/contrib/llvm/lib/VMCore/Type.cpp b/contrib/llvm/lib/VMCore/Type.cpp index be28ad1f7122..b15304cc9593 100644 --- a/contrib/llvm/lib/VMCore/Type.cpp +++ b/contrib/llvm/lib/VMCore/Type.cpp @@ -17,6 +17,7 @@ #include "llvm/Assembly/Writer.h" #include "llvm/LLVMContext.h" #include "llvm/Metadata.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SCCIterator.h" @@ -460,7 +461,7 @@ bool FunctionType::isValidArgumentType(const Type *ArgTy) { } FunctionType::FunctionType(const Type *Result, - const std::vector &Params, + ArrayRef Params, bool IsVarArgs) : DerivedType(Result->getContext(), FunctionTyID), isVarArgs(IsVarArgs) { ContainedTys = reinterpret_cast(this+1); @@ -483,7 +484,7 @@ FunctionType::FunctionType(const Type *Result, } StructType::StructType(LLVMContext &C, - const std::vector &Types, bool isPacked) + ArrayRef Types, bool isPacked) : CompositeType(C, StructTyID) { ContainedTys = reinterpret_cast(this + 1); NumContainedTys = Types.size(); @@ -838,7 +839,7 @@ FunctionValType FunctionValType::get(const FunctionType *FT) { // FunctionType::get - The factory function for the FunctionType class... FunctionType *FunctionType::get(const Type *ReturnType, - const std::vector &Params, + ArrayRef Params, bool isVarArg) { FunctionValType VT(ReturnType, Params, isVarArg); FunctionType *FT = 0; @@ -915,7 +916,7 @@ bool VectorType::isValidElementType(const Type *ElemTy) { // StructType *StructType::get(LLVMContext &Context, - const std::vector &ETypes, + ArrayRef ETypes, bool isPacked) { StructValType STV(ETypes, isPacked); StructType *ST = 0; diff --git a/contrib/llvm/lib/VMCore/TypesContext.h b/contrib/llvm/lib/VMCore/TypesContext.h index 4694486c41b6..ad09478bbcfd 100644 --- a/contrib/llvm/lib/VMCore/TypesContext.h +++ b/contrib/llvm/lib/VMCore/TypesContext.h @@ -15,6 +15,7 @@ #ifndef LLVM_TYPESCONTEXT_H #define LLVM_TYPESCONTEXT_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include @@ -157,8 +158,8 @@ class StructValType { std::vector ElTypes; bool packed; public: - StructValType(const std::vector &args, bool isPacked) - : ElTypes(args), packed(isPacked) {} + StructValType(ArrayRef args, bool isPacked) + : ElTypes(args.vec()), packed(isPacked) {} static StructValType get(const StructType *ST) { std::vector ElTypes; @@ -187,8 +188,8 @@ class FunctionValType { std::vector ArgTypes; bool isVarArg; public: - FunctionValType(const Type *ret, const std::vector &args, - bool isVA) : RetTy(ret), ArgTypes(args), isVarArg(isVA) {} + FunctionValType(const Type *ret, ArrayRef args, bool isVA) + : RetTy(ret), ArgTypes(args.vec()), isVarArg(isVA) {} static FunctionValType get(const FunctionType *FT); @@ -369,7 +370,7 @@ class TypeMap : public TypeMapBase { // Remove the old entry form TypesByHash. If the hash values differ // now, remove it from the old place. Otherwise, continue scanning - // withing this hashcode to reduce work. + // within this hashcode to reduce work. if (NewTypeHash != OldTypeHash) { RemoveFromTypesByHash(OldTypeHash, Ty); } else { diff --git a/contrib/llvm/lib/VMCore/Verifier.cpp b/contrib/llvm/lib/VMCore/Verifier.cpp index 58ec6fe88d35..8b891100839a 100644 --- a/contrib/llvm/lib/VMCore/Verifier.cpp +++ b/contrib/llvm/lib/VMCore/Verifier.cpp @@ -471,6 +471,23 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { "invalid linkage type for global declaration", &GV); } + if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || + GV.getName() == "llvm.global_dtors")) { + Assert1(!GV.hasInitializer() || GV.hasAppendingLinkage(), + "invalid linkage for intrinsic global variable", &GV); + // Don't worry about emitting an error for it not being an array, + // visitGlobalValue will complain on appending non-array. + if (const ArrayType *ATy = dyn_cast(GV.getType())) { + const StructType *STy = dyn_cast(ATy->getElementType()); + const PointerType *FuncPtrTy = + FunctionType::get(Type::getVoidTy(*Context), false)->getPointerTo(); + Assert1(STy && STy->getNumElements() == 2 && + STy->getTypeAtIndex(0u)->isIntegerTy(32) && + STy->getTypeAtIndex(1) == FuncPtrTy, + "wrong type for intrinsic global variable", &GV); + } + } + visitGlobalValue(GV); } @@ -826,30 +843,10 @@ void Verifier::visitReturnInst(ReturnInst &RI) { Assert2(N == 0, "Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); - else if (N == 1 && F->getReturnType() == RI.getOperand(0)->getType()) { - // Exactly one return value and it matches the return type. Good. - } else if (const StructType *STy = dyn_cast(F->getReturnType())) { - // The return type is a struct; check for multiple return values. - Assert2(STy->getNumElements() == N, - "Incorrect number of return values in ret instruction!", - &RI, F->getReturnType()); - for (unsigned i = 0; i != N; ++i) - Assert2(STy->getElementType(i) == RI.getOperand(i)->getType(), - "Function return type does not match operand " - "type of return inst!", &RI, F->getReturnType()); - } else if (const ArrayType *ATy = dyn_cast(F->getReturnType())) { - // The return type is an array; check for multiple return values. - Assert2(ATy->getNumElements() == N, - "Incorrect number of return values in ret instruction!", - &RI, F->getReturnType()); - for (unsigned i = 0; i != N; ++i) - Assert2(ATy->getElementType() == RI.getOperand(i)->getType(), - "Function return type does not match operand " - "type of return inst!", &RI, F->getReturnType()); - } else { - CheckFailed("Function return type does not match operand " - "type of return inst!", &RI, F->getReturnType()); - } + else + Assert2(N == 1 && F->getReturnType() == RI.getOperand(0)->getType(), + "Function return type does not match operand " + "type of return inst!", &RI, F->getReturnType()); // Check to make sure that the return value has necessary properties for // terminators... diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h index 722f6be538b4..d89a903e4112 100644 --- a/contrib/llvm/tools/clang/include/clang-c/Index.h +++ b/contrib/llvm/tools/clang/include/clang-c/Index.h @@ -1012,7 +1012,68 @@ CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU, unsigned num_unsaved_files, struct CXUnsavedFile *unsaved_files, unsigned options); - + +/** + * \brief Categorizes how memory is being used by a translation unit. + */ +enum CXTUResourceUsageKind { + CXTUResourceUsage_AST = 1, + CXTUResourceUsage_Identifiers = 2, + CXTUResourceUsage_Selectors = 3, + CXTUResourceUsage_GlobalCompletionResults = 4, + CXTUResourceUsage_SourceManagerContentCache = 5, + CXTUResourceUsage_AST_SideTables = 6, + CXTUResourceUsage_SourceManager_Membuffer_Malloc = 7, + CXTUResourceUsage_SourceManager_Membuffer_MMap = 8, + CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc = 9, + CXTUResourceUsage_ExternalASTSource_Membuffer_MMap = 10, + CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN = CXTUResourceUsage_AST, + CXTUResourceUsage_MEMORY_IN_BYTES_END = + CXTUResourceUsage_ExternalASTSource_Membuffer_MMap, + + CXTUResourceUsage_First = CXTUResourceUsage_AST, + CXTUResourceUsage_Last = CXTUResourceUsage_ExternalASTSource_Membuffer_MMap +}; + +/** + * \brief Returns the human-readable null-terminated C string that represents + * the name of the memory category. This string should never be freed. + */ +CINDEX_LINKAGE +const char *clang_getTUResourceUsageName(enum CXTUResourceUsageKind kind); + +typedef struct CXTUResourceUsageEntry { + /* \brief The memory usage category. */ + enum CXTUResourceUsageKind kind; + /* \brief Amount of resources used. + The units will depend on the resource kind. */ + unsigned long amount; +} CXTUResourceUsageEntry; + +/** + * \brief The memory usage of a CXTranslationUnit, broken into categories. + */ +typedef struct CXTUResourceUsage { + /* \brief Private data member, used for queries. */ + void *data; + + /* \brief The number of entries in the 'entries' array. */ + unsigned numEntries; + + /* \brief An array of key-value pairs, representing the breakdown of memory + usage. */ + CXTUResourceUsageEntry *entries; + +} CXTUResourceUsage; + +/** + * \brief Return the memory usage of a translation unit. This object + * should be released with clang_disposeCXTUResourceUsage(). + */ +CINDEX_LINKAGE CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU); + +CINDEX_LINKAGE void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage); + /** * @} */ @@ -1101,10 +1162,12 @@ enum CXCursorKind { CXCursor_NamespaceAlias = 33, /** \brief A C++ using directive. */ CXCursor_UsingDirective = 34, - /** \brief A using declaration. */ + /** \brief A C++ using declaration. */ CXCursor_UsingDeclaration = 35, + /** \brief A C++ alias declaration */ + CXCursor_TypeAliasDecl = 36, CXCursor_FirstDecl = CXCursor_UnexposedDecl, - CXCursor_LastDecl = CXCursor_UsingDeclaration, + CXCursor_LastDecl = CXCursor_TypeAliasDecl, /* References */ CXCursor_FirstRef = 40, /* Decl references */ @@ -2871,6 +2934,15 @@ CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results, */ CINDEX_LINKAGE CXString clang_getClangVersion(); + +/** + * \brief Enable/disable crash recovery. + * + * \param Flag to indicate if crash recovery is enabled. A non-zero value + * enables crash recovery, while 0 disables it. + */ +CINDEX_LINKAGE void clang_toggleCrashRecovery(unsigned isEnabled); + /** * \brief Visitor invoked for each file in a translation unit * (used with clang_getInclusions()). diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h index 08ee4ef40de0..fcc91768dac3 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h @@ -89,7 +89,7 @@ class ASTConsumer { /// \brief If the consumer is interested in entities getting modified after /// their initial creation, it should return a pointer to - /// a GetASTMutationListener here. + /// an ASTMutationListener here. virtual ASTMutationListener *GetASTMutationListener() { return 0; } /// \brief If the consumer is interested in entities being deserialized from diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h index c0eeb5af3892..28ec8cf88d52 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h @@ -14,10 +14,12 @@ #ifndef LLVM_CLANG_AST_ASTCONTEXT_H #define LLVM_CLANG_AST_ASTCONTEXT_H +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/VersionTuple.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" @@ -27,6 +29,7 @@ #include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Allocator.h" @@ -68,7 +71,7 @@ namespace clang { class TemplateTypeParmDecl; class TranslationUnitDecl; class TypeDecl; - class TypedefDecl; + class TypedefNameDecl; class UsingDecl; class UsingShadowDecl; class UnresolvedSetIterator; @@ -77,7 +80,7 @@ namespace clang { /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. -class ASTContext { +class ASTContext : public llvm::RefCountedBase { ASTContext &this_() { return *this; } mutable std::vector Types; @@ -96,7 +99,8 @@ class ASTContext { DependentSizedExtVectorTypes; mutable llvm::FoldingSet VectorTypes; mutable llvm::FoldingSet FunctionNoProtoTypes; - mutable llvm::FoldingSet FunctionProtoTypes; + mutable llvm::ContextualFoldingSet + FunctionProtoTypes; mutable llvm::FoldingSet DependentTypeOfExprTypes; mutable llvm::FoldingSet DependentDecltypeTypes; mutable llvm::FoldingSet TemplateTypeParmTypes; @@ -310,6 +314,9 @@ class ASTContext { llvm::OwningPtr ABI; CXXABI *createCXXABI(const TargetInfo &T); + /// \brief The logical -> physical address space map. + const LangAS::Map &AddrSpaceMap; + friend class ASTDeclReader; public: @@ -335,6 +342,14 @@ class ASTContext { } void Deallocate(void *Ptr) const { } + /// Return the total amount of physical memory allocated for representing + /// AST nodes and type information. + size_t getASTAllocatedMemory() const { + return BumpAlloc.getTotalMemory(); + } + /// Return the total memory used for various side tables. + size_t getSideTableAllocatedMemory() const; + PartialDiagnostic::StorageAllocator &getDiagAllocator() { return DiagAllocator; } @@ -381,6 +396,16 @@ class ASTContext { FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); + + /// ZeroBitfieldFollowsNonBitfield - return 'true" if 'FD' is a zero-length + /// bitfield which follows the non-bitfield 'LastFD'. + bool ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const; + + /// ZeroBitfieldFollowsBitfield - return 'true" if 'FD' is a zero-length + /// bitfield which follows the bitfield 'LastFD'. + bool ZeroBitfieldFollowsBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const; // Access to the set of methods overridden by the given C++ method. typedef CXXMethodVector::iterator overridden_cxx_method_iterator; @@ -413,10 +438,13 @@ class ASTContext { CanQualType FloatTy, DoubleTy, LongDoubleTy; CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType VoidPtrTy, NullPtrTy; - CanQualType OverloadTy; - CanQualType DependentTy; + CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; + // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. + mutable QualType AutoDeductTy; // Deduction against 'auto'. + mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'. + ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, @@ -654,9 +682,9 @@ class ASTContext { } /// getTypedefType - Return the unique reference to the type for the - /// specified typename decl. - QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType()) - const; + /// specified typedef-name decl. + QualType getTypedefType(const TypedefNameDecl *Decl, + QualType Canon = QualType()) const; QualType getRecordType(const RecordDecl *Decl) const; @@ -676,7 +704,7 @@ class ASTContext { QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name = 0) const; + TemplateTypeParmDecl *ParmDecl = 0) const; QualType getTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, @@ -739,6 +767,12 @@ class ASTContext { /// getAutoType - C++0x deduced auto type. QualType getAutoType(QualType DeducedType) const; + /// getAutoDeductType - C++0x deduction pattern for 'auto' type. + QualType getAutoDeductType() const; + + /// getAutoRRefDeductType - C++0x deduction pattern for 'auto &&' type. + QualType getAutoRRefDeductType() const; + /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. QualType getTagDeclType(const TagDecl *Decl) const; @@ -1294,6 +1328,21 @@ class ASTContext { QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize, QualType typeDomain) const; + unsigned getTargetAddressSpace(QualType T) const { + return getTargetAddressSpace(T.getQualifiers()); + } + + unsigned getTargetAddressSpace(Qualifiers Q) const { + return getTargetAddressSpace(Q.getAddressSpace()); + } + + unsigned getTargetAddressSpace(unsigned AS) const { + if (AS < LangAS::Offset || AS >= LangAS::Offset + LangAS::Count) + return AS; + else + return AddrSpaceMap[AS - LangAS::Offset]; + } + private: // Helper for integer ordering unsigned getIntegerRank(const Type *T) const; @@ -1332,7 +1381,8 @@ class ASTContext { const ObjCObjectType *RHS); bool canAssignObjCInterfacesInBlockPointer( const ObjCObjectPointerType *LHSOPT, - const ObjCObjectPointerType *RHSOPT); + const ObjCObjectPointerType *RHSOPT, + bool BlockReturnType); bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); @@ -1340,7 +1390,7 @@ class ASTContext { // Functions for calculating composite types QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false, - bool Unqualified = false); + bool Unqualified = false, bool BlockReturnType = false); QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified = false); QualType mergeFunctionArgumentTypes(QualType, QualType, @@ -1528,13 +1578,13 @@ class ASTContext { }; /// @brief Utility function for constructing a nullary selector. -static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { +static inline Selector GetNullarySelector(llvm::StringRef name, ASTContext& Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(0, &II); } /// @brief Utility function for constructing an unary selector. -static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) { +static inline Selector GetUnarySelector(llvm::StringRef name, ASTContext& Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(1, &II); } diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h index 1ab53b3e9148..1cb803a3396a 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define ASTSTART #include "clang/Basic/DiagnosticASTKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h index 01e618024913..470cca8ee76e 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h @@ -20,6 +20,8 @@ namespace clang { class CXXRecordDecl; class ClassTemplateDecl; class ClassTemplateSpecializationDecl; + class FunctionDecl; + class FunctionTemplateDecl; /// \brief An abstract interface that should be implemented by listeners /// that want to be notified when an AST entity gets modified after its @@ -41,6 +43,17 @@ class ASTMutationListener { /// template declaration. virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {} + + /// \brief A template specialization (or partial one) was added to the + /// template declaration. + virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D) {} + + /// \brief An implicit member got a definition. + virtual void CompletedImplicitDefinition(const FunctionDecl *D) {} + + /// \brief A static data member was implicitly instantiated. + virtual void StaticDataMemberInstantiated(const VarDecl *D) {} }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/Attr.h b/contrib/llvm/tools/clang/include/clang/AST/Attr.h index 67968fde2d6b..719023926bae 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Attr.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Attr.h @@ -17,9 +17,11 @@ #include "llvm/Support/Casting.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "clang/Basic/AttrKinds.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/VersionTuple.h" #include #include #include @@ -120,6 +122,19 @@ class InheritableAttr : public Attr { static bool classof(const InheritableAttr *) { return true; } }; +class InheritableParamAttr : public InheritableAttr { +protected: + InheritableParamAttr(attr::Kind AK, SourceLocation L) + : InheritableAttr(AK, L) {} + +public: + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() <= attr::LAST_INHERITABLE_PARAM; + } + static bool classof(const InheritableParamAttr *) { return true; } +}; + #include "clang/AST/Attrs.inc" /// AttrVec - A vector of Attr, which is how they are stored on the AST. diff --git a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h index 2d30cb3b8b62..d712e7d0c751 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h +++ b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h @@ -87,7 +87,7 @@ class CXXBasePath : public llvm::SmallVector { /// BasePaths - Represents the set of paths from a derived class to /// one of its (direct or indirect) bases. For example, given the -/// following class hierachy: +/// following class hierarchy: /// /// @code /// class A { }; diff --git a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h index 4d7fcfd1d121..b3550f877323 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h +++ b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h @@ -655,7 +655,8 @@ struct CanProxyAdaptor LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier) }; template<> diff --git a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h index cf909e88220f..d7cbd08e6c2e 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h +++ b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h @@ -34,7 +34,7 @@ namespace clang { /// architectures where the two are the same size. /// /// For portability, never assume that a target character is 8 bits wide. Use - /// CharUnit values whereever you calculate sizes, offsets, or alignments + /// CharUnit values wherever you calculate sizes, offsets, or alignments /// in character units. class CharUnits { public: @@ -70,10 +70,24 @@ namespace clang { Quantity += Other.Quantity; return *this; } + CharUnits& operator++ () { + ++Quantity; + return *this; + } + CharUnits operator++ (int) { + return CharUnits(Quantity++); + } CharUnits& operator-= (const CharUnits &Other) { Quantity -= Other.Quantity; return *this; } + CharUnits& operator-- () { + --Quantity; + return *this; + } + CharUnits operator-- (int) { + return CharUnits(Quantity--); + } // Comparison operators. bool operator== (const CharUnits &Other) const { diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h index 31cee24df993..ef4920520391 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Decl.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h @@ -20,6 +20,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" #include "clang/Basic/Linkage.h" +#include "llvm/ADT/Optional.h" namespace clang { class CXXTemporary; @@ -119,14 +120,6 @@ class NamedDecl : public Decl { return getIdentifier() ? getIdentifier()->getName() : ""; } - llvm::StringRef getMessageUnavailableAttr(bool unavailable) const { - if (!unavailable) - return ""; - if (const UnavailableAttr *UA = getAttr()) - return UA->getMessage(); - return ""; - } - /// getNameAsString - Get a human-readable name for the declaration, even if /// it is one of the special kinds of names (C++ constructor, Objective-C /// selector, etc). Creating this name requires expensive string @@ -281,6 +274,10 @@ class NamedDecl : public Decl { /// \brief Determines the linkage and visibility of this entity. LinkageInfo getLinkageAndVisibility() const; + /// \brief If visibility was explicitly specified for this + /// declaration, return that visibility. + llvm::Optional getExplicitVisibility() const; + /// \brief Clear the linkage cache in response to a change /// to the declaration. void ClearLinkageCache(); @@ -310,16 +307,32 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, /// location is where the __label__ is. class LabelDecl : public NamedDecl { LabelStmt *TheStmt; - LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II, LabelStmt *S) - : NamedDecl(Label, DC, L, II), TheStmt(S) {} - + /// LocStart - For normal labels, this is the same as the main declaration + /// label, i.e., the location of the identifier; for GNU local labels, + /// this is the location of the __label__ keyword. + SourceLocation LocStart; + + LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, + LabelStmt *S, SourceLocation StartL) + : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {} + public: static LabelDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *II); + SourceLocation IdentL, IdentifierInfo *II); + static LabelDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation IdentL, IdentifierInfo *II, + SourceLocation GnuLabelL); LabelStmt *getStmt() const { return TheStmt; } void setStmt(LabelStmt *T) { TheStmt = T; } - + + bool isGnuLocal() const { return LocStart != getLocation(); } + void setLocStart(SourceLocation L) { LocStart = L; } + + SourceRange getSourceRange() const { + return SourceRange(LocStart, getLocation()); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const LabelDecl *D) { return true; } @@ -330,7 +343,11 @@ class LabelDecl : public NamedDecl { class NamespaceDecl : public NamedDecl, public DeclContext { bool IsInline : 1; - SourceLocation LBracLoc, RBracLoc; + /// LocStart - The starting location of the source range, pointing + /// to either the namespace or the inline keyword. + SourceLocation LocStart; + /// RBraceLoc - The ending location of the source range. + SourceLocation RBraceLoc; // For extended namespace definitions: // @@ -357,13 +374,16 @@ class NamespaceDecl : public NamedDecl, public DeclContext { /// namespace declaration (which the boolean indicates). llvm::PointerIntPair OrigOrAnonNamespace; - NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) - : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), - IsInline(false), NextNamespace(), OrigOrAnonNamespace(0, true) { } + NamespaceDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id) + : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), + IsInline(false), LocStart(StartLoc), RBraceLoc(), + NextNamespace(), OrigOrAnonNamespace(0, true) { } public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id); + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id); /// \brief Returns true if this is an anonymous namespace declaration. /// @@ -427,7 +447,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext { void setAnonymousNamespace(NamespaceDecl *D) { assert(!D || D->isAnonymousNamespace()); - assert(!D || D->getParent() == this); + assert(!D || D->getParent()->getRedeclContext() == this); getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D); } @@ -437,14 +457,14 @@ class NamespaceDecl : public NamedDecl, public DeclContext { } virtual SourceRange getSourceRange() const { - return SourceRange(getLocation(), RBracLoc); + return SourceRange(LocStart, RBraceLoc); } - SourceLocation getLBracLoc() const { return LBracLoc; } - SourceLocation getRBracLoc() const { return RBracLoc; } - void setLBracLoc(SourceLocation L) { LBracLoc = L; } - void setRBracLoc(SourceLocation R) { RBracLoc = R; } - + SourceLocation getLocStart() const { return LocStart; } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setLocStart(SourceLocation L) { LocStart = L; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamespaceDecl *D) { return true; } @@ -484,16 +504,24 @@ class ValueDecl : public NamedDecl { /// name qualifier, to be used for the case of out-of-line declarations. struct QualifierInfo { NestedNameSpecifierLoc QualifierLoc; - /// NumTemplParamLists - The number of template parameter lists - /// that were matched against the template-ids occurring into the NNS. + + /// NumTemplParamLists - The number of "outer" template parameter lists. + /// The count includes all of the template parameter lists that were matched + /// against the template-ids occurring into the NNS and possibly (in the + /// case of an explicit specialization) a final "template <>". unsigned NumTemplParamLists; + /// TemplParamLists - A new-allocated array of size NumTemplParamLists, - /// containing pointers to the matched template parameter lists. + /// containing pointers to the "outer" template parameter lists. + /// It includes all of the template parameter lists that were matched + /// against the template-ids occurring into the NNS and possibly (in the + /// case of an explicit specialization) a final "template <>". TemplateParameterList** TemplParamLists; /// Default constructor. QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {} - /// setTemplateParameterListsInfo - Sets info about matched template + + /// setTemplateParameterListsInfo - Sets info about "outer" template /// parameter lists. void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, @@ -516,14 +544,20 @@ class DeclaratorDecl : public ValueDecl { llvm::PointerUnion DeclInfo; + /// InnerLocStart - The start of the source range for this declaration, + /// ignoring outer template declarations. + SourceLocation InnerLocStart; + bool hasExtInfo() const { return DeclInfo.is(); } ExtInfo *getExtInfo() { return DeclInfo.get(); } const ExtInfo *getExtInfo() const { return DeclInfo.get(); } protected: DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo) - : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {} + DeclarationName N, QualType T, TypeSourceInfo *TInfo, + SourceLocation StartL) + : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) { + } public: TypeSourceInfo *getTypeSourceInfo() const { @@ -540,14 +574,14 @@ class DeclaratorDecl : public ValueDecl { /// getInnerLocStart - Return SourceLocation representing start of source /// range ignoring outer template declarations. - virtual SourceLocation getInnerLocStart() const { return getLocation(); } + SourceLocation getInnerLocStart() const { return InnerLocStart; } + void setInnerLocStart(SourceLocation L) { InnerLocStart = L; } /// getOuterLocStart - Return SourceLocation representing start of source /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; - SourceRange getSourceRange() const { - return SourceRange(getOuterLocStart(), getLocation()); - } + + virtual SourceRange getSourceRange() const; /// \brief Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. @@ -574,9 +608,7 @@ class DeclaratorDecl : public ValueDecl { return getExtInfo()->TemplParamLists[index]; } void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists) { - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); - } + TemplateParameterList **TPLists); SourceLocation getTypeSpecStartLoc() const; @@ -650,32 +682,77 @@ class VarDecl : public DeclaratorDecl, public Redeclarable { mutable InitType Init; private: - // FIXME: This can be packed into the bitfields in Decl. - unsigned SClass : 3; - unsigned SClassAsWritten : 3; - bool ThreadSpecified : 1; - bool HasCXXDirectInit : 1; + class VarDeclBitfields { + friend class VarDecl; + friend class ASTDeclReader; - /// \brief Whether this variable is the exception variable in a C++ catch - /// or an Objective-C @catch statement. - bool ExceptionVar : 1; + unsigned SClass : 3; + unsigned SClassAsWritten : 3; + unsigned ThreadSpecified : 1; + unsigned HasCXXDirectInit : 1; + + /// \brief Whether this variable is the exception variable in a C++ catch + /// or an Objective-C @catch statement. + unsigned ExceptionVar : 1; - /// \brief Whether this local variable could be allocated in the return - /// slot of its function, enabling the named return value optimization (NRVO). - bool NRVOVariable : 1; + /// \brief Whether this local variable could be allocated in the return + /// slot of its function, enabling the named return value optimization (NRVO). + unsigned NRVOVariable : 1; + + /// \brief Whether this variable is the for-range-declaration in a C++0x + /// for-range statement. + unsigned CXXForRangeDecl : 1; + }; + enum { NumVarDeclBits = 13 }; // two reserved bits for now - friend class StmtIteratorBase; friend class ASTDeclReader; + friend class StmtIteratorBase; protected: - VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + class ParmVarDeclBitfields { + friend class ParmVarDecl; + friend class ASTDeclReader; + + unsigned : NumVarDeclBits; + + /// Whether this parameter inherits a default argument from a + /// prior declaration. + unsigned HasInheritedDefaultArg : 1; + + /// Whether this parameter undergoes K&R argument promotion. + unsigned IsKNRPromoted : 1; + + /// Whether this parameter is an ObjC method parameter or not. + unsigned IsObjCMethodParam : 1; + + /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier. + /// Otherwise, the number of function parameter scopes enclosing + /// the function parameter scope in which this parameter was + /// declared. + unsigned ScopeDepthOrObjCQuals : 8; + + /// The number of parameters preceding this parameter in the + /// function parameter scope in which it was declared. + unsigned ParameterIndex : 8; + }; + + union { + unsigned AllBits; + VarDeclBitfields VarDeclBits; + ParmVarDeclBitfields ParmVarDeclBits; + }; + + VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC, StorageClass SCAsWritten) - : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), - ThreadSpecified(false), HasCXXDirectInit(false), - ExceptionVar(false), NRVOVariable(false) { - SClass = SC; - SClassAsWritten = SCAsWritten; + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() { + assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); + assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); + AllBits = 0; + VarDeclBits.SClass = SC; + VarDeclBits.SClassAsWritten = SCAsWritten; + // Everything else is implicitly initialized to false. } typedef Redeclarable redeclarable_base; @@ -691,26 +768,27 @@ class VarDecl : public DeclaratorDecl, public Redeclarable { } static VarDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass S, - StorageClass SCAsWritten); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + StorageClass S, StorageClass SCAsWritten); - virtual SourceLocation getInnerLocStart() const; virtual SourceRange getSourceRange() const; - StorageClass getStorageClass() const { return (StorageClass)SClass; } + StorageClass getStorageClass() const { + return (StorageClass) VarDeclBits.SClass; + } StorageClass getStorageClassAsWritten() const { - return (StorageClass) SClassAsWritten; + return (StorageClass) VarDeclBits.SClassAsWritten; } void setStorageClass(StorageClass SC); void setStorageClassAsWritten(StorageClass SC) { assert(isLegalForVariable(SC)); - SClassAsWritten = SC; + VarDeclBits.SClassAsWritten = SC; } - void setThreadSpecified(bool T) { ThreadSpecified = T; } + void setThreadSpecified(bool T) { VarDeclBits.ThreadSpecified = T; } bool isThreadSpecified() const { - return ThreadSpecified; + return VarDeclBits.ThreadSpecified; } /// hasLocalStorage - Returns true if a variable with function scope @@ -988,7 +1066,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable { Eval->IsICE = IsICE; } - void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; } + void setCXXDirectInitializer(bool T) { VarDeclBits.HasCXXDirectInit = T; } /// hasCXXDirectInitializer - If true, the initializer was a direct /// initializer, e.g: "int x(1);". The Init expression will be the expression @@ -997,15 +1075,15 @@ class VarDecl : public DeclaratorDecl, public Redeclarable { /// by checking hasCXXDirectInitializer. /// bool hasCXXDirectInitializer() const { - return HasCXXDirectInit; + return VarDeclBits.HasCXXDirectInit; } /// \brief Determine whether this variable is the exception variable in a /// C++ catch statememt or an Objective-C @catch statement. bool isExceptionVariable() const { - return ExceptionVar; + return VarDeclBits.ExceptionVar; } - void setExceptionVariable(bool EV) { ExceptionVar = EV; } + void setExceptionVariable(bool EV) { VarDeclBits.ExceptionVar = EV; } /// \brief Determine whether this local variable can be used with the named /// return value optimization (NRVO). @@ -1017,8 +1095,13 @@ class VarDecl : public DeclaratorDecl, public Redeclarable { /// return slot when returning from the function. Within the function body, /// each return that returns the NRVO object will have this variable as its /// NRVO candidate. - bool isNRVOVariable() const { return NRVOVariable; } - void setNRVOVariable(bool NRVO) { NRVOVariable = NRVO; } + bool isNRVOVariable() const { return VarDeclBits.NRVOVariable; } + void setNRVOVariable(bool NRVO) { VarDeclBits.NRVOVariable = NRVO; } + + /// \brief Determine whether this variable is the for-range-declaration in + /// a C++0x for-range statement. + bool isCXXForRangeDecl() const { return VarDeclBits.CXXForRangeDecl; } + void setCXXForRangeDecl(bool FRD) { VarDeclBits.CXXForRangeDecl = FRD; } /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member @@ -1048,12 +1131,12 @@ class VarDecl : public DeclaratorDecl, public Redeclarable { class ImplicitParamDecl : public VarDecl { public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T); - ImplicitParamDecl(DeclContext *DC, SourceLocation loc, - IdentifierInfo *name, QualType type) - : VarDecl(ImplicitParam, DC, loc, name, type, + ImplicitParamDecl(DeclContext *DC, SourceLocation IdLoc, + IdentifierInfo *Id, QualType Type) + : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type, /*tinfo*/ 0, SC_None, SC_None) { setImplicit(); } @@ -1064,35 +1147,85 @@ class ImplicitParamDecl : public VarDecl { static bool classofKind(Kind K) { return K == ImplicitParam; } }; -/// ParmVarDecl - Represent a parameter to a function. +/// ParmVarDecl - Represents a parameter to a function. class ParmVarDecl : public VarDecl { - // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum - /// FIXME: Also can be paced into the bitfields in Decl. - /// in, inout, etc. - unsigned objcDeclQualifier : 6; - bool HasInheritedDefaultArg : 1; +public: + enum { MaxFunctionScopeDepth = 255 }; + enum { MaxFunctionScopeIndex = 255 }; protected: - ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, Expr *DefArg) - : VarDecl(DK, DC, L, Id, T, TInfo, S, SCAsWritten), - objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) { + : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S, SCAsWritten) { + assert(ParmVarDeclBits.HasInheritedDefaultArg == false); + assert(ParmVarDeclBits.IsKNRPromoted == false); + assert(ParmVarDeclBits.IsObjCMethodParam == false); setDefaultArg(DefArg); } public: static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L,IdentifierInfo *Id, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, Expr *DefArg); + void setObjCMethodScopeInfo(unsigned parameterIndex) { + ParmVarDeclBits.IsObjCMethodParam = true; + + ParmVarDeclBits.ParameterIndex = parameterIndex; + assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!"); + } + + void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex) { + assert(!ParmVarDeclBits.IsObjCMethodParam); + + ParmVarDeclBits.ScopeDepthOrObjCQuals = scopeDepth; + assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth && "truncation!"); + + ParmVarDeclBits.ParameterIndex = parameterIndex; + assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!"); + } + + bool isObjCMethodParameter() const { + return ParmVarDeclBits.IsObjCMethodParam; + } + + unsigned getFunctionScopeDepth() const { + if (ParmVarDeclBits.IsObjCMethodParam) return 0; + return ParmVarDeclBits.ScopeDepthOrObjCQuals; + } + + /// Returns the index of this parameter in its prototype or method scope. + unsigned getFunctionScopeIndex() const { + return ParmVarDeclBits.ParameterIndex; + } + ObjCDeclQualifier getObjCDeclQualifier() const { - return ObjCDeclQualifier(objcDeclQualifier); + if (!ParmVarDeclBits.IsObjCMethodParam) return OBJC_TQ_None; + return ObjCDeclQualifier(ParmVarDeclBits.ScopeDepthOrObjCQuals); } void setObjCDeclQualifier(ObjCDeclQualifier QTVal) { - objcDeclQualifier = QTVal; + assert(ParmVarDeclBits.IsObjCMethodParam); + ParmVarDeclBits.ScopeDepthOrObjCQuals = QTVal; + } + + /// True if the value passed to this parameter must undergo + /// K&R-style default argument promotion: + /// + /// C99 6.5.2.2. + /// If the expression that denotes the called function has a type + /// that does not include a prototype, the integer promotions are + /// performed on each argument, and arguments that have type float + /// are promoted to double. + bool isKNRPromoted() const { + return ParmVarDeclBits.IsKNRPromoted; + } + void setKNRPromoted(bool promoted) { + ParmVarDeclBits.IsKNRPromoted = promoted; } Expr *getDefaultArg(); @@ -1158,11 +1291,11 @@ class ParmVarDecl : public VarDecl { } bool hasInheritedDefaultArg() const { - return HasInheritedDefaultArg; + return ParmVarDeclBits.HasInheritedDefaultArg; } void setHasInheritedDefaultArg(bool I = true) { - HasInheritedDefaultArg = I; + ParmVarDeclBits.HasInheritedDefaultArg = I; } QualType getOriginalType() const { @@ -1233,6 +1366,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext, bool IsDeleted : 1; bool IsTrivial : 1; // sunk from CXXMethodDecl bool HasImplicitReturnZero : 1; + bool IsLateTemplateParsed : 1; /// \brief End part of this FunctionDecl's source range. /// @@ -1302,17 +1436,20 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext, void setParams(ASTContext &C, ParmVarDecl **NewParamInfo, unsigned NumParams); protected: - FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo, + FunctionDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified) - : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo), + : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, + StartLoc), DeclContext(DK), ParamInfo(0), Body(), - SClass(S), SClassAsWritten(SCAsWritten), + SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), - HasImplicitReturnZero(false), EndRangeLoc(NameInfo.getEndLoc()), + HasImplicitReturnZero(false), IsLateTemplateParsed(false), + EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(), DNLoc(NameInfo.getInfo()) {} @@ -1328,22 +1465,25 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext, return redeclarable_base::redecls_end(); } - static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + static FunctionDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass S = SC_None, + StorageClass SC = SC_None, StorageClass SCAsWritten = SC_None, bool isInlineSpecified = false, bool hasWrittenPrototype = true) { - DeclarationNameInfo NameInfo(N, L); - return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten, + DeclarationNameInfo NameInfo(N, NLoc); + return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, + SC, SCAsWritten, isInlineSpecified, hasWrittenPrototype); } static FunctionDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass S = SC_None, + StorageClass SC = SC_None, StorageClass SCAsWritten = SC_None, bool isInlineSpecified = false, bool hasWrittenPrototype = true); @@ -1356,12 +1496,9 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext, const PrintingPolicy &Policy, bool Qualified) const; - virtual SourceRange getSourceRange() const { - return SourceRange(getOuterLocStart(), EndRangeLoc); - } - void setLocEnd(SourceLocation E) { - EndRangeLoc = E; - } + void setRangeEnd(SourceLocation E) { EndRangeLoc = E; } + + virtual SourceRange getSourceRange() const; /// \brief Returns true if the function has a body (definition). The /// function body might be in any of the (re-)declarations of this @@ -1395,7 +1532,9 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext, /// previous definition); for that information, use getBody. /// FIXME: Should return true if function is deleted or defaulted. However, /// CodeGenModule.cpp uses it, and I don't know if this would break it. - bool isThisDeclarationADefinition() const { return Body; } + bool isThisDeclarationADefinition() const { + return Body || IsLateTemplateParsed; + } void setBody(Stmt *B); void setLazyBody(uint64_t Offset) { Body = Offset; } @@ -1412,6 +1551,14 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext, bool isPure() const { return IsPure; } void setPure(bool P = true); + /// Whether this is a constexpr function or constexpr constructor. + // FIXME: C++0x: Implement tracking of the constexpr specifier. + bool isConstExpr() const { return false; } + + /// Whether this templated function will be late parsed. + bool isLateTemplateParsed() const { return IsLateTemplateParsed; } + void setLateTemplateParsed(bool ILT = true) { IsLateTemplateParsed = ILT; } + /// Whether this function is "trivial" in some specialized C++ senses. /// Can only be true for default constructors, copy constructors, /// copy assignment operators, and destructors. Not meaningful until @@ -1757,16 +1904,17 @@ class FieldDecl : public DeclaratorDecl { Expr *BitWidth; protected: - FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - Expr *BW, bool Mutable) - : DeclaratorDecl(DK, DC, L, Id, T, TInfo), + FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable) + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) { } public: static FieldDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, QualType T, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable); /// getFieldIndex - Returns the index of this field within its record, @@ -1803,7 +1951,9 @@ class FieldDecl : public DeclaratorDecl { RecordDecl *getParent() { return cast(getDeclContext()); } - + + SourceRange getSourceRange() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FieldDecl *D) { return true; } @@ -1895,6 +2045,8 @@ class TypeDecl : public NamedDecl { /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. mutable const Type *TypeForDecl; + /// LocStart - The start of the source range for this declaration. + SourceLocation LocStart; friend class ASTContext; friend class DeclContext; friend class TagDecl; @@ -1902,15 +2054,24 @@ class TypeDecl : public NamedDecl { friend class TagType; protected: - TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id) - : NamedDecl(DK, DC, L, Id), TypeForDecl(0) {} + TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + SourceLocation StartL = SourceLocation()) + : NamedDecl(DK, DC, L, Id), TypeForDecl(0), LocStart(StartL) {} public: // Low-level accessor const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) { TypeForDecl = TD; } + SourceLocation getLocStart() const { return LocStart; } + void setLocStart(SourceLocation L) { LocStart = L; } + virtual SourceRange getSourceRange() const { + if (LocStart.isValid()) + return SourceRange(LocStart, getLocation()); + else + return SourceRange(getLocation()); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TypeDecl *D) { return true; } @@ -1918,17 +2079,21 @@ class TypeDecl : public NamedDecl { }; -class TypedefDecl : public TypeDecl, public Redeclarable { +/// Base class for declarations which introduce a typedef-name. +class TypedefNameDecl : public TypeDecl, public Redeclarable { /// UnderlyingType - This is the type the typedef is set to. TypeSourceInfo *TInfo; - TypedefDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} - protected: - typedef Redeclarable redeclarable_base; - virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + TypedefNameDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + TypeSourceInfo *TInfo) + : TypeDecl(DK, DC, IdLoc, Id, StartLoc), TInfo(TInfo) {} + + typedef Redeclarable redeclarable_base; + virtual TypedefNameDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; @@ -1939,19 +2104,15 @@ class TypedefDecl : public TypeDecl, public Redeclarable { return redeclarable_base::redecls_end(); } - static TypedefDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - TypeSourceInfo *TInfo); - TypeSourceInfo *getTypeSourceInfo() const { return TInfo; } - /// Retrieves the canonical declaration of this typedef. - TypedefDecl *getCanonicalDecl() { + /// Retrieves the canonical declaration of this typedef-name. + TypedefNameDecl *getCanonicalDecl() { return getFirstDeclaration(); } - const TypedefDecl *getCanonicalDecl() const { + const TypedefNameDecl *getCanonicalDecl() const { return getFirstDeclaration(); } @@ -1962,13 +2123,53 @@ class TypedefDecl : public TypeDecl, public Redeclarable { TInfo = newType; } + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypedefNameDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= firstTypedefName && K <= lastTypedefName; + } +}; + +/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' +/// type specifier. +class TypedefDecl : public TypedefNameDecl { + TypedefDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(Typedef, DC, StartLoc, IdLoc, Id, TInfo) {} + +public: + static TypedefDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo); + + SourceRange getSourceRange() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TypedefDecl *D) { return true; } static bool classofKind(Kind K) { return K == Typedef; } }; -class TypedefDecl; +/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x +/// alias-declaration. +class TypeAliasDecl : public TypedefNameDecl { + TypeAliasDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(TypeAlias, DC, StartLoc, IdLoc, Id, TInfo) {} + +public: + static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo); + + SourceRange getSourceRange() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypeAliasDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TypeAlias; } +}; /// TagDecl - Represents the declaration of a struct/union/class/enum. class TagDecl @@ -2013,32 +2214,31 @@ class TagDecl bool IsFixed : 1; private: - SourceLocation TagKeywordLoc; SourceLocation RBraceLoc; // A struct representing syntactic qualifier info, // to be used for the (uncommon) case of out-of-line declarations. typedef QualifierInfo ExtInfo; - /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name + /// TypedefNameDeclOrQualifier - If the (out-of-line) tag declaration name /// is qualified, it points to the qualifier info (nns and range); /// otherwise, if the tag declaration is anonymous and it is part of - /// a typedef, it points to the TypedefDecl (used for mangling); - /// otherwise, it is a null (TypedefDecl) pointer. - llvm::PointerUnion TypedefDeclOrQualifier; + /// a typedef or alias, it points to the TypedefNameDecl (used for mangling); + /// otherwise, it is a null (TypedefNameDecl) pointer. + llvm::PointerUnion TypedefNameDeclOrQualifier; - bool hasExtInfo() const { return TypedefDeclOrQualifier.is(); } - ExtInfo *getExtInfo() { return TypedefDeclOrQualifier.get(); } + bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is(); } + ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get(); } const ExtInfo *getExtInfo() const { - return TypedefDeclOrQualifier.get(); + return TypedefNameDeclOrQualifier.get(); } protected: TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - TagDecl *PrevDecl, SourceLocation TKL = SourceLocation()) - : TypeDecl(DK, DC, L, Id), DeclContext(DK), TagKeywordLoc(TKL), - TypedefDeclOrQualifier((TypedefDecl*) 0) { + TagDecl *PrevDecl, SourceLocation StartL) + : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), + TypedefNameDeclOrQualifier((TypedefNameDecl*) 0) { assert((DK != Enum || TK == TTK_Enum) && "EnumDecl not matched with TTK_Enum"); TagDeclKind = TK; @@ -2068,12 +2268,9 @@ class TagDecl SourceLocation getRBraceLoc() const { return RBraceLoc; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } - SourceLocation getTagKeywordLoc() const { return TagKeywordLoc; } - void setTagKeywordLoc(SourceLocation TKL) { TagKeywordLoc = TKL; } - /// getInnerLocStart - Return SourceLocation representing start of source /// range ignoring outer template declarations. - virtual SourceLocation getInnerLocStart() const { return TagKeywordLoc; } + SourceLocation getInnerLocStart() const { return getLocStart(); } /// getOuterLocStart - Return SourceLocation representing start of source /// range taking into account any outer template declarations. @@ -2146,11 +2343,11 @@ class TagDecl bool isUnion() const { return getTagKind() == TTK_Union; } bool isEnum() const { return getTagKind() == TTK_Enum; } - TypedefDecl *getTypedefForAnonDecl() const { - return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get(); + TypedefNameDecl *getTypedefNameForAnonDecl() const { + return hasExtInfo() ? 0 : TypedefNameDeclOrQualifier.get(); } - void setTypedefForAnonDecl(TypedefDecl *TDD); + void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); /// \brief Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. @@ -2177,9 +2374,7 @@ class TagDecl return getExtInfo()->TemplParamLists[i]; } void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists) { - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); - } + TemplateParameterList **TPLists); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2235,18 +2430,19 @@ class EnumDecl : public TagDecl { NumBitsMask = (1 << NumBitsWidth) - 1 }; - EnumDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL, + EnumDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) - : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { - assert(Scoped || !ScopedUsingClassTag); - IntegerType = (const Type*)0; - NumNegativeBits = 0; - NumPositiveBits = 0; - IsScoped = Scoped; - IsScopedUsingClassTag = ScopedUsingClassTag; - IsFixed = Fixed; - } + : TagDecl(Enum, TTK_Enum, DC, IdLoc, Id, PrevDecl, StartLoc), + InstantiatedFrom(0) { + assert(Scoped || !ScopedUsingClassTag); + IntegerType = (const Type*)0; + NumNegativeBits = 0; + NumPositiveBits = 0; + IsScoped = Scoped; + IsScopedUsingClassTag = ScopedUsingClassTag; + IsFixed = Fixed; + } public: EnumDecl *getCanonicalDecl() { return cast(TagDecl::getCanonicalDecl()); @@ -2263,8 +2459,8 @@ class EnumDecl : public TagDecl { } static EnumDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL, EnumDecl *PrevDecl, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed); static EnumDecl *Create(ASTContext &C, EmptyShell Empty); @@ -2326,7 +2522,7 @@ class EnumDecl : public TagDecl { return IntegerType.dyn_cast(); } - /// \brief Returns the width in bits requred to store all the + /// \brief Returns the width in bits required to store all the /// non-negative enumerators of this enum. unsigned getNumPositiveBits() const { return NumPositiveBits; @@ -2336,7 +2532,7 @@ class EnumDecl : public TagDecl { assert(NumPositiveBits == Num && "can't store this bitcount"); } - /// \brief Returns the width in bits requred to store all the + /// \brief Returns the width in bits required to store all the /// negative enumerators of this enum. These widths include /// the rightmost leading 1; that is: /// @@ -2419,14 +2615,13 @@ class RecordDecl : public TagDecl { protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - RecordDecl *PrevDecl, SourceLocation TKL); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, RecordDecl *PrevDecl); public: static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL = SourceLocation(), - RecordDecl* PrevDecl = 0); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, RecordDecl* PrevDecl = 0); static RecordDecl *Create(const ASTContext &C, EmptyShell Empty); const RecordDecl *getPreviousDeclaration() const { @@ -2519,11 +2714,21 @@ class RecordDecl : public TagDecl { class FileScopeAsmDecl : public Decl { StringLiteral *AsmString; - FileScopeAsmDecl(DeclContext *DC, SourceLocation L, StringLiteral *asmstring) - : Decl(FileScopeAsm, DC, L), AsmString(asmstring) {} + SourceLocation RParenLoc; + FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring, + SourceLocation StartL, SourceLocation EndL) + : Decl(FileScopeAsm, DC, StartL), AsmString(asmstring), RParenLoc(EndL) {} public: static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, StringLiteral *Str); + StringLiteral *Str, SourceLocation AsmLoc, + SourceLocation RParenLoc); + + SourceLocation getAsmLoc() const { return getLocation(); } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + SourceRange getSourceRange() const { + return SourceRange(getAsmLoc(), getRParenLoc()); + } const StringLiteral *getAsmString() const { return AsmString; } StringLiteral *getAsmString() { return AsmString; } diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h index b35d134d0534..ce48187f3ade 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h @@ -62,6 +62,15 @@ template<> namespace clang { + /// \brief Captures the result of checking the availability of a + /// declaration. + enum AvailabilityResult { + AR_Available = 0, + AR_NotYetIntroduced, + AR_Deprecated, + AR_Unavailable + }; + /// Decl - This represents one declaration (or definition), e.g. a variable, /// typedef, function, struct, etc. /// @@ -147,9 +156,20 @@ class Decl { IDNS_NonMemberOperator = 0x0400 }; - /// ObjCDeclQualifier - Qualifier used on types in method declarations - /// for remote messaging. They are meant for the arguments though and - /// applied to the Decls (ObjCMethodDecl and ParmVarDecl). + /// ObjCDeclQualifier - 'Qualifiers' written next to the return and + /// parameter types in method declarations. Other than remembering + /// them and mangling them into the method's signature string, these + /// are ignored by the compiler; they are consumed by certain + /// remote-messaging frameworks. + /// + /// in, inout, and out are mutually exclusive and apply only to + /// method parameters. bycopy and byref are mutually exclusive and + /// apply only to method parameters (?). oneway applies only to + /// results. All of these expect their corresponding parameter to + /// have a particular type. None of this is currently enforced by + /// clang. + /// + /// This should be kept in sync with ObjCDeclSpec::ObjCDeclQualifier. enum ObjCDeclQualifier { OBJC_TQ_None = 0x0, OBJC_TQ_In = 0x1, @@ -218,6 +238,12 @@ class Decl { /// required. unsigned Used : 1; + /// \brief Whether this declaration was "referenced". + /// The difference with 'Used' is whether the reference appears in a + /// evaluated context or not, e.g. functions used in uninstantiated templates + /// are regarded as "referenced" but not "used". + unsigned Referenced : 1; + protected: /// Access - Used by C++ decls for the access specifier. // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum @@ -252,7 +278,7 @@ class Decl { Decl(Kind DK, DeclContext *DC, SourceLocation L) : NextDeclInContext(0), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), + HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), HasCachedLinkage(0) @@ -262,7 +288,7 @@ class Decl { Decl(Kind DK, EmptyShell Empty) : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), + HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), HasCachedLinkage(0) @@ -399,6 +425,57 @@ class Decl { void setUsed(bool U = true) { Used = U; } + /// \brief Whether this declaration was referenced. + bool isReferenced() const; + + void setReferenced(bool R = true) { Referenced = R; } + + /// \brief Determine the availability of the given declaration. + /// + /// This routine will determine the most restrictive availability of + /// the given declaration (e.g., preferring 'unavailable' to + /// 'deprecated'). + /// + /// \param Message If non-NULL and the result is not \c + /// AR_Available, will be set to a (possibly empty) message + /// describing why the declaration has not been introduced, is + /// deprecated, or is unavailable. + AvailabilityResult getAvailability(std::string *Message = 0) const; + + /// \brief Determine whether this declaration is marked 'deprecated'. + /// + /// \param Message If non-NULL and the declaration is deprecated, + /// this will be set to the message describing why the declaration + /// was deprecated (which may be empty). + bool isDeprecated(std::string *Message = 0) const { + return getAvailability(Message) == AR_Deprecated; + } + + /// \brief Determine whether this declaration is marked 'unavailable'. + /// + /// \param Message If non-NULL and the declaration is unavailable, + /// this will be set to the message describing why the declaration + /// was made unavailable (which may be empty). + bool isUnavailable(std::string *Message = 0) const { + return getAvailability(Message) == AR_Unavailable; + } + + /// \brief Determine whether this is a weak-imported symbol. + /// + /// Weak-imported symbols are typically marked with the + /// 'weak_import' attribute, but may also be marked with an + /// 'availability' attribute where we're targing a platform prior to + /// the introduction of this feature. + bool isWeakImported() const; + + /// \brief Determines whether this symbol can be weak-imported, + /// e.g., whether it would be well-formed to add the weak_import + /// attribute. + /// + /// \param IsDefinition Set to \c true to indicate that this + /// declaration cannot be weak-imported because it has a definition. + bool canBeWeakImported(bool &IsDefinition) const; + /// \brief Retrieve the level of precompiled header from which this /// declaration was generated. /// diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h index 1656a7e9737c..8c819e38781d 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h @@ -306,6 +306,37 @@ class CXXRecordDecl : public RecordDecl { /// one pure virtual function, (that can come from a base class). bool Abstract : 1; + /// IsStandardLayout - True when this class has standard layout. + /// + /// C++0x [class]p7. A standard-layout class is a class that: + /// * has no non-static data members of type non-standard-layout class (or + /// array of such types) or reference, + /// * has no virtual functions (10.3) and no virtual base classes (10.1), + /// * has the same access control (Clause 11) for all non-static data members + /// * has no non-standard-layout base classes, + /// * either has no non-static data members in the most derived class and at + /// most one base class with non-static data members, or has no base + /// classes with non-static data members, and + /// * has no base classes of the same type as the first non-static data + /// member. + bool IsStandardLayout : 1; + + /// HasNoNonEmptyBases - True when there are no non-empty base classes. + /// + /// This is a helper bit of state used to implement IsStandardLayout more + /// efficiently. + bool HasNoNonEmptyBases : 1; + + /// HasPrivateFields - True when there are private non-static data members. + bool HasPrivateFields : 1; + + /// HasProtectedFields - True when there are protected non-static data + /// members. + bool HasProtectedFields : 1; + + /// HasPublicFields - True when there are private non-static data members. + bool HasPublicFields : 1; + /// HasTrivialConstructor - True when this class has a trivial constructor. /// /// C++ [class.ctor]p5. A constructor is trivial if it is an @@ -316,31 +347,71 @@ class CXXRecordDecl : public RecordDecl { /// (or array thereof), each such class has a trivial constructor. bool HasTrivialConstructor : 1; + /// HasConstExprNonCopyMoveConstructor - True when this class has at least + /// one constexpr constructor which is neither the copy nor move + /// constructor. + bool HasConstExprNonCopyMoveConstructor : 1; + /// HasTrivialCopyConstructor - True when this class has a trivial copy /// constructor. /// - /// C++ [class.copy]p6. A copy constructor for class X is trivial - /// if it is implicitly declared and if - /// * class X has no virtual functions and no virtual base classes, and - /// * each direct base class of X has a trivial copy constructor, and - /// * for all the nonstatic data members of X that are of class type (or - /// array thereof), each such class type has a trivial copy constructor; - /// otherwise the copy constructor is non-trivial. + /// C++0x [class.copy]p13: + /// A copy/move constructor for class X is trivial if it is neither + /// user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the constructor selected to copy/move each direct base class + /// subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the constructor selected to copy/move that member + /// is trivial; + /// otherwise the copy/move constructor is non-trivial. bool HasTrivialCopyConstructor : 1; + /// HasTrivialMoveConstructor - True when this class has a trivial move + /// constructor. + /// + /// C++0x [class.copy]p13: + /// A copy/move constructor for class X is trivial if it is neither + /// user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the constructor selected to copy/move each direct base class + /// subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the constructor selected to copy/move that member + /// is trivial; + /// otherwise the copy/move constructor is non-trivial. + bool HasTrivialMoveConstructor : 1; + /// HasTrivialCopyAssignment - True when this class has a trivial copy /// assignment operator. /// - /// C++ [class.copy]p11. A copy assignment operator for class X is - /// trivial if it is implicitly declared and if - /// * class X has no virtual functions and no virtual base classes, and - /// * each direct base class of X has a trivial copy assignment operator, and - /// * for all the nonstatic data members of X that are of class type (or - /// array thereof), each such class type has a trivial copy assignment - /// operator; - /// otherwise the copy assignment operator is non-trivial. + /// C++0x [class.copy]p27: + /// A copy/move assignment operator for class X is trivial if it is + /// neither user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the assignment operator selected to copy/move each direct base + /// class subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the assignment operator selected to copy/move + /// that member is trivial; + /// otherwise the copy/move assignment operator is non-trivial. bool HasTrivialCopyAssignment : 1; + /// HasTrivialMoveAssignment - True when this class has a trivial move + /// assignment operator. + /// + /// C++0x [class.copy]p27: + /// A copy/move assignment operator for class X is trivial if it is + /// neither user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the assignment operator selected to copy/move each direct base + /// class subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the assignment operator selected to copy/move + /// that member is trivial; + /// otherwise the copy/move assignment operator is non-trivial. + bool HasTrivialMoveAssignment : 1; + /// HasTrivialDestructor - True when this class has a trivial destructor. /// /// C++ [class.dtor]p3. A destructor is trivial if it is an @@ -351,6 +422,10 @@ class CXXRecordDecl : public RecordDecl { /// type (or array thereof), each such class has a trivial destructor. bool HasTrivialDestructor : 1; + /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least + /// one non-static data member or base class of non literal type. + bool HasNonLiteralTypeFieldsOrBases : 1; + /// ComputedVisibleConversions - True when visible conversion functions are /// already computed and are available. bool ComputedVisibleConversions : 1; @@ -449,9 +524,8 @@ class CXXRecordDecl : public RecordDecl { protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - CXXRecordDecl *PrevDecl, - SourceLocation TKL = SourceLocation()); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, CXXRecordDecl *PrevDecl); public: /// base_class_iterator - Iterator that traverses the base classes @@ -494,9 +568,8 @@ class CXXRecordDecl : public RecordDecl { bool hasDefinition() const { return DefinitionData != 0; } static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL = SourceLocation(), - CXXRecordDecl* PrevDecl=0, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); static CXXRecordDecl *Create(const ASTContext &C, EmptyShell Empty); @@ -723,26 +796,58 @@ class CXXRecordDecl : public RecordDecl { /// which means that the class contains or inherits a pure virtual function. bool isAbstract() const { return data().Abstract; } + /// isStandardLayout - Whether this class has standard layout + /// (C++ [class]p7) + bool isStandardLayout() const { return data().IsStandardLayout; } + // hasTrivialConstructor - Whether this class has a trivial constructor // (C++ [class.ctor]p5) bool hasTrivialConstructor() const { return data().HasTrivialConstructor; } + // hasConstExprNonCopyMoveConstructor - Whether this class has at least one + // constexpr constructor other than the copy or move constructors + bool hasConstExprNonCopyMoveConstructor() const { + return data().HasConstExprNonCopyMoveConstructor; + } + // hasTrivialCopyConstructor - Whether this class has a trivial copy - // constructor (C++ [class.copy]p6) + // constructor (C++ [class.copy]p6, C++0x [class.copy]p13) bool hasTrivialCopyConstructor() const { return data().HasTrivialCopyConstructor; } + // hasTrivialMoveConstructor - Whether this class has a trivial move + // constructor (C++0x [class.copy]p13) + bool hasTrivialMoveConstructor() const { + return data().HasTrivialMoveConstructor; + } + // hasTrivialCopyAssignment - Whether this class has a trivial copy - // assignment operator (C++ [class.copy]p11) + // assignment operator (C++ [class.copy]p11, C++0x [class.copy]p27) bool hasTrivialCopyAssignment() const { return data().HasTrivialCopyAssignment; } + // hasTrivialMoveAssignment - Whether this class has a trivial move + // assignment operator (C++0x [class.copy]p27) + bool hasTrivialMoveAssignment() const { + return data().HasTrivialMoveAssignment; + } + // hasTrivialDestructor - Whether this class has a trivial destructor // (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } + // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal type + // non-static data member or base class. + bool hasNonLiteralTypeFieldsOrBases() const { + return data().HasNonLiteralTypeFieldsOrBases; + } + + // isTriviallyCopyable - Whether this class is considered trivially copyable + // (C++0x [class]p5). + bool isTriviallyCopyable() const; + /// \brief If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// @@ -1034,20 +1139,27 @@ class CXXRecordDecl : public RecordDecl { /// struct/union/class. class CXXMethodDecl : public FunctionDecl { protected: - CXXMethodDecl(Kind DK, CXXRecordDecl *RD, + CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic, StorageClass SCAsWritten, bool isInline) - : FunctionDecl(DK, RD, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_None), - SCAsWritten, isInline) {} + bool isStatic, StorageClass SCAsWritten, bool isInline, + SourceLocation EndLocation) + : FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo, + (isStatic ? SC_Static : SC_None), + SCAsWritten, isInline) { + if (EndLocation.isValid()) + setRangeEnd(EndLocation); + } public: static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic = false, - StorageClass SCAsWritten = SC_None, - bool isInline = false); + bool isStatic, + StorageClass SCAsWritten, + bool isInline, + SourceLocation EndLocation); bool isStatic() const { return getStorageClass() == SC_Static; } bool isInstance() const { return !isStatic(); } @@ -1148,13 +1260,16 @@ class CXXMethodDecl : public FunctionDecl { /// @endcode class CXXCtorInitializer { /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal - /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being - /// initialized. - llvm::PointerUnion3 + /// field (FieldDecl), anonymous field (IndirectFieldDecl*), or target + /// constructor (CXXConstructorDecl*) being initialized. + llvm::PointerUnion4 Initializee; /// \brief The source location for the field name or, for a base initializer - /// pack expansion, the location of the ellipsis. + /// pack expansion, the location of the ellipsis. In the case of a delegating + /// constructor, it will still include the type's source location as the + /// Initializee points to the CXXConstructorDecl (to allow loop detection). SourceLocation MemberOrEllipsisLocation; /// \brief The argument used to initialize the base or member, which may @@ -1199,11 +1314,17 @@ class CXXCtorInitializer { SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); + /// CXXCtorInitializer - Creates a new anonymous field initializer. explicit CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); + /// CXXCtorInitializer - Creates a new delegating Initializer. + explicit + CXXCtorInitializer(ASTContext &Context, SourceLocation D, SourceLocation L, + CXXConstructorDecl *Target, Expr *Init, SourceLocation R); + /// \brief Creates a new member initializer that optionally contains /// array indices used to describe an elementwise initialization. static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member, @@ -1227,6 +1348,12 @@ class CXXCtorInitializer { return Initializee.is(); } + /// isDelegatingInitializer - Returns true when this initializer is creating + /// a delegating constructor. + bool isDelegatingInitializer() const { + return Initializee.is(); + } + /// \brief Determine whether this initializer is a pack expansion. bool isPackExpansion() const { return isBaseInitializer() && MemberOrEllipsisLocation.isValid(); @@ -1284,6 +1411,13 @@ class CXXCtorInitializer { return 0; } + CXXConstructorDecl *getTargetConstructor() const { + if (isDelegatingInitializer()) + return Initializee.get(); + else + return 0; + } + SourceLocation getMemberLocation() const { return MemberOrEllipsisLocation; } @@ -1373,12 +1507,13 @@ class CXXConstructorDecl : public CXXMethodDecl { CXXCtorInitializer **CtorInitializers; unsigned NumCtorInitializers; - CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false, - SC_None, isInline), + : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false, + SC_None, isInline, SourceLocation()), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), CtorInitializers(0), NumCtorInitializers(0) { setImplicit(isImplicitlyDeclared); @@ -1387,6 +1522,7 @@ class CXXConstructorDecl : public CXXMethodDecl { public: static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicit, @@ -1472,6 +1608,23 @@ class CXXConstructorDecl : public CXXMethodDecl { void setCtorInitializers(CXXCtorInitializer ** initializers) { CtorInitializers = initializers; } + + /// isDelegatingConstructor - Whether this constructor is a + /// delegating constructor + bool isDelegatingConstructor() const { + return (getNumCtorInitializers() == 1) && + CtorInitializers[0]->isDelegatingInitializer(); + } + + /// getTargetConstructor - When this constructor delegates to + /// another, retrieve the target + CXXConstructorDecl *getTargetConstructor() const { + if (isDelegatingConstructor()) + return CtorInitializers[0]->getTargetConstructor(); + else + return 0; + } + /// isDefaultConstructor - Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to /// default-initialize a class of this type. @@ -1508,8 +1661,11 @@ class CXXConstructorDecl : public CXXMethodDecl { /// \brief Determine whether this constructor is a move constructor /// (C++0x [class.copy]p3), which can be used to move values of the class. - bool isMoveConstructor() const; - + bool isMoveConstructor() const { + unsigned TypeQuals = 0; + return isMoveConstructor(TypeQuals); + } + /// \brief Determine whether this is a copy or move constructor. /// /// \param TypeQuals Will be set to the type qualifiers on the reference @@ -1567,11 +1723,12 @@ class CXXDestructorDecl : public CXXMethodDecl { FunctionDecl *OperatorDelete; - CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, TInfo, false, - SC_None, isInline), + : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, false, + SC_None, isInline, SourceLocation()), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } @@ -1579,6 +1736,7 @@ class CXXDestructorDecl : public CXXMethodDecl { public: static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo* TInfo, bool isInline, @@ -1629,19 +1787,23 @@ class CXXConversionDecl : public CXXMethodDecl { /// explicitly wrote a cast. This is a C++0x feature. bool IsExplicitSpecified : 1; - CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + CXXConversionDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicitSpecified) - : CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false, - SC_None, isInline), + bool isInline, bool isExplicitSpecified, + SourceLocation EndLocation) + : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, false, + SC_None, isInline, EndLocation), IsExplicitSpecified(isExplicitSpecified) { } public: static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicit); + bool isInline, bool isExplicit, + SourceLocation EndLocation); /// IsExplicitSpecified - Whether this conversion function declaration is /// marked "explicit", meaning that it can only be applied when the user @@ -1688,33 +1850,48 @@ class LinkageSpecDecl : public Decl, public DeclContext { private: /// Language - The language for this linkage specification. LanguageIDs Language; + /// ExternLoc - The source location for the extern keyword. + SourceLocation ExternLoc; + /// RBraceLoc - The source location for the right brace (if valid). + SourceLocation RBraceLoc; - /// HadBraces - Whether this linkage specification had curly braces or not. - bool HadBraces : 1; - - LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang, - bool Braces) - : Decl(LinkageSpec, DC, L), - DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { } + LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, + SourceLocation LangLoc, LanguageIDs lang, + SourceLocation RBLoc) + : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec), + Language(lang), ExternLoc(ExternLoc), RBraceLoc(RBLoc) { } public: static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, LanguageIDs Lang, - bool Braces); + SourceLocation ExternLoc, + SourceLocation LangLoc, LanguageIDs Lang, + SourceLocation RBraceLoc = SourceLocation()); /// \brief Return the language specified by this linkage specification. LanguageIDs getLanguage() const { return Language; } - /// \brief Set the language specified by this linkage specification. void setLanguage(LanguageIDs L) { Language = L; } /// \brief Determines whether this linkage specification had braces in /// its syntactic form. - bool hasBraces() const { return HadBraces; } + bool hasBraces() const { return RBraceLoc.isValid(); } - /// \brief Set whether this linkage specification has braces in its - /// syntactic form. - void setHasBraces(bool B) { HadBraces = B; } + SourceLocation getExternLoc() const { return ExternLoc; } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setExternLoc(SourceLocation L) { ExternLoc = L; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + + SourceLocation getLocEnd() const { + if (hasBraces()) + return getRBraceLoc(); + // No braces: get the end location of the (only) declaration in context + // (if present). + return decls_empty() ? getLocation() : decls_begin()->getLocEnd(); + } + + SourceRange getSourceRange() const { + return SourceRange(ExternLoc, getLocEnd()); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const LinkageSpecDecl *D) { return true; } @@ -2023,12 +2200,6 @@ class UsingDecl : public NamedDecl { return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the name. - SourceRange getQualifierRange() const { - return QualifierLoc.getSourceRange(); - } - DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } @@ -2154,12 +2325,6 @@ class UnresolvedUsingValueDecl : public ValueDecl { return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the name. - SourceRange getQualifierRange() const { - return QualifierLoc.getSourceRange(); - } - DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } @@ -2205,15 +2370,15 @@ class UnresolvedUsingTypenameDecl : public TypeDecl { NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, IdentifierInfo *TargetName) - : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), - UsingLocation(UsingLoc), TypenameLocation(TypenameLoc), - QualifierLoc(QualifierLoc) { } + : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName, + UsingLoc), + TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { } friend class ASTDeclReader; public: /// \brief Returns the source location of the 'using' keyword. - SourceLocation getUsingLoc() const { return UsingLocation; } + SourceLocation getUsingLoc() const { return getLocStart(); } /// \brief Returns the source location of the 'typename' keyword. SourceLocation getTypenameLoc() const { return TypenameLocation; } @@ -2227,22 +2392,11 @@ class UnresolvedUsingTypenameDecl : public TypeDecl { return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the name. - SourceRange getQualifierRange() const { - return QualifierLoc.getSourceRange(); - } - - // FIXME: DeclarationNameInfo static UnresolvedUsingTypenameDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, DeclarationName TargetName); - SourceRange getSourceRange() const { - return SourceRange(UsingLocation, getLocation()); - } - static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; } static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } @@ -2252,15 +2406,19 @@ class UnresolvedUsingTypenameDecl : public TypeDecl { class StaticAssertDecl : public Decl { Expr *AssertExpr; StringLiteral *Message; + SourceLocation RParenLoc; - StaticAssertDecl(DeclContext *DC, SourceLocation L, - Expr *assertexpr, StringLiteral *message) - : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { } + StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc, + Expr *assertexpr, StringLiteral *message, + SourceLocation RParenLoc) + : Decl(StaticAssert, DC, StaticAssertLoc), AssertExpr(assertexpr), + Message(message), RParenLoc(RParenLoc) { } public: static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, Expr *AssertExpr, - StringLiteral *Message); + SourceLocation StaticAssertLoc, + Expr *AssertExpr, StringLiteral *Message, + SourceLocation RParenLoc); Expr *getAssertExpr() { return AssertExpr; } const Expr *getAssertExpr() const { return AssertExpr; } @@ -2268,6 +2426,13 @@ class StaticAssertDecl : public Decl { StringLiteral *getMessage() { return Message; } const StringLiteral *getMessage() const { return Message; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + SourceRange getSourceRange() const { + return SourceRange(getLocation(), getRParenLoc()); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(StaticAssertDecl *D) { return true; } static bool classofKind(Kind K) { return K == StaticAssert; } diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h index 20d6da19b8ca..b84e5bba86b7 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h @@ -98,6 +98,17 @@ class FriendDecl : public Decl { return FriendLoc; } + /// Retrieves the source range for the friend declaration. + SourceRange getSourceRange() const { + /* FIXME: consider the case of templates wrt start of range. */ + if (NamedDecl *ND = getFriendDecl()) + return SourceRange(getFriendLoc(), ND->getLocEnd()); + else if (TypeSourceInfo *TInfo = getFriendType()) + return SourceRange(getFriendLoc(), TInfo->getTypeLoc().getEndLoc()); + else + return SourceRange(getFriendLoc(), getLocation()); + } + /// Determines if this friend kind is unsupported. bool isUnsupportedFriend() const { return UnsupportedFriend; diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h index b3ca474fcc19..0a4d864cd867 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h @@ -112,17 +112,20 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext { public: enum ImplementationControl { None, Required, Optional }; private: - /// Bitfields must be first fields in this class so they pack with those - /// declared in class Decl. + // The conventional meaning of this method; an ObjCMethodFamily. + // This is not serialized; instead, it is computed on demand and + // cached. + mutable unsigned Family : ObjCMethodFamilyBitWidth; + /// instance (true) or class (false) method. - bool IsInstance : 1; - bool IsVariadic : 1; + unsigned IsInstance : 1; + unsigned IsVariadic : 1; // Synthesized declaration method for a property setter/getter - bool IsSynthesized : 1; + unsigned IsSynthesized : 1; // Method has a definition. - bool IsDefined : 1; + unsigned IsDefined : 1; // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum /// @required/@optional @@ -170,7 +173,7 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext { ImplementationControl impControl = None, unsigned numSelectorArgs = 0) : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), - DeclContext(ObjCMethod), + DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), IsDefined(isDefined), @@ -279,6 +282,9 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext { ImplicitParamDecl * getCmdDecl() const { return CmdDecl; } void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; } + /// Determines the family of this method. + ObjCMethodFamily getMethodFamily() const; + bool isInstanceMethod() const { return IsInstance; } void setInstanceMethod(bool isInst) { IsInstance = isInst; } bool isVariadic() const { return IsVariadic; } @@ -453,7 +459,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { /// /// Categories are stored as a linked list in the AST, since the categories /// and class extensions come long after the initial interface declaration, - /// and we avoid dynamically-resized arrays in the AST whereever possible. + /// and we avoid dynamically-resized arrays in the AST wherever possible. ObjCCategoryDecl *CategoryList; /// IvarList - List of all ivars defined by this class; including class @@ -701,15 +707,18 @@ class ObjCIvarDecl : public FieldDecl { }; private: - ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, + ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, bool synthesized) - : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), - NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} + : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW, + /*Mutable=*/false), + NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} public: static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, - SourceLocation L, IdentifierInfo *Id, QualType T, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW = NULL, bool synthesized=false); @@ -753,17 +762,18 @@ class ObjCIvarDecl : public FieldDecl { /// @defs(...). class ObjCAtDefsFieldDecl : public FieldDecl { private: - ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW) - : FieldDecl(ObjCAtDefsField, DC, L, Id, T, + : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T, /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ? BW, /*Mutable=*/false) {} public: static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - IdentifierInfo *Id, QualType T, - Expr *BW); + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, Expr *BW); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -773,7 +783,7 @@ class ObjCAtDefsFieldDecl : public FieldDecl { /// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols /// declare a pure abstract type (i.e no instance variables are permitted). -/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++ +/// Protocols originally drew inspiration from C++ pure virtual functions (a C++ /// feature with nice semantics and lousy syntax:-). Here is an example: /// /// @protocol NSDraggingInfo diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h index f41859c85790..ddbe344cdffd 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h @@ -771,9 +771,20 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl, /// \brief Data that is common to all of the declarations of a given /// function template. struct Common : CommonBase { + Common() : InjectedArgs(0) { } + /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. llvm::FoldingSet Specializations; + + /// \brief The set of "injected" template arguments used within this + /// function template. + /// + /// This pointer refers to the template arguments (there are as + /// many template arguments as template parameaters) for the function + /// template, and is allocated lazily, since most function templates do not + /// require the use of this information. + TemplateArgument *InjectedArgs; }; FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, @@ -793,6 +804,13 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl, llvm::FoldingSet &getSpecializations() { return getCommonPtr()->Specializations; } + + /// \brief Add a specialization of this function template. + /// + /// \param InsertPos Insert position in the FoldingSet, must have been + /// retrieved by an earlier call to findSpecialization(). + void addSpecialization(FunctionTemplateSpecializationInfo* Info, + void *InsertPos); public: /// Get the underlying function declaration of the template. @@ -844,13 +862,25 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl, return makeSpecIterator(getSpecializations(), true); } - /// Create a template function node. + /// \brief Retrieve the "injected" template arguments that correspond to the + /// template parameters of this function template. + /// + /// Although the C++ standard has no notion of the "injected" template + /// arguments for a function template, the notion is convenient when + /// we need to perform substitutions inside the definition of a function + /// template. + std::pair getInjectedTemplateArgs(); + + /// \brief Create a function template node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl); + /// \brief Create an empty function template node. + static FunctionTemplateDecl *Create(ASTContext &C, EmptyShell); + // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FunctionTemplateDecl *D) { return true; } @@ -915,25 +945,23 @@ class TemplateTypeParmDecl : public TypeDecl { /// default argument. bool InheritedDefault : 1; - /// \brief Whether this is a parameter pack. - bool ParameterPack : 1; - /// \brief The default template argument, if any. TypeSourceInfo *DefaultArgument; - TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - bool Typename, QualType Type, bool ParameterPack) - : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename), - InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() { - TypeForDecl = Type.getTypePtrOrNull(); - } + TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + bool Typename) + : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), + InheritedDefault(false), DefaultArgument() { } /// Sema creates these on the stack during auto type deduction. friend class Sema; public: static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, unsigned P, + SourceLocation KeyLoc, + SourceLocation NameLoc, + unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack); static TemplateTypeParmDecl *Create(const ASTContext &C, EmptyShell Empty); @@ -978,9 +1006,6 @@ class TemplateTypeParmDecl : public TypeDecl { /// the 'typename' or 'class' keyword. void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; } - /// \brief Set whether this is a parameter pack. - void setParameterPack(bool isParamPack) { ParameterPack = isParamPack; } - /// \brief Retrieve the depth of the template parameter. unsigned getDepth() const; @@ -988,7 +1013,9 @@ class TemplateTypeParmDecl : public TypeDecl { unsigned getIndex() const; /// \brief Returns whether this is a parameter pack. - bool isParameterPack() const { return ParameterPack; } + bool isParameterPack() const; + + SourceRange getSourceRange() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1021,17 +1048,19 @@ class NonTypeTemplateParmDecl /// \brief The number of types in an expanded parameter pack. unsigned NumExpandedTypes; - NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo) - : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo), + : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false), ParameterPack(ParameterPack), ExpandedParameterPack(false), NumExpandedTypes(0) { } - NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, const QualType *ExpandedTypes, unsigned NumExpandedTypes, @@ -1041,13 +1070,14 @@ class NonTypeTemplateParmDecl public: static NonTypeTemplateParmDecl * - Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, - TypeSourceInfo *TInfo); + Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, + QualType T, bool ParameterPack, TypeSourceInfo *TInfo); static NonTypeTemplateParmDecl * - Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, const QualType *ExpandedTypes, unsigned NumExpandedTypes, TypeSourceInfo **ExpandedTInfos); @@ -1057,7 +1087,6 @@ class NonTypeTemplateParmDecl using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; - SourceLocation getInnerLocStart() const; SourceRange getSourceRange() const; /// \brief Determine whether this template parameter has a default @@ -1316,7 +1345,8 @@ class ClassTemplateSpecializationDecl protected: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, - DeclContext *DC, SourceLocation L, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, @@ -1326,7 +1356,8 @@ class ClassTemplateSpecializationDecl public: static ClassTemplateSpecializationDecl * - Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, @@ -1488,7 +1519,7 @@ class ClassTemplateSpecializationDecl return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } - SourceLocation getInnerLocStart() const { return getTemplateKeywordLoc(); } + SourceRange getSourceRange() const; void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext()); @@ -1544,7 +1575,9 @@ class ClassTemplatePartialSpecializationDecl InstantiatedFromMember; ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, - DeclContext *DC, SourceLocation L, + DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, @@ -1552,14 +1585,7 @@ class ClassTemplatePartialSpecializationDecl TemplateArgumentLoc *ArgInfos, unsigned NumArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl, - unsigned SequenceNumber) - : ClassTemplateSpecializationDecl(Context, - ClassTemplatePartialSpecialization, - TK, DC, L, SpecializedTemplate, - Args, NumArgs, PrevDecl), - TemplateParams(Params), ArgsAsWritten(ArgInfos), - NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), - InstantiatedFromMember(0, false) { } + unsigned SequenceNumber); ClassTemplatePartialSpecializationDecl() : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization), @@ -1569,7 +1595,8 @@ class ClassTemplatePartialSpecializationDecl public: static ClassTemplatePartialSpecializationDecl * - Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK,DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, @@ -1742,6 +1769,10 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl, TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } + ClassTemplateDecl(EmptyShell Empty) + : RedeclarableTemplateDecl(ClassTemplate, 0, SourceLocation(), + DeclarationName(), 0, 0) { } + CommonBase *newCommon(ASTContext &C); Common *getCommonPtr() { @@ -1768,6 +1799,9 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl, NamedDecl *Decl, ClassTemplateDecl *PrevDecl); + /// Create an empty class template node. + static ClassTemplateDecl *Create(ASTContext &C, EmptyShell); + /// \brief Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. ClassTemplateSpecializationDecl * diff --git a/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h index 035f57c12ea7..bab1606dcee4 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h @@ -37,7 +37,8 @@ class EvaluatedExprVisitor : public StmtVisitor { // other sub-expressions). void VisitDeclRefExpr(DeclRefExpr *E) { } void VisitOffsetOfExpr(OffsetOfExpr *E) { } - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { } + void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { } + void VisitExpressionTraitExpr(ExpressionTraitExpr *E) { } void VisitBlockExpr(BlockExpr *E) { } void VisitCXXUuidofExpr(CXXUuidofExpr *E) { } void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { } diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h index 95bfad5a16c2..5f2d144eb544 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h @@ -21,12 +21,12 @@ #include "clang/AST/OperationKinds.h" #include "clang/AST/ASTVector.h" #include "clang/AST/UsuallyTinyPtrVector.h" +#include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include -#include namespace clang { class ASTContext; @@ -172,6 +172,7 @@ class Expr : public Stmt { LV_IncompleteVoidType, LV_DuplicateVectorComponents, LV_InvalidExpression, + LV_InvalidMessageExpression, LV_MemberFunction, LV_SubObjCPropertySetting, LV_ClassTemporary @@ -203,6 +204,7 @@ class Expr : public Stmt { MLV_NoSetterProperty, MLV_MemberFunction, MLV_SubObjCPropertySetting, + MLV_InvalidMessageExpression, MLV_ClassTemporary }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, @@ -218,10 +220,12 @@ class Expr : public Stmt { CL_XValue, CL_Function, // Functions cannot be lvalues in C. CL_Void, // Void cannot be an lvalue in C. + CL_AddressableVoid, // Void expression whose address can be taken in C. CL_DuplicateVectorComponents, // A vector shuffle with dupes. CL_MemberFunction, // An expression referring to a member function CL_SubObjCPropertySetting, CL_ClassTemporary, // A prvalue of class type + CL_ObjCMessageRValue, // ObjC message is an rvalue CL_PRValue // A prvalue for any other reason, of any other type }; /// \brief The results of modification testing. @@ -482,6 +486,11 @@ class Expr : public Stmt { /// \brief Returns true if this expression is a bound member function. bool isBoundMemberFunction(ASTContext &Ctx) const; + /// \brief Given an expression of bound-member type, find the type + /// of the member. Returns null if this is an *overloaded* bound + /// member expression. + static QualType findBoundMemberType(const Expr *expr); + /// \brief Result type of CanThrow(). enum CanThrowResult { CT_Cannot, @@ -536,6 +545,9 @@ class Expr : public Stmt { /// temporary object of the given class type. bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const; + /// \brief Whether this expression is an implicit reference to 'this' in C++. + bool isImplicitCXXThis() const; + const Expr *IgnoreParens() const { return const_cast(this)->IgnoreParens(); } @@ -618,16 +630,6 @@ class OpaqueValueExpr : public Expr { static bool classof(const OpaqueValueExpr *) { return true; } }; -/// \brief Represents the qualifier that may precede a C++ name, e.g., the -/// "std::" in "std::sort". -struct NameQualifier { - /// \brief The nested name specifier. - NestedNameSpecifier *NNS; - - /// \brief The source range covered by the nested name specifier. - SourceRange Range; -}; - /// \brief Represents an explicit template argument list in C++, e.g., /// the "" in "sort". struct ExplicitTemplateArgumentList { @@ -659,95 +661,118 @@ struct ExplicitTemplateArgumentList { static std::size_t sizeFor(unsigned NumTemplateArgs); static std::size_t sizeFor(const TemplateArgumentListInfo &List); }; - -/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, -/// enum, etc. -class DeclRefExpr : public Expr { - enum { - // Flag on DecoratedD that specifies when this declaration reference - // expression has a C++ nested-name-specifier. - HasQualifierFlag = 0x01, - // Flag on DecoratedD that specifies when this declaration reference - // expression has an explicit C++ template argument list. - HasExplicitTemplateArgumentListFlag = 0x02 - }; - - // DecoratedD - The declaration that we are referencing, plus two bits to - // indicate whether (1) the declaration's name was explicitly qualified and - // (2) the declaration's name was followed by an explicit template - // argument list. - llvm::PointerIntPair DecoratedD; - // Loc - The location of the declaration name itself. +/// \brief A reference to a declared variable, function, enum, etc. +/// [C99 6.5.1p2] +/// +/// This encodes all the information about how a declaration is referenced +/// within an expression. +/// +/// There are several optional constructs attached to DeclRefExprs only when +/// they apply in order to conserve memory. These are laid out past the end of +/// the object, and flags in the DeclRefExprBitfield track whether they exist: +/// +/// DeclRefExprBits.HasQualifier: +/// Specifies when this declaration reference expression has a C++ +/// nested-name-specifier. +/// DeclRefExprBits.HasFoundDecl: +/// Specifies when this declaration reference expression has a record of +/// a NamedDecl (different from the referenced ValueDecl) which was found +/// during name lookup and/or overload resolution. +/// DeclRefExprBits.HasExplicitTemplateArgs: +/// Specifies when this declaration reference expression has an explicit +/// C++ template argument list. +class DeclRefExpr : public Expr { + /// \brief The declaration that we are referencing. + ValueDecl *D; + + /// \brief The location of the declaration name itself. SourceLocation Loc; - /// DNLoc - Provides source/type location info for the - /// declaration name embedded in DecoratedD. + /// \brief Provides source/type location info for the declaration name + /// embedded in D. DeclarationNameLoc DNLoc; - /// \brief Retrieve the qualifier that preceded the declaration name, if any. - NameQualifier *getNameQualifier() { - if ((DecoratedD.getInt() & HasQualifierFlag) == 0) - return 0; - - return reinterpret_cast (this + 1); - } - - /// \brief Retrieve the qualifier that preceded the member name, if any. - const NameQualifier *getNameQualifier() const { - return const_cast(this)->getNameQualifier(); + /// \brief Helper to retrieve the optional NestedNameSpecifierLoc. + NestedNameSpecifierLoc &getInternalQualifierLoc() { + assert(hasQualifier()); + return *reinterpret_cast(this + 1); } - DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - ValueDecl *D, SourceLocation NameLoc, - const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK); + /// \brief Helper to retrieve the optional NestedNameSpecifierLoc. + const NestedNameSpecifierLoc &getInternalQualifierLoc() const { + return const_cast(this)->getInternalQualifierLoc(); + } - DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + /// \brief Test whether there is a distinct FoundDecl attached to the end of + /// this DRE. + bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; } + + /// \brief Helper to retrieve the optional NamedDecl through which this + /// reference occured. + NamedDecl *&getInternalFoundDecl() { + assert(hasFoundDecl()); + if (hasQualifier()) + return *reinterpret_cast(&getInternalQualifierLoc() + 1); + return *reinterpret_cast(this + 1); + } + + /// \brief Helper to retrieve the optional NamedDecl through which this + /// reference occured. + NamedDecl *getInternalFoundDecl() const { + return const_cast(this)->getInternalFoundDecl(); + } + + DeclRefExpr(NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, const DeclarationNameInfo &NameInfo, + NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK); /// \brief Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) { } - + /// \brief Computes the type- and value-dependence flags for this /// declaration reference expression. void computeDependence(); public: - DeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK, SourceLocation l) : - Expr(DeclRefExprClass, t, VK, OK_Ordinary, false, false, false), - DecoratedD(d, 0), Loc(l) { + DeclRefExpr(ValueDecl *D, QualType T, ExprValueKind VK, SourceLocation L) + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), + D(D), Loc(L) { + DeclRefExprBits.HasQualifier = 0; + DeclRefExprBits.HasExplicitTemplateArgs = 0; + DeclRefExprBits.HasFoundDecl = 0; computeDependence(); } static DeclRefExpr *Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, SourceLocation NameLoc, QualType T, ExprValueKind VK, + NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0); static DeclRefExpr *Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, + NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0); /// \brief Construct an empty declaration reference expression. static DeclRefExpr *CreateEmpty(ASTContext &Context, - bool HasQualifier, + bool HasQualifier, + bool HasFoundDecl, bool HasExplicitTemplateArgs, unsigned NumTemplateArgs); - - ValueDecl *getDecl() { return DecoratedD.getPointer(); } - const ValueDecl *getDecl() const { return DecoratedD.getPointer(); } - void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); } + + ValueDecl *getDecl() { return D; } + const ValueDecl *getDecl() const { return D; } + void setDecl(ValueDecl *NewD) { D = NewD; } DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc); @@ -759,43 +784,62 @@ class DeclRefExpr : public Expr { /// \brief Determine whether this declaration reference was preceded by a /// C++ nested-name-specifier, e.g., \c N::foo. - bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; } - - /// \brief If the name was qualified, retrieves the source range of - /// the nested-name-specifier that precedes the name. Otherwise, - /// returns an empty source range. - SourceRange getQualifierRange() const { - if (!hasQualifier()) - return SourceRange(); - - return getNameQualifier()->Range; - } - - /// \brief If the name was qualified, retrieves the nested-name-specifier + bool hasQualifier() const { return DeclRefExprBits.HasQualifier; } + + /// \brief If the name was qualified, retrieves the nested-name-specifier /// that precedes the name. Otherwise, returns NULL. NestedNameSpecifier *getQualifier() const { if (!hasQualifier()) return 0; - - return getNameQualifier()->NNS; + + return getInternalQualifierLoc().getNestedNameSpecifier(); } - + + /// \brief If the name was qualified, retrieves the nested-name-specifier + /// that precedes the name, with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { + if (!hasQualifier()) + return NestedNameSpecifierLoc(); + + return getInternalQualifierLoc(); + } + + /// \brief Get the NamedDecl through which this reference occured. + /// + /// This Decl may be different from the ValueDecl actually referred to in the + /// presence of using declarations, etc. It always returns non-NULL, and may + /// simple return the ValueDecl when appropriate. + NamedDecl *getFoundDecl() { + return hasFoundDecl() ? getInternalFoundDecl() : D; + } + + /// \brief Get the NamedDecl through which this reference occurred. + /// See non-const variant. + const NamedDecl *getFoundDecl() const { + return hasFoundDecl() ? getInternalFoundDecl() : D; + } + + /// \brief Determines whether this declaration reference was followed by an + /// explict template argument list. bool hasExplicitTemplateArgs() const { - return (DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag); + return DeclRefExprBits.HasExplicitTemplateArgs; } - + /// \brief Retrieve the explicit template argument list that followed the /// member template name. ExplicitTemplateArgumentList &getExplicitTemplateArgs() { assert(hasExplicitTemplateArgs()); + if (hasFoundDecl()) + return *reinterpret_cast( + &getInternalFoundDecl() + 1); - if ((DecoratedD.getInt() & HasQualifierFlag) == 0) - return *reinterpret_cast(this + 1); - - return *reinterpret_cast( - getNameQualifier() + 1); + if (hasQualifier()) + return *reinterpret_cast( + &getInternalQualifierLoc() + 1); + + return *reinterpret_cast(this + 1); } - + /// \brief Retrieve the explicit template argument list that followed the /// member template name. const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { @@ -809,50 +853,50 @@ class DeclRefExpr : public Expr { if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } - + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) getExplicitTemplateArgs().copyInto(List); } - + /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { if (!hasExplicitTemplateArgs()) return SourceLocation(); - + return getExplicitTemplateArgs().LAngleLoc; } - + /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; - + return getExplicitTemplateArgs().getTemplateArgs(); } - + /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; - + return getExplicitTemplateArgs().NumTemplateArgs; } - + /// \brief Retrieve the location of the right angle bracket following the /// template arguments ('>'). SourceLocation getRAngleLoc() const { if (!hasExplicitTemplateArgs()) return SourceLocation(); - + return getExplicitTemplateArgs().RAngleLoc; } - + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } @@ -860,7 +904,7 @@ class DeclRefExpr : public Expr { // Iterators child_range children() { return child_range(); } - + friend class ASTStmtReader; friend class ASTStmtWriter; }; @@ -1133,9 +1177,12 @@ class ImaginaryLiteral : public Expr { /// In this case, getByteLength() will return 6, but the string literal will /// have type "char[2]". class StringLiteral : public Expr { + friend class ASTStmtReader; + const char *StrData; unsigned ByteLength; bool IsWide; + bool IsPascal; unsigned NumConcatenated; SourceLocation TokLocs[1]; @@ -1146,14 +1193,15 @@ class StringLiteral : public Expr { /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. static StringLiteral *Create(ASTContext &C, const char *StrData, - unsigned ByteLength, bool Wide, QualType Ty, + unsigned ByteLength, bool Wide, bool Pascal, + QualType Ty, const SourceLocation *Loc, unsigned NumStrs); /// Simple constructor for string literals made from one token. static StringLiteral *Create(ASTContext &C, const char *StrData, - unsigned ByteLength, - bool Wide, QualType Ty, SourceLocation Loc) { - return Create(C, StrData, ByteLength, Wide, Ty, &Loc, 1); + unsigned ByteLength, bool Wide, + bool Pascal, QualType Ty, SourceLocation Loc) { + return Create(C, StrData, ByteLength, Wide, Pascal, Ty, &Loc, 1); } /// \brief Construct an empty string literal. @@ -1169,8 +1217,8 @@ class StringLiteral : public Expr { void setString(ASTContext &C, llvm::StringRef Str); bool isWide() const { return IsWide; } - void setWide(bool W) { IsWide = W; } - + bool isPascal() const { return IsPascal; } + bool containsNonAsciiOrNull() const { llvm::StringRef Str = getString(); for (unsigned i = 0, e = Str.size(); i != e; ++i) @@ -1458,7 +1506,7 @@ class OffsetOfExpr : public Expr { /// the square brackets. For a field or identifier node, the source range /// contains the location of the period (if there is one) and the /// identifier. - SourceRange getRange() const { return Range; } + SourceRange getSourceRange() const { return Range; } }; private: @@ -1556,10 +1604,11 @@ class OffsetOfExpr : public Expr { } }; -/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of -/// types and expressions. -class SizeOfAlignOfExpr : public Expr { - bool isSizeof : 1; // true if sizeof, false if alignof. +/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) +/// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and +/// vec_step (OpenCL 1.1 6.11.12). +class UnaryExprOrTypeTraitExpr : public Expr { + unsigned Kind : 2; bool isType : 1; // true if operand is a type, false if an expression union { TypeSourceInfo *Ty; @@ -1568,36 +1617,38 @@ class SizeOfAlignOfExpr : public Expr { SourceLocation OpLoc, RParenLoc; public: - SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo, - QualType resultType, SourceLocation op, - SourceLocation rp) : - Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary, + UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. TInfo->getType()->isDependentType(), TInfo->getType()->containsUnexpandedParameterPack()), - isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) { + Kind(ExprKind), isType(true), OpLoc(op), RParenLoc(rp) { Argument.Ty = TInfo; } - SizeOfAlignOfExpr(bool issizeof, Expr *E, - QualType resultType, SourceLocation op, - SourceLocation rp) : - Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary, + UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. E->isTypeDependent(), E->containsUnexpandedParameterPack()), - isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) { + Kind(ExprKind), isType(false), OpLoc(op), RParenLoc(rp) { Argument.Ex = E; } /// \brief Construct an empty sizeof/alignof expression. - explicit SizeOfAlignOfExpr(EmptyShell Empty) - : Expr(SizeOfAlignOfExprClass, Empty) { } + explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty) + : Expr(UnaryExprOrTypeTraitExprClass, Empty) { } - bool isSizeOf() const { return isSizeof; } - void setSizeof(bool S) { isSizeof = S; } + UnaryExprOrTypeTrait getKind() const { + return static_cast(Kind); + } + void setKind(UnaryExprOrTypeTrait K) { Kind = K; } bool isArgumentType() const { return isType; } QualType getArgumentType() const { @@ -1612,7 +1663,7 @@ class SizeOfAlignOfExpr : public Expr { return static_cast(Argument.Ex); } const Expr *getArgumentExpr() const { - return const_cast(this)->getArgumentExpr(); + return const_cast(this)->getArgumentExpr(); } void setArgument(Expr *E) { Argument.Ex = E; isType = false; } @@ -1638,9 +1689,9 @@ class SizeOfAlignOfExpr : public Expr { } static bool classof(const Stmt *T) { - return T->getStmtClass() == SizeOfAlignOfExprClass; + return T->getStmtClass() == UnaryExprOrTypeTraitExprClass; } - static bool classof(const SizeOfAlignOfExpr *) { return true; } + static bool classof(const UnaryExprOrTypeTraitExpr *) { return true; } // Iterators child_range children(); @@ -1862,7 +1913,13 @@ class CallExpr : public Expr { /// class MemberExpr : public Expr { /// Extra data stored in some member expressions. - struct MemberNameQualifier : public NameQualifier { + struct MemberNameQualifier { + /// \brief The nested-name-specifier that qualifies the name, including + /// source-location information. + NestedNameSpecifierLoc QualifierLoc; + + /// \brief The DeclAccessPair through which the MemberDecl was found due to + /// name qualifiers. DeclAccessPair FoundDecl; }; @@ -1936,7 +1993,7 @@ class MemberExpr : public Expr { HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, - NestedNameSpecifier *qual, SourceRange qualrange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *targs, @@ -1965,16 +2022,6 @@ class MemberExpr : public Expr { /// x->Base::foo. bool hasQualifier() const { return getQualifier() != 0; } - /// \brief If the member name was qualified, retrieves the source range of - /// the nested-name-specifier that precedes the member name. Otherwise, - /// returns an empty source range. - SourceRange getQualifierRange() const { - if (!HasQualifierOrFoundDecl) - return SourceRange(); - - return getMemberQualifier()->Range; - } - /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. @@ -1982,7 +2029,17 @@ class MemberExpr : public Expr { if (!HasQualifierOrFoundDecl) return 0; - return getMemberQualifier()->NNS; + return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier(); + } + + /// \brief If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name, with source-location + /// information. + NestedNameSpecifierLoc getQualifierLoc() const { + if (!hasQualifier()) + return NestedNameSpecifierLoc(); + + return getMemberQualifier()->QualifierLoc; } /// \brief Determines whether this member expression actually had a C++ @@ -2075,20 +2132,15 @@ class MemberExpr : public Expr { SourceLocation getMemberLoc() const { return MemberLoc; } void setMemberLoc(SourceLocation L) { MemberLoc = L; } - SourceRange getSourceRange() const { - // If we have an implicit base (like a C++ implicit this), - // make sure not to return its location - SourceLocation EndLoc = (HasExplicitTemplateArgumentList) - ? getRAngleLoc() : getMemberNameInfo().getEndLoc(); - - SourceLocation BaseLoc = getBase()->getLocStart(); - if (BaseLoc.isInvalid()) - return SourceRange(MemberLoc, EndLoc); - return SourceRange(BaseLoc, EndLoc); - } - + SourceRange getSourceRange() const; + SourceLocation getExprLoc() const { return MemberLoc; } + /// \brief Determine whether the base of this explicit is implicit. + bool isImplicitAccess() const { + return getBase() && getBase()->isImplicitCXXThis(); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == MemberExprClass; } @@ -2234,6 +2286,12 @@ class CastExpr : public Expr { } CXXBaseSpecifier **path_buffer(); + void setBasePathSize(unsigned basePathSize) { + CastExprBits.BasePathSize = basePathSize; + assert(CastExprBits.BasePathSize == basePathSize && + "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!"); + } + protected: CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, Expr *op, unsigned BasePathSize) : @@ -2249,14 +2307,14 @@ class CastExpr : public Expr { Op(op) { assert(kind != CK_Invalid && "creating cast with invalid cast kind"); CastExprBits.Kind = kind; - CastExprBits.BasePathSize = BasePathSize; + setBasePathSize(BasePathSize); CheckCastConsistency(); } /// \brief Construct an empty cast. CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) : Expr(SC, Empty) { - CastExprBits.BasePathSize = BasePathSize; + setBasePathSize(BasePathSize); } public: @@ -3173,9 +3231,14 @@ class InitListExpr : public Expr { /// written in the source code. InitListExpr *SyntacticForm; - /// If this initializer list initializes a union, specifies which - /// field within the union will be initialized. - FieldDecl *UnionFieldInit; + /// \brief Either: + /// If this initializer list initializes an array with more elements than + /// there are initializers in the list, specifies an expression to be used + /// for value initialization of the rest of the elements. + /// Or + /// If this initializer list initializes a union, specifies which + /// field within the union will be initialized. + llvm::PointerUnion ArrayFillerOrUnionFieldInit; /// Whether this initializer list originally had a GNU array-range /// designator in it. This is a temporary marker used by CodeGen. @@ -3227,17 +3290,29 @@ class InitListExpr : public Expr { /// /// When @p Init is out of range for this initializer list, the /// initializer list will be extended with NULL expressions to - /// accomodate the new entry. + /// accommodate the new entry. Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr); + /// \brief If this initializer list initializes an array with more elements + /// than there are initializers in the list, specifies an expression to be + /// used for value initialization of the rest of the elements. + Expr *getArrayFiller() { + return ArrayFillerOrUnionFieldInit.dyn_cast(); + } + void setArrayFiller(Expr *filler); + /// \brief If this initializes a union, specifies which field in the /// union to initialize. /// /// Typically, this field is the first named field within the /// union. However, a designated initializer can specify the /// initialization of a different field within the union. - FieldDecl *getInitializedFieldInUnion() { return UnionFieldInit; } - void setInitializedFieldInUnion(FieldDecl *FD) { UnionFieldInit = FD; } + FieldDecl *getInitializedFieldInUnion() { + return ArrayFillerOrUnionFieldInit.dyn_cast(); + } + void setInitializedFieldInUnion(FieldDecl *FD) { + ArrayFillerOrUnionFieldInit = FD; + } // Explicit InitListExpr's originate from source code (and have valid source // locations). Implicit InitListExpr's are created by the semantic analyzer. @@ -3288,6 +3363,9 @@ class InitListExpr : public Expr { const_reverse_iterator rbegin() const { return InitExprs.rbegin(); } reverse_iterator rend() { return InitExprs.rend(); } const_reverse_iterator rend() const { return InitExprs.rend(); } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// @brief Represents a C99 designated initializer expression. @@ -3492,6 +3570,12 @@ class DesignatedInitExpr : public Expr { else return getLBracketLoc(); } + SourceLocation getEndLocation() const { + return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); + } + SourceRange getSourceRange() const { + return SourceRange(getStartLocation(), getEndLocation()); + } }; static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, @@ -3574,6 +3658,8 @@ class DesignatedInitExpr : public Expr { void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First, const Designator *Last); + SourceRange getDesignatorsSourceRange() const; + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { @@ -3667,6 +3753,118 @@ class ParenListExpr : public Expr { }; +/// \brief Represents a C1X generic selection. +/// +/// A generic selection (C1X 6.5.1.1) contains an unevaluated controlling +/// expression, followed by one or more generic associations. Each generic +/// association specifies a type name and an expression, or "default" and an +/// expression (in which case it is known as a default generic association). +/// The type and value of the generic selection are identical to those of its +/// result expression, which is defined as the expression in the generic +/// association with a type name that is compatible with the type of the +/// controlling expression, or the expression in the default generic association +/// if no types are compatible. For example: +/// +/// @code +/// _Generic(X, double: 1, float: 2, default: 3) +/// @endcode +/// +/// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f +/// or 3 if "hello". +/// +/// As an extension, generic selections are allowed in C++, where the following +/// additional semantics apply: +/// +/// Any generic selection whose controlling expression is type-dependent or +/// which names a dependent type in its association list is result-dependent, +/// which means that the choice of result expression is dependent. +/// Result-dependent generic associations are both type- and value-dependent. +class GenericSelectionExpr : public Expr { + enum { CONTROLLING, END_EXPR }; + TypeSourceInfo **AssocTypes; + Stmt **SubExprs; + unsigned NumAssocs, ResultIndex; + SourceLocation GenericLoc, DefaultLoc, RParenLoc; + +public: + GenericSelectionExpr(ASTContext &Context, + SourceLocation GenericLoc, Expr *ControllingExpr, + TypeSourceInfo **AssocTypes, Expr **AssocExprs, + unsigned NumAssocs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, + unsigned ResultIndex); + + /// This constructor is used in the result-dependent case. + GenericSelectionExpr(ASTContext &Context, + SourceLocation GenericLoc, Expr *ControllingExpr, + TypeSourceInfo **AssocTypes, Expr **AssocExprs, + unsigned NumAssocs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack); + + explicit GenericSelectionExpr(EmptyShell Empty) + : Expr(GenericSelectionExprClass, Empty) { } + + unsigned getNumAssocs() const { return NumAssocs; } + + SourceLocation getGenericLoc() const { return GenericLoc; } + SourceLocation getDefaultLoc() const { return DefaultLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + + const Expr *getAssocExpr(unsigned i) const { + return cast(SubExprs[END_EXPR+i]); + } + Expr *getAssocExpr(unsigned i) { return cast(SubExprs[END_EXPR+i]); } + + const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { + return AssocTypes[i]; + } + TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } + + QualType getAssocType(unsigned i) const { + if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i)) + return TS->getType(); + else + return QualType(); + } + + const Expr *getControllingExpr() const { + return cast(SubExprs[CONTROLLING]); + } + Expr *getControllingExpr() { return cast(SubExprs[CONTROLLING]); } + + /// Whether this generic selection is result-dependent. + bool isResultDependent() const { return ResultIndex == -1U; } + + /// The zero-based index of the result expression's generic association in + /// the generic selection's association list. Defined only if the + /// generic selection is not result-dependent. + unsigned getResultIndex() const { + assert(!isResultDependent() && "Generic selection is result-dependent"); + return ResultIndex; + } + + /// The generic selection's result expression. Defined only if the + /// generic selection is not result-dependent. + const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); } + Expr *getResultExpr() { return getAssocExpr(getResultIndex()); } + + SourceRange getSourceRange() const { + return SourceRange(GenericLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == GenericSelectionExprClass; + } + static bool classof(const GenericSelectionExpr *) { return true; } + + child_range children() { + return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs); + } + + friend class ASTStmtReader; +}; + //===----------------------------------------------------------------------===// // Clang Extensions //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h index 225db3c11fd0..a97057973745 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_EXPRCXX_H #include "clang/Basic/TypeTraits.h" +#include "clang/Basic/ExpressionTraits.h" #include "clang/AST/Expr.h" #include "clang/AST/UnresolvedSet.h" #include "clang/AST/TemplateBase.h" @@ -99,7 +100,10 @@ class CXXMemberCallExpr : public CallExpr { /// getImplicitObjectArgument - Retrieves the implicit object /// argument for the member call. For example, in "x.f(5)", this /// operation would return "x". - Expr *getImplicitObjectArgument(); + Expr *getImplicitObjectArgument() const; + + /// Retrieves the declaration of the called method. + CXXMethodDecl *getMethodDecl() const; /// getRecordDecl - Retrieves the CXXRecordDecl for the underlying type of /// the implicit object argument. Note that this is may not be the same @@ -250,6 +254,8 @@ class CXXDynamicCastExpr : public CXXNamedCastExpr { static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context, unsigned pathSize); + bool isAlwaysNull() const; + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDynamicCastExprClass; } @@ -774,7 +780,8 @@ class CXXConstructExpr : public Expr { enum ConstructionKind { CK_Complete, CK_NonVirtualBase, - CK_VirtualBase + CK_VirtualBase, + CK_Delegating }; private: @@ -1080,6 +1087,17 @@ class CXXNewExpr : public Expr { TypeSourceInfo *getAllocatedTypeSourceInfo() const { return AllocatedTypeInfo; } + + /// \brief True if the allocation result needs to be null-checked. + /// C++0x [expr.new]p13: + /// If the allocation function returns null, initialization shall + /// not be done, the deallocation function shall not be called, + /// and the value of the new-expression shall be null. + /// An allocation function is not allowed to return null unless it + /// has a non-throwing exception-specification. The '03 rule is + /// identical except that the definition of a non-throwing + /// exception specification is just "is it throw()?". + bool shouldNullCheckAllocation(ASTContext &Ctx) const; FunctionDecl *getOperatorNew() const { return OperatorNew; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } @@ -1577,6 +1595,122 @@ class BinaryTypeTraitExpr : public Expr { friend class ASTStmtReader; }; +/// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the +/// implementation of __array_rank and __array_extent. +/// Example: +/// __array_rank(int[10][20]) == 2 +/// __array_extent(int, 1) == 20 +class ArrayTypeTraitExpr : public Expr { + /// ATT - The trait. An ArrayTypeTrait enum in MSVC compat unsigned. + unsigned ATT : 2; + + /// The value of the type trait. Unspecified if dependent. + uint64_t Value; + + /// The array dimension being queried, or -1 if not used + Expr *Dimension; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + /// The type being queried. + TypeSourceInfo *QueriedType; + +public: + ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, + TypeSourceInfo *queried, uint64_t value, + Expr *dimension, SourceLocation rparen, QualType ty) + : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, + false, queried->getType()->isDependentType(), + queried->getType()->containsUnexpandedParameterPack()), + ATT(att), Value(value), Dimension(dimension), + Loc(loc), RParen(rparen), QueriedType(queried) { } + + + explicit ArrayTypeTraitExpr(EmptyShell Empty) + : Expr(ArrayTypeTraitExprClass, Empty), ATT(0), Value(false), + QueriedType() { } + + virtual ~ArrayTypeTraitExpr() { } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen); } + + ArrayTypeTrait getTrait() const { return static_cast(ATT); } + + QualType getQueriedType() const { return QueriedType->getType(); } + + TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } + + uint64_t getValue() const { assert(!isTypeDependent()); return Value; } + + Expr *getDimensionExpression() const { return Dimension; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ArrayTypeTraitExprClass; + } + static bool classof(const ArrayTypeTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTStmtReader; +}; + +/// ExpressionTraitExpr - An expression trait intrinsic +/// Example: +/// __is_lvalue_expr(std::cout) == true +/// __is_lvalue_expr(1) == false +class ExpressionTraitExpr : public Expr { + /// ET - The trait. A ExpressionTrait enum in MSVC compat unsigned. + unsigned ET : 31; + /// The value of the type trait. Unspecified if dependent. + bool Value : 1; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + Expr* QueriedExpression; +public: + ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, + Expr *queried, bool value, + SourceLocation rparen, QualType resultType) + : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary, + false, // Not type-dependent + // Value-dependent if the argument is type-dependent. + queried->isTypeDependent(), + queried->containsUnexpandedParameterPack()), + ET(et), Value(value), Loc(loc), RParen(rparen), QueriedExpression(queried) { } + + explicit ExpressionTraitExpr(EmptyShell Empty) + : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false), + QueriedExpression() { } + + SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} + + ExpressionTrait getTrait() const { return static_cast(ET); } + + Expr *getQueriedExpression() const { return QueriedExpression; } + + bool getValue() const { return Value; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ExpressionTraitExprClass; + } + static bool classof(const ExpressionTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTStmtReader; +}; + + /// \brief A reference to an overloaded function set, either an /// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr. class OverloadExpr : public Expr { @@ -1590,18 +1724,15 @@ class OverloadExpr : public Expr { /// The common name of these declarations. DeclarationNameInfo NameInfo; - /// The scope specifier, if any. - NestedNameSpecifier *Qualifier; - - /// The source range of the scope specifier. - SourceRange QualifierRange; + /// \brief The nested-name-specifier that qualifies the name, if any. + NestedNameSpecifierLoc QualifierLoc; protected: /// True if the name was a template-id. bool HasExplicitTemplateArgs; OverloadExpr(StmtClass K, ASTContext &C, - NestedNameSpecifier *Qualifier, SourceRange QRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, @@ -1610,7 +1741,7 @@ class OverloadExpr : public Expr { OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty), Results(0), NumResults(0), - Qualifier(0), HasExplicitTemplateArgs(false) { } + QualifierLoc(), HasExplicitTemplateArgs(false) { } void initializeResults(ASTContext &C, UnresolvedSetIterator Begin, @@ -1665,23 +1796,21 @@ class OverloadExpr : public Expr { /// Gets the full name info. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; } /// Gets the name looked up. DeclarationName getName() const { return NameInfo.getName(); } - void setName(DeclarationName N) { NameInfo.setName(N); } /// Gets the location of the name. SourceLocation getNameLoc() const { return NameInfo.getLoc(); } - void setNameLoc(SourceLocation Loc) { NameInfo.setLoc(Loc); } /// Fetches the nested-name qualifier, if one was given. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } - /// Fetches the range of the nested-name qualifier. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + /// Fetches the nested-name qualifier with source-location information, if + /// one was given. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// \brief Determines whether this expression had an explicit /// template argument list, e.g. f. @@ -1727,6 +1856,10 @@ class UnresolvedLookupExpr : public OverloadExpr { /// call. bool RequiresADL; + /// True if namespace ::std should be considered an associated namespace + /// for the purposes of argument-dependent lookup. See C++0x [stmt.ranged]p1. + bool StdIsAssociatedNamespace; + /// True if these lookup results are overloaded. This is pretty /// trivially rederivable if we urgently need to kill this field. bool Overloaded; @@ -1740,39 +1873,46 @@ class UnresolvedLookupExpr : public OverloadExpr { UnresolvedLookupExpr(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, SourceRange QRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedLookupExprClass, C, Qualifier, QRange, NameInfo, + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool StdIsAssociatedNamespace) + : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, NameInfo, TemplateArgs, Begin, End), - RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) + RequiresADL(RequiresADL), + StdIsAssociatedNamespace(StdIsAssociatedNamespace), + Overloaded(Overloaded), NamingClass(NamingClass) {} UnresolvedLookupExpr(EmptyShell Empty) : OverloadExpr(UnresolvedLookupExprClass, Empty), - RequiresADL(false), Overloaded(false), NamingClass(0) + RequiresADL(false), StdIsAssociatedNamespace(false), Overloaded(false), + NamingClass(0) {} + friend class ASTStmtReader; + public: static UnresolvedLookupExpr *Create(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool ADL, bool Overloaded, UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { - return new(C) UnresolvedLookupExpr(C, NamingClass, Qualifier, - QualifierRange, NameInfo, ADL, - Overloaded, 0, Begin, End); + UnresolvedSetIterator End, + bool StdIsAssociatedNamespace = false) { + assert((ADL || !StdIsAssociatedNamespace) && + "std considered associated namespace when not performing ADL"); + return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, NameInfo, + ADL, Overloaded, 0, Begin, End, + StdIsAssociatedNamespace); } static UnresolvedLookupExpr *Create(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool ADL, const TemplateArgumentListInfo &Args, @@ -1786,17 +1926,18 @@ class UnresolvedLookupExpr : public OverloadExpr { /// True if this declaration should be extended by /// argument-dependent lookup. bool requiresADL() const { return RequiresADL; } - void setRequiresADL(bool V) { RequiresADL = V; } + + /// True if namespace ::std should be artificially added to the set of + /// associated namespaecs for argument-dependent lookup purposes. + bool isStdAssociatedNamespace() const { return StdIsAssociatedNamespace; } /// True if this lookup is overloaded. bool isOverloaded() const { return Overloaded; } - void setOverloaded(bool V) { Overloaded = V; } /// Gets the 'naming class' (in the sense of C++0x /// [class.access.base]p5) of the lookup. This is the scope /// that was looked in to find these results. CXXRecordDecl *getNamingClass() const { return NamingClass; } - void setNamingClass(CXXRecordDecl *D) { NamingClass = D; } // Note that, inconsistently with the explicit-template-argument AST // nodes, users are *forbidden* from calling these methods on objects @@ -1845,8 +1986,10 @@ class UnresolvedLookupExpr : public OverloadExpr { SourceRange getSourceRange() const { SourceRange Range(getNameInfo().getSourceRange()); - if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); - if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); + if (getQualifierLoc()) + Range.setBegin(getQualifierLoc().getBeginLoc()); + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); return Range; } @@ -2186,16 +2329,13 @@ class CXXDependentScopeMemberExpr : public Expr { SourceLocation OperatorLoc; /// \brief The nested-name-specifier that precedes the member name, if any. - NestedNameSpecifier *Qualifier; - - /// \brief The source range covering the nested name specifier. - SourceRange QualifierRange; + NestedNameSpecifierLoc QualifierLoc; /// \brief In a qualified member access expression such as t->Base::f, this /// member stores the resolves of name lookup in the context of the member /// access expression, to be used at instantiation time. /// - /// FIXME: This member, along with the Qualifier and QualifierRange, could + /// FIXME: This member, along with the QualifierLoc, could /// be stuck into a structure that is optionally allocated at the end of /// the CXXDependentScopeMemberExpr, to save space in the common case. NamedDecl *FirstQualifierFoundInScope; @@ -2208,8 +2348,7 @@ class CXXDependentScopeMemberExpr : public Expr { CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2219,8 +2358,7 @@ class CXXDependentScopeMemberExpr : public Expr { Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo); @@ -2228,8 +2366,7 @@ class CXXDependentScopeMemberExpr : public Expr { Create(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2241,7 +2378,7 @@ class CXXDependentScopeMemberExpr : public Expr { /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source /// location of the operator is invalid in this case. - bool isImplicitAccess() const { return Base == 0; } + bool isImplicitAccess() const; /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -2249,30 +2386,27 @@ class CXXDependentScopeMemberExpr : public Expr { assert(!isImplicitAccess()); return cast(Base); } - void setBase(Expr *E) { Base = E; } QualType getBaseType() const { return BaseType; } - void setBaseType(QualType T) { BaseType = T; } /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } /// \brief Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieve the nested-name-specifier that qualifies the member /// name. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } - - /// \brief Retrieve the source range covering the nested-name-specifier - /// that qualifies the member name. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + /// \brief Retrieve the nested-name-specifier that qualifies the member + /// name, with source location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the first part of the nested-name-specifier that was /// found in the scope of the member access expression when the member access /// was initially parsed. @@ -2287,26 +2421,20 @@ class CXXDependentScopeMemberExpr : public Expr { NamedDecl *getFirstQualifierFoundInScope() const { return FirstQualifierFoundInScope; } - void setFirstQualifierFoundInScope(NamedDecl *D) { - FirstQualifierFoundInScope = D; - } /// \brief Retrieve the name of the member that this expression /// refers to. const DeclarationNameInfo &getMemberNameInfo() const { return MemberNameInfo; } - void setMemberNameInfo(const DeclarationNameInfo &N) { MemberNameInfo = N; } /// \brief Retrieve the name of the member that this expression /// refers to. DeclarationName getMember() const { return MemberNameInfo.getName(); } - void setMember(DeclarationName N) { MemberNameInfo.setName(N); } // \brief Retrieve the location of the name of the member that this // expression refers to. SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); } - void setMemberLoc(SourceLocation L) { MemberNameInfo.setLoc(L); } /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f. @@ -2376,7 +2504,7 @@ class CXXDependentScopeMemberExpr : public Expr { if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); else if (getQualifier()) - Range.setBegin(getQualifierRange().getBegin()); + Range.setBegin(getQualifierLoc().getBeginLoc()); else Range.setBegin(MemberNameInfo.getBeginLoc()); @@ -2438,8 +2566,7 @@ class UnresolvedMemberExpr : public OverloadExpr { UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2448,13 +2575,14 @@ class UnresolvedMemberExpr : public OverloadExpr { : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), HasUnresolvedUsing(false), Base(0) { } + friend class ASTStmtReader; + public: static UnresolvedMemberExpr * Create(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2466,7 +2594,7 @@ class UnresolvedMemberExpr : public OverloadExpr { /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source /// location of the operator is invalid in this case. - bool isImplicitAccess() const { return Base == 0; } + bool isImplicitAccess() const; /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -2478,24 +2606,19 @@ class UnresolvedMemberExpr : public OverloadExpr { assert(!isImplicitAccess()); return cast(Base); } - void setBase(Expr *E) { Base = E; } QualType getBaseType() const { return BaseType; } - void setBaseType(QualType T) { BaseType = T; } /// \brief Determine whether the lookup results contain an unresolved using /// declaration. bool hasUnresolvedUsing() const { return HasUnresolvedUsing; } - void setHasUnresolvedUsing(bool V) { HasUnresolvedUsing = V; } /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } /// \brief Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieves the naming class of this lookup. CXXRecordDecl *getNamingClass() const; @@ -2503,17 +2626,14 @@ class UnresolvedMemberExpr : public OverloadExpr { /// \brief Retrieve the full name info for the member that this expression /// refers to. const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); } - void setMemberNameInfo(const DeclarationNameInfo &N) { setNameInfo(N); } /// \brief Retrieve the name of the member that this expression /// refers to. DeclarationName getMemberName() const { return getName(); } - void setMemberName(DeclarationName N) { setName(N); } // \brief Retrieve the location of the name of the member that this // expression refers to. SourceLocation getMemberLoc() const { return getNameLoc(); } - void setMemberLoc(SourceLocation L) { setNameLoc(L); } /// \brief Retrieve the explicit template argument list that followed the /// member template name. @@ -2570,8 +2690,8 @@ class UnresolvedMemberExpr : public OverloadExpr { SourceRange Range = getMemberNameInfo().getSourceRange(); if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); - else if (getQualifier()) - Range.setBegin(getQualifierRange().getBegin()); + else if (getQualifierLoc()) + Range.setBegin(getQualifierLoc().getBeginLoc()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h index 285efb757bbb..8163923d62d1 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h @@ -337,6 +337,39 @@ class ObjCPropertyRefExpr : public Expr { QualType getSuperReceiverType() const { return QualType(Receiver.get(), 0); } + QualType getGetterResultType() const { + QualType ResultType; + if (isExplicitProperty()) { + const ObjCPropertyDecl *PDecl = getExplicitProperty(); + if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl()) + ResultType = Getter->getResultType(); + else + ResultType = getType(); + } else { + const ObjCMethodDecl *Getter = getImplicitPropertyGetter(); + ResultType = Getter->getResultType(); // with reference! + } + return ResultType; + } + + QualType getSetterArgType() const { + QualType ArgType; + if (isImplicitProperty()) { + const ObjCMethodDecl *Setter = getImplicitPropertySetter(); + ObjCMethodDecl::param_iterator P = Setter->param_begin(); + ArgType = (*P)->getType(); + } else { + if (ObjCPropertyDecl *PDecl = getExplicitProperty()) + if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) { + ObjCMethodDecl::param_iterator P = Setter->param_begin(); + ArgType = (*P)->getType(); + } + if (ArgType.isNull()) + ArgType = getType(); + } + return ArgType; + } + ObjCInterfaceDecl *getClassReceiver() const { return Receiver.get(); } @@ -741,6 +774,11 @@ class ObjCMessageExpr : public Expr { SelectorOrMethod = reinterpret_cast(MD); } + ObjCMethodFamily getMethodFamily() const { + if (HasMethod) return getMethodDecl()->getMethodFamily(); + return getSelector().getMethodFamily(); + } + /// \brief Return the number of actual arguments in this message, /// not counting the receiver. unsigned getNumArgs() const { return NumArgs; } @@ -808,7 +846,7 @@ class ObjCMessageExpr : public Expr { }; /// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. -/// (similiar in spirit to MemberExpr). +/// (similar in spirit to MemberExpr). class ObjCIsaExpr : public Expr { /// Base - the expression for the base object pointer. Stmt *Base; diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h index 7b23766b0714..6db233641220 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines the ExternalASTSource interface, which enables -// construction of AST nodes from some external source.x +// construction of AST nodes from some external source. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H @@ -16,7 +16,6 @@ #include "clang/AST/DeclBase.h" #include -#include namespace llvm { template class SmallVectorImpl; @@ -26,9 +25,6 @@ namespace clang { class ASTConsumer; class CXXBaseSpecifier; -class Decl; -class DeclContext; -class DeclContextLookupResult; class DeclarationName; class ExternalSemaSource; // layering violation required for downcasting class NamedDecl; @@ -74,17 +70,23 @@ class ExternalASTSource { /// /// This method only needs to be implemented if the AST source ever /// passes back decl sets as VisibleDeclaration objects. - virtual Decl *GetExternalDecl(uint32_t ID) = 0; + /// + /// The default implementation of this method is a no-op. + virtual Decl *GetExternalDecl(uint32_t ID); /// \brief Resolve a selector ID into a selector. /// /// This operation only needs to be implemented if the AST source /// returns non-zero for GetNumKnownSelectors(). - virtual Selector GetExternalSelector(uint32_t ID) = 0; + /// + /// The default implementation of this method is a no-op. + virtual Selector GetExternalSelector(uint32_t ID); /// \brief Returns the number of selectors known to the external AST /// source. - virtual uint32_t GetNumExternalSelectors() = 0; + /// + /// The default implementation of this method is a no-op. + virtual uint32_t GetNumExternalSelectors(); /// \brief Resolve the offset of a statement in the decl stream into /// a statement. @@ -92,21 +94,26 @@ class ExternalASTSource { /// This operation is meant to be used via a LazyOffsetPtr. It only /// needs to be implemented if the AST source uses methods like /// FunctionDecl::setLazyBody when building decls. - virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0; + /// + /// The default implementation of this method is a no-op. + virtual Stmt *GetExternalDeclStmt(uint64_t Offset); /// \brief Resolve the offset of a set of C++ base specifiers in the decl /// stream into an array of specifiers. - virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) = 0; - + /// + /// The default implementation of this method is a no-op. + virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); + /// \brief Finds all declarations with the given name in the /// given context. /// /// Generally the final step of this method is either to call /// SetExternalVisibleDeclsForName or to recursively call lookup on /// the DeclContext after calling SetExternalVisibleDecls. + /// + /// The default implementation of this method is a no-op. virtual DeclContextLookupResult - FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name) = 0; + FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); /// \brief Deserialize all the visible declarations from external storage. /// @@ -114,7 +121,9 @@ class ExternalASTSource { /// may not have a complete name lookup table. This function deserializes /// the rest of visible declarations from the external storage and completes /// the name lookup table of the DeclContext. - virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0; + /// + /// The default implementation of this method is a no-op. + virtual void MaterializeVisibleDecls(const DeclContext *DC); /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. @@ -124,9 +133,11 @@ class ExternalASTSource { /// are returned. /// /// \return true if an error occurred + /// + /// The default implementation of this method is a no-op. virtual bool FindExternalLexicalDecls(const DeclContext *DC, bool (*isKindWeWant)(Decl::Kind), - llvm::SmallVectorImpl &Result) = 0; + llvm::SmallVectorImpl &Result); /// \brief Finds all declarations lexically contained within the given /// DeclContext. @@ -154,7 +165,7 @@ class ExternalASTSource { /// set on the ObjCInterfaceDecl via the function /// \c ObjCInterfaceDecl::setExternallyCompleted(). virtual void CompleteType(ObjCInterfaceDecl *Class) { } - + /// \brief Notify ExternalASTSource that we started deserialization of /// a decl or type so until FinishedDeserializing is called there may be /// decls that are initializing. Must be paired with FinishedDeserializing. @@ -179,6 +190,28 @@ class ExternalASTSource { /// /// The default implementation of this method is a no-op. virtual void PrintStats(); + + //===--------------------------------------------------------------------===// + // Queries for performance analysis. + //===--------------------------------------------------------------------===// + + struct MemoryBufferSizes { + size_t malloc_bytes; + size_t mmap_bytes; + + MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) + : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} + }; + + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + MemoryBufferSizes getMemoryBufferSizes() const { + MemoryBufferSizes sizes(0, 0); + getMemoryBufferSizes(sizes); + return sizes; + } + + virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const = 0; protected: static DeclContextLookupResult @@ -270,7 +303,7 @@ typedef LazyOffsetPtr typedef LazyOffsetPtr LazyCXXBaseSpecifiersPtr; - + } // end namespace clang #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h index 024bf402894b..c21c76b006ff 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h +++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h @@ -312,6 +312,146 @@ class NestedNameSpecifierLoc { } }; +/// \brief Class that aids in the construction of nested-name-specifiers along +/// with source-location information for all of the components of the +/// nested-name-specifier. +class NestedNameSpecifierLocBuilder { + /// \brief The current representation of the nested-name-specifier we're + /// building. + NestedNameSpecifier *Representation; + + /// \brief Buffer used to store source-location information for the + /// nested-name-specifier. + /// + /// Note that we explicitly manage the buffer (rather than using a + /// SmallVector) because \c Declarator expects it to be possible to memcpy() + /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. + char *Buffer; + + /// \brief The size of the buffer used to store source-location information + /// for the nested-name-specifier. + unsigned BufferSize; + + /// \brief The capacity of the buffer used to store source-location + /// information for the nested-name-specifier. + unsigned BufferCapacity; + +public: + NestedNameSpecifierLocBuilder(); + + NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); + + NestedNameSpecifierLocBuilder & + operator=(const NestedNameSpecifierLocBuilder &Other); + + ~NestedNameSpecifierLocBuilder(); + + /// \brief Retrieve the representation of the nested-name-specifier. + NestedNameSpecifier *getRepresentation() const { return Representation; } + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'type::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param TemplateKWLoc The location of the 'template' keyword, if present. + /// + /// \param TL The TypeLoc that describes the type preceding the '::'. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, + SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'identifier::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Identifier The identifier. + /// + /// \param IdentifierLoc The location of the identifier. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Namespace The namespace. + /// + /// \param NamespaceLoc The location of the namespace name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace-alias::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Alias The namespace alias. + /// + /// \param AliasLoc The location of the namespace alias + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, SourceLocation ColonColonLoc); + + /// \brief Turn this (empty) nested-name-specifier into the global + /// nested-name-specifier '::'. + void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); + + /// \brief Make a new nested-name-specifier from incomplete source-location + /// information. + /// + /// This routine should be used very, very rarely, in cases where we + /// need to synthesize a nested-name-specifier. Most code should instead use + /// \c Adopt() with a proper \c NestedNameSpecifierLoc. + void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, + SourceRange R); + + /// \brief Adopt an existing nested-name-specifier (with source-range + /// information). + void Adopt(NestedNameSpecifierLoc Other); + + /// \brief Retrieve the source range covered by this nested-name-specifier. + SourceRange getSourceRange() const { + return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); + } + + /// \brief Retrieve a nested-name-specifier with location information, + /// copied into the given AST context. + /// + /// \param Context The context into which this nested-name-specifier will be + /// copied. + NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; + + /// \brief Clear out this builder, and prepare it to build another + /// nested-name-specifier with source-location information. + void Clear() { + Representation = 0; + BufferSize = 0; + } + + /// \brief Retrieve the underlying buffer. + /// + /// \returns A pair containing a pointer to the buffer of source-location + /// data and the size of the source-location data that resides in that + /// buffer. + std::pair getBuffer() const { + return std::make_pair(Buffer, BufferSize); + } +}; + /// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h index a59c302ffc1e..cf5fadbd1850 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h +++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h @@ -38,7 +38,8 @@ struct PrintingPolicy { /// \brief Create a default printing policy for C. PrintingPolicy(const LangOptions &LO) : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), - SuppressTag(false), SuppressScope(false), + SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), + SuppressInitializers(false), Dump(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true) { } @@ -64,6 +65,16 @@ struct PrintingPolicy { /// "const int" type specifier and instead only print the "*y". bool SuppressSpecifiers : 1; + /// \brief Whether type printing should skip printing the tag keyword. + /// + /// This is used when printing the inner type of elaborated types, + /// (as the tag keyword is part of the elaborated type): + /// + /// \code + /// struct Geometry::Point; + /// \endcode + bool SuppressTagKeyword : 1; + /// \brief Whether type printing should skip printing the actual tag type. /// /// This is used when the caller needs to print a tag definition in front @@ -77,6 +88,19 @@ struct PrintingPolicy { /// \brief Suppresses printing of scope specifiers. bool SuppressScope : 1; + /// \brief Suppress printing of variable initializers. + /// + /// This flag is used when printing the loop variable in a for-range + /// statement. For example, given: + /// + /// \code + /// for (auto x : coll) + /// \endcode + /// + /// SuppressInitializers will be true when printing "auto x", so that the + /// internal initializer constructed for x will not be printed. + bool SuppressInitializers : 1; + /// \brief True when we are "dumping" rather than "pretty-printing", /// where dumping involves printing the internal details of the AST /// and pretty-printing involves printing something similar to diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h index e85b6dcd279a..930d19373cdc 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h @@ -600,12 +600,15 @@ bool RecursiveASTVisitor::TraverseTemplateArgumentLoc( // FIXME: how can TSI ever be NULL? if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); - else - return true; + else + return getDerived().TraverseType(Arg.getAsType()); } case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: + if (ArgLoc.getTemplateQualifierLoc()) + TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( + ArgLoc.getTemplateQualifierLoc())); return getDerived().TraverseTemplateName( Arg.getAsTemplateOrTemplatePattern()); @@ -933,7 +936,11 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { const FunctionProtoType *T = TL.getTypePtr(); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseDecl(TL.getArg(I))); + if (TL.getArg(I)) { + TRY_TO(TraverseDecl(TL.getArg(I))); + } else if (I < T->getNumArgs()) { + TRY_TO(TraverseType(T->getArgType(I))); + } } for (FunctionProtoType::exception_iterator E = T->exception_begin(), @@ -987,21 +994,22 @@ DEF_TRAVERSE_TYPELOC(AttributedType, { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) -// FIXME: use the sourceloc on qualifier? DEF_TRAVERSE_TYPELOC(ElaboratedType, { - if (TL.getTypePtr()->getQualifier()) { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); } TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); }) -// FIXME: use the sourceloc on qualifier? DEF_TRAVERSE_TYPELOC(DependentNameType, { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); }) DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); + } + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); } @@ -1041,7 +1049,9 @@ bool RecursiveASTVisitor::TraverseDeclContextHelper(DeclContext *DC) { for (DeclContext::decl_iterator Child = DC->decls_begin(), ChildEnd = DC->decls_end(); Child != ChildEnd; ++Child) { - TRY_TO(TraverseDecl(*Child)); + // BlockDecls are traversed through BlockExprs. + if (!isa(*Child)) + TRY_TO(TraverseDecl(*Child)); } return true; @@ -1060,10 +1070,12 @@ bool RecursiveASTVisitor::Traverse##DECL (DECL *D) { \ DEF_TRAVERSE_DECL(AccessSpecDecl, { }) DEF_TRAVERSE_DECL(BlockDecl, { - // We don't traverse nodes in param_begin()/param_end(), as they - // appear in decls_begin()/decls_end() and thus are handled by the - // DEF_TRAVERSE_DECL macro already. + TRY_TO(TraverseTypeLoc(D->getSignatureAsWritten()->getTypeLoc())); TRY_TO(TraverseStmt(D->getBody())); + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; }) DEF_TRAVERSE_DECL(FileScopeAsmDecl, { @@ -1164,9 +1176,17 @@ DEF_TRAVERSE_DECL(ObjCProtocolDecl, { }) DEF_TRAVERSE_DECL(ObjCMethodDecl, { - // We don't traverse nodes in param_begin()/param_end(), as they - // appear in decls_begin()/decls_end() and thus are handled. - TRY_TO(TraverseStmt(D->getBody())); + if (D->getResultTypeSourceInfo()) { + TRY_TO(TraverseTypeLoc(D->getResultTypeSourceInfo()->getTypeLoc())); + } + for (ObjCMethodDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + if (D->isThisDeclarationADefinition()) { + TRY_TO(TraverseStmt(D->getBody())); + } + return true; }) DEF_TRAVERSE_DECL(ObjCPropertyDecl, { @@ -1341,6 +1361,13 @@ DEF_TRAVERSE_DECL(TypedefDecl, { // source. }) +DEF_TRAVERSE_DECL(TypeAliasDecl, { + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type alias, not something that was written in the + // source. + }) + DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { // A dependent using declaration which was marked with 'typename'. // template class A : public B { using typename B::foo; }; @@ -1354,7 +1381,7 @@ DEF_TRAVERSE_DECL(EnumDecl, { if (D->getTypeForDecl()) TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); // The enumerators are already traversed by // decls_begin()/decls_end(). }) @@ -1367,7 +1394,7 @@ bool RecursiveASTVisitor::TraverseRecordHelper( // We shouldn't traverse D->getTypeForDecl(); it's a result of // declaring the type, not something that was written in the source. - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); return true; } @@ -1464,9 +1491,11 @@ DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) template bool RecursiveASTVisitor::TraverseDeclaratorHelper(DeclaratorDecl *D) { - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); if (D->getTypeSourceInfo()) TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + else + TRY_TO(TraverseType(D->getType())); return true; } @@ -1492,7 +1521,7 @@ DEF_TRAVERSE_DECL(ObjCIvarDecl, { template bool RecursiveASTVisitor::TraverseFunctionHelper(FunctionDecl *D) { - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); // If we're an explicit template specialization, iterate over the // template args that were explicitly specified. If we were doing @@ -1678,13 +1707,14 @@ DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, { }) DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) +DEF_TRAVERSE_STMT(CXXForRangeStmt, { }) DEF_TRAVERSE_STMT(ReturnStmt, { }) DEF_TRAVERSE_STMT(SwitchStmt, { }) DEF_TRAVERSE_STMT(WhileStmt, { }) DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); @@ -1692,7 +1722,7 @@ DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { }) DEF_TRAVERSE_STMT(DeclRefExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); }) @@ -1707,10 +1737,9 @@ DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { }) DEF_TRAVERSE_STMT(MemberExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); - // FIXME: Should we be recursing on the qualifier? - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); }) DEF_TRAVERSE_STMT(ImplicitCastExpr, { @@ -1759,6 +1788,22 @@ bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) { return true; } +// GenericSelectionExpr is a special case because the types and expressions +// are interleaved. We also need to watch out for null types (default +// generic associations). +template +bool RecursiveASTVisitor:: +TraverseGenericSelectionExpr(GenericSelectionExpr *S) { + TRY_TO(WalkUpFromGenericSelectionExpr(S)); + TRY_TO(TraverseStmt(S->getControllingExpr())); + for (unsigned i = 0; i != S->getNumAssocs(); ++i) { + if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i)) + TRY_TO(TraverseTypeLoc(TS->getTypeLoc())); + TRY_TO(TraverseStmt(S->getAssocExpr(i))); + } + return true; +} + DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { // This is called for code like 'return T()' where T is a built-in // (i.e. non-class) type. @@ -1778,7 +1823,7 @@ DEF_TRAVERSE_STMT(OffsetOfExpr, { TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); }) -DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { +DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, { // The child-iterator will pick up the arg if it's an expression, // but not if it's a type. if (S->isArgumentType()) @@ -1808,6 +1853,14 @@ DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, { TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { + TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(ExpressionTraitExpr, { + TRY_TO(TraverseStmt(S->getQueriedExpression())); + }) + DEF_TRAVERSE_STMT(VAArgExpr, { // The child-iterator will pick up the expression argument. TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); @@ -1834,7 +1887,10 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, { }) DEF_TRAVERSE_STMT(AddrLabelExpr, { }) DEF_TRAVERSE_STMT(ArraySubscriptExpr, { }) DEF_TRAVERSE_STMT(BlockDeclRefExpr, { }) -DEF_TRAVERSE_STMT(BlockExpr, { }) +DEF_TRAVERSE_STMT(BlockExpr, { + TRY_TO(TraverseDecl(S->getBlockDecl())); + return true; // no child statements to loop through. +}) DEF_TRAVERSE_STMT(ChooseExpr, { }) DEF_TRAVERSE_STMT(CompoundLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) @@ -1869,7 +1925,7 @@ DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), S->getNumTemplateArgs())); @@ -1877,13 +1933,17 @@ DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { }) DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), S->getNumTemplateArgs())); } }) +DEF_TRAVERSE_STMT(SEHTryStmt, {}) +DEF_TRAVERSE_STMT(SEHExceptStmt, {}) +DEF_TRAVERSE_STMT(SEHFinallyStmt,{}) + DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { }) DEF_TRAVERSE_STMT(OpaqueValueExpr, { }) DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { }) @@ -1921,7 +1981,7 @@ DEF_TRAVERSE_STMT(ObjCStringLiteral, { }) // Candidates: // // http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html -// http://clang.llvm.org/doxygen/classclang_1_1SizeOfAlignOfExpr.html +// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html // http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html // Every class that has getQualifier. diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h index d1f7d667f33d..695fb0403ead 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h @@ -158,6 +158,16 @@ class Stmt { }; enum { NumExprBits = 15 }; + class DeclRefExprBitfields { + friend class DeclRefExpr; + friend class ASTStmtReader; // deserialization + unsigned : NumExprBits; + + unsigned HasQualifier : 1; + unsigned HasExplicitTemplateArgs : 1; + unsigned HasFoundDecl : 1; + }; + class CastExprBitfields { friend class CastExpr; unsigned : NumExprBits; @@ -180,6 +190,7 @@ class Stmt { StmtBitfields StmtBits; CompoundStmtBitfields CompoundStmtBits; ExprBitfields ExprBits; + DeclRefExprBitfields DeclRefExprBits; CastExprBitfields CastExprBits; CallExprBitfields CallExprBits; }; @@ -383,14 +394,15 @@ class DeclStmt : public Stmt { class NullStmt : public Stmt { SourceLocation SemiLoc; - /// \brief Whether the null statement was preceded by an empty macro, e.g: + /// \brief If the null statement was preceded by an empty macro this is + /// its instantiation source location, e.g: /// @code /// #define CALL(x) /// CALL(0); /// @endcode - bool LeadingEmptyMacro; + SourceLocation LeadingEmptyMacro; public: - NullStmt(SourceLocation L, bool LeadingEmptyMacro = false) + NullStmt(SourceLocation L, SourceLocation LeadingEmptyMacro =SourceLocation()) : Stmt(NullStmtClass), SemiLoc(L), LeadingEmptyMacro(LeadingEmptyMacro) {} /// \brief Build an empty null statement. @@ -399,7 +411,8 @@ class NullStmt : public Stmt { SourceLocation getSemiLoc() const { return SemiLoc; } void setSemiLoc(SourceLocation L) { SemiLoc = L; } - bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro; } + bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro.isValid(); } + SourceLocation getLeadingEmptyMacroLoc() const { return LeadingEmptyMacro; } SourceRange getSourceRange() const { return SourceRange(SemiLoc); } @@ -424,6 +437,8 @@ class CompoundStmt : public Stmt { SourceLocation LB, SourceLocation RB) : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) { CompoundStmtBits.NumStmts = NumStmts; + assert(CompoundStmtBits.NumStmts == NumStmts && + "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); if (NumStmts == 0) { Body = 0; @@ -516,6 +531,9 @@ class SwitchCase : public Stmt { void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } Stmt *getSubStmt(); + const Stmt *getSubStmt() const { + return const_cast(this)->getSubStmt(); + } SourceRange getSourceRange() const { return SourceRange(); } @@ -527,7 +545,7 @@ class SwitchCase : public Stmt { }; class CaseStmt : public SwitchCase { - enum { SUBSTMT, LHS, RHS, END_EXPR }; + enum { LHS, RHS, SUBSTMT, END_EXPR }; Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for // GNU "case 1 ... 4" extension SourceLocation CaseLoc; @@ -688,6 +706,12 @@ class IfStmt : public Stmt { VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + /// If this IfStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast(SubExprs[VAR]); + } + const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } const Stmt *getThen() const { return SubExprs[THEN]; } @@ -754,6 +778,12 @@ class SwitchStmt : public Stmt { /// \endcode VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + + /// If this SwitchStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast(SubExprs[VAR]); + } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} const Stmt *getBody() const { return SubExprs[BODY]; } @@ -835,6 +865,12 @@ class WhileStmt : public Stmt { VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + /// If this WhileStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast(SubExprs[VAR]); + } + Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } @@ -939,6 +975,12 @@ class ForStmt : public Stmt { VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + /// If this ForStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast(SubExprs[CONDVAR]); + } + Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } Stmt *getBody() { return SubExprs[BODY]; } @@ -1406,6 +1448,122 @@ class AsmStmt : public Stmt { } }; +class SEHExceptStmt : public Stmt { + SourceLocation Loc; + Stmt *Children[2]; + + enum { FILTER_EXPR, BLOCK }; + + SEHExceptStmt(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block); + +public: + static SEHExceptStmt* Create(ASTContext &C, + SourceLocation ExceptLoc, + Expr *FilterExpr, + Stmt *Block); + SourceRange getSourceRange() const { + return SourceRange(getExceptLoc(), getEndLoc()); + } + + SourceLocation getExceptLoc() const { return Loc; } + SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); } + + Expr *getFilterExpr() const { return reinterpret_cast(Children[FILTER_EXPR]); } + CompoundStmt *getBlock() const { return llvm::cast(Children[BLOCK]); } + + child_range children() { + return child_range(Children,Children+2); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHExceptStmtClass; + } + + static bool classof(SEHExceptStmt *) { return true; } + +}; + +class SEHFinallyStmt : public Stmt { + SourceLocation Loc; + Stmt *Block; + + SEHFinallyStmt(SourceLocation Loc, + Stmt *Block); + +public: + static SEHFinallyStmt* Create(ASTContext &C, + SourceLocation FinallyLoc, + Stmt *Block); + + SourceRange getSourceRange() const { + return SourceRange(getFinallyLoc(), getEndLoc()); + } + + SourceLocation getFinallyLoc() const { return Loc; } + SourceLocation getEndLoc() const { return Block->getLocEnd(); } + + CompoundStmt *getBlock() const { return llvm::cast(Block); } + + child_range children() { + return child_range(&Block,&Block+1); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHFinallyStmtClass; + } + + static bool classof(SEHFinallyStmt *) { return true; } + +}; + +class SEHTryStmt : public Stmt { + bool IsCXXTry; + SourceLocation TryLoc; + Stmt *Children[2]; + + enum { TRY = 0, HANDLER = 1 }; + + SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try' + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); + +public: + static SEHTryStmt* Create(ASTContext &C, + bool isCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); + + SourceRange getSourceRange() const { + return SourceRange(getTryLoc(), getEndLoc()); + } + + SourceLocation getTryLoc() const { return TryLoc; } + SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); } + + bool getIsCXXTry() const { return IsCXXTry; } + CompoundStmt* getTryBlock() const { return llvm::cast(Children[TRY]); } + Stmt *getHandler() const { return Children[HANDLER]; } + + /// Returns 0 if not defined + SEHExceptStmt *getExceptHandler() const; + SEHFinallyStmt *getFinallyHandler() const; + + child_range children() { + return child_range(Children,Children+2); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHTryStmtClass; + } + + static bool classof(SEHTryStmt *) { return true; } + +}; + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h index f08815fd562d..42dcf2bb7b79 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h @@ -119,6 +119,88 @@ class CXXTryStmt : public Stmt { friend class ASTStmtReader; }; +/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for +/// statement, represented as 'for (range-declarator : range-expression)'. +/// +/// This is stored in a partially-desugared form to allow full semantic +/// analysis of the constituent components. The original syntactic components +/// can be extracted using getLoopVariable and getRangeInit. +class CXXForRangeStmt : public Stmt { + enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END }; + // SubExprs[RANGE] is an expression or declstmt. + // SubExprs[COND] and SubExprs[INC] are expressions. + Stmt *SubExprs[END]; + SourceLocation ForLoc; + SourceLocation ColonLoc; + SourceLocation RParenLoc; +public: + CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd, + Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, + SourceLocation FL, SourceLocation CL, SourceLocation RPL); + CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { } + + + VarDecl *getLoopVariable(); + Expr *getRangeInit(); + + const VarDecl *getLoopVariable() const; + const Expr *getRangeInit() const; + + + DeclStmt *getRangeStmt() { return cast(SubExprs[RANGE]); } + DeclStmt *getBeginEndStmt() { return cast_or_null(SubExprs[BEGINEND]); } + Expr *getCond() { return cast_or_null(SubExprs[COND]); } + Expr *getInc() { return cast_or_null(SubExprs[INC]); } + DeclStmt *getLoopVarStmt() { return cast(SubExprs[LOOPVAR]); } + Stmt *getBody() { return SubExprs[BODY]; } + + const DeclStmt *getRangeStmt() const { + return cast(SubExprs[RANGE]); + } + const DeclStmt *getBeginEndStmt() const { + return cast_or_null(SubExprs[BEGINEND]); + } + const Expr *getCond() const { + return cast_or_null(SubExprs[COND]); + } + const Expr *getInc() const { + return cast_or_null(SubExprs[INC]); + } + const DeclStmt *getLoopVarStmt() const { + return cast(SubExprs[LOOPVAR]); + } + const Stmt *getBody() const { return SubExprs[BODY]; } + + void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast(E); } + void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } + void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; } + void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } + void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast(E); } + void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + + SourceLocation getForLoc() const { return ForLoc; } + void setForLoc(SourceLocation Loc) { ForLoc = Loc; } + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } + + SourceRange getSourceRange() const { + return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXForRangeStmtClass; + } + static bool classof(const CXXForRangeStmt *) { return true; } + + // Iterators + child_range children() { + return child_range(&SubExprs[0], &SubExprs[END]); + } +}; + } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h index 851c001adc54..05b50db7def7 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h +++ b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace clang { diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h index a4e074e083f6..821b4fcbb168 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h +++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h @@ -362,7 +362,10 @@ struct TemplateArgumentLocInfo { Expr *Expression; TypeSourceInfo *Declarator; struct { - unsigned QualifierRange[2]; + // FIXME: We'd like to just use the qualifier in the TemplateName, + // but template arguments get canonicalized too quickly. + NestedNameSpecifier *Qualifier; + void *QualifierLocData; unsigned TemplateNameLoc; unsigned EllipsisLoc; } Template; @@ -375,12 +378,12 @@ struct TemplateArgumentLocInfo { TemplateArgumentLocInfo(Expr *E) : Expression(E) {} - TemplateArgumentLocInfo(SourceRange QualifierRange, + TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) { - Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); - Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); + Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); + Template.QualifierLocData = QualifierLoc.getOpaqueData(); Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); } @@ -393,10 +396,9 @@ struct TemplateArgumentLocInfo { return Expression; } - SourceRange getTemplateQualifierRange() const { - return SourceRange( - SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), - SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); + NestedNameSpecifierLoc getTemplateQualifierLoc() const { + return NestedNameSpecifierLoc(Template.Qualifier, + Template.QualifierLocData); } SourceLocation getTemplateNameLoc() const { @@ -433,11 +435,10 @@ class TemplateArgumentLoc { } TemplateArgumentLoc(const TemplateArgument &Argument, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc = SourceLocation()) - : Argument(Argument), - LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) { + : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); } @@ -477,10 +478,10 @@ class TemplateArgumentLoc { return LocInfo.getAsExpr(); } - SourceRange getTemplateQualifierRange() const { + NestedNameSpecifierLoc getTemplateQualifierLoc() const { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); - return LocInfo.getTemplateQualifierRange(); + return LocInfo.getTemplateQualifierLoc(); } SourceLocation getTemplateNameLoc() const { diff --git a/contrib/llvm/tools/clang/include/clang/AST/Type.h b/contrib/llvm/tools/clang/include/clang/AST/Type.h index 9b177cceed96..975a66fefa89 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Type.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Type.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_TYPE_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" @@ -72,7 +73,7 @@ namespace llvm { namespace clang { class ASTContext; - class TypedefDecl; + class TypedefNameDecl; class TemplateDecl; class TemplateTypeParmDecl; class NonTypeTemplateParmDecl; @@ -212,6 +213,11 @@ class Qualifiers { assert(type); setObjCGCAttr(type); } + Qualifiers withoutObjCGCAttr() const { + Qualifiers qs = *this; + qs.removeObjCGCAttr(); + return qs; + } bool hasAddressSpace() const { return Mask & AddressSpaceMask; } unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } @@ -293,8 +299,10 @@ class Qualifiers { (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); } - bool isSupersetOf(Qualifiers Other) const; - + /// \brief Determine whether this set of qualifiers is a strict superset of + /// another set of qualifiers, not considering qualifier compatibility. + bool isStrictSupersetOf(Qualifiers Other) const; + bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } @@ -354,7 +362,9 @@ enum CallingConv { CC_X86StdCall, // __attribute__((stdcall)) CC_X86FastCall, // __attribute__((fastcall)) CC_X86ThisCall, // __attribute__((thiscall)) - CC_X86Pascal // __attribute__((pascal)) + CC_X86Pascal, // __attribute__((pascal)) + CC_AAPCS, // __attribute__((pcs("aapcs"))) + CC_AAPCS_VFP // __attribute__((pcs("aapcs-vfp"))) }; typedef std::pair SplitQualType; @@ -598,8 +608,14 @@ class QualType { /// ASTContext::getUnqualifiedArrayType. inline SplitQualType getSplitUnqualifiedType() const; + /// \brief Determine whether this type is more qualified than the other + /// given type, requiring exact equality for non-CVR qualifiers. bool isMoreQualifiedThan(QualType Other) const; + + /// \brief Determine whether this type is at least as qualified as the other + /// given type, requiring exact equality for non-CVR qualifiers. bool isAtLeastAsQualifiedAs(QualType Other) const; + QualType getNonReferenceType() const; /// \brief Determine the type of a (typically non-lvalue) expression with the @@ -1163,6 +1179,20 @@ class Type : public ExtQualsTypeCommonBase { /// (C++0x [basic.types]p10) bool isLiteralType() const; + /// isTrivialType - Return true if this is a trivial type + /// (C++0x [basic.types]p9) + bool isTrivialType() const; + + /// \brief Test if this type is a standard-layout type. + /// (C++0x [basic.type]p9) + bool isStandardLayoutType() const; + + /// isCXX11PODType() - Return true if this is a POD type according to the + /// more relaxed rules of the C++11 standard, regardless of the current + /// compilation's language. + /// (C++0x [basic.types]p9) + bool isCXX11PODType() const; + /// Helper methods to distinguish type categories. All type predicates /// operate on the canonical type, ignoring typedefs and qualifiers. @@ -1178,6 +1208,9 @@ class Type : public ExtQualsTypeCommonBase { /// BuiltinTypes. bool isPlaceholderType() const; + /// isSpecificPlaceholderType - Test for a specific placeholder type. + bool isSpecificPlaceholderType(unsigned K) const; + /// isIntegerType() does *not* include complex integers (a GCC extension). /// isComplexIntegerType() can be used to test for complex integers. bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) @@ -1207,6 +1240,8 @@ class Type : public ExtQualsTypeCommonBase { bool isDerivedType() const; // C99 6.2.5p20 bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers) bool isAggregateType() const; + bool isFundamentalType() const; + bool isCompoundType() const; // Type Predicates: Check to see if this type is structurally the specified // type, ignoring typedefs and qualifiers. @@ -1321,6 +1356,7 @@ class Type : public ExtQualsTypeCommonBase { // for object declared using an interface. const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; + const ObjCObjectPointerType *getAsObjCQualifiedClassType() const; const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; const CXXRecordDecl *getCXXRecordDeclForPointerType() const; @@ -1475,25 +1511,52 @@ class BuiltinType : public Type { NullPtr, // This is the type of C++0x 'nullptr'. + /// The primitive Objective C 'id' type. The user-visible 'id' + /// type is a typedef of an ObjCObjectPointerType to an + /// ObjCObjectType with this as its base. In fact, this only ever + /// shows up in an AST as the base type of an ObjCObjectType. + ObjCId, + + /// The primitive Objective C 'Class' type. The user-visible + /// 'Class' type is a typedef of an ObjCObjectPointerType to an + /// ObjCObjectType with this as its base. In fact, this only ever + /// shows up in an AST as the base type of an ObjCObjectType. + ObjCClass, + + /// The primitive Objective C 'SEL' type. The user-visible 'SEL' + /// type is a typedef of a PointerType to this. + ObjCSel, + /// This represents the type of an expression whose type is /// totally unknown, e.g. 'T::foo'. It is permitted for this to /// appear in situations where the structure of the type is /// theoretically deducible. Dependent, - Overload, // This represents the type of an overloaded function declaration. + /// The type of an unresolved overload set. A placeholder type. + /// Expressions with this type have one of the following basic + /// forms, with parentheses generally permitted: + /// foo # possibly qualified, not if an implicit access + /// foo # possibly qualified, not if an implicit access + /// &foo # possibly qualified, not if an implicit access + /// x->foo # only if might be a static member function + /// &x->foo # only if might be a static member function + /// &Class::foo # when a pointer-to-member; sub-expr also has this type + /// OverloadExpr::find can be used to analyze the expression. + Overload, - /// The primitive Objective C 'id' type. The type pointed to by the - /// user-visible 'id' type. Only ever shows up in an AST as the base - /// type of an ObjCObjectType. - ObjCId, + /// The type of a bound C++ non-static member function. + /// A placeholder type. Expressions with this type have one of the + /// following basic forms: + /// foo # if an implicit access + /// x->foo # if only contains non-static members + BoundMember, - /// The primitive Objective C 'Class' type. The type pointed to by the - /// user-visible 'Class' type. Only ever shows up in an AST as the - /// base type of an ObjCObjectType. - ObjCClass, - - ObjCSel // This represents the ObjC 'SEL' type. + /// __builtin_any_type. A placeholder type. Useful for clients + /// like debuggers that don't know what type to give something. + /// Only a small number of operations are valid on expressions of + /// unknown type, most notably explicit casts. + UnknownAny }; public: @@ -1526,11 +1589,11 @@ class BuiltinType : public Type { return getKind() >= Float && getKind() <= LongDouble; } - /// Determines whether this type is a "forbidden" placeholder type, - /// i.e. a type which cannot appear in arbitrary positions in a - /// fully-formed expression. + /// Determines whether this type is a placeholder type, i.e. a type + /// which cannot appear in arbitrary positions in a fully-formed + /// expression. bool isPlaceholderType() const { - return getKind() == Overload; + return getKind() >= Overload; } static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } @@ -1991,7 +2054,7 @@ class VariableArrayType : public ArrayType { friend class StmtIteratorBase; void Profile(llvm::FoldingSetNodeID &ID) { - assert(0 && "Cannnot unique VariableArrayTypes."); + assert(0 && "Cannot unique VariableArrayTypes."); } }; @@ -2257,12 +2320,13 @@ class FunctionType : public Type { // you'll need to adjust both the Bits field below and // Type::FunctionTypeBitfields. - // | CC |noreturn|regparm - // |0 .. 2| 3 |4 .. 6 + // | CC |noreturn|hasregparm|regparm + // |0 .. 2| 3 | 4 |5 .. 7 enum { CallConvMask = 0x7 }; enum { NoReturnMask = 0x8 }; + enum { HasRegParmMask = 0x10 }; enum { RegParmMask = ~(CallConvMask | NoReturnMask), - RegParmOffset = 4 }; + RegParmOffset = 5 }; unsigned char Bits; @@ -2273,9 +2337,10 @@ class FunctionType : public Type { public: // Constructor with no defaults. Use this when you know that you // have all the elements (when reading an AST file for example). - ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) { + ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc) { Bits = ((unsigned) cc) | (noReturn ? NoReturnMask : 0) | + (hasRegParm ? HasRegParmMask : 0) | (regParm << RegParmOffset); } @@ -2284,6 +2349,7 @@ class FunctionType : public Type { ExtInfo() : Bits(0) {} bool getNoReturn() const { return Bits & NoReturnMask; } + bool getHasRegParm() const { return Bits & HasRegParmMask; } unsigned getRegParm() const { return Bits >> RegParmOffset; } CallingConv getCC() const { return CallingConv(Bits & CallConvMask); } @@ -2305,7 +2371,7 @@ class FunctionType : public Type { } ExtInfo withRegParm(unsigned RegParm) const { - return ExtInfo((Bits & ~RegParmMask) | (RegParm << RegParmOffset)); + return ExtInfo(HasRegParmMask | (Bits & ~RegParmMask) | (RegParm << RegParmOffset)); } ExtInfo withCallingConv(CallingConv cc) const { @@ -2341,7 +2407,8 @@ class FunctionType : public Type { public: QualType getResultType() const { return ResultType; } - + + bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } unsigned getRegParmType() const { return getExtInfo().getRegParm(); } bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } CallingConv getCallConv() const { return getExtInfo().getCC(); } @@ -2403,17 +2470,17 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { /// ExtProtoInfo - Extra information about a function prototype. struct ExtProtoInfo { ExtProtoInfo() : - Variadic(false), HasExceptionSpec(false), HasAnyExceptionSpec(false), - TypeQuals(0), RefQualifier(RQ_None), NumExceptions(0), Exceptions(0) {} + Variadic(false), ExceptionSpecType(EST_None), TypeQuals(0), + RefQualifier(RQ_None), NumExceptions(0), Exceptions(0), NoexceptExpr(0) {} FunctionType::ExtInfo ExtInfo; bool Variadic; - bool HasExceptionSpec; - bool HasAnyExceptionSpec; + ExceptionSpecificationType ExceptionSpecType; unsigned char TypeQuals; RefQualifierKind RefQualifier; unsigned NumExceptions; const QualType *Exceptions; + Expr *NoexceptExpr; }; private: @@ -2435,13 +2502,10 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { unsigned NumArgs : 20; /// NumExceptions - The number of types in the exception spec, if any. - unsigned NumExceptions : 10; + unsigned NumExceptions : 9; - /// HasExceptionSpec - Whether this function has an exception spec at all. - unsigned HasExceptionSpec : 1; - - /// HasAnyExceptionSpec - Whether this function has a throw(...) spec. - unsigned HasAnyExceptionSpec : 1; + /// ExceptionSpecType - The type of exception specification this function has. + unsigned ExceptionSpecType : 3; /// ArgInfo - There is an variable size array after the class in memory that /// holds the argument types. @@ -2449,6 +2513,9 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { /// Exceptions - There is another variable size array after ArgInfo that /// holds the exception types. + /// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing + /// to the expression in the noexcept() specifier. + friend class ASTContext; // ASTContext creates these. public: @@ -2462,29 +2529,66 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { ExtProtoInfo EPI; EPI.ExtInfo = getExtInfo(); EPI.Variadic = isVariadic(); - EPI.HasExceptionSpec = hasExceptionSpec(); - EPI.HasAnyExceptionSpec = hasAnyExceptionSpec(); + EPI.ExceptionSpecType = getExceptionSpecType(); EPI.TypeQuals = static_cast(getTypeQuals()); EPI.RefQualifier = getRefQualifier(); - EPI.NumExceptions = NumExceptions; - EPI.Exceptions = exception_begin(); + if (EPI.ExceptionSpecType == EST_Dynamic) { + EPI.NumExceptions = NumExceptions; + EPI.Exceptions = exception_begin(); + } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + EPI.NoexceptExpr = getNoexceptExpr(); + } return EPI; } - bool hasExceptionSpec() const { return HasExceptionSpec; } - bool hasAnyExceptionSpec() const { return HasAnyExceptionSpec; } + /// \brief Get the kind of exception specification on this function. + ExceptionSpecificationType getExceptionSpecType() const { + return static_cast(ExceptionSpecType); + } + /// \brief Return whether this function has any kind of exception spec. + bool hasExceptionSpec() const { + return getExceptionSpecType() != EST_None; + } + /// \brief Return whether this function has a dynamic (throw) exception spec. + bool hasDynamicExceptionSpec() const { + return isDynamicExceptionSpec(getExceptionSpecType()); + } + /// \brief Return whether this function has a noexcept exception spec. + bool hasNoexceptExceptionSpec() const { + return isNoexceptExceptionSpec(getExceptionSpecType()); + } + /// \brief Result type of getNoexceptSpec(). + enum NoexceptResult { + NR_NoNoexcept, ///< There is no noexcept specifier. + NR_BadNoexcept, ///< The noexcept specifier has a bad expression. + NR_Dependent, ///< The noexcept specifier is dependent. + NR_Throw, ///< The noexcept specifier evaluates to false. + NR_Nothrow ///< The noexcept specifier evaluates to true. + }; + /// \brief Get the meaning of the noexcept spec on this function, if any. + NoexceptResult getNoexceptSpec(ASTContext &Ctx) const; unsigned getNumExceptions() const { return NumExceptions; } QualType getExceptionType(unsigned i) const { assert(i < NumExceptions && "Invalid exception number!"); return exception_begin()[i]; } - bool hasEmptyExceptionSpec() const { - return hasExceptionSpec() && !hasAnyExceptionSpec() && - getNumExceptions() == 0; + Expr *getNoexceptExpr() const { + if (getExceptionSpecType() != EST_ComputedNoexcept) + return 0; + // NoexceptExpr sits where the arguments end. + return *reinterpret_cast(arg_type_end()); + } + bool isNothrow(ASTContext &Ctx) const { + ExceptionSpecificationType EST = getExceptionSpecType(); + if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) + return true; + if (EST != EST_ComputedNoexcept) + return false; + return getNoexceptSpec(Ctx) == NR_Nothrow; } using FunctionType::isVariadic; - + /// \brief Determines whether this function prototype contains a /// parameter pack at the end. /// @@ -2513,6 +2617,8 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { return arg_type_end(); } exception_iterator exception_end() const { + if (getExceptionSpecType() != EST_Dynamic) + return exception_begin(); return exception_begin() + NumExceptions; } @@ -2524,10 +2630,10 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { } static bool classof(const FunctionProtoType *) { return true; } - void Profile(llvm::FoldingSetNodeID &ID); + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx); static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, arg_type_iterator ArgTys, unsigned NumArgs, - const ExtProtoInfo &EPI); + const ExtProtoInfo &EPI, const ASTContext &Context); }; @@ -2566,18 +2672,18 @@ class UnresolvedUsingType : public Type { class TypedefType : public Type { - TypedefDecl *Decl; + TypedefNameDecl *Decl; protected: - TypedefType(TypeClass tc, const TypedefDecl *D, QualType can) + TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast(D)) { + Decl(const_cast(D)) { assert(!isa(can) && "Invalid canonical type"); } friend class ASTContext; // ASTContext creates these. public: - TypedefDecl *getDecl() const { return Decl; } + TypedefNameDecl *getDecl() const { return Decl; } bool isSugared() const { return true; } QualType desugar() const; @@ -2807,9 +2913,10 @@ class AttributedType : public Type, public llvm::FoldingSetNode { // Enumerated operand (string or keyword). attr_objc_gc, + attr_pcs, FirstEnumOperandKind = attr_objc_gc, - LastEnumOperandKind = attr_objc_gc, + LastEnumOperandKind = attr_pcs, // No operand. attr_noreturn, @@ -2864,44 +2971,68 @@ class AttributedType : public Type, public llvm::FoldingSetNode { }; class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { - unsigned Depth : 15; - unsigned ParameterPack : 1; - unsigned Index : 16; - IdentifierInfo *Name; + // Helper data collector for canonical types. + struct CanonicalTTPTInfo { + unsigned Depth : 15; + unsigned ParameterPack : 1; + unsigned Index : 16; + }; - TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N, - QualType Canon) + union { + // Info for the canonical type. + CanonicalTTPTInfo CanTTPTInfo; + // Info for the non-canonical type. + TemplateTypeParmDecl *TTPDecl; + }; + + /// Build a non-canonical type. + TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) : Type(TemplateTypeParm, Canon, /*Dependent=*/true, - /*VariablyModified=*/false, PP), - Depth(D), ParameterPack(PP), Index(I), Name(N) { } + /*VariablyModified=*/false, + Canon->containsUnexpandedParameterPack()), + TTPDecl(TTPDecl) { } + /// Build the canonical type. TemplateTypeParmType(unsigned D, unsigned I, bool PP) : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true, - /*VariablyModified=*/false, PP), - Depth(D), ParameterPack(PP), Index(I), Name(0) { } + /*VariablyModified=*/false, PP) { + CanTTPTInfo.Depth = D; + CanTTPTInfo.Index = I; + CanTTPTInfo.ParameterPack = PP; + } friend class ASTContext; // ASTContext creates these + const CanonicalTTPTInfo& getCanTTPTInfo() const { + QualType Can = getCanonicalTypeInternal(); + return Can->castAs()->CanTTPTInfo; + } + public: - unsigned getDepth() const { return Depth; } - unsigned getIndex() const { return Index; } - bool isParameterPack() const { return ParameterPack; } - IdentifierInfo *getName() const { return Name; } + unsigned getDepth() const { return getCanTTPTInfo().Depth; } + unsigned getIndex() const { return getCanTTPTInfo().Index; } + bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; } + + TemplateTypeParmDecl *getDecl() const { + return isCanonicalUnqualified() ? 0 : TTPDecl; + } + + IdentifierInfo *getIdentifier() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Depth, Index, ParameterPack, Name); + Profile(ID, getDepth(), getIndex(), isParameterPack(), getDecl()); } static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name) { + TemplateTypeParmDecl *TTPDecl) { ID.AddInteger(Depth); ID.AddInteger(Index); ID.AddBoolean(ParameterPack); - ID.AddPointer(Name); + ID.AddPointer(TTPDecl); } static bool classof(const Type *T) { @@ -2930,8 +3061,6 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { friend class ASTContext; public: - IdentifierInfo *getName() const { return Replaced->getName(); } - /// Gets the template parameter that was substituted for. const TemplateTypeParmType *getReplacedParameter() const { return Replaced; @@ -2992,7 +3121,7 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { friend class ASTContext; public: - IdentifierInfo *getName() const { return Replaced->getName(); } + IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); } /// Gets the template parameter that was substituted for. const TemplateTypeParmType *getReplacedParameter() const { @@ -4064,12 +4193,6 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { return getFunctionExtInfo(*t); } -/// \brief Determine whether this set of qualifiers is a superset of the given -/// set of qualifiers. -inline bool Qualifiers::isSupersetOf(Qualifiers Other) const { - return Mask != Other.Mask && (Mask | Other.Mask) == Mask; -} - /// isMoreQualifiedThan - Determine whether this type is more /// qualified than the Other type. For example, "const volatile int" /// is more qualified than "const int", "volatile int", and @@ -4105,6 +4228,40 @@ inline QualType QualType::getNonReferenceType() const { return *this; } +/// \brief Tests whether the type is categorized as a fundamental type. +/// +/// \returns True for types specified in C++0x [basic.fundamental]. +inline bool Type::isFundamentalType() const { + return isVoidType() || + // FIXME: It's really annoying that we don't have an + // 'isArithmeticType()' which agrees with the standard definition. + (isArithmeticType() && !isEnumeralType()); +} + +/// \brief Tests whether the type is categorized as a compound type. +/// +/// \returns True for types specified in C++0x [basic.compound]. +inline bool Type::isCompoundType() const { + // C++0x [basic.compound]p1: + // Compound types can be constructed in the following ways: + // -- arrays of objects of a given type [...]; + return isArrayType() || + // -- functions, which have parameters of given types [...]; + isFunctionType() || + // -- pointers to void or objects or functions [...]; + isPointerType() || + // -- references to objects or functions of a given type. [...] + isReferenceType() || + // -- classes containing a sequence of objects of various types, [...]; + isRecordType() || + // -- unions, which ar classes capable of containing objects of different types at different times; + isUnionType() || + // -- enumerations, which comprise a set of named constant values. [...]; + isEnumeralType() || + // -- pointers to non-static class members, [...]. + isMemberPointerType(); +} + inline bool Type::isFunctionType() const { return isa(CanonicalType); } @@ -4236,6 +4393,12 @@ inline bool Type::isPlaceholderType() const { return false; } +inline bool Type::isSpecificPlaceholderType(unsigned K) const { + if (const BuiltinType *BT = dyn_cast(this)) + return (BT->getKind() == (BuiltinType::Kind) K); + return false; +} + /// \brief Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h index c7f5ee76330c..a1df744c2a72 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h +++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h @@ -527,7 +527,7 @@ class TypedefTypeLoc : public InheritingConcreteTypeLoc { public: - TypedefDecl *getTypedefDecl() const { + TypedefNameDecl *getTypedefNameDecl() const { return getTypePtr()->getDecl(); } }; @@ -584,6 +584,8 @@ class TemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc { +public: + TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } }; /// \brief Wrapper for substituted template type parameters. @@ -943,10 +945,14 @@ class BlockPointerTypeLoc : public PointerLikeTypeLoc { + MemberPointerType, + MemberPointerLocInfo> { public: SourceLocation getStarLoc() const { return getSigilLoc(); @@ -954,6 +960,28 @@ class MemberPointerTypeLoc : public PointerLikeTypeLocgetClass(); + } + TypeSourceInfo *getClassTInfo() const { + return getLocalData()->ClassTInfo; + } + void setClassTInfo(TypeSourceInfo* TI) { + getLocalData()->ClassTInfo = TI; + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setSigilLoc(Loc); + setClassTInfo(0); + } + + SourceRange getLocalSourceRange() const { + if (TypeSourceInfo *TI = getClassTInfo()) + return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc()); + else + return SourceRange(getStarLoc()); + } }; /// Wraps an ObjCPointerType with source location information. @@ -1007,7 +1035,8 @@ class RValueReferenceTypeLoc : struct FunctionLocInfo { - SourceLocation LParenLoc, RParenLoc; + SourceLocation LocalRangeBegin; + SourceLocation LocalRangeEnd; bool TrailingReturn; }; @@ -1017,18 +1046,18 @@ class FunctionTypeLoc : public ConcreteTypeLoc { public: - SourceLocation getLParenLoc() const { - return getLocalData()->LParenLoc; + SourceLocation getLocalRangeBegin() const { + return getLocalData()->LocalRangeBegin; } - void setLParenLoc(SourceLocation Loc) { - getLocalData()->LParenLoc = Loc; + void setLocalRangeBegin(SourceLocation L) { + getLocalData()->LocalRangeBegin = L; } - SourceLocation getRParenLoc() const { - return getLocalData()->RParenLoc; + SourceLocation getLocalRangeEnd() const { + return getLocalData()->LocalRangeEnd; } - void setRParenLoc(SourceLocation Loc) { - getLocalData()->RParenLoc = Loc; + void setLocalRangeEnd(SourceLocation L) { + getLocalData()->LocalRangeEnd = L; } bool getTrailingReturn() const { @@ -1056,12 +1085,12 @@ class FunctionTypeLoc : public ConcreteTypeLocgetLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; + NestedNameSpecifierLoc getQualifierLoc() const { + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceRange getLocalSourceRange() const { if (getKeywordLoc().isValid()) - if (getQualifierRange().getEnd().isValid()) - return SourceRange(getKeywordLoc(), getQualifierRange().getEnd()); + if (getQualifierLoc()) + return SourceRange(getKeywordLoc(), getQualifierLoc().getEndLoc()); else return SourceRange(getKeywordLoc()); else - return getQualifierRange(); + return getQualifierLoc().getSourceRange(); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); - setQualifierRange(SourceRange(Loc)); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); TypeLoc getNamedTypeLoc() const { return getInnerTypeLoc(); @@ -1444,6 +1478,9 @@ class ElaboratedTypeLoc : public ConcreteTypeLocgetLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; + NestedNameSpecifierLoc getQualifierLoc() const { + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } - + SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } @@ -1476,7 +1518,7 @@ class DependentNameTypeLoc : public ConcreteTypeLocgetLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; + NestedNameSpecifierLoc getQualifierLoc() const { + if (!getLocalData()->QualifierData) + return NestedNameSpecifierLoc(); + + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + if (!QualifierLoc) { + // Even if we have a nested-name-specifier in the dependent + // template specialization type, we won't record the nested-name-specifier + // location information when this type-source location information is + // part of a nested-name-specifier. + getLocalData()->QualifierData = 0; + return; + } + + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceLocation getNameLoc() const { @@ -1559,8 +1613,10 @@ class DependentTemplateSpecializationTypeLoc : SourceRange getLocalSourceRange() const { if (getKeywordLoc().isValid()) return SourceRange(getKeywordLoc(), getRAngleLoc()); + else if (getQualifierLoc()) + return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc()); else - return SourceRange(getQualifierRange().getBegin(), getRAngleLoc()); + return SourceRange(getNameLoc(), getRAngleLoc()); } void copy(DependentTemplateSpecializationTypeLoc Loc) { @@ -1569,16 +1625,7 @@ class DependentTemplateSpecializationTypeLoc : memcpy(Data, Loc.Data, size); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); - setQualifierRange(SourceRange(Loc)); - setNameLoc(Loc); - setLAngleLoc(Loc); - setRAngleLoc(Loc); - TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), - getTypePtr()->getArgs(), - getArgInfos(), Loc); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); unsigned getExtraLocalDataSize() const { return getNumArgs() * sizeof(TemplateArgumentLocInfo); diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h index 72f644aaf028..a61d9e47881d 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h @@ -29,13 +29,13 @@ class CFGBlock; // tend to have a common destination, so we lazily do a predecessor search // from the destination node and cache the results to prevent work // duplication. -class CFGReachabilityAnalysis { +class CFGReverseBlockReachabilityAnalysis { typedef llvm::BitVector ReachableSet; typedef llvm::DenseMap ReachableMap; ReachableSet analyzed; ReachableMap reachable; public: - CFGReachabilityAnalysis(const CFG &cfg); + CFGReverseBlockReachabilityAnalysis(const CFG &cfg); /// Returns true if the block 'Dst' can be reached from block 'Src'. bool isReachable(const CFGBlock *Src, const CFGBlock *Dst); diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h index cd771acb06a5..b966f3a90fff 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h @@ -1,4 +1,4 @@ -//===- UninitializedValues.h - unintialized values analysis ----*- C++ --*-===// +//= UninitializedValues.h - Finding uses of uninitialized values --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -7,71 +7,35 @@ // //===----------------------------------------------------------------------===// // -// This file provides the interface for the Unintialized Values analysis, -// a flow-sensitive analysis that detects when variable values are unintialized. +// This file defines APIs for invoking and reported uninitialized values +// warnings. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_UNITVALS_H -#define LLVM_CLANG_UNITVALS_H - -#include "clang/Analysis/Support/BlkExprDeclBitVector.h" -#include "clang/Analysis/FlowSensitive/DataflowValues.h" +#ifndef LLVM_CLANG_UNINIT_VALS_H +#define LLVM_CLANG_UNINIT_VALS_H namespace clang { - class BlockVarDecl; - class Expr; - class DeclRefExpr; - class VarDecl; - -/// UninitializedValues_ValueTypes - Utility class to wrap type declarations -/// for dataflow values and dataflow analysis state for the -/// Unitialized Values analysis. -class UninitializedValues_ValueTypes { +class AnalysisContext; +class CFG; +class DeclContext; +class Expr; +class VarDecl; + +class UninitVariablesHandler { public: - - struct ObserverTy; - - struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy { - AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {} - virtual ~AnalysisDataTy() {} - - ObserverTy* Observer; - bool FullUninitTaint; - }; - - typedef StmtDeclBitVector_Types::ValTy ValTy; - - //===--------------------------------------------------------------------===// - // ObserverTy - Observer for querying DeclRefExprs that use an uninitalized - // value. - //===--------------------------------------------------------------------===// - - struct ObserverTy { - virtual ~ObserverTy(); - virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD, - DeclRefExpr* DR, VarDecl* VD) = 0; - }; + UninitVariablesHandler() {} + virtual ~UninitVariablesHandler(); + + virtual void handleUseOfUninitVariable(const Expr *ex, + const VarDecl *vd, + bool isAlwaysUninit) {} }; + +void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, + AnalysisContext &ac, + UninitVariablesHandler &handler); -/// UninitializedValues - Objects of this class encapsulate dataflow analysis -/// information regarding what variable declarations in a function are -/// potentially unintialized. -class UninitializedValues : - public DataflowValues { -public: - typedef UninitializedValues_ValueTypes::ObserverTy ObserverTy; - - UninitializedValues(CFG &cfg) { getAnalysisData().setCFG(cfg); } - - /// IntializeValues - Create initial dataflow values and meta data for - /// a given CFG. This is intended to be called by the dataflow solver. - void InitializeValues(const CFG& cfg); -}; - - -void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags, - bool FullUninitTaint=false); -} // end namespace clang +} #endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValuesV2.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValuesV2.h deleted file mode 100644 index c1fe040793e1..000000000000 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValuesV2.h +++ /dev/null @@ -1,40 +0,0 @@ -//= UninitializedValuesV2.h - Finding uses of uninitialized values --*- 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 APIs for invoking and reported uninitialized values -// warnings. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_UNINIT_VALS_H -#define LLVM_CLANG_UNINIT_VALS_H - -namespace clang { - -class AnalysisContext; -class CFG; -class DeclContext; -class Expr; -class VarDecl; - -class UninitVariablesHandler { -public: - UninitVariablesHandler() {} - virtual ~UninitVariablesHandler(); - - virtual void handleUseOfUninitVariable(const Expr *ex, - const VarDecl *vd) {} -}; - -void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, - AnalysisContext &ac, - UninitVariablesHandler &handler); - -} -#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h index 851451457881..66c12a5384d4 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/Analysis/CFG.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" @@ -27,9 +28,7 @@ namespace clang { class Decl; class Stmt; -class CFG; -class CFGBlock; -class CFGReachabilityAnalysis; +class CFGReverseBlockReachabilityAnalysis; class CFGStmtMap; class LiveVariables; class ParentMap; @@ -48,33 +47,32 @@ class AnalysisContext { // TranslationUnit is NULL if we don't have multiple translation units. idx::TranslationUnit *TU; - // AnalysisContext owns the following data. - CFG *cfg, *completeCFG; - CFGStmtMap *cfgStmtMap; + llvm::OwningPtr cfg, completeCFG; + llvm::OwningPtr cfgStmtMap; + + CFG::BuildOptions cfgBuildOptions; + CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; + bool builtCFG, builtCompleteCFG; - LiveVariables *liveness; - LiveVariables *relaxedLiveness; - ParentMap *PM; - PseudoConstantAnalysis *PCA; - CFGReachabilityAnalysis *CFA; - llvm::DenseMap *ReferencedBlockVars; + const bool useUnoptimizedCFG; + + llvm::OwningPtr liveness; + llvm::OwningPtr relaxedLiveness; + llvm::OwningPtr PM; + llvm::OwningPtr PCA; + llvm::OwningPtr CFA; + llvm::BumpPtrAllocator A; - bool UseUnoptimizedCFG; - bool AddEHEdges; - bool AddImplicitDtors; - bool AddInitializers; + + // FIXME: remove. + llvm::DenseMap *ReferencedBlockVars; + public: AnalysisContext(const Decl *d, idx::TranslationUnit *tu, bool useUnoptimizedCFG = false, bool addehedges = false, bool addImplicitDtors = false, - bool addInitializers = false) - : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0), - builtCFG(false), builtCompleteCFG(false), - liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0), - ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG), - AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors), - AddInitializers(addInitializers) {} + bool addInitializers = false); ~AnalysisContext(); @@ -87,18 +85,22 @@ class AnalysisContext { /// callExprs. If this is false, then try/catch statements and blocks /// reachable from them can appear to be dead in the CFG, analysis passes must /// cope with that. - bool getAddEHEdges() const { return AddEHEdges; } - - bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; } - bool getAddImplicitDtors() const { return AddImplicitDtors; } - bool getAddInitializers() const { return AddInitializers; } + bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } + bool getUseUnoptimizedCFG() const { + return cfgBuildOptions.PruneTriviallyFalseEdges; + } + bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } + bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } + void registerForcedBlockExpression(const Stmt *stmt); + const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); + Stmt *getBody(); CFG *getCFG(); CFGStmtMap *getCFGStmtMap(); - CFGReachabilityAnalysis *getCFGReachablityAnalysis(); + CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis(); /// Return a version of the CFG without any edges pruned. CFG *getUnoptimizedCFG(); diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h index 295d0a2133d3..dbf4e4c9aefe 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define ANALYSISSTART #include "clang/Basic/DiagnosticAnalysisKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h index b337d74495c9..ca46459afd9a 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h @@ -19,6 +19,8 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/DenseMap.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/Basic/SourceLocation.h" #include @@ -29,6 +31,7 @@ namespace llvm { } namespace clang { + class CXXDestructorDecl; class Decl; class Stmt; class Expr; @@ -47,45 +50,45 @@ class CFGElement { public: enum Kind { // main kind + Invalid, Statement, Initializer, - ImplicitDtor, // dtor kind AutomaticObjectDtor, BaseDtor, MemberDtor, TemporaryDtor, - DTOR_BEGIN = AutomaticObjectDtor + DTOR_BEGIN = AutomaticObjectDtor, + DTOR_END = TemporaryDtor }; protected: - // The int bits are used to mark the main kind. + // The int bits are used to mark the kind. llvm::PointerIntPair Data1; - // The int bits are used to mark the dtor kind. llvm::PointerIntPair Data2; - CFGElement(void *Ptr, unsigned Int) : Data1(Ptr, Int) {} - CFGElement(void *Ptr1, unsigned Int1, void *Ptr2, unsigned Int2) - : Data1(Ptr1, Int1), Data2(Ptr2, Int2) {} + CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0) + : Data1(const_cast(Ptr1), ((unsigned) kind) & 0x3), + Data2(const_cast(Ptr2), (((unsigned) kind) >> 2) & 0x3) {} public: CFGElement() {} - Kind getKind() const { return static_cast(Data1.getInt()); } - - Kind getDtorKind() const { - assert(getKind() == ImplicitDtor); - return static_cast(Data2.getInt() + DTOR_BEGIN); + Kind getKind() const { + unsigned x = Data2.getInt(); + x <<= 2; + x |= Data1.getInt(); + return (Kind) x; } - - bool isValid() const { return Data1.getPointer(); } + + bool isValid() const { return getKind() != Invalid; } operator bool() const { return isValid(); } - - template ElemTy getAs() const { + + template const ElemTy *getAs() const { if (llvm::isa(this)) - return *static_cast(this); - return ElemTy(); + return static_cast(this); + return 0; } static bool classof(const CFGElement *E) { return true; } @@ -93,13 +96,10 @@ class CFGElement { class CFGStmt : public CFGElement { public: - CFGStmt() {} - CFGStmt(Stmt *S) : CFGElement(S, 0) {} + CFGStmt(Stmt *S) : CFGElement(Statement, S) {} Stmt *getStmt() const { return static_cast(Data1.getPointer()); } - operator Stmt*() const { return getStmt(); } - static bool classof(const CFGElement *E) { return E->getKind() == Statement; } @@ -109,14 +109,12 @@ class CFGStmt : public CFGElement { /// constructor's initialization list. class CFGInitializer : public CFGElement { public: - CFGInitializer() {} - CFGInitializer(CXXCtorInitializer* I) - : CFGElement(I, Initializer) {} + CFGInitializer(CXXCtorInitializer *initializer) + : CFGElement(Initializer, initializer) {} CXXCtorInitializer* getInitializer() const { return static_cast(Data1.getPointer()); } - operator CXXCtorInitializer*() const { return getInitializer(); } static bool classof(const CFGElement *E) { return E->getKind() == Initializer; @@ -127,14 +125,18 @@ class CFGInitializer : public CFGElement { /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { protected: - CFGImplicitDtor(unsigned K, void* P, void* S) - : CFGElement(P, ImplicitDtor, S, K - DTOR_BEGIN) {} + CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0) + : CFGElement(kind, data1, data2) { + assert(kind >= DTOR_BEGIN && kind <= DTOR_END); + } public: - CFGImplicitDtor() {} + const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const; + bool isNoReturn(ASTContext &astContext) const; static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor; + Kind kind = E->getKind(); + return kind >= DTOR_BEGIN && kind <= DTOR_END; } }; @@ -143,22 +145,20 @@ class CFGImplicitDtor : public CFGElement { /// of leaving its local scope. class CFGAutomaticObjDtor: public CFGImplicitDtor { public: - CFGAutomaticObjDtor() {} - CFGAutomaticObjDtor(VarDecl* VD, Stmt* S) - : CFGImplicitDtor(AutomaticObjectDtor, VD, S) {} + CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt) + : CFGImplicitDtor(AutomaticObjectDtor, var, stmt) {} - VarDecl* getVarDecl() const { + const VarDecl *getVarDecl() const { return static_cast(Data1.getPointer()); } // Get statement end of which triggered the destructor call. - Stmt* getTriggerStmt() const { + const Stmt *getTriggerStmt() const { return static_cast(Data2.getPointer()); } - static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && - E->getDtorKind() == AutomaticObjectDtor; + static bool classof(const CFGElement *elem) { + return elem->getKind() == AutomaticObjectDtor; } }; @@ -166,16 +166,15 @@ class CFGAutomaticObjDtor: public CFGImplicitDtor { /// base object in destructor. class CFGBaseDtor : public CFGImplicitDtor { public: - CFGBaseDtor() {} - CFGBaseDtor(const CXXBaseSpecifier *BS) - : CFGImplicitDtor(BaseDtor, const_cast(BS), NULL) {} + CFGBaseDtor(const CXXBaseSpecifier *base) + : CFGImplicitDtor(BaseDtor, base) {} const CXXBaseSpecifier *getBaseSpecifier() const { return static_cast(Data1.getPointer()); } static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && E->getDtorKind() == BaseDtor; + return E->getKind() == BaseDtor; } }; @@ -183,16 +182,15 @@ class CFGBaseDtor : public CFGImplicitDtor { /// member object in destructor. class CFGMemberDtor : public CFGImplicitDtor { public: - CFGMemberDtor() {} - CFGMemberDtor(FieldDecl *FD) - : CFGImplicitDtor(MemberDtor, FD, NULL) {} + CFGMemberDtor(const FieldDecl *field) + : CFGImplicitDtor(MemberDtor, field, 0) {} - FieldDecl *getFieldDecl() const { - return static_cast(Data1.getPointer()); + const FieldDecl *getFieldDecl() const { + return static_cast(Data1.getPointer()); } static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && E->getDtorKind() == MemberDtor; + return E->getKind() == MemberDtor; } }; @@ -200,16 +198,15 @@ class CFGMemberDtor : public CFGImplicitDtor { /// at the end of full expression for temporary object. class CFGTemporaryDtor : public CFGImplicitDtor { public: - CFGTemporaryDtor() {} - CFGTemporaryDtor(CXXBindTemporaryExpr *E) - : CFGImplicitDtor(TemporaryDtor, E, NULL) {} + CFGTemporaryDtor(CXXBindTemporaryExpr *expr) + : CFGImplicitDtor(TemporaryDtor, expr, 0) {} - CXXBindTemporaryExpr *getBindTemporaryExpr() const { - return static_cast(Data1.getPointer()); + const CXXBindTemporaryExpr *getBindTemporaryExpr() const { + return static_cast(Data1.getPointer()); } static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && E->getDtorKind() == TemporaryDtor; + return E->getKind() == TemporaryDtor; } }; @@ -267,6 +264,8 @@ class CFGTerminator { /// ? operator LHS expression; RHS expression /// &&, || expression that uses result of && or ||, RHS /// +/// But note that any of that may be NULL in case of optimized-out edges. +/// class CFGBlock { class ElementList { typedef BumpVector ImplTy; @@ -471,8 +470,6 @@ class CFGBlock { const Stmt *getLoopTarget() const { return LoopTarget; } - bool hasBinaryBranchTerminator() const; - Stmt* getLabel() { return Label; } const Stmt* getLabel() const { return Label; } @@ -537,13 +534,16 @@ class CFG { class BuildOptions { public: + typedef llvm::DenseMap ForcedBlkExprs; + ForcedBlkExprs **forcedBlkExprs; + bool PruneTriviallyFalseEdges:1; bool AddEHEdges:1; bool AddInitializers:1; bool AddImplicitDtors:1; BuildOptions() - : PruneTriviallyFalseEdges(true) + : forcedBlkExprs(0), PruneTriviallyFalseEdges(true) , AddEHEdges(false) , AddInitializers(false) , AddImplicitDtors(false) {} @@ -552,7 +552,7 @@ class CFG { /// buildCFG - Builds a CFG from an AST. The responsibility to free the /// constructed CFG belongs to the caller. static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C, - BuildOptions BO = BuildOptions()); + const BuildOptions &BO); /// createBlock - Create a new block in the CFG. The CFG owns the block; /// the caller should not directly free it. @@ -607,8 +607,8 @@ class CFG { for (const_iterator I=begin(), E=end(); I != E; ++I) for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end(); BI != BE; ++BI) { - if (CFGStmt S = BI->getAs()) - O(S); + if (const CFGStmt *stmt = BI->getAs()) + O(stmt->getStmt()); } } diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h index 7e6e3815400c..18e81fed79f8 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h @@ -22,7 +22,7 @@ namespace cocoa { enum NamingConvention { NoConvention, CreateRule, InitRule }; - NamingConvention deriveNamingConvention(Selector S, bool ignorePrefix = true); + NamingConvention deriveNamingConvention(Selector S); static inline bool followsFundamentalRule(Selector S) { return deriveNamingConvention(S) == CreateRule; diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h index d75d333db6b6..9561b964b5f8 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -277,8 +277,8 @@ class DataflowSolver { for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) { CFGElement El = *I; - if (CFGStmt S = El.getAs()) - ProcessStmt(S, recordStmtValues, AnalysisDirTag()); + if (const CFGStmt *S = El.getAs()) + ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag()); } TF.VisitTerminator(const_cast(B)); @@ -293,8 +293,8 @@ class DataflowSolver { for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) { CFGElement El = *I; - if (CFGStmt S = El.getAs()) - ProcessStmt(S, recordStmtValues, AnalysisDirTag()); + if (const CFGStmt *S = El.getAs()) + ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag()); } } diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h index 54cfc3dc0db6..07b4dea987de 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h @@ -43,6 +43,7 @@ class ProgramPoint { PostStoreKind, PostPurgeDeadSymbolsKind, PostStmtCustomKind, + PostConditionKind, PostLValueKind, PostInitializerKind, CallEnterKind, @@ -221,7 +222,17 @@ class PostStmtCustom : public PostStmt { } }; - +// PostCondition represents the post program point of a branch condition. +class PostCondition : public PostStmt { +public: + PostCondition(const Stmt* S, const LocationContext *L, const void *tag = 0) + : PostStmt(S, PostConditionKind, L, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostConditionKind; + } +}; + class LocationCheck : public StmtPoint { protected: LocationCheck(const Stmt *S, const LocationContext *L, diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h index d197e69babde..7fb4ab3ebad9 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -82,6 +82,7 @@ class CFGStmtVisitor : public StmtVisitor { DISPATCH_CASE(ConditionalOperator) DISPATCH_CASE(BinaryConditionalOperator) DISPATCH_CASE(ObjCForCollectionStmt) + DISPATCH_CASE(CXXForRangeStmt) case Stmt::BinaryOperatorClass: { BinaryOperator* B = cast(S); @@ -109,6 +110,10 @@ class CFGStmtVisitor : public StmtVisitor { return static_cast(this)->BlockStmt_VisitStmt(S); } + RetTy BlockStmt_VisitCXXForRangeStmt(CXXForRangeStmt* S) { + return static_cast(this)->BlockStmt_VisitStmt(S); + } + RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) { return static_cast(this)->BlockStmt_VisitExpr(E); } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h b/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h new file mode 100644 index 000000000000..d44a9c3b0361 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h @@ -0,0 +1,44 @@ +//===--- AddressSpaces.h - Language-specific address spaces -----*- 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 definitions for the various language-specific address +// spaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H +#define LLVM_CLANG_BASIC_ADDRESSSPACES_H + +namespace clang { + +namespace LangAS { + +/// This enum defines the set of possible language-specific address spaces. +/// It uses a high starting offset so as not to conflict with any address +/// space used by a target. +enum ID { + Offset = 0xFFFF00, + + opencl_global = Offset, + opencl_local, + opencl_constant, + + Last, + Count = Last-Offset +}; + +/// The type of a lookup table which maps from language-specific address spaces +/// to target-specific ones. +typedef unsigned Map[Count]; + +} + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td index 3e62d411d51a..e4c6722e8378 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td @@ -46,6 +46,7 @@ class Argument { string Name = name; } +class BoolArgument : Argument; class IdentifierArgument : Argument; class IntArgument : Argument; class StringArgument : Argument; @@ -55,6 +56,9 @@ class TypeArgument : Argument; class UnsignedArgument : Argument; class VariadicUnsignedArgument : Argument; +// A version of the form major.minor[.subminor]. +class VersionArgument : Argument; + // This one's a doozy, so it gets its own special type // It can be an unsigned integer, or a type. Either can // be dependent. @@ -89,8 +93,13 @@ class Attr { code AdditionalMembers = [{}]; } +/// An inheritable attribute is inherited by later redeclarations. class InheritableAttr : Attr; +/// An inheritable parameter attribute is inherited by later +/// redeclarations, even when it's written on a parameter. +class InheritableParamAttr : InheritableAttr; + // // Attributes begin here // @@ -129,12 +138,26 @@ def AsmLabel : InheritableAttr { let Args = [StringArgument<"Label">]; } +def Availability : InheritableAttr { + let Spellings = ["availability"]; + let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">, + VersionArgument<"deprecated">, VersionArgument<"obsoleted">, + BoolArgument<"unavailable">]; + let AdditionalMembers = +[{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) { + return llvm::StringSwitch(Platform) + .Case("ios", "iOS") + .Case("macosx", "Mac OS X") + .Default(llvm::StringRef()); +} }]; +} + def Blocks : InheritableAttr { let Spellings = ["blocks"]; let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>]; } -def CarriesDependency : InheritableAttr { +def CarriesDependency : InheritableParamAttr { let Spellings = ["carries_dependency"]; let Subjects = [ParmVar, Function]; let Namespaces = ["", "std"]; @@ -154,7 +177,7 @@ def CFReturnsNotRetained : InheritableAttr { let Subjects = [ObjCMethod, Function]; } -def CFConsumed : InheritableAttr { +def CFConsumed : InheritableParamAttr { let Spellings = ["cf_consumed"]; let Subjects = [ParmVar]; } @@ -224,10 +247,6 @@ def DLLImport : InheritableAttr { let Spellings = ["dllimport"]; } -def Explicit : InheritableAttr { - let Spellings = []; -} - def FastCall : InheritableAttr { let Spellings = ["fastcall", "__fastcall"]; } @@ -236,6 +255,10 @@ def Final : InheritableAttr { let Spellings = []; } +def MsStruct : InheritableAttr { + let Spellings = ["__ms_struct__"]; +} + def Format : InheritableAttr { let Spellings = ["format"]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, @@ -261,7 +284,7 @@ def IBOutlet : InheritableAttr { def IBOutletCollection : InheritableAttr { let Spellings = ["iboutletcollection"]; - let Args = [TypeArgument<"Interface">]; + let Args = [TypeArgument<"InterFace">]; } def Malloc : InheritableAttr { @@ -355,7 +378,7 @@ def NSConsumesSelf : InheritableAttr { let Subjects = [ObjCMethod]; } -def NSConsumed : InheritableAttr { +def NSConsumed : InheritableParamAttr { let Spellings = ["ns_consumed"]; let Subjects = [ParmVar]; } @@ -364,6 +387,15 @@ def ObjCException : InheritableAttr { let Spellings = ["objc_exception"]; } +def ObjCMethodFamily : InheritableAttr { + let Spellings = ["objc_method_family"]; + let Subjects = [ObjCMethod]; + let Args = [EnumArgument<"Family", "FamilyKind", + ["none", "alloc", "copy", "init", "mutableCopy", "new"], + ["OMF_None", "OMF_alloc", "OMF_copy", "OMF_init", + "OMF_mutableCopy", "OMF_new"]>]; +} + def ObjCNSObject : InheritableAttr { let Spellings = ["NSObject"]; } @@ -388,6 +420,13 @@ def Packed : InheritableAttr { let Spellings = ["packed"]; } +def Pcs : InheritableAttr { + let Spellings = ["pcs"]; + let Args = [EnumArgument<"PCS", "PCSType", + ["aapcs", "aapcs-vfp"], + ["AAPCS", "AAPCS_VFP"]>]; +} + def Pure : InheritableAttr { let Spellings = ["pure"]; } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h index 65c4f98c952c..9d5ae588c50f 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h @@ -22,6 +22,7 @@ namespace attr { enum Kind { #define ATTR(X) X, #define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X, +#define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = X, #include "clang/Basic/AttrList.inc" NUM_ATTRS }; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def index b73ac1f4dd45..9a4c768dc649 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def @@ -443,7 +443,7 @@ BUILTIN(__builtin_dwarf_sp_column, "Ui", "n") BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t // GCC Object size checking builtins -BUILTIN(__builtin_object_size, "zv*i", "n") +BUILTIN(__builtin_object_size, "zvC*i", "n") BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___mempcpy_chk, "v*v*vC*zz", "nF") @@ -577,6 +577,13 @@ BUILTIN(__sync_lock_release_4, "viD*.", "n") BUILTIN(__sync_lock_release_8, "vLLiD*.", "n") BUILTIN(__sync_lock_release_16, "vLLLiD*.", "n") +BUILTIN(__sync_swap, "v.", "") +BUILTIN(__sync_swap_1, "ccD*c.", "n") +BUILTIN(__sync_swap_2, "ssD*s.", "n") +BUILTIN(__sync_swap_4, "iiD*i.", "n") +BUILTIN(__sync_swap_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_swap_16, "LLLiLLLiD*LLLi.", "n") + // Non-overloaded atomic builtins. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPTX.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPTX.def new file mode 100644 index 000000000000..f90a43f7f404 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPTX.def @@ -0,0 +1,62 @@ +//===--- BuiltinsPTX.def - PTX Builtin function database ----*- 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 PTX-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +BUILTIN(__builtin_ptx_read_tid_x, "i", "nc") +BUILTIN(__builtin_ptx_read_tid_y, "i", "nc") +BUILTIN(__builtin_ptx_read_tid_z, "i", "nc") +BUILTIN(__builtin_ptx_read_tid_w, "i", "nc") + +BUILTIN(__builtin_ptx_read_ntid_x, "i", "nc") +BUILTIN(__builtin_ptx_read_ntid_y, "i", "nc") +BUILTIN(__builtin_ptx_read_ntid_z, "i", "nc") +BUILTIN(__builtin_ptx_read_ntid_w, "i", "nc") + +BUILTIN(__builtin_ptx_read_ctaid_x, "i", "nc") +BUILTIN(__builtin_ptx_read_ctaid_y, "i", "nc") +BUILTIN(__builtin_ptx_read_ctaid_z, "i", "nc") +BUILTIN(__builtin_ptx_read_ctaid_w, "i", "nc") + +BUILTIN(__builtin_ptx_read_nctaid_x, "i", "nc") +BUILTIN(__builtin_ptx_read_nctaid_y, "i", "nc") +BUILTIN(__builtin_ptx_read_nctaid_z, "i", "nc") +BUILTIN(__builtin_ptx_read_nctaid_w, "i", "nc") + +BUILTIN(__builtin_ptx_read_laneid, "i", "nc") +BUILTIN(__builtin_ptx_read_warpid, "i", "nc") +BUILTIN(__builtin_ptx_read_nwarpid, "i", "nc") + +BUILTIN(__builtin_ptx_read_smid, "i", "nc") +BUILTIN(__builtin_ptx_read_nsmid, "i", "nc") +BUILTIN(__builtin_ptx_read_gridid, "i", "nc") + +BUILTIN(__builtin_ptx_read_lanemask_eq, "i", "nc") +BUILTIN(__builtin_ptx_read_lanemask_le, "i", "nc") +BUILTIN(__builtin_ptx_read_lanemask_lt, "i", "nc") +BUILTIN(__builtin_ptx_read_lanemask_ge, "i", "nc") +BUILTIN(__builtin_ptx_read_lanemask_gt, "i", "nc") + +BUILTIN(__builtin_ptx_read_clock, "i", "n") +BUILTIN(__builtin_ptx_read_clock64, "Li", "n") + +BUILTIN(__builtin_ptx_read_pm0, "i", "n") +BUILTIN(__builtin_ptx_read_pm1, "i", "n") +BUILTIN(__builtin_ptx_read_pm2, "i", "n") +BUILTIN(__builtin_ptx_read_pm3, "i", "n") + +BUILTIN(__builtin_ptx_bar_sync, "vi", "n") + + +#undef BUILTIN diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def index da106daf26ec..2c2a84ab30ae 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def @@ -24,6 +24,37 @@ // FIXME: Are these nothrow/const? +// 3DNow! +// +BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "nc") +BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "nc") +BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "nc") +// GCC has pfrsqrtit1, even though this is not the name of the instruction. +BUILTIN(__builtin_ia32_pfrsqrtit1, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc") +BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "nc") +// 3DNow! Extensions. +BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "nc") +BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "nc") +BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "nc") +BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc") + // MMX // // FIXME: All MMX instructions will be generated via builtins. Any MMX vector @@ -209,7 +240,6 @@ BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "") BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "") BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "") BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "") -BUILTIN(__builtin_ia32_loadups, "V4ffC*", "") BUILTIN(__builtin_ia32_storeups, "vf*V4f", "") BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "") BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "") @@ -223,7 +253,6 @@ BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "") BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "") BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "") BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "") -BUILTIN(__builtin_ia32_loadupd, "V2ddC*", "") BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "") BUILTIN(__builtin_ia32_movmskpd, "iV2d", "") BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "") @@ -342,10 +371,10 @@ BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16cic","") BUILTIN(__builtin_ia32_pcmpgtq, "V2LLiV2LLiV2LLi", "") -BUILTIN(__builtin_ia32_crc32qi, "iic", "") -BUILTIN(__builtin_ia32_crc32hi, "iis", "") -BUILTIN(__builtin_ia32_crc32si, "iii", "") -BUILTIN(__builtin_ia32_crc32di, "LLiLLiLLi", "") +BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "") +BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "") +BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "") +BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "") // AES BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "") diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h b/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h index 4da2ad757223..d928f9d0f66b 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h @@ -87,6 +87,9 @@ ------------------------------------------------------------------------ */ +#ifndef CLANG_BASIC_CONVERTUTF_H +#define CLANG_BASIC_CONVERTUTF_H + /* --------------------------------------------------------------------- The following 4 definitions are compiler-specific. The C standard does not guarantee that wchar_t has at least @@ -156,4 +159,6 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); } #endif +#endif + /* --------------------------------------------------------------------- */ diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td index 2ec7427cf758..9e69492e13c7 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td @@ -17,7 +17,9 @@ def Named : Decl<1>; def NamespaceAlias : DDecl; def Label : DDecl; def Type : DDecl; - def Typedef : DDecl; + def TypedefName : DDecl; + def Typedef : DDecl; + def TypeAlias : DDecl; def UnresolvedUsingTypename : DDecl; def Tag : DDecl, DeclContext; def Enum : DDecl; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h index 3fc60d136b5c..7fc400f31bb0 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h @@ -585,7 +585,7 @@ class Diagnostic : public llvm::RefCountedBase { /// DiagArgumentsVal - The values for the various substitution positions. This /// is used when the argument is not an std::string. The specific value is - /// mangled into an intptr_t and the intepretation depends on exactly what + /// mangled into an intptr_t and the interpretation depends on exactly what /// sort of argument kind it is. intptr_t DiagArgumentsVal[MaxArguments]; @@ -741,9 +741,6 @@ class DiagnosticBuilder { } void AddFixItHint(const FixItHint &Hint) const { - if (Hint.isNull()) - return; - assert(NumFixItHints < Diagnostic::MaxFixItHints && "Too many fix-it hints!"); if (DiagObj) diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td index be510ed844e1..50a22c4a9120 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td @@ -18,6 +18,8 @@ def MAP_IGNORE : DiagMapping; def MAP_WARNING : DiagMapping; def MAP_ERROR : DiagMapping; def MAP_FATAL : DiagMapping; +def MAP_WARNING_NO_WERROR : DiagMapping; +def MAP_WARNING_SHOW_IN_SYSTEM_HEADER : DiagMapping; // Define the diagnostic classes. class DiagClass; @@ -60,6 +62,8 @@ class Diagnostic { DiagMapping DefaultMapping = defaultmapping; DiagGroup Group; string CategoryName = ""; + string Brief = ""; + string Explanation = ""; } class Error : Diagnostic; @@ -73,10 +77,20 @@ class DefaultIgnore { DiagMapping DefaultMapping = MAP_IGNORE; } class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; } class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; } class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; } +class DefaultWarnNoWerror { DiagMapping DefaultMapping= MAP_WARNING_NO_WERROR; } +class DefaultWarnShowInSystemHeader { + DiagMapping DefaultMapping = MAP_WARNING_SHOW_IN_SYSTEM_HEADER; +} class NoSFINAE { bit SFINAE = 0; } class AccessControl { bit AccessControl = 1; } +class Brief { string Brief = str; } +class FullExplanation { + string Brief = brief; + string Explanation = full; +} + // Definitions for Diagnostics. include "DiagnosticASTKinds.td" include "DiagnosticAnalysisKinds.td" diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td index 85c64c5cef65..0b0bca0395cb 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -45,6 +45,8 @@ def ext_no_declarators : ExtWarn<"declaration does not declare anything">, InGroup; def err_param_redefinition : Error<"redefinition of parameter %0">; def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">; +def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">, + InGroup, DefaultIgnore; def err_invalid_storage_class_in_func_decl : Error< "invalid storage class specifier in function declarator">; def err_expected_namespace_name : Error<"expected namespace name">; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td index ef1c9e7d8b9a..908a69b162c4 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -39,8 +39,10 @@ def err_drv_invalid_darwin_version : Error< "invalid Darwin version number: %0">; def err_drv_missing_argument : Error< "argument to '%0' is missing (expected %1 %plural{1:value|:values}1)">; -def err_drv_invalid_Xarch_argument : Error< - "invalid Xarch argument: '%0'">; +def err_drv_invalid_Xarch_argument_with_args : Error< + "invalid Xarch argument: '%0', options requiring arguments are unsupported">; +def err_drv_invalid_Xarch_argument_isdriver : Error< + "invalid Xarch argument: '%0', cannot change driver behavior inside Xarch argument">; def err_drv_argument_only_allowed_with : Error< "invalid argument '%0' only allowed with '%1'">; def err_drv_argument_not_allowed_with : Error< @@ -76,6 +78,10 @@ def err_drv_cc_print_options_failure : Error< "unable to open CC_PRINT_OPTIONS file: %0">; def err_drv_preamble_format : Error< "incorrect format for -preamble-bytes=N,END">; +def err_drv_conflicting_deployment_targets : Error< + "conflicting deployment targets, both '%0' and '%1' are present in environment">; +def err_drv_invalid_arch_for_deployment_target : Error< + "invalid architecture '%0' for deployment target '%1'">; def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for c++ and objective-c++ only">; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 30706769d45e..67fc22e410fe 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -79,6 +79,8 @@ def warn_fe_macro_contains_embedded_newline : Warning< "macro '%0' contains embedded newline, text after the newline is ignored.">; def warn_fe_cc_print_header_failure : Warning< "unable to open CC_PRINT_HEADERS file: %0 (using stderr)">; +def warn_fe_cc_log_diagnostics_failure : Warning< + "unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">; def err_verify_missing_start : Error< "cannot find start ('{{') of expected %0">; @@ -113,6 +115,9 @@ def warn_pch_target_triple : Error< def warn_pch_c99 : Error< "C99 support was %select{disabled|enabled}0 in PCH file but is " "currently %select{disabled|enabled}1">; +def warn_pch_c1x : Error< + "C1X support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; def warn_pch_cplusplus : Error< "C++ support was %select{disabled|enabled}0 in PCH file but is " "currently %select{disabled|enabled}1">; @@ -230,6 +235,9 @@ def warn_pch_gnu_inline : Error< def warn_pch_no_inline : Error< "the macro '__NO_INLINE__' was %select{not defined|defined}0 in " "the PCH file but is currently %select{undefined|defined}1">; +def warn_pch_deprecated : Error< + "the macro '__DEPRECATED' was %select{not defined|defined}0 in " + "the PCH file but is currently %select{undefined|defined}1">; def warn_pch_gc_mode : Error< "the PCH file was built with %select{no||hybrid}0 garbage collection but " "the current translation unit will compiled with %select{no||hybrid}1 " diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td index 412fb587108e..c85acc510770 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td @@ -24,6 +24,7 @@ def : DiagGroup<"aggregate-return">; def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">; def : DiagGroup<"attributes">; def : DiagGroup<"bad-function-cast">; +def Availability : DiagGroup<"availability">; def BoolConversions : DiagGroup<"bool-conversions">; def CXXCompat: DiagGroup<"c++-compat">; def CastAlign : DiagGroup<"cast-align">; @@ -54,6 +55,7 @@ def CXXHexFloats : DiagGroup<"c++-hex-floats">; def : DiagGroup<"c++0x-compat", [CXXHexFloats]>; def : DiagGroup<"effc++">; +def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; def FourByteMultiChar : DiagGroup<"four-char-constants">; def GlobalConstructors : DiagGroup<"global-constructors">; def : DiagGroup<"idiomatic-parentheses">; @@ -94,6 +96,8 @@ def Padded : DiagGroup<"padded">; def PointerArith : DiagGroup<"pointer-arith">; def PoundWarning : DiagGroup<"#warnings">, DiagCategory<"#warning Directive">; +def PoundPragmaMessage : DiagGroup<"#pragma messages">, + DiagCategory<"#pragma message Directive">; def : DiagGroup<"pointer-to-int-cast">; def : DiagGroup<"redundant-decls">; def ReturnType : DiagGroup<"return-type">; @@ -109,6 +113,7 @@ def : DiagGroup<"stack-protector">; def : DiagGroup<"switch-default">; def : DiagGroup<"synth">; def TautologicalCompare : DiagGroup<"tautological-compare">; +def HeaderHygiene : DiagGroup<"header-hygiene">; // Preprocessor warnings. def : DiagGroup<"builtin-macro-redefined">; @@ -137,13 +142,17 @@ def Trigraphs : DiagGroup<"trigraphs">; def : DiagGroup<"type-limits">; def Uninitialized : DiagGroup<"uninitialized">; +def UninitializedMaybe : DiagGroup<"conditional-uninitialized">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; def UnknownAttributes : DiagGroup<"unknown-attributes">; def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">; def UnusedArgument : DiagGroup<"unused-argument">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; -def UnusedFunction : DiagGroup<"unused-function">; -def UnusedMemberFunction : DiagGroup<"unused-member-function">; +def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">; +def UnneededMemberFunction : DiagGroup<"unneeded-member-function">; +def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>; +def UnusedMemberFunction : DiagGroup<"unused-member-function", + [UnneededMemberFunction]>; def UnusedLabel : DiagGroup<"unused-label">; def UnusedParameter : DiagGroup<"unused-parameter">; def UnusedValue : DiagGroup<"unused-value">; @@ -165,17 +174,22 @@ def VariadicMacros : DiagGroup<"variadic-macros">; def VectorConversions : DiagGroup<"vector-conversions">; // clang specific def VLA : DiagGroup<"vla">; def VolatileRegisterVar : DiagGroup<"volatile-register-var">; -def : DiagGroup<"write-strings">; + +// GCC calls -Wdeprecated-writable-strings -Wwrite-strings. +def GCCWriteStrings : DiagGroup<"write-strings" , [DeprecatedWritableStr]>; + def CharSubscript : DiagGroup<"char-subscripts">; def LargeByValueCopy : DiagGroup<"large-by-value-copy">; +def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">; // Aggregation warning settings. // -Widiomatic-parentheses contains warnings about 'idiomatic' -// missing parentheses; it is off by default. +// missing parentheses; it is off by default. We do not include it +// in -Wparentheses because most users who use -Wparentheses explicitly +// do not want these warnings. def Parentheses : DiagGroup<"parentheses", - [LogicalOpParentheses, - DiagGroup<"idiomatic-parentheses">]>; + [LogicalOpParentheses]>; // -Wconversion has its own warnings, but we split a few out for // legacy reasons: @@ -187,6 +201,7 @@ def Conversion : DiagGroup<"conversion", [DiagGroup<"shorten-64-to-32">, DiagGroup<"constant-conversion">, DiagGroup<"literal-conversion">, + DiagGroup<"sign-conversion">, BoolConversions]>, DiagCategory<"Value Conversion Issue">; @@ -253,7 +268,9 @@ def NonGCC : DiagGroup<"non-gcc", // A warning group for warnings about using C++0x features as extensions in // earlier C++ versions. -def CXX0x : DiagGroup<"c++0x-extensions">; +def CXX0xStaticNonIntegralInitializer : + DiagGroup<"c++0x-static-nonintegral-init">; +def CXX0x : DiagGroup<"c++0x-extensions", [CXX0xStaticNonIntegralInitializer]>; // A warning group for warnings about GCC extensions. def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h index 2b03cae565c8..0296b96d00f6 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h @@ -42,7 +42,8 @@ namespace clang { // Get typedefs for common diagnostics. enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #include "clang/Basic/DiagnosticCommonKinds.inc" NUM_BUILTIN_COMMON_DIAGNOSTICS #undef DIAG @@ -63,9 +64,12 @@ namespace clang { /// Map this diagnostic to "warning", but make it immune to -Werror. This /// happens when you specify -Wno-error=foo. MAP_WARNING_NO_WERROR = 5, + /// Map this diagnostic to "warning", but make it immune to + /// -Wno-system-headers. + MAP_WARNING_SHOW_IN_SYSTEM_HEADER = 6, /// Map this diagnostic to "error", but make it immune to -Wfatal-errors. /// This happens for -Wno-fatal-errors=foo. - MAP_ERROR_NO_WFATAL = 6 + MAP_ERROR_NO_WFATAL = 7 }; } @@ -99,7 +103,7 @@ class DiagnosticIDs : public llvm::RefCountedBase { /// issue. const char *getDescription(unsigned DiagID) const; - /// isNoteWarningOrExtension - Return true if the unmapped diagnostic + /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic /// level of the specified diagnostic ID is a Warning or Extension. /// This only works on builtin diagnostics, not custom ones, and is not legal to /// call on NOTEs. @@ -130,7 +134,7 @@ class DiagnosticIDs : public llvm::RefCountedBase { /// the diagnostic, this returns null. static const char *getWarningOptionForDiag(unsigned DiagID); - /// getWarningOptionForDiag - Return the category number that a specified + /// getCategoryNumberForDiag - Return the category number that a specified /// DiagID belongs to, or 0 if no category. static unsigned getCategoryNumberForDiag(unsigned DiagID); @@ -174,6 +178,20 @@ class DiagnosticIDs : public llvm::RefCountedBase { /// are not SFINAE errors. static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); + /// getName - Given a diagnostic ID, return its name + static const char *getName(unsigned DiagID); + + /// getIdFromName - Given a diagnostic name, return its ID, or 0 + static unsigned getIdFromName(char const *Name); + + /// getBriefExplanation - Given a diagnostic ID, return a brief explanation + /// of the issue + static const char *getBriefExplanation(unsigned DiagID); + + /// getFullExplanation - Given a diagnostic ID, return a full explanation + /// of the issue + static const char *getFullExplanation(unsigned DiagID); + private: /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g. /// "unknown-pragmas" to have the specified mapping. This returns true and diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td index 6d1d9b6ad869..3514ccace22a 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -114,7 +114,8 @@ def err_invalid_pth_file : Error< //===----------------------------------------------------------------------===// // Preprocessor Diagnostics //===----------------------------------------------------------------------===// -def pp_hash_warning : Warning<"#warning%0">, InGroup; +def pp_hash_warning : Warning<"#warning%0">, + InGroup, DefaultWarnShowInSystemHeader; def pp_include_next_in_primary : Warning< "#include_next in primary source file">; def pp_include_macros_out_of_predefines : Error< @@ -239,7 +240,8 @@ def err_pragma_push_pop_macro_malformed : Error< "pragma %0 requires a parenthesized string">; def warn_pragma_pop_macro_no_push : Warning< "pragma pop_macro could not pop '%0', no matching push_macro">; -def warn_pragma_message : Warning<"%0">; +def warn_pragma_message : Warning<"%0">, + InGroup, DefaultWarnNoWerror; def warn_pragma_ignored : Warning<"unknown pragma ignored">, InGroup, DefaultIgnore; def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, @@ -247,8 +249,8 @@ def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, def ext_on_off_switch_syntax : ExtWarn<"expected 'ON' or 'OFF' or 'DEFAULT' in pragma">, InGroup; -def ext_pragma_syntax_eom : - ExtWarn<"expected end of macro in pragma">, +def ext_pragma_syntax_eod : + ExtWarn<"expected end of directive in pragma">, InGroup; def warn_stdc_fenv_access_not_supported : Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">, diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td index 9a68af9c45ca..c37e510b3479 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -67,6 +67,13 @@ def ext_ms_enum_fixed_underlying_type : Extension< "enumeration types with a fixed underlying type are a Microsoft extension">, InGroup; +def ext_c1x_generic_selection : Extension< + "generic selections are a C1X-specific feature">; +def err_duplicate_default_assoc : Error< + "duplicate default generic association">; +def note_previous_default_assoc : Note< + "previous default generic association is here">; + def ext_gnu_indirect_goto : Extension< "use of GNU indirect-goto extension">, InGroup; def ext_gnu_address_of_label : Extension< @@ -111,7 +118,7 @@ def err_expected_semi_declaration : Error< "expected ';' at end of declaration">; def err_expected_semi_decl_list : Error< "expected ';' at end of declaration list">; -def ext_expected_semi_decl_list : Extension< +def ext_expected_semi_decl_list : ExtWarn< "expected ';' at end of declaration list">; def err_expected_member_name_or_semi : Error< "expected member name or ';' after declaration specifiers">; @@ -119,6 +126,10 @@ def err_function_declared_typedef : Error< "function definition declared 'typedef'">; def err_iboutletcollection_builtintype : Error< "type argument of iboutletcollection attribute cannot be a builtin type">; + +def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">; +def err_at_in_class : Error<"unexpected '@' in member specification">; + def err_expected_fn_body : Error< "expected function body after function declarator">; def err_expected_method_body : Error<"expected method body">; @@ -130,6 +141,7 @@ def err_expected_statement : Error<"expected statement">; def err_expected_lparen_after : Error<"expected '(' after '%0'">; def err_expected_lparen_after_id : Error<"expected '(' after %0">; def err_expected_less_after : Error<"expected '<' after '%0'">; +def err_expected_equal_after : Error<"expected '=' after %0">; def err_expected_comma : Error<"expected ','">; def err_expected_lbrace_in_compound_literal : Error< "expected '{' in compound literal">; @@ -178,6 +190,9 @@ def ext_ref_qualifier : ExtWarn< "reference qualifiers on functions are a C++0x extension">, InGroup; def ext_inline_namespace : ExtWarn< "inline namespaces are a C++0x feature">, InGroup; +def ext_generalized_initializer_lists : ExtWarn< + "generalized initializer lists are a C++0x extension unsupported in Clang">, + InGroup; def err_argument_required_after_attribute : Error< "argument required after attribute">; def err_missing_param : Error<"expected parameter declarator">; @@ -189,6 +204,9 @@ def err_expected_class_name : Error<"expected class name">; def err_unspecified_vla_size_with_static : Error< "'static' may not be used with an unspecified variable length array size">; +def err_expected_case_before_expression: Error< + "expected 'case' keyword before expression">; + // Declarations. def err_typename_requires_specqual : Error< "type name requires a specifier or qualifier">; @@ -226,6 +244,8 @@ def err_unexected_colon_in_nested_name_spec : Error< "unexpected ':' in nested name specifier">; def err_bool_redeclaration : Error< "redeclaration of C++ built-in type 'bool'">; +def ext_c1x_static_assert : Extension< + "_Static_assert is a C1X-specific feature">; /// Objective-C parser diagnostics def err_expected_minus_or_plus : Error< @@ -266,7 +286,7 @@ def err_missing_id_definition : Error<"cannot find definition of 'id'">; def err_missing_proto_definition : Error< "cannot find definition of 'Protocol'">; def err_missing_class_definition : Error<"cannot find definition of 'Class'">; -def warn_expected_implementation : Warning< +def err_expected_implementation : Error< "@end must appear in an @implementation context">; def error_property_ivar_decl : Error< "property synthesize requires specification of an ivar">; @@ -300,6 +320,8 @@ def err_expected_lbrace_after_base_specifiers : Error< "expected '{' after base class list">; def ext_ellipsis_exception_spec : Extension< "exception specification of '...' is a Microsoft extension">; +def err_dynamic_and_noexcept_specification : Error< + "cannot have both throw() and noexcept() clause on the same function">; def err_expected_catch : Error<"expected catch">; def err_expected_lbrace_or_comma : Error<"expected '{' or ','">; def err_using_namespace_in_class : Error< @@ -363,6 +385,8 @@ def err_enum_template : Error<"enumeration cannot be a template">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; +def warn_missing_dependent_template_keyword : ExtWarn< + "use 'template' keyword to treat '%0' as a dependent template name">; def warn_static_inline_explicit_inst_ignored : Warning< "ignoring '%select{static|inline}0' keyword on explicit template " @@ -380,6 +404,8 @@ def err_out_of_line_type_names_constructor : Error< def err_expected_qualified_after_typename : Error< "expected a qualified name after 'typename'">; +def warn_expected_qualified_after_typename : ExtWarn< + "expected a qualified name after 'typename'">; def err_expected_semi_after_tagdecl : Error< "expected ';' after %0">; @@ -401,15 +427,23 @@ def err_ctor_init_missing_comma : Error< // C++ declarations def err_friend_decl_defines_class : Error< "cannot define a type in a friend declaration">; +def err_missing_whitespace_digraph : Error< + "found '<::' after a " + "%select{template name|const_cast|dynamic_cast|reinterpret_cast|static_cast}0" + " which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?">; def warn_deleted_function_accepted_as_extension: ExtWarn< "deleted function definition accepted as a C++0x extension">, InGroup; +// C++0x alias-declaration +def ext_alias_declaration : ExtWarn< + "alias declarations accepted as a C++0x extension">, InGroup; +def err_alias_declaration_not_identifier : Error< + "name defined in alias declaration must be an identifier">; + // C++0x override control def ext_override_control_keyword : Extension< "'%0' keyword accepted as a C++0x extension">, InGroup; -def ext_override_inline: Extension< - "'%0' keyword only allowed in declarations, allowed as an extension">; def err_duplicate_virt_specifier : Error< "class member already marked '%0'">; @@ -426,6 +460,23 @@ def err_paren_sizeof_parameter_pack : Error< def err_sizeof_parameter_pack : Error< "expected parenthesized parameter pack name in 'sizeof...' expression">; +// Availability attribute +def err_expected_version : Error< + "expected a version of the form 'major[.minor[.subminor]]'">; +def err_zero_version : Error< + "version number must have non-zero major, minor, or sub-minor version">; +def err_availability_expected_platform : Error< + "expected a platform name, e.g., 'macosx'">; +def err_availability_expected_change : Error< + "expected 'introduced', 'deprecated', or 'obsoleted'">; +def err_availability_unknown_change : Error< + "%0 is not an availability stage; use 'introduced', 'deprecated', or " + "'obsoleted'">; +def err_availability_redundant : Error< + "redundant %0 availability change; only the last specified change will " "be used">; +def warn_availability_and_unavailable : Warning< + "'unavailable' availability overrides all other availability information">; + // Language specific pragmas // - Generic warnings def warn_pragma_expected_lparen : Warning< @@ -434,6 +485,8 @@ def warn_pragma_expected_rparen : Warning< "missing ')' after '#pragma %0' - ignoring">; def warn_pragma_expected_identifier : Warning< "expected identifier in '#pragma %0' - ignored">; +def warn_pragma_ms_struct : Warning< + "incorrect use of '#pragma ms_struct on|off' - ignored">; def warn_pragma_extra_tokens_at_eol : Warning< "extra tokens at end of '#pragma %0' - ignored">; // - #pragma options @@ -468,5 +521,17 @@ def warn_pragma_expected_enable_disable : Warning< def warn_pragma_unknown_extension : Warning< "unknown OpenCL extension %0 - ignoring">; +def err_seh_expected_handler : Error< + "expected '__except' or '__finally' block">; + +def err_seh___except_block : Error< + "%0 only allowed in __except block">; + +def err_seh___except_filter : Error< + "%0 only allowed in __except filter expression">; + +def err_seh___finally_block : Error< + "%0 only allowed in __finally block">; + } // end of Parse Issue category. } // end of Parser diagnostics diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index a9fb2da00176..0a0c91ac9144 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -30,6 +30,8 @@ def warn_float_overflow : Warning< def warn_float_underflow : Warning< "magnitude of floating-point constant too small for type %0; minimum is %1">, InGroup; +def warn_double_const_requires_fp64 : Warning< + "double precision constant requires cl_khr_fp64, casting to single precision">; // C99 variable-length arrays def ext_vla : Extension< @@ -57,6 +59,8 @@ def err_variably_modified_new_type : Error< // C99 Designated Initializers def ext_designated_init : Extension< + "designated initializers are a C99 feature">; +def ext_designated_init_cxx : Extension< "designated initializers are a C99 feature, accepted in C++ as an extension">; def err_array_designator_negative : Error< "array designator value '%0' is negative">; @@ -114,6 +118,12 @@ def warn_unused_member_function : Warning<"unused member function %0">, InGroup, DefaultIgnore; def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">, InGroup, DefaultIgnore; +def warn_unneeded_internal_decl : Warning< + "%select{function|variable}0 %1 is not needed and will not be emitted">, + InGroup, DefaultIgnore; +def warn_unneeded_member_function : Warning< + "member function %0 is not needed and will not be emitted">, + InGroup, DefaultIgnore; def warn_parameter_size: Warning< "%0 is a large (%1 bytes) pass-by-value argument; " @@ -202,6 +212,9 @@ def warn_global_constructor : Warning< def warn_global_destructor : Warning< "declaration requires a global destructor">, InGroup, DefaultIgnore; +def warn_exit_time_destructor : Warning< + "declaration requires an exit-time destructor">, + InGroup, DefaultIgnore; def err_invalid_thread : Error< "'__thread' is only allowed on variable declarations">; @@ -248,6 +261,11 @@ def err_builtin_definition : Error<"definition of builtin function %0">; def err_types_compatible_p_in_cplusplus : Error< "__builtin_types_compatible_p is not valid in C++">; def warn_builtin_unknown : Warning<"use of unknown builtin %0">, DefaultError; +def warn_non_pod_memset : Warning< + "destination for this memset call is a pointer to a non-POD type %0">, + InGroup>, DefaultIgnore; +def note_non_pod_memset_silence : Note< + "explicitly cast the pointer to silence this warning">; /// main() // static/inline main() are not errors in C, just in C++. @@ -382,7 +400,7 @@ def note_declared_at : Note<"declared here">; def note_method_declared_at : Note<"method declared here">; def err_setter_type_void : Error<"type of setter must be void">; def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; -def warn_missing_atend : Warning<"'@end' is missing in implementation context">; +def err_missing_atend : Error<"'@end' is missing in implementation context">; def err_objc_var_decl_inclass : Error<"cannot declare variable inside @interface or @protocol">; def error_missing_method_context : Error< @@ -540,7 +558,7 @@ def ext_using_undefined_std : ExtWarn< // C++ exception specifications def err_exception_spec_in_typedef : Error< - "exception specifications are not allowed in typedefs">; + "exception specifications are not allowed in %select{typedefs|type aliases}0">; def err_distant_exception_spec : Error< "exception specifications are not allowed beyond a single level " "of indirection">; @@ -549,6 +567,8 @@ def err_incomplete_in_exception_spec : Error< "in exception specification">; def err_mismatched_exception_spec : Error< "exception specification in declaration does not match previous declaration">; +def warn_mismatched_exception_spec : ExtWarn< + "exception specification in declaration does not match previous declaration">; def err_override_exception_spec : Error< "exception specification of overriding function is more lax than " "base version">; @@ -558,6 +578,8 @@ def err_deep_exception_specs_differ : Error< "exception specifications of %select{return|argument}0 types differ">; def warn_missing_exception_specification : Warning< "%0 is missing exception specification '%1'">; +def err_noexcept_needs_constant_expression : Error< + "argument to noexcept specifier must be a constant expression">; // C++ access checking def err_class_redeclared_with_different_access : Error< @@ -786,20 +808,28 @@ def err_destructor_redeclared : Error<"destructor cannot be redeclared">; def err_destructor_with_params : Error<"destructor cannot have any parameters">; def err_destructor_variadic : Error<"destructor cannot be variadic">; def err_destructor_typedef_name : Error< - "destructor cannot be declared using a typedef %0 of the class name">; + "destructor cannot be declared using a %select{typedef|type alias}1 %0 of the class name">; def err_destructor_name : Error< "expected the class name after '~' to name the enclosing class">; def err_destructor_class_name : Error< "expected the class name after '~' to name a destructor">; -def err_ident_in_pseudo_dtor_not_a_type : Error< - "identifier %0 in pseudo-destructor expression does not name a type">; +def err_ident_in_dtor_not_a_type : Error< + "identifier %0 in object destruction expression does not name a type">; +def err_destructor_expr_type_mismatch : Error< + "destructor type %0 in object destruction expression does not match the " + "type %1 of the object being destroyed">; +def note_destructor_type_here : Note< + "type %0 is declared here">; + +def err_destructor_template : Error< + "destructor cannot be declared as a template">; // C++ initialization def err_init_conversion_failed : Error< "cannot initialize %select{a variable|a parameter|return object|an " "exception object|a member subobject|an array element|a new value|a value|a " - "base class|a vector element}0 of type %1 with an %select{rvalue|lvalue}2 of " - "type %3">; + "base class|a constructor delegation|a vector element}0 of type %1 with an " + "%select{rvalue|lvalue}2 of type %3">; def err_lvalue_to_rvalue_ref : Error<"rvalue reference to type %0 cannot bind " "to lvalue of type %1">; @@ -854,13 +884,23 @@ def note_uninit_reference_member : Note< "uninitialized reference member is here">; def warn_field_is_uninit : Warning<"field is uninitialized when used here">, InGroup; -def warn_uninit_var : Warning<"variable %0 is possibly uninitialized when used here">, - InGroup>, DefaultIgnore; +def warn_uninit_self_reference_in_init : Warning< + "variable %0 is uninitialized when used within its own initialization">, + InGroup; +def warn_uninit_var : Warning< + "variable %0 is uninitialized when used here">, + InGroup, DefaultIgnore; +def warn_maybe_uninit_var : + Warning<"variable %0 may be uninitialized when used here">, + InGroup, DefaultIgnore; def note_uninit_var_def : Note< "variable %0 is declared here">; def warn_uninit_var_captured_by_block : Warning< - "variable %0 is possibly uninitialized when captured by block">, - InGroup>, DefaultIgnore; + "variable %0 is uninitialized when captured by block">, + InGroup, DefaultIgnore; +def warn_maybe_uninit_var_captured_by_block : Warning< + "variable %0 may be uninitialized when captured by block">, + InGroup, DefaultIgnore; def note_var_fixit_add_initialization : Note< "add initialization to silence this warning">; def err_init_incomplete_type : Error<"initialization of incomplete type %0">; @@ -905,7 +945,7 @@ def err_auto_not_allowed : Error< "'auto' not allowed %select{in function prototype|in struct member" "|in union member|in class member|in exception declaration" "|in template parameter|in block literal|in template argument" - "|in typedef|in function return type|here}0">; + "|in typedef|in type alias|in function return type|here}0">; def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< @@ -944,9 +984,6 @@ def err_final_function_overridden : Error< def err_final_base : Error< "derivation from 'final' %0">; -def err_function_overriding_without_override : Error< - "%0 overrides function%s1 without being marked 'override'">; - // C++0x scoped enumerations def err_enum_invalid_underlying : Error< "non-integral type %0 is an invalid underlying type">; @@ -969,6 +1006,34 @@ def err_delegation_0x_only : Error< "delegating constructors are permitted only in C++0x">; def err_delegation_unimplemented : Error< "delegating constructors are not fully implemented">; +def err_delegating_initializer_alone : Error< + "an initializer for a delegating constructor must appear alone">; +def err_delegating_ctor_loop : Error< + "constructor %0 delegates to itself (possibly indirectly)">; +def err_delegating_codegen_not_implemented : Error< + "code generation for delegating constructors not implemented">; + +// C++0x range-based for loop +def err_for_range_decl_must_be_var : Error< + "for range declaration must declare a variable">; +def err_for_range_storage_class : Error< + "loop variable %0 may not be declared %select{'extern'|'static'|" + "'__private_extern__'|'auto'|'register'|'constexpr'}1">; +def err_type_defined_in_for_range : Error< + "types may not be defined in a for range declaration">; +def err_for_range_deduction_failure : Error< + "cannot use type %0 as a range">; +def err_for_range_incomplete_type : Error< + "cannot use incomplete type %0 as a range">; +def err_for_range_iter_deduction_failure : Error< + "cannot use type %0 as an iterator">; +def err_for_range_member_begin_end_mismatch : Error< + "range type %0 has '%select{begin|end}1' member but no '%select{end|begin}1' member">; +def err_for_range_begin_end_types_differ : Error< + "'begin' and 'end' must return the same type (got %0 and %1)">; +def note_for_range_type : Note<"range has type %0">; +def note_for_range_begin_end : Note< + "selected '%select{begin|end}0' %select{function|template }1%2 with iterator type %3">; // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< @@ -982,7 +1047,10 @@ def err_attribute_can_be_applied_only_to_symbol_declaration : Error< def err_attributes_are_not_compatible : Error< "%0 and %1 attributes are not compatible">; def err_attribute_wrong_number_arguments : Error< - "attribute requires %0 argument(s)">; + "attribute %plural{0:takes no arguments|1:takes one argument|" + ":requires exactly %0 arguments}0">; +def err_attribute_too_many_arguments : Error< + "attribute takes no more than %0 argument%s0">; def err_iboutletcollection_type : Error< "invalid type %0 as argument of iboutletcollection attribute">; def err_iboutletcollection_object_type : Error< @@ -1026,6 +1094,7 @@ def err_format_attribute_result_not : Error<"function does not return %0">; def err_format_attribute_implicit_this_format_string : Error< "format attribute cannot specify the implicit this argument as the format " "string">; +def warn_unknown_method_family : Warning<"unrecognized method family">; def err_attribute_invalid_size : Error< "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero vector size">; @@ -1101,7 +1170,9 @@ def err_attribute_wrong_decl_type : Error< "classes and virtual methods|functions, methods, and parameters|" "classes|virtual methods|class members|variables|methods}1">; def warn_function_attribute_wrong_type : Warning< - "%0 only applies to function types; type here is %1">; + "'%0' only applies to function types; type here is %1">; +def warn_pointer_attribute_wrong_type : Warning< + "'%0' only applies to pointer types; type here is %1">; def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">; @@ -1119,6 +1190,15 @@ def err_cconv_varargs : Error< def err_regparm_mismatch : Error<"function declared with with regparm(%0) " "attribute was previously declared " "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">; +def err_invalid_pcs : Error<"Invalid PCS type">; + +// Availability attribute +def warn_availability_unknown_platform : Warning< + "unknown platform %0 in availability macro">; +def warn_availability_version_ordering : Warning< + "feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version " + "%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; " + "attribute ignored">; def warn_impcast_vector_scalar : Warning< "implicit conversion turns vector to scalar: %0 to %1">, @@ -1134,10 +1214,10 @@ def warn_impcast_float_integer : Warning< InGroup>, DefaultIgnore; def warn_impcast_integer_sign : Warning< "implicit conversion changes signedness: %0 to %1">, - InGroup>, DefaultIgnore; + InGroup>, DefaultIgnore; def warn_impcast_integer_sign_conditional : Warning< "operand of ? changes signedness: %0 to %1">, - InGroup>, DefaultIgnore; + InGroup>, DefaultIgnore; def warn_impcast_integer_precision : Warning< "implicit conversion loses integer precision: %0 to %1">, InGroup>, DefaultIgnore; @@ -1154,9 +1234,15 @@ def warn_impcast_literal_float_to_integer : Warning< "implicit conversion turns literal floating-point number into integer: " "%0 to %1">, InGroup>, DefaultIgnore; +def note_fix_integral_float_as_integer : Note< + "this can be rewritten as an integer literal with the exact same value">; def warn_impcast_different_enum_types : Warning< "implicit conversion from enumeration type %0 to different enumeration type " "%1">, InGroup>; +def warn_impcast_bool_to_null_pointer : Warning< + "initialization of pointer of type %0 to NULL from a constant boolean " + "expression">, InGroup; + def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, @@ -1252,11 +1338,13 @@ def err_ident_list_in_fn_declaration : Error< def ext_param_not_declared : Extension< "parameter %0 was not declared, defaulting to type 'int'">; def err_param_typedef_of_void : Error< - "empty parameter list defined with a typedef of 'void' not allowed in C++">; + "empty parameter list defined with a %select{typedef|type alias}0 of 'void' not allowed%select{ in C++|}0">; def err_param_default_argument : Error< "C does not support default arguments">; def err_param_default_argument_redefinition : Error< "redefinition of default argument">; +def warn_param_default_argument_redefinition : ExtWarn< + "redefinition of default argument">; def err_param_default_argument_missing : Error< "missing default argument on parameter">; def err_param_default_argument_missing_name : Error< @@ -1311,11 +1399,11 @@ def err_ovl_no_viable_member_function_in_call : Error< def err_ovl_ambiguous_call : Error< "call to %0 is ambiguous">; def err_ovl_deleted_call : Error< - "call to %select{unavailable|deleted}0 function %1 %2">; + "call to %select{unavailable|deleted}0 function %1%2">; def err_ovl_ambiguous_member_call : Error< "call to member function %0 is ambiguous">; def err_ovl_deleted_member_call : Error< - "call to %select{unavailable|deleted}0 member function %1 %2">; + "call to %select{unavailable|deleted}0 member function %1%2">; def note_ovl_too_many_candidates : Note< "remaining %0 candidate%s0 omitted; " "pass -fshow-overloads=all to show them">; @@ -1327,10 +1415,6 @@ def note_ovl_candidate : Note<"candidate " "is the implicit copy assignment operator|" "is an inherited constructor}0%1">; -def warn_init_pointer_from_false : Warning< - "initialization of pointer of type %0 from literal 'false'">, - InGroup; - def note_ovl_candidate_inherited_constructor : Note<"inherited from here">; def note_ovl_candidate_bad_deduction : Note< "candidate template ignored: failed template argument deduction">; @@ -1408,6 +1492,15 @@ def note_ovl_candidate_bad_addrspace : Note<"candidate " "constructor (inherited)}0%1 not viable: " "%select{%ordinal6|'this'}5 argument (%2) is in " "address space %3, but parameter must be in address space %4">; +def note_ovl_candidate_bad_gc : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)|" + "constructor (inherited)}0%1 not viable: " + "%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 " + "lifetime, but parameter has %select{no|__weak|__strong}4 lifetime">; def note_ovl_candidate_bad_cvr_this : Note<"candidate " "%select{|function|||function||||" "function (the implicit copy assignment operator)|}0 not viable: " @@ -1467,13 +1560,13 @@ def err_ovl_ambiguous_oper_binary : Error< "use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">; def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">; def err_ovl_deleted_oper : Error< - "overload resolution selected %select{unavailable|deleted}0 operator '%1' %2">; + "overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">; def err_ovl_no_viable_subscript : Error<"no viable overloaded operator[] for type %0">; def err_ovl_no_oper : Error<"type %0 does not provide a %select{subscript|call}1 operator">; def err_ovl_unresolvable : - Error<"cannot resolve overloaded function from context">; + Error<"cannot resolve overloaded function %0 from context">; def err_ovl_no_viable_object_call : Error< @@ -1481,7 +1574,7 @@ def err_ovl_no_viable_object_call : Error< def err_ovl_ambiguous_object_call : Error< "call to object of type %0 is ambiguous">; def err_ovl_deleted_object_call : Error< - "call to %select{unavailable|deleted}0 function call operator in type %1 %2">; + "call to %select{unavailable|deleted}0 function call operator in type %1%2">; def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">; def err_member_call_without_object : Error< "call to non-static member function without an object argument">; @@ -1707,6 +1800,8 @@ def err_template_spec_default_arg : Error< def err_not_class_template_specialization : Error< "cannot specialize a %select{dependent template|template template " "parameter}0">; +def err_function_specialization_in_class : Error< + "cannot specialize a function %0 within class scope">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error< @@ -1777,6 +1872,9 @@ def err_template_recursion_depth_exceeded : Error< def note_template_recursion_depth : Note< "use -ftemplate-depth-N to increase recursive template instantiation depth">; +def err_template_instantiate_within_definition : Error< + "%select{implicit|explicit}0 instantiation of template %1 within its" + " own definition">; def err_template_instantiate_undefined : Error< "%select{implicit|explicit}0 instantiation of undefined template %1">; def err_implicit_instantiate_member_undefined : Error< @@ -1900,6 +1998,8 @@ def note_typename_refers_here : Note< "referenced member %0 is declared here">; def err_typename_missing : Error< "missing 'typename' prior to dependent type name '%0%1'">; +def warn_typename_missing : ExtWarn< + "missing 'typename' prior to dependent type name '%0%1'">; def ext_typename_outside_of_template : ExtWarn< "'typename' occurs outside of a template">, InGroup; def err_typename_refers_to_using_value_decl : Error< @@ -1921,6 +2021,14 @@ def err_template_kw_missing : Error< def ext_template_outside_of_template : ExtWarn< "'template' keyword outside of a template">, InGroup; +def err_non_type_template_in_nested_name_specifier : Error< + "qualified name refers into a specialization of function template '%0'">; +def err_template_id_not_a_type : Error< + "template name refers to non-type template '%0'">; +def note_template_declared_here : Note< + "%select{function template|class template|template template parameter}0 " + "%1 declared here">; + // C++0x Variadic Templates def err_template_param_pack_default_arg : Error< "template parameter pack cannot have a default argument">; @@ -2039,6 +2147,8 @@ def err_inline_declaration_block_scope : Error< "inline declaration of %0 not allowed in block scope">; def err_static_non_static : Error< "static declaration of %0 follows non-static declaration">; +def warn_static_non_static : ExtWarn< + "static declaration of %0 follows non-static declaration">; def err_non_static_static : Error< "non-static declaration of %0 follows static declaration">; def err_extern_non_extern : Error< @@ -2054,17 +2164,17 @@ def err_redefinition_different_type : Error< def err_redefinition_different_kind : Error< "redefinition of %0 as different kind of symbol">; def err_redefinition_different_typedef : Error< - "typedef redefinition with different types (%0 vs %1)">; + "%select{typedef|type alias}0 redefinition with different types (%1 vs %2)">; def err_tag_reference_non_tag : Error< - "elaborated type refers to %select{a non-tag type|a typedef|a template}0">; + "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template}0">; def err_tag_reference_conflict : Error< "implicit declaration introduced by elaborated type conflicts with " - "%select{a declaration|a typedef|a template}0 of the same name">; + "%select{a declaration|a typedef|a type alias|a template}0 of the same name">; def err_dependent_tag_decl : Error< "%select{declaration|definition}0 of %select{struct|union|class|enum}1 " "in a dependent scope">; def err_tag_definition_of_typedef : Error< - "definition of type %0 conflicts with typedef of the same name">; + "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">; def err_conflicting_types : Error<"conflicting types for %0">; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< @@ -2154,6 +2264,8 @@ def err_excess_initializers_in_char_array_initializer : Error< "excess elements in char array initializer">; def warn_excess_initializers_in_char_array_initializer : ExtWarn< "excess elements in char array initializer">; +def err_initializer_string_for_char_array_too_long : Error< + "initializer-string for char array is too long">; def warn_initializer_string_for_char_array_too_long : ExtWarn< "initializer-string for char array is too long">; def warn_missing_field_initializers : Warning< @@ -2180,6 +2292,8 @@ def err_bitfield_width_exceeds_type_size : Error< "size of bit-field %0 (%1 bits) exceeds size of its type (%2 bits)">; def err_anon_bitfield_width_exceeds_type_size : Error< "size of anonymous bit-field (%0 bits) exceeds size of its type (%1 bits)">; +def err_incorrect_number_of_vector_initializers : Error< + "number of elements must be either one or match the size of the vector">; // Used by C++ which allows bit-fields that are wider than the type. def warn_bitfield_width_exceeds_type_size: Warning< @@ -2212,6 +2326,8 @@ def note_protected_by_cleanup : Note< "jump bypasses initialization of variable with __attribute__((cleanup))">; def note_protected_by_vla_typedef : Note< "jump bypasses initialization of VLA typedef">; +def note_protected_by_vla_type_alias : Note< + "jump bypasses initialization of VLA type alias">; def note_protected_by_vla : Note< "jump bypasses initialization of variable length array">; def note_protected_by_objc_try : Note< @@ -2266,12 +2382,17 @@ def ext_flexible_array_in_array : Extension< "%0 may not be used as an array element due to flexible array member">; def err_flexible_array_init_nonempty : Error< "non-empty initialization of flexible array member inside subobject">; -def ext_flexible_array_empty_aggregate : Extension< +def ext_flexible_array_empty_aggregate_ms : Extension< "flexible array member %0 in otherwise empty %select{struct|class}1 " "is a Microsoft extension">, InGroup; -def ext_flexible_array_union : Extension< +def ext_flexible_array_union_ms : Extension< "flexible array member %0 in a union is a Microsoft extension">, InGroup; +def ext_flexible_array_empty_aggregate_gnu : Extension< + "flexible array member %0 in otherwise empty %select{struct|class}1 " + "is a GNU extension">, InGroup; +def ext_flexible_array_union_gnu : Extension< + "flexible array member %0 in a union is a GNU extension">, InGroup; def err_flexible_array_init_needs_braces : Error< "flexible array requires brace-enclosed initializer">; @@ -2314,14 +2435,18 @@ def err_func_def_incomplete_result : Error< def ext_sizeof_function_type : Extension< "invalid application of 'sizeof' to a function type">, InGroup; def err_sizeof_alignof_overloaded_function_type : Error< - "invalid application of '%select{sizeof|__alignof}0' to an overloaded " - "function">; + "invalid application of '%select{sizeof|__alignof|vec_step}0' to an " + "overloaded function">; def ext_sizeof_void_type : Extension< - "invalid application of '%0' to a void type">, InGroup; + "invalid application of '%select{sizeof|__alignof|vec_step}0' to a void " + "type">, InGroup; def err_sizeof_alignof_incomplete_type : Error< - "invalid application of '%select{sizeof|__alignof}0' to an incomplete type %1">; + "invalid application of '%select{sizeof|__alignof|vec_step}0' to an " + "incomplete type %1">; def err_sizeof_alignof_bitfield : Error< "invalid application of '%select{sizeof|__alignof}0' to bit-field">; +def err_vecstep_non_scalar_vector_type : Error< + "'vec_step' requires built-in scalar or vector type, %0 invalid">; def err_offsetof_incomplete_type : Error< "offsetof of incomplete type %0">; def err_offsetof_record_type : Error< @@ -2417,6 +2542,11 @@ def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">; def err_no_member : Error<"no member named %0 in %1">; +def err_member_not_yet_instantiated : Error< + "no member %0 in %1; it has not yet been instantiated">; +def note_non_instantiated_member_here : Note< + "not-yet-instantiated member is declared here">; + def err_member_redeclared : Error<"class member cannot be redeclared">; def err_member_name_of_class : Error<"member %0 has the same name as its class">; def err_member_def_undefined_record : Error< @@ -2483,6 +2613,7 @@ def err_typecheck_sclass_fscope : Error< "illegal storage class on file-scoped variable">; def err_unsupported_global_register : Error< "global register variables are not supported">; +def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">; def err_typecheck_sclass_func : Error<"illegal storage class on function">; def err_static_block_func : Error< "function declared in block scope cannot have 'static' storage class">; @@ -2618,6 +2749,8 @@ def err_ref_array_type : Error< "cannot refer to declaration with an array type inside block">; def err_property_not_found : Error< "property %0 not found on object of type %1">; +def err_invalid_property_name : Error< + "%0 is not a valid property name (accessing an object of type %1)">; def err_getter_not_found : Error< "expected getter method not found on object of type %0">; def err_property_not_found_forward_class : Error< @@ -2636,6 +2769,8 @@ def ext_gnu_ptr_func_arith : Extension< InGroup; def error_readonly_property_assignment : Error< "assigning to property with 'readonly' attribute not allowed">; +def error_readonly_message_assignment : Error< + "assigning to 'readonly' return result of an objective-c message not allowed">; def ext_integer_increment_complex : Extension< "ISO C does not support '++'/'--' on complex integer type %0">; def ext_integer_complement_complex : Extension< @@ -2655,9 +2790,11 @@ def err_imaginary_not_supported : Error<"imaginary types are not supported">; def warn_root_inst_method_not_found : Warning< "instance method %0 is being used on 'Class' which is not in the root class">; def warn_class_method_not_found : Warning< - "method %objcclass0 not found (return type defaults to 'id')">; + "class method %objcclass0 not found (return type defaults to 'id')">; +def warn_instance_method_on_class_found : Warning< + "instance method %0 found instead of class method %1">; def warn_inst_method_not_found : Warning< - "method %objcinstance0 not found (return type defaults to 'id')">; + "instance method %objcinstance0 not found (return type defaults to 'id')">; def error_no_super_class_message : Error< "no @interface declaration found in class messaging of %0">; def error_root_class_cannot_use_super : Error< @@ -2735,9 +2872,9 @@ def err_bad_cxx_cast_generic : Error< def err_bad_cxx_cast_rvalue : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from rvalue to reference type %2">; -def err_bad_cxx_cast_const_away : Error< +def err_bad_cxx_cast_qualifiers_away : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" - "functional-style cast}0 from %1 to %2 casts away constness">; + "functional-style cast}0 from %1 to %2 casts away qualifiers">; def err_bad_const_cast_dest : Error< "%select{const_cast||||C-style cast|functional-style cast}0 to %2, " "which is not a reference, pointer-to-object, or pointer-to-data-member">; @@ -2765,6 +2902,8 @@ def err_bad_cxx_cast_member_pointer_size : Error< "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer " "type %1 to member pointer type %2 of different size">; def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">; +def err_bad_reinterpret_cast_reference : Error< + "reinterpret_cast of a %0 to %1 needs its address which is not allowed">; // These messages don't adhere to the pattern. // FIXME: Display the path somehow better. @@ -2823,7 +2962,11 @@ def ext_array_size_conversion : Extension< "implicit conversion from array size expression of type %0 to " "%select{integral|enumeration}1 type %2 is a C++0x extension">, InGroup; - +def err_address_space_qualified_new : Error< + "'new' cannot allocate objects of type %0 in address space '%1'">; +def err_address_space_qualified_delete : Error< + "'delete' cannot delete objects of type %0 in address space '%1'">; + def err_default_init_const : Error< "default initialization of an object of const type %0" "%select{| requires a user-provided default constructor}1">; @@ -2878,6 +3021,9 @@ def warn_overloaded_virtual : Warning< InGroup, DefaultIgnore; def note_hidden_overloaded_virtual_declared_here : Note< "hidden overloaded virtual function %q0 declared here">; +def warn_using_directive_in_header : Warning< + "using namespace directive in global context in header">, + InGroup, DefaultIgnore; def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " @@ -3067,11 +3213,6 @@ def err_typecheck_incompatible_address_space : Error< " changes address space of pointer">; def err_typecheck_convert_ambiguous : Error< "ambiguity in initializing value of type %0 with initializer of type %1">; -def err_cannot_initialize_decl_noname : Error< - "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 " - "of type %2">; -def err_cannot_initialize_decl : Error< - "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">; def err_typecheck_comparison_of_distinct_blocks : Error< "comparison of distinct block types (%0 and %1)">; @@ -3109,6 +3250,8 @@ def err_typecheck_call_too_few_args_at_least : Error< def err_typecheck_call_too_many_args : Error< "too many arguments to %select{function|block|method}0 call, " "expected %1, have %2">; +def note_typecheck_call_too_many_args : Note< + "%0 declared here">; def err_typecheck_call_too_many_args_at_most : Error< "too many arguments to %select{function|block|method}0 call, " "expected at most %1, have %2">; @@ -3196,6 +3339,8 @@ def warn_unused_call : Warning< def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">; +def err_dimension_expr_not_constant_integer : Error< + "dimension expression does not evaluate to a constant unsigned int">; def err_expected_ident_or_lparen : Error<"expected identifier or '('">; def err_typecheck_cond_incompatible_operands_null : Error< @@ -3278,7 +3423,7 @@ def err_in_class_initializer_bad_type : Error< "static data member of type %0 must be initialized out of line">; def ext_in_class_initializer_float_type : ExtWarn< "in-class initializer for static data member of type %0 " - "is a C++0x extension">, InGroup; + "is a C++0x extension">, InGroup; def err_in_class_initializer_non_constant : Error< "in-class initializer is not a constant expression">; @@ -3544,6 +3689,21 @@ def warn_stringcompare : Warning< "result of comparison against %select{a string literal|@encode}0 is " "unspecified (use strncmp instead)">; +// Generic selections. +def err_assoc_type_incomplete : Error< + "type %0 in generic association incomplete">; +def err_assoc_type_nonobject : Error< + "type %0 in generic association not an object type">; +def err_assoc_type_variably_modified : Error< + "type %0 in generic association is a variably modified type">; +def err_assoc_compatible_types : Error< + "type %0 in generic association compatible with previously specified type %1">; +def note_compat_assoc : Note< + "compatible type %0 specified here">; +def err_generic_sel_no_match : Error< + "controlling expression type %0 not compatible with any generic association type">; +def err_generic_sel_multi_match : Error< + "controlling expression type %0 compatible with %1 generic association types">; // Blocks @@ -3559,8 +3719,6 @@ def err_block_returning_array_function : Error< // CFString checking def err_cfstring_literal_not_string_constant : Error< "CFString literal is not a string constant">; -def warn_cfstring_literal_contains_nul_character : Warning< - "CFString literal contains NUL character">; def warn_cfstring_truncated : Warning< "input conversion stopped due to an input byte that does not " "belong to the input codeset UTF-8">; @@ -3722,6 +3880,8 @@ def warn_ivar_use_hidden : Warning< "local declaration of %0 hides instance variable">; def error_ivar_use_in_class_method : Error< "instance variable %0 accessed in class method">; +def error_implicit_ivar_access : Error< + "instance variable %0 cannot be accessed because 'self' has been redeclared">; def error_private_ivar_access : Error<"instance variable %0 is private">, AccessControl; def error_protected_ivar_access : Error<"instance variable %0 is protected">, @@ -3776,6 +3936,26 @@ def err_sizeof_pack_no_pack_name_suggest : Error< "%0 does not refer to the name of a parameter pack; did you mean %1?">; def note_parameter_pack_here : Note<"parameter pack %0 declared here">; +def err_uncasted_use_of_unknown_any : Error< + "%0 has unknown type; cast it to its declared type to use it">; +def err_uncasted_call_of_unknown_any : Error< + "%0 has unknown return type; cast the call to its declared return type">; +def err_unsupported_unknown_any_decl : Error< + "%0 has unknown type, which is unsupported for this kind of declaration">; +def err_unsupported_unknown_any_expr : Error< + "unsupported expression with unknown type">; +def err_unsupported_unknown_any_call : Error< + "call to unsupported expression with unknown type">; +def err_unknown_any_addrof : Error< + "the address of a declaration with unknown type " + "can only be cast to a pointer type">; +def err_unknown_any_var_function_type : Error< + "variable %0 with unknown type cannot be given a function type">; + +def err_filter_expression_integral : Error< + "filter expression type should be an integral value not %0">; + } // end of sema category + } // end of sema component. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h b/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h new file mode 100644 index 000000000000..aecf6eb269b7 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h @@ -0,0 +1,39 @@ +//===--- ExceptionSpecificationType.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 defines the ExceptionSpecificationType enumeration and various +// utility functions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H +#define LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H + +namespace clang { + +/// \brief The various types of exception specifications that exist in C++0x. +enum ExceptionSpecificationType { + EST_None, ///< no exception specification + EST_DynamicNone, ///< throw() + EST_Dynamic, ///< throw(T1, T2) + EST_MSAny, ///< Microsoft throw(...) extension + EST_BasicNoexcept, ///< noexcept + EST_ComputedNoexcept ///< noexcept(expression) +}; + +inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) { + return ESpecType >= EST_DynamicNone && ESpecType <= EST_MSAny; +} + +inline bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType) { + return ESpecType == EST_BasicNoexcept || ESpecType == EST_ComputedNoexcept; +} + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h new file mode 100644 index 000000000000..403a59a8d19c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h @@ -0,0 +1,25 @@ +//===--- ExpressionTraits.h - C++ Expression Traits Support Enumerations ----*- 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 enumerations for expression traits intrinsics. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_EXPRESSIONTRAITS_H +#define LLVM_CLANG_EXPRESSIONTRAITS_H + +namespace clang { + + enum ExpressionTrait { + ET_IsLValueExpr, + ET_IsRValueExpr + }; +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h index 563157fa8fbe..2ca344d55370 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_FILEMANAGER_H #include "clang/Basic/FileSystemOptions.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -105,7 +106,7 @@ class FileEntry { /// properties, such as uniquing files based on "inode", so that a file with two /// names (e.g. symlinked) will be treated as a single file. /// -class FileManager { +class FileManager : public llvm::RefCountedBase { FileSystemOptions FileSystemOpts; class UniqueDirContainer; @@ -176,10 +177,11 @@ class FileManager { /// const DirectoryEntry *getDirectory(llvm::StringRef DirName); - /// getFile - Lookup, cache, and verify the specified file (real or + /// \brief Lookup, cache, and verify the specified file (real or /// virtual). This returns NULL if the file doesn't exist. /// - const FileEntry *getFile(llvm::StringRef Filename); + /// \param openFile if true and the file exists, it will be opened. + const FileEntry *getFile(llvm::StringRef Filename, bool openFile = false); /// \brief Retrieve a file entry for a "virtual" file that acts as /// if there were a file with the given name on disk. The file @@ -194,13 +196,16 @@ class FileManager { llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename, std::string *ErrorStr = 0); + // getNoncachedStatValue - Will get the 'stat' information for the given path. + // If the path is relative, it will be resolved against the WorkingDir of the + // FileManager's FileSystemOptions. + bool getNoncachedStatValue(llvm::StringRef Path, struct stat &StatBuf); + /// \brief If path is not absolute and FileSystemOptions set the working /// directory, the path is modified to be relative to the given /// working directory. - static void FixupRelativePath(llvm::sys::Path &path, - const FileSystemOptions &FSOpts); + void FixupRelativePath(llvm::SmallVectorImpl &path) const; - /// \brief Produce an array mapping from the unique IDs assigned to each /// file to the corresponding FileEntry pointer. void GetUniqueIDMapping( diff --git a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h index d576643550bd..683ec8312e91 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h @@ -255,6 +255,25 @@ class IdentifierInfo { } }; +/// \brief an RAII object for [un]poisoning an identifier +/// within a certain scope. II is allowed to be null, in +/// which case, objects of this type have no effect. +class PoisonIdentifierRAIIObject { + IdentifierInfo *const II; + const bool OldValue; +public: + PoisonIdentifierRAIIObject(IdentifierInfo *II, bool NewValue) + : II(II), OldValue(II ? II->isPoisoned() : false) { + if(II) + II->setIsPoisoned(NewValue); + } + + ~PoisonIdentifierRAIIObject() { + if(II) + II->setIsPoisoned(OldValue); + } +}; + /// \brief An iterator that walks over all of the known identifiers /// in the lookup table. /// @@ -325,7 +344,7 @@ class ExternalIdentifierLookup { /// IdentifierTable - This table implements an efficient mapping from strings to /// IdentifierInfo nodes. It has no other purpose, but this is an -/// extremely performance-critical piece of the code, as each occurrance of +/// extremely performance-critical piece of the code, as each occurrence of /// every identifier goes through here when lexed. class IdentifierTable { // Shark shows that using MallocAllocator is *much* slower than using this @@ -443,6 +462,52 @@ class IdentifierTable { void AddKeywords(const LangOptions &LangOpts); }; +/// ObjCMethodFamily - A family of Objective-C methods. These +/// families have no inherent meaning in the language, but are +/// nonetheless central enough in the existing implementations to +/// merit direct AST support. While, in theory, arbitrary methods can +/// be considered to form families, we focus here on the methods +/// involving allocation and retain-count management, as these are the +/// most "core" and the most likely to be useful to diverse clients +/// without extra information. +/// +/// Both selectors and actual method declarations may be classified +/// into families. Method families may impose additional restrictions +/// beyond their selector name; for example, a method called '_init' +/// that returns void is not considered to be in the 'init' family +/// (but would be if it returned 'id'). It is also possible to +/// explicitly change or remove a method's family. Therefore the +/// method's family should be considered the single source of truth. +enum ObjCMethodFamily { + /// \brief No particular method family. + OMF_None, + + // Selectors in these families may have arbitrary arity, may be + // written with arbitrary leading underscores, and may have + // additional CamelCase "words" in their first selector chunk + // following the family name. + OMF_alloc, + OMF_copy, + OMF_init, + OMF_mutableCopy, + OMF_new, + + // These families are singletons consisting only of the nullary + // selector with the given name. + OMF_autorelease, + OMF_dealloc, + OMF_release, + OMF_retain, + OMF_retainCount +}; + +/// Enough bits to store any enumerator in ObjCMethodFamily or +/// InvalidObjCMethodFamily. +enum { ObjCMethodFamilyBitWidth = 4 }; + +/// An invalid value of ObjCMethodFamily. +enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 }; + /// Selector - This smart pointer class efficiently represents Objective-C /// method names. This class will either point to an IdentifierInfo or a /// MultiKeywordSelector (which is private). This enables us to optimize @@ -479,6 +544,8 @@ class Selector { return InfoPtr & ArgFlags; } + static ObjCMethodFamily getMethodFamilyImpl(Selector sel); + public: friend class SelectorTable; // only the SelectorTable can create these friend class DeclarationName; // and the AST's DeclarationName. @@ -541,6 +608,11 @@ class Selector { /// it as an std::string. std::string getAsString() const; + /// getMethodFamily - Derive the conventional family of this method. + ObjCMethodFamily getMethodFamily() const { + return getMethodFamilyImpl(*this); + } + static Selector getEmptyMarker() { return Selector(uintptr_t(-1)); } @@ -571,6 +643,9 @@ class SelectorTable { return Selector(ID, 0); } + /// Return the total amount of memory allocated for managing selectors. + size_t getTotalMemory() const; + /// constructSetterName - Return the setter name for the given /// identifier, i.e. "set" + Name where the initial character of Name /// has been capitalized. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h index a9fd25ce007a..ff13fe0882a3 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h @@ -34,6 +34,7 @@ class LangOptions { unsigned Digraphs : 1; // C94, C99 and C++ unsigned HexFloats : 1; // C99 Hexadecimal float constants. unsigned C99 : 1; // C99 Support + unsigned C1X : 1; // C1X Support unsigned Microsoft : 1; // Microsoft extensions. unsigned Borland : 1; // Borland extensions. unsigned CPlusPlus : 1; // C++ Support @@ -56,6 +57,7 @@ class LangOptions { unsigned ObjCExceptions : 1; // Support Objective-C exceptions. unsigned CXXExceptions : 1; // Support C++ exceptions. unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling. + unsigned TraditionalCPP : 1; /// Enable some traditional CPP emulation. unsigned RTTI : 1; // Support RTTI information. unsigned MSBitfields : 1; // MS-compatible structure layout @@ -88,6 +90,8 @@ class LangOptions { // used (instead of C99 semantics). unsigned NoInline : 1; // Should __NO_INLINE__ be defined. + unsigned Deprecated : 1; // Should __DEPRECATED be defined. + unsigned ObjCGCBitmapPrint : 1; // Enable printing of gc's bitmap layout // for __weak/__strong ivars. @@ -113,6 +117,7 @@ class LangOptions { unsigned NoConstantCFStrings : 1; // Do not do CF strings unsigned InlineVisibilityHidden : 1; // Whether inline C++ methods have // hidden visibility by default. + unsigned ParseUnknownAnytype: 1; /// Let the user write __unknown_anytype. unsigned SpellChecking : 1; // Whether to perform spell-checking for error // recovery. @@ -124,6 +129,11 @@ class LangOptions { unsigned DefaultFPContract : 1; // Default setting for FP_CONTRACT // FIXME: This is just a temporary option, for testing purposes. unsigned NoBitFieldTypeAlign : 1; + unsigned FakeAddressSpaceMap : 1; // Use a fake address space map, for + // testing languages such as OpenCL. + + unsigned MRTD : 1; // -mrtd calling convention + unsigned DelayedTemplateParsing : 1; // Delayed template parsing private: // We declare multibit enums as unsigned because MSVC insists on making enums @@ -165,10 +175,10 @@ class LangOptions { AppleKext = 0; ObjCDefaultSynthProperties = 0; NoConstantCFStrings = 0; InlineVisibilityHidden = 0; - C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0; + C99 = C1X = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; Exceptions = ObjCExceptions = CXXExceptions = SjLjExceptions = 0; - Freestanding = NoBuiltin = 0; + TraditionalCPP = Freestanding = NoBuiltin = 0; MSBitfields = 0; NeXTRuntime = 1; RTTI = 1; @@ -206,6 +216,8 @@ class LangOptions { GNUInline = 0; NoInline = 0; + Deprecated = 0; + CharIsSigned = 1; ShortWChar = 0; ShortEnums = 0; @@ -217,6 +229,10 @@ class LangOptions { FastRelaxedMath = 0; DefaultFPContract = 0; NoBitFieldTypeAlign = 0; + FakeAddressSpaceMap = 0; + MRTD = 0; + DelayedTemplateParsing = 0; + ParseUnknownAnytype = 0; } GCMode getGCMode() const { return (GCMode) GC; } @@ -241,8 +257,8 @@ class LangOptions { SignedOverflowBehavior = (unsigned)V; } - bool areExceptionsEnabled() const { - return Exceptions; + bool isSignedOverflowDefined() const { + return getSignedOverflowBehavior() == SOB_Defined; } }; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenCL.h b/contrib/llvm/tools/clang/include/clang/Basic/OpenCL.h new file mode 100644 index 000000000000..6f9785f25677 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenCL.h @@ -0,0 +1,28 @@ +//===--- OpenCL.h - OpenCL enums --------------------------------*- 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 some OpenCL-specific enums. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_OPENCL_H +#define LLVM_CLANG_BASIC_OPENCL_H + +namespace clang { + +/// Names for the OpenCL image access qualifiers (OpenCL 1.1 6.6). +enum OpenCLImageAccess { + CLIA_read_only = 1, + CLIA_write_only = 2, + CLIA_read_write = 3 +}; + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h index c63619440551..7d7c0896f505 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h @@ -53,7 +53,7 @@ class PartialDiagnostic { /// DiagArgumentsVal - The values for the various substitution positions. /// This is used when the argument is not an std::string. The specific value - /// is mangled into an intptr_t and the intepretation depends on exactly + /// is mangled into an intptr_t and the interpretation depends on exactly /// what sort of argument kind it is. intptr_t DiagArgumentsVal[MaxArguments]; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h index 605c4bbafc74..14bb2b724fd4 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h @@ -16,6 +16,7 @@ #include "llvm/Support/PointerLikeTypeTraits.h" #include +#include #include namespace llvm { @@ -295,6 +296,14 @@ class FullSourceLoc : public SourceLocation { return isBeforeInTranslationUnitThan((SourceLocation)Loc); } + /// \brief Comparison function class, useful for sorting FullSourceLocs. + struct BeforeThanCompare : public std::binary_function { + bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const { + return lhs.isBeforeInTranslationUnitThan(rhs); + } + }; + /// Prints information about this FullSourceLoc to stderr. Useful for /// debugging. void dump() const { SourceLocation::dump(*SrcMgr); } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h index b1443dad09fd..c121bbb34f34 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h @@ -19,12 +19,13 @@ #include "llvm/Support/DataTypes.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/MemoryBuffer.h" #include #include namespace llvm { -class MemoryBuffer; class StringRef; } @@ -66,10 +67,16 @@ namespace SrcMgr { mutable llvm::PointerIntPair Buffer; public: - /// Reference to the file entry. This reference does not own - /// the FileEntry object. It is possible for this to be NULL if + /// Reference to the file entry representing this ContentCache. + /// This reference does not own the FileEntry object. + /// It is possible for this to be NULL if /// the ContentCache encapsulates an imaginary text buffer. - const FileEntry *Entry; + const FileEntry *OrigEntry; + + /// \brief References the file which the contents were actually loaded from. + /// Can be different from 'Entry' if we overridden the contents of one file + /// with the contents of another file. + const FileEntry *ContentsEntry; /// SourceLineCache - A bump pointer allocated array of offsets for each /// source line. This is lazily computed. This is owned by the @@ -104,6 +111,10 @@ namespace SrcMgr { /// this ContentCache. This can be 0 if the MemBuffer was not actually /// instantiated. unsigned getSizeBytesMapped() const; + + /// Returns the kind of memory used to back the memory buffer for + /// this content cache. This is used for performance analysis. + llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const; void setBuffer(const llvm::MemoryBuffer *B) { assert(!Buffer.getPointer() && "MemoryBuffer already set."); @@ -132,17 +143,23 @@ namespace SrcMgr { } ContentCache(const FileEntry *Ent = 0) - : Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {} + : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent), + SourceLineCache(0), NumLines(0) {} + + ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) + : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt), + SourceLineCache(0), NumLines(0) {} ~ContentCache(); /// The copy ctor does not allow copies where source object has either /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory - /// is not transfered, so this is a logical error. + /// is not transferred, so this is a logical error. ContentCache(const ContentCache &RHS) : Buffer(0, false), SourceLineCache(0) { - Entry = RHS.Entry; + OrigEntry = RHS.OrigEntry; + ContentsEntry = RHS.ContentsEntry; assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 && "Passed ContentCache object cannot own a buffer."); @@ -301,7 +318,10 @@ class ExternalSLocEntrySource { virtual ~ExternalSLocEntrySource(); /// \brief Read the source location entry with index ID. - virtual void ReadSLocEntry(unsigned ID) = 0; + /// + /// \returns true if an error occurred that prevented the source-location + /// entry from being loaded. + virtual bool ReadSLocEntry(unsigned ID) = 0; }; @@ -364,9 +384,9 @@ class IsBeforeInTranslationUnitCache { /// Spelling locations represent where the bytes corresponding to a token came /// from and instantiation locations represent where the location is in the /// user's view. In the case of a macro expansion, for example, the spelling -/// location indicates where the expanded token came from and the instantiation +/// location indicates where the expanded token came from and the instantiation /// location specifies where it was expanded. -class SourceManager { +class SourceManager : public llvm::RefCountedBase { /// \brief Diagnostic object. Diagnostic &Diag; @@ -380,6 +400,13 @@ class SourceManager { /// non-null, FileEntry pointers. llvm::DenseMap FileInfos; + /// \brief True if the ContentCache for files that are overriden by other + /// files, should report the original file name. Defaults to true. + bool OverridenFilesKeepOriginalName; + + /// \brief Files that have been overriden with the contents from another file. + llvm::DenseMap OverriddenFiles; + /// MemBufferInfos - Information about various memory buffers that we have /// read in. All FileEntry* within the stored ContentCache objects are NULL, /// as they do not refer to a file. @@ -425,6 +452,9 @@ class SourceManager { // Cache results for the isBeforeInTranslationUnit method. mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache; + // Cache for the "fake" buffer used for error-recovery purposes. + mutable llvm::MemoryBuffer *FakeBufferForRecovery; + // SourceManager doesn't support copy construction. explicit SourceManager(const SourceManager&); void operator=(const SourceManager&); @@ -438,6 +468,12 @@ class SourceManager { FileManager &getFileManager() const { return FileMgr; } + /// \brief Set true if the SourceManager should report the original file name + /// for contents of files that were overriden by other files.Defaults to true. + void setOverridenFilesKeepOriginalName(bool value) { + OverridenFilesKeepOriginalName = value; + } + //===--------------------------------------------------------------------===// // MainFileID creation and querying methods. //===--------------------------------------------------------------------===// @@ -527,6 +563,15 @@ class SourceManager { const llvm::MemoryBuffer *Buffer, bool DoNotFree = false); + /// \brief Override the the given source file with another one. + /// + /// \param SourceFile the source file which will be overriden. + /// + /// \param NewFile the file whose contents will be used as the + /// data instead of the contents of the given source file. + void overrideFileContents(const FileEntry *SourceFile, + const FileEntry *NewFile); + //===--------------------------------------------------------------------===// // FileID manipulation methods. //===--------------------------------------------------------------------===// @@ -536,18 +581,48 @@ class SourceManager { /// buffer and returns a non-empty error string. const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc, bool *Invalid = 0) const { - return getSLocEntry(FID).getFile().getContentCache() - ->getBuffer(Diag, *this, Loc, Invalid); + bool MyInvalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); + if (MyInvalid || !Entry.isFile()) { + if (Invalid) + *Invalid = true; + + return getFakeBufferForRecovery(); + } + + return Entry.getFile().getContentCache()->getBuffer(Diag, *this, Loc, + Invalid); } const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const { - return getSLocEntry(FID).getFile().getContentCache() - ->getBuffer(Diag, *this, SourceLocation(), Invalid); + bool MyInvalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); + if (MyInvalid || !Entry.isFile()) { + if (Invalid) + *Invalid = true; + + return getFakeBufferForRecovery(); + } + + return Entry.getFile().getContentCache()->getBuffer(Diag, *this, + SourceLocation(), + Invalid); } /// getFileEntryForID - Returns the FileEntry record for the provided FileID. const FileEntry *getFileEntryForID(FileID FID) const { - return getSLocEntry(FID).getFile().getContentCache()->Entry; + bool MyInvalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); + if (MyInvalid || !Entry.isFile()) + return 0; + + return Entry.getFile().getContentCache()->OrigEntry; + } + + /// Returns the FileEntry record for the provided SLocEntry. + const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const + { + return sloc.getFile().getContentCache()->OrigEntry; } /// getBufferData - Return a StringRef to the source buffer data for the @@ -581,8 +656,12 @@ class SourceManager { /// first byte of the specified file. SourceLocation getLocForStartOfFile(FileID FID) const { assert(FID.ID < SLocEntryTable.size() && "FileID out of range"); - assert(getSLocEntry(FID).isFile() && "FileID is not a file"); - unsigned FileOffset = getSLocEntry(FID).getOffset(); + bool Invalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); + if (Invalid || !Entry.isFile()) + return SourceLocation(); + + unsigned FileOffset = Entry.getOffset(); return SourceLocation::getFileLoc(FileOffset); } @@ -774,6 +853,28 @@ class SourceManager { /// \brief Retrieve the stored line table. LineTableInfo &getLineTable(); + //===--------------------------------------------------------------------===// + // Queries for performance analysis. + //===--------------------------------------------------------------------===// + + /// Return the total amount of physical memory allocated by the + /// ContentCache allocator. + size_t getContentCacheSize() const { + return ContentCacheAlloc.getTotalMemory(); + } + + struct MemoryBufferSizes { + const size_t malloc_bytes; + const size_t mmap_bytes; + + MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) + : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} + }; + + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + MemoryBufferSizes getMemoryBufferSizes() const; + //===--------------------------------------------------------------------===// // Other miscellaneous methods. //===--------------------------------------------------------------------===// @@ -810,17 +911,22 @@ class SourceManager { // any other external source). unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); } - const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const { + const SrcMgr::SLocEntry &getSLocEntry(unsigned ID, bool *Invalid = 0) const { assert(ID < SLocEntryTable.size() && "Invalid id"); + // If we haven't loaded this source-location entry from the external source + // yet, do so now. if (ExternalSLocEntries && ID < SLocEntryLoaded.size() && - !SLocEntryLoaded[ID]) - ExternalSLocEntries->ReadSLocEntry(ID); + !SLocEntryLoaded[ID] && + ExternalSLocEntries->ReadSLocEntry(ID) && + Invalid) + *Invalid = true; + return SLocEntryTable[ID]; } - const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const { - return getSLocEntry(FID.ID); + const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const { + return getSLocEntry(FID.ID, Invalid); } unsigned getNextOffset() const { return NextOffset; } @@ -836,6 +942,8 @@ class SourceManager { void ClearPreallocatedSLocEntries(); private: + const llvm::MemoryBuffer *getFakeBufferForRecovery() const; + /// isOffsetInFileID - Return true if the specified FileID contains the /// specified SourceLocation offset. This is a very hot method. inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const { diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h index e6b6218100ad..2f0ad9ffb688 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h @@ -55,6 +55,7 @@ namespace clang { TST_typeofExpr, TST_decltype, // C++0x decltype TST_auto, // C++0x auto + TST_unknown_anytype, // __unknown_anytype extension TST_error // erroneous type }; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td index be0d8ff091e8..15ac760ce725 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td @@ -41,6 +41,7 @@ def ObjCForCollectionStmt : Stmt; // C++ statments def CXXCatchStmt : Stmt; def CXXTryStmt : Stmt; +def CXXForRangeStmt : Stmt; // Expressions def Expr : Stmt<1>; @@ -54,7 +55,7 @@ def CharacterLiteral : DStmt; def ParenExpr : DStmt; def UnaryOperator : DStmt; def OffsetOfExpr : DStmt; -def SizeOfAlignOfExpr : DStmt; +def UnaryExprOrTypeTraitExpr : DStmt; def ArraySubscriptExpr : DStmt; def CallExpr : DStmt; def MemberExpr : DStmt; @@ -74,6 +75,7 @@ def DesignatedInitExpr : DStmt; def ImplicitValueInitExpr : DStmt; def ParenListExpr : DStmt; def VAArgExpr : DStmt; +def GenericSelectionExpr : DStmt; // GNU Extensions. def AddrLabelExpr : DStmt; @@ -102,6 +104,8 @@ def CXXDeleteExpr : DStmt; def CXXPseudoDestructorExpr : DStmt; def UnaryTypeTraitExpr : DStmt; def BinaryTypeTraitExpr : DStmt; +def ArrayTypeTraitExpr : DStmt; +def ExpressionTraitExpr : DStmt; def DependentScopeDeclRefExpr : DStmt; def CXXConstructExpr : DStmt; def CXXBindTemporaryExpr : DStmt; @@ -138,4 +142,7 @@ def OpaqueValueExpr : DStmt; // Microsoft Extensions. def CXXUuidofExpr : DStmt; +def SEHTryStmt : Stmt; +def SEHExceptStmt : Stmt; +def SEHFinallyStmt : Stmt; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h index f1edd1d45162..8bc60ff5386d 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h @@ -35,6 +35,17 @@ namespace clang { }; } + /// PTX builtins + namespace PTX { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsPTX.def" + LastTSBuiltin + }; + } + + /// X86 builtins namespace X86 { enum { diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h index b9087f2c47e8..b830bf2f82cd 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h @@ -14,18 +14,20 @@ #ifndef LLVM_CLANG_BASIC_TARGETINFO_H #define LLVM_CLANG_BASIC_TARGETINFO_H -// FIXME: Daniel isn't smart enough to use a prototype for this. +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" +#include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/VersionTuple.h" #include #include #include namespace llvm { struct fltSemantics; -class StringRef; } namespace clang { @@ -56,7 +58,7 @@ enum TargetCXXABI { /// TargetInfo - This class exposes information about the current target. /// -class TargetInfo { +class TargetInfo : public llvm::RefCountedBase { llvm::Triple Triple; protected: // Target values set by the ctor of the actual target implementation. Default @@ -78,6 +80,10 @@ class TargetInfo { const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat; unsigned char RegParmMax, SSERegParmMax; TargetCXXABI CXXABI; + const LangAS::Map *AddrSpaceMap; + + mutable llvm::StringRef PlatformName; + mutable VersionTuple PlatformMinVersion; unsigned HasAlignMac68kSupport : 1; unsigned RealTypeUsesObjCFPRet : 3; @@ -530,6 +536,19 @@ class TargetInfo { virtual const char *getStaticInitSectionSpecifier() const { return 0; } + + const LangAS::Map &getAddressSpaceMap() const { + return *AddrSpaceMap; + } + + /// \brief Retrieve the name of the platform as it is used in the + /// availability attribute. + llvm::StringRef getPlatformName() const { return PlatformName; } + + /// \brief Retrieve the minimum desired version of the platform, to + /// which the program should be compiled. + VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; } + protected: virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return PointerWidth; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def index b84b04da3de2..f9d1f4ef158e 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def @@ -38,6 +38,9 @@ #ifndef OBJC2_AT_KEYWORD #define OBJC2_AT_KEYWORD(X) #endif +#ifndef TESTING_KEYWORD +#define TESTING_KEYWORD(X, L) KEYWORD(X, L) +#endif #ifndef ANNOTATION #define ANNOTATION(X) TOK(annot_ ## X) #endif @@ -94,7 +97,8 @@ PPKEYWORD(unassert) TOK(unknown) // Not a token. TOK(eof) // End of file. -TOK(eom) // End of macro (end of line inside a macro). +TOK(eod) // End of preprocessing directive (end of line inside a + // directive). TOK(code_completion) // Code completion marker TOK(cxx_defaultarg_end) // C++ default argument end marker @@ -186,6 +190,7 @@ PUNCTUATOR(greatergreatergreater, ">>>") // is a keyword in the implementation namespace that should // always be treated as a keyword // KEYC99 - This is a keyword introduced to C in C99 +// KEYC1X - This is a keyword introduced to C in C1X // KEYCXX - This is a C++ keyword, or a C++-specific keyword in the // implementation namespace // KEYNOCXX - This is a keyword in every non-C++ dialect. @@ -195,6 +200,7 @@ PUNCTUATOR(greatergreatergreater, ">>>") // KEYOPENCL - This is a keyword in OpenCL // KEYALTIVEC - This is a keyword in AltiVec // KEYBORLAND - This is a keyword if Borland extensions are enabled +// BOOLSUPPORT - This is a keyword if 'bool' is a built-in type // KEYWORD(auto , KEYALL) KEYWORD(break , KEYALL) @@ -232,7 +238,9 @@ KEYWORD(volatile , KEYALL) KEYWORD(while , KEYALL) KEYWORD(_Bool , KEYNOCXX) KEYWORD(_Complex , KEYALL) +KEYWORD(_Generic , KEYALL) KEYWORD(_Imaginary , KEYALL) +KEYWORD(_Static_assert , KEYALL) KEYWORD(__func__ , KEYALL) // C++ 2.11p1: Keywords. @@ -251,7 +259,7 @@ KEYWORD(mutable , KEYCXX) KEYWORD(namespace , KEYCXX) KEYWORD(new , KEYCXX) KEYWORD(operator , KEYCXX) -KEYWORD(private , KEYCXX) +KEYWORD(private , KEYCXX|KEYOPENCL) KEYWORD(protected , KEYCXX) KEYWORD(public , KEYCXX) KEYWORD(reinterpret_cast , KEYCXX) @@ -328,11 +336,50 @@ KEYWORD(__is_class , KEYCXX) KEYWORD(__is_convertible_to , KEYCXX) KEYWORD(__is_empty , KEYCXX) KEYWORD(__is_enum , KEYCXX) -KEYWORD(__is_pod , KEYCXX) -KEYWORD(__is_polymorphic , KEYCXX) -KEYWORD(__is_union , KEYCXX) // Tentative name - there's no implementation of std::is_literal_type yet. KEYWORD(__is_literal , KEYCXX) +// Name for GCC 4.6 compatibility - people have already written libraries using +// this name unfortunately. +KEYWORD(__is_literal_type , KEYCXX) +KEYWORD(__is_pod , KEYCXX) +KEYWORD(__is_polymorphic , KEYCXX) +KEYWORD(__is_trivial , KEYCXX) +KEYWORD(__is_union , KEYCXX) + +// Embarcadero Expression Traits +KEYWORD(__is_lvalue_expr , KEYCXX) +KEYWORD(__is_rvalue_expr , KEYCXX) + +// Embarcadero Unary Type Traits +KEYWORD(__is_arithmetic , KEYCXX) +KEYWORD(__is_floating_point , KEYCXX) +KEYWORD(__is_integral , KEYCXX) +KEYWORD(__is_complete_type , KEYCXX) +KEYWORD(__is_void , KEYCXX) +KEYWORD(__is_array , KEYCXX) +KEYWORD(__is_function , KEYCXX) +KEYWORD(__is_reference , KEYCXX) +KEYWORD(__is_lvalue_reference , KEYCXX) +KEYWORD(__is_rvalue_reference , KEYCXX) +KEYWORD(__is_fundamental , KEYCXX) +KEYWORD(__is_object , KEYCXX) +KEYWORD(__is_scalar , KEYCXX) +KEYWORD(__is_compound , KEYCXX) +KEYWORD(__is_pointer , KEYCXX) +KEYWORD(__is_member_object_pointer , KEYCXX) +KEYWORD(__is_member_function_pointer, KEYCXX) +KEYWORD(__is_member_pointer , KEYCXX) +KEYWORD(__is_const , KEYCXX) +KEYWORD(__is_volatile , KEYCXX) +KEYWORD(__is_standard_layout , KEYCXX) +KEYWORD(__is_signed , KEYCXX) +KEYWORD(__is_unsigned , KEYCXX) + +// Embarcadero Binary Type Traits +KEYWORD(__is_same , KEYCXX) +KEYWORD(__is_convertible , KEYCXX) +KEYWORD(__array_rank , KEYCXX) +KEYWORD(__array_extent , KEYCXX) // Apple Extension. KEYWORD(__private_extern__ , KEYALL) @@ -345,9 +392,23 @@ KEYWORD(__fastcall , KEYALL) KEYWORD(__thiscall , KEYALL) KEYWORD(__forceinline , KEYALL) -// OpenCL-specific keywords (see OpenCL 1.1 [6.1.9]) +// OpenCL-specific keywords KEYWORD(__kernel , KEYOPENCL) ALIAS("kernel", __kernel , KEYOPENCL) +KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC) +KEYWORD(__private , KEYOPENCL) +KEYWORD(__global , KEYOPENCL) +KEYWORD(__local , KEYOPENCL) +KEYWORD(__constant , KEYOPENCL) +ALIAS("global", __global , KEYOPENCL) +ALIAS("local", __local , KEYOPENCL) +ALIAS("constant", __constant , KEYOPENCL) +KEYWORD(__read_only , KEYOPENCL) +KEYWORD(__write_only , KEYOPENCL) +KEYWORD(__read_write , KEYOPENCL) +ALIAS("read_only", __read_only , KEYOPENCL) +ALIAS("write_only", __write_only , KEYOPENCL) +ALIAS("read_write", __read_write , KEYOPENCL) // Borland Extensions. KEYWORD(__pascal , KEYALL) @@ -358,18 +419,19 @@ KEYWORD(__pixel , KEYALTIVEC) // Alternate spelling for various tokens. There are GCC extensions in all // languages, but should not be disabled in strict conformance mode. -ALIAS("__attribute__", __attribute, KEYALL) -ALIAS("__const" , const , KEYALL) -ALIAS("__const__" , const , KEYALL) ALIAS("__alignof__" , __alignof , KEYALL) ALIAS("__asm" , asm , KEYALL) ALIAS("__asm__" , asm , KEYALL) +ALIAS("__attribute__", __attribute, KEYALL) ALIAS("__complex" , _Complex , KEYALL) ALIAS("__complex__" , _Complex , KEYALL) +ALIAS("__const" , const , KEYALL) +ALIAS("__const__" , const , KEYALL) +ALIAS("__decltype" , decltype , KEYCXX) ALIAS("__imag__" , __imag , KEYALL) ALIAS("__inline" , inline , KEYALL) ALIAS("__inline__" , inline , KEYALL) -ALIAS("__nullptr" , nullptr , KEYCXX) +ALIAS("__nullptr" , nullptr , KEYCXX) ALIAS("__real__" , __real , KEYALL) ALIAS("__restrict" , restrict , KEYALL) ALIAS("__restrict__" , restrict , KEYALL) @@ -384,6 +446,14 @@ ALIAS("__volatile__" , volatile , KEYALL) KEYWORD(__ptr64 , KEYMS) KEYWORD(__w64 , KEYMS) KEYWORD(__uuidof , KEYMS | KEYBORLAND) +KEYWORD(__try , KEYMS | KEYBORLAND) +KEYWORD(__except , KEYMS | KEYBORLAND) +KEYWORD(__finally , KEYMS | KEYBORLAND) +KEYWORD(__leave , KEYMS | KEYBORLAND) +KEYWORD(__int64 , KEYMS) +ALIAS("__int8" , char , KEYMS) +ALIAS("__int16" , short , KEYMS) +ALIAS("__int32" , int , KEYMS) ALIAS("_asm" , asm , KEYMS) ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND) ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND) @@ -391,6 +461,8 @@ ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND) ALIAS("_thiscall" , __thiscall , KEYMS) ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) ALIAS("_inline" , inline , KEYMS) +ALIAS("_declspec" , __declspec , KEYMS) +ALIAS("__interface" , class , KEYMS) // Borland Extensions which should be disabled in strict conformance mode. ALIAS("_pascal" , __pascal , KEYBORLAND) @@ -399,9 +471,12 @@ ALIAS("_pascal" , __pascal , KEYBORLAND) ALIAS("__char16_t" , char16_t , KEYCXX) ALIAS("__char32_t" , char32_t , KEYCXX) +// Clang-specific keywords enabled only in testing. +TESTING_KEYWORD(__unknown_anytype , KEYALL) + //===----------------------------------------------------------------------===// -// Objective-C @-preceeded keywords. +// Objective-C @-preceded keywords. //===----------------------------------------------------------------------===// // These have meaning after an '@' in Objective-C mode. These define enums in @@ -443,6 +518,7 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly ANNOTATION(template_id) // annotation for a C++ template-id that names a // function template specialization (not a type), // e.g., "std::swap" +ANNOTATION(primary_expr) // annotation for a primary expression // Annotation for #pragma unused(...) // For each argument inside the parentheses the pragma handler will produce @@ -450,6 +526,7 @@ ANNOTATION(template_id) // annotation for a C++ template-id that names a ANNOTATION(pragma_unused) #undef ANNOTATION +#undef TESTING_KEYWORD #undef OBJC2_AT_KEYWORD #undef OBJC1_AT_KEYWORD #undef CXX_KEYWORD_OPERATOR diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h index 00c6e9ed5000..4a2a2c67e0eb 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h @@ -27,20 +27,59 @@ namespace clang { UTT_HasTrivialDestructor, UTT_HasVirtualDestructor, UTT_IsAbstract, + UTT_IsArithmetic, + UTT_IsArray, UTT_IsClass, + UTT_IsCompleteType, + UTT_IsCompound, + UTT_IsConst, UTT_IsEmpty, UTT_IsEnum, + UTT_IsFloatingPoint, + UTT_IsFunction, + UTT_IsFundamental, + UTT_IsIntegral, + UTT_IsLiteral, + UTT_IsLvalueReference, + UTT_IsMemberFunctionPointer, + UTT_IsMemberObjectPointer, + UTT_IsMemberPointer, + UTT_IsObject, UTT_IsPOD, + UTT_IsPointer, UTT_IsPolymorphic, + UTT_IsReference, + UTT_IsRvalueReference, + UTT_IsScalar, + UTT_IsSigned, + UTT_IsStandardLayout, + UTT_IsTrivial, UTT_IsUnion, - UTT_IsLiteral + UTT_IsUnsigned, + UTT_IsVoid, + UTT_IsVolatile }; /// BinaryTypeTrait - Names for the binary type traits. enum BinaryTypeTrait { BTT_IsBaseOf, - BTT_TypeCompatible, - BTT_IsConvertibleTo + BTT_IsConvertible, + BTT_IsConvertibleTo, + BTT_IsSame, + BTT_TypeCompatible + }; + + /// ArrayTypeTrait - Names for the array type traits. + enum ArrayTypeTrait { + ATT_ArrayRank, + ATT_ArrayExtent + }; + + /// UnaryExprOrTypeTrait - Names for the "expression or type" traits. + enum UnaryExprOrTypeTrait { + UETT_SizeOf, + UETT_AlignOf, + UETT_VecStep }; } diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Version.h b/contrib/llvm/tools/clang/include/clang/Basic/Version.h index ede68ed50d52..15cdf1fa02e6 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Version.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Version.h @@ -58,6 +58,11 @@ namespace clang { /// which includes the clang version number, the repository version, /// and the vendor tag. std::string getClangFullVersion(); + + /// \brief Retrieves a string representing the complete clang version suitable + /// for use in the CPP __VERSION__ macro, which includes the clang version + /// number, the repository version, and the vendor tag. + std::string getClangFullCPPVersion(); } #endif // LLVM_CLANG_BASIC_VERSION_H diff --git a/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h b/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h new file mode 100644 index 000000000000..91eb68eaad9f --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h @@ -0,0 +1,126 @@ +//===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the VersionTuple class, which represents a version in +// the form major[.minor[.subminor]]. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_VERSIONTUPLE_H +#define LLVM_CLANG_BASIC_VERSIONTUPLE_H + +#include "llvm/ADT/Optional.h" +#include + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +/// \brief Represents a version number in the form major[.minor[.subminor]]. +class VersionTuple { + unsigned Major; + unsigned Minor : 31; + unsigned Subminor : 31; + unsigned HasMinor : 1; + unsigned HasSubminor : 1; + +public: + VersionTuple() + : Major(0), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false) { } + + explicit VersionTuple(unsigned Major) + : Major(Major), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false) + { } + + explicit VersionTuple(unsigned Major, unsigned Minor) + : Major(Major), Minor(Minor), Subminor(0), HasMinor(true), + HasSubminor(false) + { } + + explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor) + : Major(Major), Minor(Minor), Subminor(Subminor), HasMinor(true), + HasSubminor(true) + { } + + /// \brief Determine whether this version information is empty + /// (e.g., all version components are zero). + bool empty() const { return Major == 0 && Minor == 0 && Subminor == 0; } + + /// \brief Retrieve the major version number. + unsigned getMajor() const { return Major; } + + /// \brief Retrieve the minor version number, if provided. + llvm::Optional getMinor() const { + if (!HasMinor) + return llvm::Optional(); + return Minor; + } + + /// \brief Retrieve the subminor version number, if provided. + llvm::Optional getSubminor() const { + if (!HasSubminor) + return llvm::Optional(); + return Subminor; + } + + /// \brief Determine if two version numbers are equivalent. If not + /// provided, minor and subminor version numbers are considered to be zero. + friend bool operator==(const VersionTuple& X, const VersionTuple &Y) { + return X.Major == Y.Major && X.Minor == Y.Minor && X.Subminor == Y.Subminor; + } + + /// \brief Determine if two version numbers are not equivalent. If + /// not provided, minor and subminor version numbers are considered to be + /// zero. + friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) { + return !(X == Y); + } + + /// \brief Determine whether one version number precedes another. If not + /// provided, minor and subminor version numbers are considered to be zero. + friend bool operator<(const VersionTuple &X, const VersionTuple &Y) { + if (X.Major != Y.Major) + return X.Major < Y.Major; + + if (X.Minor != Y.Minor) + return X.Minor < Y.Minor; + + return X.Subminor < Y.Subminor; + } + + /// \brief Determine whether one version number follows another. If not + /// provided, minor and subminor version numbers are considered to be zero. + friend bool operator>(const VersionTuple &X, const VersionTuple &Y) { + return Y < X; + } + + /// \brief Determine whether one version number precedes or is + /// equivalent to another. If not provided, minor and subminor + /// version numbers are considered to be zero. + friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) { + return !(Y < X); + } + + /// \brief Determine whether one version number follows or is + /// equivalent to another. If not provided, minor and subminor + /// version numbers are considered to be zero. + friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) { + return !(X < Y); + } + + /// \brief Retrieve a string representation of the version number/ + std::string getAsString() const; +}; + +/// \brief Print a version number. +llvm::raw_ostream& operator<<(llvm::raw_ostream &Out, const VersionTuple &V); + +} // end namespace clang +#endif // LLVM_CLANG_BASIC_VERSIONTUPLE_H diff --git a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td index 880a0da6bc68..6d6c7c7bede3 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td @@ -22,13 +22,11 @@ def OP_SUB : Op; def OP_SUBL : Op; def OP_SUBW : Op; def OP_MUL : Op; -def OP_MULL : Op; def OP_MLA : Op; def OP_MLAL : Op; def OP_MLS : Op; def OP_MLSL : Op; def OP_MUL_N : Op; -def OP_MULL_N: Op; def OP_MLA_N : Op; def OP_MLS_N : Op; def OP_MLAL_N : Op; @@ -144,8 +142,7 @@ def VQDMULH : SInst<"vqdmulh", "ddd", "siQsQi">; def VQRDMULH : SInst<"vqrdmulh", "ddd", "siQsQi">; def VQDMLAL : SInst<"vqdmlal", "wwdd", "si">; def VQDMLSL : SInst<"vqdmlsl", "wwdd", "si">; -def VMULL : Inst<"vmull", "wdd", "csiUcUsUi", OP_MULL>; -def VMULLP : SInst<"vmull", "wdd", "Pc">; +def VMULL : SInst<"vmull", "wdd", "csiUcUsUiPc">; def VQDMULL : SInst<"vqdmull", "wdd", "si">; //////////////////////////////////////////////////////////////////////////////// @@ -331,7 +328,7 @@ def VMLSL_LANE : Inst<"vmlsl_lane", "wwddi", "siUsUi", OP_MLSL_LN>; def VQDMLSL_LANE : Inst<"vqdmlsl_lane", "wwddi", "si", OP_QDMLSL_LN>; def VMUL_N : Inst<"vmul_n", "dds", "sifUsUiQsQiQfQUsQUi", OP_MUL_N>; def VMUL_LANE : Inst<"vmul_lane", "ddgi", "sifUsUiQsQiQfQUsQUi", OP_MUL_LN>; -def VMULL_N : Inst<"vmull_n", "wda", "siUsUi", OP_MULL_N>; +def VMULL_N : SInst<"vmull_n", "wda", "siUsUi">; def VMULL_LANE : Inst<"vmull_lane", "wddi", "siUsUi", OP_MULL_LN>; def VQDMULL_N : SInst<"vqdmull_n", "wda", "si">; def VQDMULL_LANE : Inst<"vqdmull_lane", "wddi", "si", OP_QDMULL_LN>; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Arg.h b/contrib/llvm/tools/clang/include/clang/Driver/Arg.h index a52789e69929..265d6d871672 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Arg.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Arg.h @@ -13,7 +13,6 @@ #include "Util.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include #include namespace clang { diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td index 50472ffdf9cd..2643c4f0e854 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td @@ -29,6 +29,10 @@ def I : JoinedOrSeparate<"-I">, MetaVarName<"">, HelpText<"Add directory to include search path">; def n : Flag<"-n">, HelpText<"Don't automatically start assembly file with a text section">; +def L : Flag<"-L">, + HelpText<"Save temporary labels in the symbol table. " + "Note this may change .s semantics, it should almost never be used " + "on compiler generated code!">; //===----------------------------------------------------------------------===// // Frontend Options @@ -72,4 +76,4 @@ def relax_all : Flag<"-relax-all">, HelpText<"Relax all fixups (for performance testing)">; def no_exec_stack : Flag<"--noexecstack">, - HelpText<"Mark the file as not needing an executable stack">; \ No newline at end of file + HelpText<"Mark the file as not needing an executable stack">; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td index 186ba9bf0ceb..258ae155bc13 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td @@ -42,14 +42,6 @@ def analysis_CFGAddImplicitDtors : Flag<"-cfg-add-implicit-dtors">, HelpText<"Add C++ implicit destructors to CFGs for all analyses">; def analysis_CFGAddInitializers : Flag<"-cfg-add-initializers">, HelpText<"Add C++ initializers to CFGs for all analyses">; -def analysis_WarnUninitVals : Flag<"-warn-uninit-values">, - HelpText<"Warn about uses of uninitialized variables">; -def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">, - HelpText<"Run the [Core] Foundation reference count checker">; -def analysis_AnalyzerStats : Flag<"-analyzer-stats">, - HelpText<"Emit warnings with analyzer statistics">; -def analysis_WarnBufferOverflows : Flag<"-analyzer-check-buffer-overflows">, - HelpText<"Warn about buffer overflows">; def analyzer_store : Separate<"-analyzer-store">, HelpText<"Source Code Analysis - Abstract Memory Store Models">; @@ -71,8 +63,6 @@ def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-bloc HelpText<"Analyze the definitions of blocks in addition to functions">; def analyzer_display_progress : Flag<"-analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">; -def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">, - HelpText<"Use experimental path-sensitive checks">; def analyze_function : Separate<"-analyze-function">, HelpText<"Run analysis on specific function">; def analyze_function_EQ : Joined<"-analyze-function=">, Alias; @@ -120,7 +110,10 @@ def disable_red_zone : Flag<"-disable-red-zone">, HelpText<"Do not emit code that uses the red zone.">; def dwarf_debug_flags : Separate<"-dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; +def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, + HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; def g : Flag<"-g">, HelpText<"Generate source level debug information">; +def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, HelpText<"Don't use the cfi directives">; def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, HelpText<"Generate runtime checks for undefined behavior.">; def flimit_debug_info : Flag<"-flimit-debug-info">, @@ -143,6 +136,10 @@ def fdata_sections : Flag<"-fdata-sections">, HelpText<"Place each data in its own section (ELF Only)">; def funroll_loops : Flag<"-funroll-loops">, HelpText<"Turn on loop unroller">; +def femit_coverage_notes : Flag<"-femit-coverage-notes">, + HelpText<"Emit a gcov coverage notes file when compiling.">; +def femit_coverage_data: Flag<"-femit-coverage-data">, + HelpText<"Instrument the program to emit gcov coverage data when run.">; def relaxed_aliasing : Flag<"-relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; def masm_verbose : Flag<"-masm-verbose">, @@ -163,10 +160,16 @@ def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, HelpText<"Omit frame pointer setup for leaf functions.">; def msoft_float : Flag<"-msoft-float">, HelpText<"Use software floating point">; +def backend_option : Separate<"-backend-option">, + HelpText<"Additional arguments to forward to LLVM backend (during code gen)">; def mregparm : Separate<"-mregparm">, HelpText<"Limit the number of registers available for integer arguments">; def mrelax_all : Flag<"-mrelax-all">, - HelpText<"Relax all machine instructions">; + HelpText<"(integrated-as) Relax all machine instructions">; +def msave_temp_labels : Flag<"-msave-temp-labels">, + HelpText<"(integrated-as) Save temporary labels">; +def mrtd: Flag<"-mrtd">, + HelpText<"Make StdCall calling convention the default">; def mrelocation_model : Separate<"-mrelocation-model">, HelpText<"The relocation model to use">; def munwind_tables : Flag<"-munwind-tables">, @@ -177,6 +180,7 @@ def mms_bitfields : Flag<"-mms-bitfields">, HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">; def O : Joined<"-O">, HelpText<"Optimization level">; def Os : Flag<"-Os">, HelpText<"Optimize for size">; +def Oz : Flag<"-Oz">, HelpText<"Optimize for size, regardless of performance">; def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">; //===----------------------------------------------------------------------===// @@ -203,6 +207,8 @@ def MP : Flag<"-MP">, def dump_build_information : Separate<"-dump-build-information">, MetaVarName<"">, HelpText<"output a dump of some build information to a file">; +def diagnostic_log_file : Separate<"-diagnostic-log-file">, + HelpText<"Filename (or -) to log diagnostics to">; def fno_show_column : Flag<"-fno-show-column">, HelpText<"Do not include column number on diagnostics">; def fno_show_source_location : Flag<"-fno-show-source-location">, @@ -214,6 +220,9 @@ def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, HelpText<"Do not include source line and caret with diagnostics">; def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, HelpText<"Do not include fixit information in diagnostics">; +def fno_diagnostics_show_note_include_stack : + Flag<"-fno-diagnostics-show-note-include-stack">, + HelpText<"Display include stacks for diagnostic notes">; def w : Flag<"-w">, HelpText<"Suppress all warnings">; def pedantic : Flag<"-pedantic">; def pedantic_errors : Flag<"-pedantic-errors">; @@ -227,11 +236,15 @@ def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-rang HelpText<"Print source range spans in numeric form">; def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, HelpText<"Print fix-its in machine parseable form">; +def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, + HelpText<"Print diagnostic name">; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, - HelpText<"Print diagnostic name with mappable diagnostics">; + HelpText<"Print option name with mappable diagnostics">; def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">, HelpText<"Print diagnostic category">; - +def fdiagnostics_show_note_include_stack : + Flag<"-fdiagnostics-show-note-include-stack">, + HelpText<"Display include stacks for diagnostic notes">; def ftabstop : Separate<"-ftabstop">, MetaVarName<"">, HelpText<"Set the tab stop distance.">; def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"">, @@ -246,8 +259,6 @@ def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, HelpText<"Use colors in diagnostics">; def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">, HelpText<"Silence ObjC rewriting warnings">; -def Wwrite_strings : Flag<"-Wwrite-strings">, - HelpText<"Remove const qualifier from string literals">; def verify : Flag<"-verify">, HelpText<"Verify emitted diagnostics and warnings">; @@ -326,8 +337,6 @@ def emit_html : Flag<"-emit-html">, HelpText<"Output input source as HTML">; def ast_print : Flag<"-ast-print">, HelpText<"Build ASTs and then pretty-print them">; -def ast_print_xml : Flag<"-ast-print-xml">, - HelpText<"Build ASTs and then print them in XML format">; def ast_dump : Flag<"-ast-dump">, HelpText<"Build ASTs and then debug dump them">; def ast_dump_xml : Flag<"-ast-dump-xml">, @@ -519,8 +528,25 @@ def trigraphs : Flag<"-trigraphs">, HelpText<"Process trigraph sequences">; def fwritable_strings : Flag<"-fwritable-strings">, HelpText<"Store string literals as writable data">; +def fconst_strings : Flag<"-fconst-strings">, + HelpText<"Use a const qualified type for string literals in C and ObjC">; +def fno_const_strings : Flag<"-fno-const-strings">, + HelpText<"Don't use a const qualified type for string literals in C and ObjC">; def fno_bitfield_type_align : Flag<"-fno-bitfield-type-align">, HelpText<"Ignore bit-field types when aligning structures">; +def traditional_cpp : Flag<"-traditional-cpp">, + HelpText<"Enable some traditional CPP emulation">; +def ffake_address_space_map : Flag<"-ffake-address-space-map">, + HelpText<"Use a fake address space map; OpenCL testing purposes only">; +def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, + HelpText<"Parse templated function definitions at the end of the " + "translation unit ">; +def funknown_anytype : Flag<"-funknown-anytype">, + HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">; +def fdeprecated_macro : Flag<"-fdeprecated-macro">, + HelpText<"Defines the __DEPRECATED macro">; +def fno_deprecated_macro : Flag<"-fno-deprecated-macro">, + HelpText<"Undefines the __DEPRECATED macro">; //===----------------------------------------------------------------------===// // Header Search Options @@ -572,6 +598,8 @@ def include_pch : Separate<"-include-pch">, MetaVarName<"">, HelpText<"Include precompiled header file">; def include_pth : Separate<"-include-pth">, MetaVarName<"">, HelpText<"Include file before parsing">; +def chain_include : Separate<"-chain-include">, MetaVarName<"">, + HelpText<"Include and chain a header file after turning it into PCH">; def preamble_bytes_EQ : Joined<"-preamble-bytes=">, HelpText<"Assume that the precompiled header is a precompiled preamble " "covering the first N bytes of the main file">; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h index 03fa0ef972d0..5a7d830b069d 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h @@ -25,6 +25,7 @@ namespace llvm { class raw_ostream; + template class ArrayRef; } namespace clang { namespace driver { @@ -77,6 +78,12 @@ class Driver { typedef llvm::SmallVector prefix_list; prefix_list PrefixDirs; + /// sysroot, if present + std::string SysRoot; + + /// If the standard library is used + bool UseStdLib; + /// Default host triple. std::string DefaultHostTriple; @@ -90,7 +97,7 @@ class Driver { /// will generally be the actual host platform, but not always. const HostInfo *Host; - /// Information about the host which can be overriden by the user. + /// Information about the host which can be overridden by the user. std::string HostBits, HostMachine, HostSystem, HostRelease; /// The file to log CC_PRINT_OPTIONS output to, if enabled. @@ -99,9 +106,15 @@ class Driver { /// The file to log CC_PRINT_HEADERS output to, if enabled. const char *CCPrintHeadersFilename; + /// The file to log CC_LOG_DIAGNOSTICS output to, if enabled. + const char *CCLogDiagnosticsFilename; + /// Whether the driver should follow g++ like behavior. unsigned CCCIsCXX : 1; + /// Whether the driver is just the preprocessor + unsigned CCCIsCPP : 1; + /// Echo commands while executing (in -v style). unsigned CCCEcho : 1; @@ -116,8 +129,13 @@ class Driver { /// information to CCPrintHeadersFilename or to stderr. unsigned CCPrintHeaders : 1; + /// Set CC_LOG_DIAGNOSTICS mode, which causes the frontend to log diagnostics + /// to CCLogDiagnosticsFilename or to stderr, in a stable machine readable + /// format. + unsigned CCLogDiagnostics : 1; + private: - /// Name to use when calling the generic gcc. + /// Name to use when invoking gcc/g++. std::string CCCGenericGCCName; /// Whether to check that input files exist when constructing compilation @@ -165,7 +183,7 @@ class Driver { /// @name Accessors /// @{ - /// Name to use when calling the generic gcc. + /// Name to use when invoking gcc/g++. const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; } @@ -206,14 +224,14 @@ class Driver { /// argument vector. A null return value does not necessarily /// indicate an error condition, the diagnostics should be queried /// to determine if an error occurred. - Compilation *BuildCompilation(int argc, const char **argv); + Compilation *BuildCompilation(llvm::ArrayRef Args); /// @name Driver Steps /// @{ /// ParseArgStrings - Parse the given list of strings into an /// ArgList. - InputArgList *ParseArgStrings(const char **ArgBegin, const char **ArgEnd); + InputArgList *ParseArgStrings(llvm::ArrayRef Args); /// BuildActions - Construct the list of actions to perform for the /// given arguments, which are only done for a single architecture. @@ -221,7 +239,7 @@ class Driver { /// \param TC - The default host tool chain. /// \param Args - The input arguments. /// \param Actions - The list to store the resulting actions onto. - void BuildActions(const ToolChain &TC, const ArgList &Args, + void BuildActions(const ToolChain &TC, const DerivedArgList &Args, ActionList &Actions) const; /// BuildUniversalActions - Construct the list of actions to perform @@ -230,7 +248,7 @@ class Driver { /// \param TC - The default host tool chain. /// \param Args - The input arguments. /// \param Actions - The list to store the resulting actions onto. - void BuildUniversalActions(const ToolChain &TC, const ArgList &Args, + void BuildUniversalActions(const ToolChain &TC, const DerivedArgList &Args, ActionList &Actions) const; /// BuildJobs - Bind actions to concrete tools and translate diff --git a/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h index 0733c51027d9..0f9376b8dea1 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define DRIVERSTART #include "clang/Basic/DiagnosticDriverKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td b/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td index 04efd00fb1d8..25ecbc35f92e 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td @@ -78,7 +78,7 @@ def RenderSeparate : OptionFlag; def Unsupported : OptionFlag; // HelpHidden - The option should not be displayed in --help, even if it has -// help text. Clients *can* use this in conjuction with the OptTable::PrintHelp +// help text. Clients *can* use this in conjunction with the OptTable::PrintHelp // arguments to implement hidden help groups. def HelpHidden : OptionFlag; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td index 0faab3b86640..2cff623fc93b 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Options.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td @@ -29,6 +29,7 @@ def X_Group : OptionGroup<"">; def a_Group : OptionGroup<"">; def d_Group : OptionGroup<"">; def f_Group : OptionGroup<"">, Group; +def f_clang_Group : OptionGroup<"">, Group; def g_Group : OptionGroup<"">; def i_Group : OptionGroup<"">, Group; def clang_i_Group : OptionGroup<"">, Group; @@ -165,6 +166,8 @@ def Wa_COMMA : CommaJoined<"-Wa,">, HelpText<"Pass the comma separated arguments in to the assembler">, MetaVarName<"">; def Wall : Flag<"-Wall">, Group; +def Wdeprecated : Flag<"-Wdeprecated">, Group; +def Wno_deprecated : Flag<"-Wno-deprecated">, Group; def Wextra : Flag<"-Wextra">, Group; def Wl_COMMA : CommaJoined<"-Wl,">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass the comma separated arguments in to the linker">, @@ -174,6 +177,8 @@ def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group; def Wp_COMMA : CommaJoined<"-Wp,">, HelpText<"Pass the comma separated arguments in to the preprocessor">, MetaVarName<"">; +def Wwrite_strings : Flag<"-Wwrite-strings">, Group; +def Wno_write_strings : Flag<"-Wno-write-strings">, Group; def W_Joined : Joined<"-W">, Group; def Xanalyzer : Separate<"-Xanalyzer">, HelpText<"Pass to the static analyzer">, MetaVarName<"">; @@ -264,18 +269,24 @@ def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group; def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group; def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group; def fcreate_profile : Flag<"-fcreate-profile">, Group; +def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group; def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group; def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group; -def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group; -def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group; -def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group; +def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group; +def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group; +def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group; -def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group; +def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, Group; +def fdiagnostics_show_note_include_stack : Flag<"-fdiagnostics-show-note-include-stack">, Group; +def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group; def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group; +def fdwarf2_cfi_asm : Flag<"-fdwarf2-cfi-asm">, Group; +def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, Group; def felide_constructors : Flag<"-felide-constructors">, Group; def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group; def femit_all_decls : Flag<"-femit-all-decls">, Group; def fencoding_EQ : Joined<"-fencoding=">, Group; +def ferror_limit_EQ : Joined<"-ferror-limit=">, Group; def fexceptions : Flag<"-fexceptions">, Group; def fextdirs_EQ : Joined<"-fextdirs=">, Group; def fhosted : Flag<"-fhosted">, Group; @@ -302,6 +313,7 @@ def flimit_debug_info : Flag<"-flimit-debug-info">, Group, HelpText<"Limit debug information produced to reduce size of debug binary">; def flimited_precision_EQ : Joined<"-flimited-precision=">, Group; def flto : Flag<"-flto">, Group; +def fno_lto : Flag<"-fno-lto">, Group; def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">, Group; def fmath_errno : Flag<"-fmath-errno">, Group; @@ -309,6 +321,7 @@ def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group; def fmessage_length_EQ : Joined<"-fmessage-length=">, Group; def fms_extensions : Flag<"-fms-extensions">, Group; def fmsc_version : Joined<"-fmsc-version=">, Group; +def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, Group; def fmudflapth : Flag<"-fmudflapth">, Group; def fmudflap : Flag<"-fmudflap">, Group; def fnested_functions : Flag<"-fnested-functions">, Group; @@ -326,8 +339,11 @@ def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group; def fno_color_diagnostics : Flag<"-fno-color-diagnostics">, Group; def fno_common : Flag<"-fno-common">, Group; def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group; +def fno_cxx_exceptions: Flag<"-fno-cxx-exceptions">, Group; def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group; +def fno_diagnostics_show_name : Flag<"-fno-diagnostics-show-name">, Group; def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group; +def fno_diagnostics_show_note_include_stack : Flag<"-fno-diagnostics-show-note-include-stack">, Group; def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group; def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group; def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group; @@ -341,6 +357,7 @@ def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group, Group; def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group; def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group; +def fno_delayed_template_parsing : Flag<"-fno-delayed-template-parsing">, Group; def fno_objc_default_synthesize_properties : Flag<"-fno-objc-default-synthesize-properties">, Group; def fno_objc_exceptions: Flag<"-fno-objc-exceptions">, Group; @@ -354,12 +371,14 @@ def fno_show_source_location : Flag<"-fno-show-source-location">, Group def fno_spell_checking : Flag<"-fno-spell-checking">, Group; def fno_stack_protector : Flag<"-fno-stack-protector">, Group; def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group; +def fno_strict_overflow : Flag<"-fno-strict-overflow">, Group; def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group; def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group; def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group; def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group; def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group; def fno_working_directory : Flag<"-fno-working-directory">, Group; +def fno_wrapv : Flag<"-fno-wrapv">, Group; def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group; def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group; def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group; @@ -407,19 +426,30 @@ def fsigned_char : Flag<"-fsigned-char">, Group; def fstack_protector_all : Flag<"-fstack-protector-all">, Group; def fstack_protector : Flag<"-fstack-protector">, Group; def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group; +def fstrict_overflow : Flag<"-fstrict-overflow">, Group; def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>; def ftabstop_EQ : Joined<"-ftabstop=">, Group; -def ferror_limit_EQ : Joined<"-ferror-limit=">, Group; def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group; def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">, Group; +def ftest_coverage : Flag<"-ftest-coverage">, Group; def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">; def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">; + +// Just silence warnings about -Wlarger-than, -Wframe-larger-than for now. +def Wlarger_than : Separate<"-Wlarger-than">, Group; +def Wlarger_than_EQ : Joined<"-Wlarger-than=">, Alias; +def Wlarger_than_ : Joined<"-Wlarger-than-">, Alias; +def Wframe_larger_than : Separate<"-Wframe-larger-than">, Group; +def Wframe_larger_than_EQ : Joined<"-Wframe-larger-than=">, Alias; + def fterminated_vtables : Flag<"-fterminated-vtables">, Group; def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group; def ftime_report : Flag<"-ftime-report">, Group; def ftrapv : Flag<"-ftrapv">, Group; def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group; +def ftrap_function_EQ : Joined<"-ftrap-function=">, Group, + HelpText<"Issue call to specified function rather than a trap instruction">; def funit_at_a_time : Flag<"-funit-at-a-time">, Group; def funroll_loops : Flag<"-funroll-loops">, Group; def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group; @@ -466,11 +496,11 @@ def m32 : Flag<"-m32">, Group, Flags<[DriverOption]>; def m3dnowa : Flag<"-m3dnowa">, Group; def m3dnow : Flag<"-m3dnow">, Group; def m64 : Flag<"-m64">, Group, Flags<[DriverOption]>; -def mabi_EQ : Joined<"-mabi=">, Group, Flags<[DriverOption]>; -def march_EQ : Joined<"-march=">, Group, Flags<[DriverOption]>; -def mcmodel_EQ : Joined<"-mcmodel=">, Group, Flags<[DriverOption]>; +def mabi_EQ : Joined<"-mabi=">, Group; +def march_EQ : Joined<"-march=">, Group; +def mcmodel_EQ : Joined<"-mcmodel=">, Group; def mconstant_cfstrings : Flag<"-mconstant-cfstrings">, Group; -def mcpu_EQ : Joined<"-mcpu=">, Group, Flags<[DriverOption]>; +def mcpu_EQ : Joined<"-mcpu=">, Group; def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group, Flags<[NoArgumentUnused]>; def mfix_and_continue : Flag<"-mfix-and-continue">, Group; def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group; @@ -478,6 +508,7 @@ def mfpu_EQ : Joined<"-mfpu=">, Group; def mhard_float : Flag<"-mhard-float">, Group; def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group; def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias; +def mios_simulator_version_min_EQ : Joined<"-mios-simulator-version-min=">, Group; def mkernel : Flag<"-mkernel">, Group; def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>; def mllvm : Separate<"-mllvm">; @@ -491,6 +522,7 @@ def mno_mmx : Flag<"-mno-mmx">, Group; def mno_pascal_strings : Flag<"-mno-pascal-strings">, Group; def mno_red_zone : Flag<"-mno-red-zone">, Group; def mno_relax_all : Flag<"-mno-relax-all">, Group; +def mno_rtd: Flag<"-mno-rtd">, Group; def mno_soft_float : Flag<"-mno-soft-float">, Group; def mno_sse2 : Flag<"-mno-sse2">, Group; def mno_sse3 : Flag<"-mno-sse3">, Group; @@ -513,6 +545,7 @@ def mpascal_strings : Flag<"-mpascal-strings">, Group; def mred_zone : Flag<"-mred-zone">, Group; def mregparm_EQ : Joined<"-mregparm=">, Group; def mrelax_all : Flag<"-mrelax-all">, Group; +def mrtd: Flag<"-mrtd">, Group; def msoft_float : Flag<"-msoft-float">, Group; def msse2 : Flag<"-msse2">, Group; def msse3 : Flag<"-msse3">, Group; diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h index f0012bd851eb..da6949f9786e 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h +++ b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h @@ -88,8 +88,10 @@ class ToolChain { return 0; } - /// SelectTool - Choose a tool to use to handle the action \arg JA. - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const = 0; + /// SelectTool - Choose a tool to use to handle the action \arg JA with the + /// given \arg Inputs. + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const = 0; // Helper methods @@ -151,6 +153,9 @@ class ToolChain { /// particular PIC mode. virtual const char *GetForcedPicModel() const = 0; + /// SupportsProfiling - Does this tool chain support -pg. + virtual bool SupportsProfiling() const { return true; } + /// Does this tool chain support Objective-C garbage collection. virtual bool SupportsObjCGC() const { return false; } diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h index c45bd4070600..3c05834ad6a7 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h @@ -14,8 +14,6 @@ #ifndef DRIVER_ASTCONSUMERS_H #define DRIVER_ASTCONSUMERS_H -#include - namespace llvm { class raw_ostream; namespace sys { class Path; } @@ -36,12 +34,6 @@ class TargetOptions; // implementation is still incomplete. ASTConsumer *CreateASTPrinter(llvm::raw_ostream *OS); -// AST XML-printer: prints out the AST in a XML format -// The output is intended to be in a format such that -// clang or any other tool could re-parse the output back into the same AST, -// but the implementation is still incomplete. -ASTConsumer *CreateASTPrinterXML(llvm::raw_ostream *OS); - // AST dumper: dumps the raw AST in human-readable form to stderr; this is // intended for debugging. ASTConsumer *CreateASTDumper(); diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h index e93563311b85..57c59d951e94 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h @@ -71,12 +71,12 @@ class ASTUnit { private: llvm::IntrusiveRefCntPtr Diagnostics; - llvm::OwningPtr FileMgr; - llvm::OwningPtr SourceMgr; + llvm::IntrusiveRefCntPtr FileMgr; + llvm::IntrusiveRefCntPtr SourceMgr; llvm::OwningPtr HeaderInfo; - llvm::OwningPtr Target; - llvm::OwningPtr PP; - llvm::OwningPtr Ctx; + llvm::IntrusiveRefCntPtr Target; + llvm::IntrusiveRefCntPtr PP; + llvm::IntrusiveRefCntPtr Ctx; FileSystemOptions FileSystemOpts; @@ -90,7 +90,7 @@ class ASTUnit { /// Optional owned invocation, just used to make the invocation used in /// LoadFromCommandLine available. - llvm::OwningPtr Invocation; + llvm::IntrusiveRefCntPtr Invocation; /// \brief The set of target features. /// @@ -115,6 +115,9 @@ class ASTUnit { /// \brief Whether we should time each operation. bool WantTiming; + + /// \brief Whether the ASTUnit should delete the remapped buffers. + bool OwnsRemappedFileBuffers; /// Track the top-level decls which appeared in an ASTUnit which was loaded /// from a source file. @@ -393,11 +396,11 @@ class ASTUnit { const SourceManager &getSourceManager() const { return *SourceMgr; } SourceManager &getSourceManager() { return *SourceMgr; } - const Preprocessor &getPreprocessor() const { return *PP.get(); } - Preprocessor &getPreprocessor() { return *PP.get(); } + const Preprocessor &getPreprocessor() const { return *PP; } + Preprocessor &getPreprocessor() { return *PP; } - const ASTContext &getASTContext() const { return *Ctx.get(); } - ASTContext &getASTContext() { return *Ctx.get(); } + const ASTContext &getASTContext() const { return *Ctx; } + ASTContext &getASTContext() { return *Ctx; } bool hasSema() const { return TheSema; } Sema &getSema() const { @@ -422,6 +425,9 @@ class ASTUnit { bool getOnlyLocalDecls() const { return OnlyLocalDecls; } + bool getOwnsRemappedFileBuffers() const { return OwnsRemappedFileBuffers; } + void setOwnsRemappedFileBuffers(bool val) { OwnsRemappedFileBuffers = val; } + /// \brief Retrieve the maximum PCH level of declarations that a /// traversal of the translation unit should consider. unsigned getMaxPCHLevel() const; @@ -529,10 +535,16 @@ class ASTUnit { /// that might still be used as a precompiled header or preamble. bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; } + typedef llvm::PointerUnion + FilenameOrMemBuf; /// \brief A mapping from a file name to the memory buffer that stores the /// remapped contents of that file. - typedef std::pair RemappedFile; - + typedef std::pair RemappedFile; + + /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation. + static ASTUnit *create(CompilerInvocation *CI, + llvm::IntrusiveRefCntPtr Diags); + /// \brief Create a ASTUnit from an AST file. /// /// \param Filename - The AST file to load. @@ -603,6 +615,7 @@ class ASTUnit { bool CaptureDiagnostics = false, RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0, + bool RemappedFilesKeepOriginalName = true, bool PrecompilePreamble = false, bool CompleteTranslationUnit = true, bool CacheCodeCompletionResults = false, @@ -647,6 +660,11 @@ class ASTUnit { /// /// \returns True if an error occurred, false otherwise. bool Save(llvm::StringRef File); + + /// \brief Serialize this translation unit with the given output stream. + /// + /// \returns True if an error occurred, false otherwise. + bool serialize(llvm::raw_ostream &OS); }; } // namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def b/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def index 75b52a824c63..f055549b4e24 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def +++ b/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def @@ -11,16 +11,6 @@ // //===----------------------------------------------------------------------===// -#ifndef ANALYSIS -#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) -#endif - -ANALYSIS(WarnUninitVals, "warn-uninit-values", - "Warn about uses of uninitialized variables", Code) - -ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem", - "Run the [Core] Foundation reference count checker", Code) - #ifndef ANALYSIS_STORE #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) #endif @@ -45,7 +35,6 @@ ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", cre ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticClient, true) ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticClient, true) -#undef ANALYSIS #undef ANALYSIS_STORE #undef ANALYSIS_CONSTRAINTS #undef ANALYSIS_DIAGNOSTICS diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h index 64263c1b54e8..ea9f5e38b7b9 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h @@ -55,7 +55,6 @@ NUM_ANALYSIS_DIAG_CLIENTS class AnalyzerOptions { public: - std::vector AnalysisList; /// \brief Pair of checker name and enable/disable. std::vector > CheckersControlList; AnalysisStores AnalysisStoreOpt; @@ -68,14 +67,11 @@ class AnalyzerOptions { unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; - unsigned AnalyzerStats : 1; unsigned EagerlyAssume : 1; - unsigned BufferOverflows : 1; unsigned PurgeDead : 1; unsigned TrimGraph : 1; unsigned VisualizeEGDot : 1; unsigned VisualizeEGUbi : 1; - unsigned EnableExperimentalChecks : 1; unsigned InlineCall : 1; unsigned UnoptimizedCFG : 1; unsigned CFGAddImplicitDtors : 1; @@ -91,14 +87,11 @@ class AnalyzerOptions { AnalyzeAll = 0; AnalyzerDisplayProgress = 0; AnalyzeNestedBlocks = 0; - AnalyzerStats = 0; EagerlyAssume = 0; - BufferOverflows = 0; PurgeDead = 1; TrimGraph = 0; VisualizeEGDot = 0; VisualizeEGUbi = 0; - EnableExperimentalChecks = 0; InlineCall = 0; UnoptimizedCFG = 0; CFGAddImplicitDtors = 0; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h index 2d5e128dac37..70f21901db4f 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h @@ -48,6 +48,9 @@ class ChainedDiagnosticClient : public DiagnosticClient { virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo &Info) { + // Default implementation (Warnings/errors count). + DiagnosticClient::HandleDiagnostic(DiagLevel, Info); + Primary->HandleDiagnostic(DiagLevel, Info); Secondary->HandleDiagnostic(DiagLevel, Info); } diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h index ee85b655c23f..8bef6a3e0d43 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H #include +#include namespace clang { @@ -51,6 +52,10 @@ class CodeGenOptions { /// Decl* various IR entities came from. Only /// useful when running CodeGen as a /// subroutine. + unsigned EmitGcovArcs : 1; /// Emit coverage data files, aka. GCDA. + unsigned EmitGcovNotes : 1; /// Emit coverage "notes" files, aka GCNO. + unsigned ForbidGuardVariables : 1; /// Issue errors if C++ guard variables + /// are required unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled unsigned HiddenWeakTemplateVTables : 1; /// Emit weak vtables and RTTI for /// template classes with hidden visibility @@ -63,6 +68,7 @@ class CodeGenOptions { /// generated. unsigned MergeAllConstants : 1; /// Merge identical constants. unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. + unsigned NoDwarf2CFIAsm : 1; /// Set when -fno-dwarf2-cfi-asm is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. unsigned NoInfsFPMath : 1; /// Assume FP arguments, results not +-Inf. unsigned NoNaNsFPMath : 1; /// Assume FP arguments, results not NaN. @@ -71,9 +77,10 @@ class CodeGenOptions { unsigned OmitLeafFramePointer : 1; /// Set when -momit-leaf-frame-pointer is /// enabled. unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. - unsigned OptimizeSize : 1; /// If -Os is specified. + unsigned OptimizeSize : 2; /// If -Os (==1) or -Oz (==2) is specified. unsigned RelaxAll : 1; /// Relax all machine code instructions. unsigned RelaxedAliasing : 1; /// Set when -fno-strict-aliasing is enabled. + unsigned SaveTempLabels : 1; /// Save temporary labels. unsigned SimplifyLibCalls : 1; /// Set when -fbuiltin is enabled. unsigned SoftFloat : 1; /// -soft-float. unsigned TimePasses : 1; /// Set when -ftime-report is enabled. @@ -112,6 +119,9 @@ class CodeGenOptions { /// The name of the relocation model to use. std::string RelocationModel; + /// A list of command-line options to forward to the LLVM backend. + std::vector BackendOptions; + /// The user specified number of registers to be used for integral arguments, /// or 0 if unspecified. unsigned NumRegisterParameters; @@ -128,6 +138,9 @@ class CodeGenOptions { DisableLLVMOpts = 0; DisableRedZone = 0; EmitDeclMetadata = 0; + EmitGcovArcs = 0; + EmitGcovNotes = 0; + ForbidGuardVariables = 0; FunctionSections = 0; HiddenWeakTemplateVTables = 0; HiddenWeakVTables = 0; @@ -136,6 +149,7 @@ class CodeGenOptions { LessPreciseFPMAD = 0; MergeAllConstants = 1; NoCommon = 0; + NoDwarf2CFIAsm = 0; NoImplicitFloat = 0; NoInfsFPMath = 0; NoNaNsFPMath = 0; @@ -147,6 +161,7 @@ class CodeGenOptions { OptimizeSize = 0; RelaxAll = 0; RelaxedAliasing = 0; + SaveTempLabels = 0; SimplifyLibCalls = 1; SoftFloat = 0; TimePasses = 0; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h index 7ea79e5599ff..004c8896e232 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h @@ -59,25 +59,25 @@ class TargetInfo; /// and a long form that takes explicit instances of any required objects. class CompilerInstance { /// The options used in this compiler instance. - llvm::OwningPtr Invocation; + llvm::IntrusiveRefCntPtr Invocation; /// The diagnostics engine instance. llvm::IntrusiveRefCntPtr Diagnostics; /// The target being compiled for. - llvm::OwningPtr Target; + llvm::IntrusiveRefCntPtr Target; /// The file manager. - llvm::OwningPtr FileMgr; + llvm::IntrusiveRefCntPtr FileMgr; /// The source manager. - llvm::OwningPtr SourceMgr; + llvm::IntrusiveRefCntPtr SourceMgr; /// The preprocessor. - llvm::OwningPtr PP; + llvm::IntrusiveRefCntPtr PP; /// The AST context. - llvm::OwningPtr Context; + llvm::IntrusiveRefCntPtr Context; /// The AST consumer. llvm::OwningPtr Consumer; @@ -161,10 +161,7 @@ class CompilerInstance { return *Invocation; } - CompilerInvocation *takeInvocation() { return Invocation.take(); } - - /// setInvocation - Replace the current invocation; the compiler instance - /// takes ownership of \arg Value. + /// setInvocation - Replace the current invocation. void setInvocation(CompilerInvocation *Value); /// } @@ -251,13 +248,13 @@ class CompilerInstance { bool hasDiagnostics() const { return Diagnostics != 0; } + /// Get the current diagnostics engine. Diagnostic &getDiagnostics() const { assert(Diagnostics && "Compiler instance has no diagnostics!"); return *Diagnostics; } - /// setDiagnostics - Replace the current diagnostics engine; the compiler - /// instance takes ownership of \arg Value. + /// setDiagnostics - Replace the current diagnostics engine. void setDiagnostics(Diagnostic *Value); DiagnosticClient &getDiagnosticClient() const { @@ -277,12 +274,7 @@ class CompilerInstance { return *Target; } - /// takeTarget - Remove the current diagnostics engine and give ownership - /// to the caller. - TargetInfo *takeTarget() { return Target.take(); } - - /// setTarget - Replace the current diagnostics engine; the compiler - /// instance takes ownership of \arg Value. + /// Replace the current diagnostics engine. void setTarget(TargetInfo *Value); /// } @@ -291,17 +283,17 @@ class CompilerInstance { bool hasFileManager() const { return FileMgr != 0; } + /// Return the current file manager to the caller. FileManager &getFileManager() const { assert(FileMgr && "Compiler instance has no file manager!"); return *FileMgr; } + + void resetAndLeakFileManager() { + FileMgr.resetWithoutRelease(); + } - /// takeFileManager - Remove the current file manager and give ownership to - /// the caller. - FileManager *takeFileManager() { return FileMgr.take(); } - - /// setFileManager - Replace the current file manager; the compiler instance - /// takes ownership of \arg Value. + /// setFileManager - Replace the current file manager. void setFileManager(FileManager *Value); /// } @@ -310,17 +302,17 @@ class CompilerInstance { bool hasSourceManager() const { return SourceMgr != 0; } + /// Return the current source manager. SourceManager &getSourceManager() const { assert(SourceMgr && "Compiler instance has no source manager!"); return *SourceMgr; } + + void resetAndLeakSourceManager() { + SourceMgr.resetWithoutRelease(); + } - /// takeSourceManager - Remove the current source manager and give ownership - /// to the caller. - SourceManager *takeSourceManager() { return SourceMgr.take(); } - - /// setSourceManager - Replace the current source manager; the compiler - /// instance takes ownership of \arg Value. + /// setSourceManager - Replace the current source manager. void setSourceManager(SourceManager *Value); /// } @@ -329,17 +321,17 @@ class CompilerInstance { bool hasPreprocessor() const { return PP != 0; } + /// Return the current preprocessor. Preprocessor &getPreprocessor() const { assert(PP && "Compiler instance has no preprocessor!"); return *PP; } - /// takePreprocessor - Remove the current preprocessor and give ownership to - /// the caller. - Preprocessor *takePreprocessor() { return PP.take(); } + void resetAndLeakPreprocessor() { + PP.resetWithoutRelease(); + } - /// setPreprocessor - Replace the current preprocessor; the compiler instance - /// takes ownership of \arg Value. + /// Replace the current preprocessor. void setPreprocessor(Preprocessor *Value); /// } @@ -352,13 +344,12 @@ class CompilerInstance { assert(Context && "Compiler instance has no AST context!"); return *Context; } + + void resetAndLeakASTContext() { + Context.resetWithoutRelease(); + } - /// takeASTContext - Remove the current AST context and give ownership to the - /// caller. - ASTContext *takeASTContext() { return Context.take(); } - - /// setASTContext - Replace the current AST context; the compiler instance - /// takes ownership of \arg Value. + /// setASTContext - Replace the current AST context. void setASTContext(ASTContext *Value); /// \brief Replace the current Sema; the compiler instance takes ownership @@ -479,11 +470,15 @@ class CompilerInstance { /// attached to (and, then, owned by) the returned Diagnostic /// object. /// + /// \param CodeGenOpts If non-NULL, the code gen options in use, which may be + /// used by some diagnostics printers (for logging purposes only). + /// /// \return The new object on success, or null on failure. static llvm::IntrusiveRefCntPtr createDiagnostics(const DiagnosticOptions &Opts, int Argc, const char* const *Argv, - DiagnosticClient *Client = 0); + DiagnosticClient *Client = 0, + const CodeGenOptions *CodeGenOpts = 0); /// Create the file manager and replace any existing one with it. void createFileManager(); diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h index e0329dbc96ec..e18f3fe63249 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h @@ -22,6 +22,7 @@ #include "clang/Frontend/LangStandard.h" #include "clang/Frontend/PreprocessorOptions.h" #include "clang/Frontend/PreprocessorOutputOptions.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" #include @@ -41,7 +42,7 @@ class Diagnostic; /// This class is designed to represent an abstract "invocation" of the /// compiler, including data such as the include paths, the code generation /// options, the warning flags, and so on. -class CompilerInvocation { +class CompilerInvocation : public llvm::RefCountedBase { /// Options controlling the static analyzer. AnalyzerOptions AnalyzerOpts; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def deleted file mode 100644 index 39ed5f9432b6..000000000000 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def +++ /dev/null @@ -1,113 +0,0 @@ -//===-- DeclContextXML.def - Metadata about Context XML nodes ---*- 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 XML context info database as written in the -// / sub-nodes of the XML document. Type nodes -// are referred by "context" reference attributes throughout the document. -// A context node never contains sub-nodes. -// The semantics of the attributes and enums are mostly self-documenting -// by looking at the appropriate internally used functions and values. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// context of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that context -// node and possible sub-nodes follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Context nodes have an "id" attribute containing a -// string, which value uniquely identify that statement. Other nodes may refer -// by "context" attributes to this value. -// -// TYPE_ATTRIBUTE_XML( FN ) - Context nodes may refer to the ids of type -// nodes by a "type" attribute, if they create a type during declaration. -// For instance 'struct S;' creates both a context 'S::' and a type 'S'. -// Contexts and types always have different ids, however declarations and -// contexts may share the same ids. FN is internally used by clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally -// used by clang. A boolean attribute have the values "0" or "1". -// -// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the -// empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is -// internally used by clang. -// -// END_ENUM_XML - Closes the enumeration definition of the current attribute. -// -//===----------------------------------------------------------------------===// - -#ifndef TYPE_ATTRIBUTE_XML -# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#endif - -#ifndef CONTEXT_ATTRIBUTE_XML -# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#endif - -NODE_XML(TranslationUnitDecl, "TranslationUnit") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(FunctionDecl, "Function") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()) -END_NODE_XML - -NODE_XML(NamespaceDecl, "Namespace") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") -END_NODE_XML - -NODE_XML(RecordDecl, "Record") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getTypeForDecl()) -END_NODE_XML - -NODE_XML(EnumDecl, "Enum") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getTypeForDecl()) -END_NODE_XML - -NODE_XML(LinkageSpecDecl, "LinkageSpec") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang") - ENUM_XML(LinkageSpecDecl::lang_c, "C") - ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX") - END_ENUM_XML -END_NODE_XML - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef TYPE_ATTRIBUTE_XML -#undef ATTRIBUTE_XML -#undef ATTRIBUTE_SPECIAL_XML -#undef ATTRIBUTE_OPT_XML -#undef ATTRIBUTE_ENUM_XML -#undef ATTRIBUTE_ENUM_OPT_XML -#undef ATTRIBUTE_FILE_LOCATION_XML -#undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML -#undef SUB_NODE_XML -#undef SUB_NODE_SEQUENCE_XML -#undef SUB_NODE_OPT_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def deleted file mode 100644 index 58f7e55fbe80..000000000000 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def +++ /dev/null @@ -1,372 +0,0 @@ -//===-- DeclXML.def - Metadata about Decl XML nodes ------------*- 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 XML statement database structure as written in -// sub-nodes of the XML document. -// The semantics of the attributes and enums are mostly self-documenting -// by looking at the appropriate internally used functions and values. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// statement of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that statement -// node and possible sub-nodes follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a -// string, which value uniquely identify that statement. Other nodes may refer -// by reference attributes to this value (currently used only for Label). -// -// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an -// expression by a "type" attribute. FN is internally used by clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally -// used by clang. A boolean attribute have the values "0" or "1". -// -// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves -// a special handling. See the appropriate documentations. -// -// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of -// a statement in the source file(s). -// -// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. -// Optional attributes are omitted for boolean types, if the value is false, -// for integral types, if the value is null and for strings, -// if the value is the empty string. FN is internally used by clang. -// -// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the -// empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is -// internally used by clang. -// -// END_ENUM_XML - Closes the enumeration definition of the current attribute. -// -// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or -// its sub-classes. -// -//===----------------------------------------------------------------------===// - -#ifndef ATTRIBUTE_FILE_LOCATION_XML -# define ATTRIBUTE_FILE_LOCATION_XML \ - ATTRIBUTE_XML(getFilename(), "file") \ - ATTRIBUTE_XML(getLine(), "line") \ - ATTRIBUTE_XML(getColumn(), "col") \ - ATTRIBUTE_OPT_XML(getFilename(), "endfile") \ - ATTRIBUTE_OPT_XML(getLine(), "endline") \ - ATTRIBUTE_OPT_XML(getColumn(), "endcol") -#endif - -#ifndef TYPE_ATTRIBUTE_XML -# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#endif - -#ifndef CONTEXT_ATTRIBUTE_XML -# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#endif - -//NODE_XML(TranslationUnitDecl, "TranslationUnit") -// SUB_NODE_SEQUENCE_XML(Decl) -//END_NODE_XML - -NODE_XML(Decl, "FIXME_Decl") - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclKindName(), "unhandled_decl_name") -END_NODE_XML - -NODE_XML(FunctionDecl, "Function") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs()->getResultType()) - ATTRIBUTE_XML(getType()->getAs(), "function_type") - ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") - ENUM_XML(SC_None, "") - ENUM_XML(SC_Extern, "extern") - ENUM_XML(SC_Static, "static") - ENUM_XML(SC_PrivateExtern, "__private_extern__") - END_ENUM_XML - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - //ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference - ATTRIBUTE_XML(getNumParams(), "num_args") - ATTRIBUTE_OPT_XML(isMain(), "main") - ATTRIBUTE_OPT_XML(isExternC(), "externc") - ATTRIBUTE_OPT_XML(isGlobal(), "global") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(CXXMethodDecl, "CXXMethod") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs()->getResultType()) - ATTRIBUTE_XML(getType()->getAs(), "function_type") - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - ATTRIBUTE_OPT_XML(isStatic(), "static") - ATTRIBUTE_OPT_XML(isVirtual(), "virtual") - ATTRIBUTE_OPT_XML(isPure(), "pure") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_XML(getNumParams(), "num_args") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(CXXConstructorDecl, "CXXConstructor") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs()->getResultType()) - ATTRIBUTE_XML(getType()->getAs(), "function_type") - ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit") - ATTRIBUTE_OPT_XML(isDefaultConstructor(), "is_default_ctor") - ATTRIBUTE_OPT_XML(isCopyConstructor(), "is_copy_ctor") - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - ATTRIBUTE_OPT_XML(isStatic(), "static") - ATTRIBUTE_OPT_XML(isVirtual(), "virtual") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_XML(getNumParams(), "num_args") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(CXXDestructorDecl, "CXXDestructor") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs()->getResultType()) - ATTRIBUTE_XML(getType()->getAs(), "function_type") - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - ATTRIBUTE_OPT_XML(isStatic(), "static") - ATTRIBUTE_OPT_XML(isVirtual(), "virtual") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_XML(getNumParams(), "num_args") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(CXXConversionDecl, "CXXConversion") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs()->getResultType()) - ATTRIBUTE_XML(getType()->getAs(), "function_type") - ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit") - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - ATTRIBUTE_OPT_XML(isStatic(), "static") - ATTRIBUTE_OPT_XML(isVirtual(), "virtual") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_XML(getNumParams(), "num_args") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(NamespaceDecl, "Namespace") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - SUB_NODE_SEQUENCE_XML(DeclContext) -END_NODE_XML - -NODE_XML(UsingDirectiveDecl, "UsingDirective") - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_XML(getNominatedNamespace(), "ref") -END_NODE_XML - -NODE_XML(NamespaceAliasDecl, "NamespaceAlias") - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_XML(getNamespace(), "ref") -END_NODE_XML - -NODE_XML(RecordDecl, "Record") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") - ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates - SUB_NODE_SEQUENCE_XML(FieldDecl) -END_NODE_XML - -NODE_XML(CXXRecordDecl, "CXXRecord") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") - ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates - SUB_NODE_SEQUENCE_XML(FieldDecl) -END_NODE_XML - -NODE_XML(EnumDecl, "Enum") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") - ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling - SUB_NODE_SEQUENCE_XML(EnumConstantDecl) // only present in definition -END_NODE_XML - -NODE_XML(EnumConstantDecl, "EnumConstant") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getInitVal().toString(10, true), "value") // integer - SUB_NODE_OPT_XML(Expr) // init expr of this constant -END_NODE_XML - -NODE_XML(FieldDecl, "Field") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_OPT_XML(isMutable(), "mutable") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_OPT_XML(isBitField(), "bitfield") - SUB_NODE_OPT_XML(Expr) // init expr of a bit field -END_NODE_XML - -NODE_XML(TypedefDecl, "Typedef") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getUnderlyingType()) -END_NODE_XML - -NODE_XML(VarDecl, "Var") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") - ENUM_XML(SC_None, "") - ENUM_XML(SC_Auto, "auto") - ENUM_XML(SC_Register, "register") - ENUM_XML(SC_Extern, "extern") - ENUM_XML(SC_Static, "static") - ENUM_XML(SC_PrivateExtern, "__private_extern__") - END_ENUM_XML - SUB_NODE_OPT_XML(Expr) // init expr -END_NODE_XML - -NODE_XML(ParmVarDecl, "ParmVar") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_OPT_XML(Expr) // default argument expression -END_NODE_XML - -NODE_XML(LinkageSpecDecl, "LinkageSpec") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang") - ENUM_XML(LinkageSpecDecl::lang_c, "C") - ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX") - END_ENUM_XML - SUB_NODE_XML(DeclContext) -END_NODE_XML - -NODE_XML(TemplateDecl, "Template") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") -END_NODE_XML - -NODE_XML(TemplateTypeParmDecl, "TemplateTypeParm") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") -END_NODE_XML - -NODE_XML(UsingShadowDecl, "UsingShadow") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getTargetDecl(), "target_decl") - ATTRIBUTE_XML(getUsingDecl(), "using_decl") -END_NODE_XML - -NODE_XML(UsingDecl, "Using") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getQualifier(), "target_nested_namespace_decl") - ATTRIBUTE_XML(isTypeName(), "is_typename") -END_NODE_XML - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef TYPE_ATTRIBUTE_XML -#undef ATTRIBUTE_XML -#undef ATTRIBUTE_SPECIAL_XML -#undef ATTRIBUTE_OPT_XML -#undef ATTRIBUTE_ENUM_XML -#undef ATTRIBUTE_ENUM_OPT_XML -#undef ATTRIBUTE_FILE_LOCATION_XML -#undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML -#undef SUB_NODE_XML -#undef SUB_NODE_SEQUENCE_XML -#undef SUB_NODE_OPT_XML -#undef SUB_NODE_FN_BODY_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h index f7f498bff024..ff92058f01df 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h @@ -31,8 +31,10 @@ class DiagnosticOptions { unsigned ShowFixits : 1; /// Show fixit information. unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form. unsigned ShowParseableFixits : 1; /// Show machine parseable fix-its. - unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable + unsigned ShowNames : 1; /// Show the diagnostic name + unsigned ShowOptionNames : 1; /// Show the option name for mappable /// diagnostics. + unsigned ShowNoteIncludeStack : 1; /// Show include stacks for notes. unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number, /// 2 -> Full Name. unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. @@ -60,6 +62,9 @@ class DiagnosticOptions { /// testing and analysis. std::string DumpBuildInformation; + /// The file to log diagnostic output to. + std::string DiagnosticLogFile; + /// The list of -W... options used to alter the diagnostic mappings, with the /// prefixes removed. std::vector Warnings; @@ -78,6 +83,7 @@ class DiagnosticOptions { ShowColumn = 1; ShowFixits = 1; ShowLocation = 1; + ShowNames = 0; ShowOptionNames = 0; ShowCategories = 0; ShowSourceRanges = 0; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def deleted file mode 100644 index 4c52bd84422f..000000000000 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def +++ /dev/null @@ -1,75 +0,0 @@ -//===-- DocumentXML.def - Metadata about Document XML nodes -----*- 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 XML root database structure as written in -// an AST XML document. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// statement of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that statement -// node and possible sub-nodes follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Some nodes have an "id" attribute containing a -// string, which value uniquely identify the entity represented by that node. -// Other nodes may refer by reference attributes to this value. -// -// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves -// a special handling. See the appropriate documentations. -// -// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or -// its sub-classes. -// -//===----------------------------------------------------------------------===// - -ROOT_NODE_XML("CLANG_XML") - ATTRIBUTE_SPECIAL_XML(ignore, "version") // special retrieving needed - SUB_NODE_XML("TranslationUnit") - SUB_NODE_XML("ReferenceSection") -END_NODE_XML - -NODE_XML("TranslationUnit") - SUB_NODE_SEQUENCE_XML(Decl) -END_NODE_XML - -NODE_XML("ReferenceSection") - SUB_NODE_XML("Types") - SUB_NODE_XML("Contexts") - SUB_NODE_XML("Files") -END_NODE_XML - -NODE_XML("Types") - SUB_NODE_SEQUENCE_XML(Type) -END_NODE_XML - -NODE_XML("Contexts") - SUB_NODE_SEQUENCE_XML(DeclContext) -END_NODE_XML - -NODE_XML("Files") - SUB_NODE_SEQUENCE_XML("File") -END_NODE_XML - -NODE_XML("File") - ID_ATTRIBUTE_XML - ATTRIBUTE_SPECIAL_XML(ignore, "name") // special retrieving needed, denotes the source file name -END_NODE_XML - - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef ATTRIBUTE_SPECIAL_XML -#undef END_NODE_XML -#undef SUB_NODE_XML -#undef SUB_NODE_SEQUENCE_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h deleted file mode 100644 index 602d84655828..000000000000 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h +++ /dev/null @@ -1,185 +0,0 @@ -//===--- DocumentXML.h - XML document for ASTs ------------------*- 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 the XML document class, which provides the means to -// dump out the AST in a XML form that exposes type details and other fields. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_FRONTEND_DOCUMENTXML_H -#define LLVM_CLANG_FRONTEND_DOCUMENTXML_H - -#include -#include -#include -#include "clang/AST/Type.h" -#include "clang/AST/TypeOrdering.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/DenseMap.h" - -namespace clang { - -//--------------------------------------------------------- forwards -class DeclContext; -class Decl; -class NamedDecl; -class FunctionDecl; -class ASTContext; -class LabelStmt; - -//--------------------------------------------------------- -namespace XML { - // id maps: - template - struct IdMap : llvm::DenseMap {}; - - template<> - struct IdMap : std::map {}; - - template<> - struct IdMap : std::map {}; -} - -//--------------------------------------------------------- -class DocumentXML { -public: - DocumentXML(const std::string& rootName, llvm::raw_ostream& out); - - void initialize(ASTContext &Context); - void PrintDecl(Decl *D); - void PrintStmt(const Stmt *S); // defined in StmtXML.cpp - void finalize(); - - - DocumentXML& addSubNode(const std::string& name); // also enters the sub node, returns *this - DocumentXML& toParent(); // returns *this - - void addAttribute(const char* pName, const QualType& pType); - void addAttribute(const char* pName, bool value); - - template - void addAttribute(const char* pName, const T* value) { - addPtrAttribute(pName, value); - } - - template - void addAttribute(const char* pName, T* value) { - addPtrAttribute(pName, value); - } - - template - void addAttribute(const char* pName, const T& value); - - template - void addAttributeOptional(const char* pName, const T& value); - - void addSourceFileAttribute(const std::string& fileName); - - PresumedLoc addLocation(const SourceLocation& Loc); - void addLocationRange(const SourceRange& R); - - static std::string escapeString(const char* pStr, std::string::size_type len); - -private: - DocumentXML(const DocumentXML&); // not defined - DocumentXML& operator=(const DocumentXML&); // not defined - - std::stack NodeStack; - llvm::raw_ostream& Out; - ASTContext *Ctx; - bool HasCurrentNodeSubNodes; - - - XML::IdMap Types; - XML::IdMap Contexts; - XML::IdMap BasicTypes; - XML::IdMap SourceFiles; - XML::IdMap Decls; - XML::IdMap Labels; - - void addContextsRecursively(const DeclContext *DC); - void addTypeRecursively(const Type* pType); - void addTypeRecursively(const QualType& pType); - - void Indent(); - - // forced pointer dispatch: - void addPtrAttribute(const char* pName, const Type* pType); - void addPtrAttribute(const char* pName, const NamedDecl* D); - void addPtrAttribute(const char* pName, const DeclContext* D); - void addPtrAttribute(const char* pName, const NamespaceDecl* D); // disambiguation - void addPtrAttribute(const char* pName, const NestedNameSpecifier* N); - void addPtrAttribute(const char* pName, const LabelStmt* L); - void addPtrAttribute(const char* pName, const char* text); - - // defined in TypeXML.cpp: - void addParentTypes(const Type* pType); - void writeTypeToXML(const Type* pType); - void writeTypeToXML(const QualType& pType); - class TypeAdder; - friend class TypeAdder; - - // defined in DeclXML.cpp: - void writeDeclToXML(Decl *D); - class DeclPrinter; - friend class DeclPrinter; - - // for addAttributeOptional: - static bool isDefault(unsigned value) { return value == 0; } - static bool isDefault(bool value) { return !value; } - static bool isDefault(Qualifiers::GC value) { return value == Qualifiers::GCNone; } - static bool isDefault(const std::string& value) { return value.empty(); } -}; - -//--------------------------------------------------------- inlines - -inline void DocumentXML::initialize(ASTContext &Context) { - Ctx = &Context; -} - -//--------------------------------------------------------- -template -inline void DocumentXML::addAttribute(const char* pName, const T& value) { - std::string repr; - { - llvm::raw_string_ostream buf(repr); - buf << value; - } - - Out << ' ' << pName << "=\"" - << DocumentXML::escapeString(repr.c_str(), repr.size()) - << "\""; -} - -//--------------------------------------------------------- -inline void DocumentXML::addPtrAttribute(const char* pName, const char* text) { - Out << ' ' << pName << "=\"" - << DocumentXML::escapeString(text, strlen(text)) - << "\""; -} - -//--------------------------------------------------------- -inline void DocumentXML::addAttribute(const char* pName, bool value) { - addPtrAttribute(pName, value ? "1" : "0"); -} - -//--------------------------------------------------------- -template -inline void DocumentXML::addAttributeOptional(const char* pName, - const T& value) { - if (!isDefault(value)) { - addAttribute(pName, value); - } -} - -//--------------------------------------------------------- - -} //namespace clang - -#endif //LLVM_CLANG_DOCUMENTXML_H diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h index 4df2e71571f7..4e67449b8549 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h @@ -42,12 +42,6 @@ class ASTPrintAction : public ASTFrontendAction { llvm::StringRef InFile); }; -class ASTPrintXMLAction : public ASTFrontendAction { -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile); -}; - class ASTDumpAction : public ASTFrontendAction { protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h index 2efbc818de1b..3e9508c009c8 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define FRONTENDSTART #include "clang/Basic/DiagnosticFrontendKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h index 19d39c3ca1b2..02f6f868fe49 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h @@ -23,7 +23,6 @@ namespace frontend { ASTDump, ///< Parse ASTs and dump them. ASTDumpXML, ///< Parse ASTs and dump them in XML. ASTPrint, ///< Parse ASTs and print them. - ASTPrintXML, ///< Parse ASTs and print them in XML. ASTView, ///< Parse ASTs and view them in Graphviz. BoostCon, ///< BoostCon mode. CreateModule, ///< Create module definition diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h index 441d34f5a388..74ca5191dd48 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h @@ -19,12 +19,13 @@ namespace frontend { enum LangFeatures { BCPLComment = (1 << 0), C99 = (1 << 1), - CPlusPlus = (1 << 2), - CPlusPlus0x = (1 << 3), - Digraphs = (1 << 4), - GNUMode = (1 << 5), - HexFloat = (1 << 6), - ImplicitInt = (1 << 7) + C1X = (1 << 2), + CPlusPlus = (1 << 3), + CPlusPlus0x = (1 << 4), + Digraphs = (1 << 5), + GNUMode = (1 << 6), + HexFloat = (1 << 7), + ImplicitInt = (1 << 8) }; } @@ -56,6 +57,9 @@ struct LangStandard { /// isC99 - Language is a superset of C99. bool isC99() const { return Flags & frontend::C99; } + /// isC1X - Language is a superset of C1X. + bool isC1X() const { return Flags & frontend::C1X; } + /// isCPlusPlus - Language is a C++ variant. bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; } diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def index d4046b3e5668..586e5c8fa2a4 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def @@ -54,11 +54,23 @@ LANGSTANDARD(iso9899_199x, LANGSTANDARD(gnu99, "gnu99", "ISO C 1999 with GNU extensions", - BCPLComment | C99 | Digraphs | GNUMode | HexFloat | Digraphs) + BCPLComment | C99 | Digraphs | GNUMode | HexFloat) LANGSTANDARD(gnu9x, "gnu9x", "ISO C 1999 with GNU extensions", BCPLComment | C99 | Digraphs | GNUMode | HexFloat) +// C1X modes +LANGSTANDARD(c1x, "c1x", + "ISO C 201X", + BCPLComment | C99 | C1X | Digraphs | HexFloat) +LANGSTANDARD(iso9899_201x, + "iso9899:201x", "ISO C 201X", + BCPLComment | C99 | C1X | Digraphs | HexFloat) + +LANGSTANDARD(gnu1x, "gnu1x", + "ISO C 201X with GNU extensions", + BCPLComment | C99 | C1X | Digraphs | GNUMode | HexFloat) + // C++ modes LANGSTANDARD(cxx98, "c++98", "ISO C++ 1998 with amendments", diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h new file mode 100644 index 000000000000..b6fc23ca1f04 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h @@ -0,0 +1,77 @@ +//===--- LogDiagnosticPrinter.h - Log Diagnostic Client ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_LOG_DIAGNOSTIC_PRINTER_H_ +#define LLVM_CLANG_FRONTEND_LOG_DIAGNOSTIC_PRINTER_H_ + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { +class DiagnosticOptions; +class LangOptions; + +class LogDiagnosticPrinter : public DiagnosticClient { + struct DiagEntry { + /// The primary message line of the diagnostic. + std::string Message; + + /// The source file name, if available. + std::string Filename; + + /// The source file line number, if available. + unsigned Line; + + /// The source file column number, if available. + unsigned Column; + + /// The ID of the diagnostic. + unsigned DiagnosticID; + + /// The level of the diagnostic. + Diagnostic::Level DiagnosticLevel; + }; + + llvm::raw_ostream &OS; + const LangOptions *LangOpts; + const DiagnosticOptions *DiagOpts; + + SourceLocation LastWarningLoc; + FullSourceLoc LastLoc; + unsigned OwnsOutputStream : 1; + + llvm::SmallVector Entries; + + std::string MainFilename; + std::string DwarfDebugFlags; + +public: + LogDiagnosticPrinter(llvm::raw_ostream &OS, const DiagnosticOptions &Diags, + bool OwnsOutputStream = false); + virtual ~LogDiagnosticPrinter(); + + void setDwarfDebugFlags(llvm::StringRef Value) { + DwarfDebugFlags = Value; + } + + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) { + LangOpts = &LO; + } + + void EndSourceFile(); + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); +}; + +} // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h index 560178be9bf8..4242f0117147 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h @@ -12,6 +12,9 @@ // //===----------------------------------------------------------------------===// +#ifndef CLANG_FRONTEND_MULTIPLEXCONSUMER_H +#define CLANG_FRONTEND_MULTIPLEXCONSUMER_H + #include "clang/Sema/SemaConsumer.h" #include "llvm/ADT/OwningPtr.h" #include @@ -52,3 +55,5 @@ class MultiplexConsumer : public SemaConsumer { }; } // end namespace clang + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h index 0d52e53ea16a..e875ec1fefd2 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h @@ -44,6 +44,9 @@ class PreprocessorOptions { /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; + /// \brief Headers that will be converted to chained PCHs in memory. + std::vector ChainedIncludes; + /// \brief When true, disables most of the normal validation performed on /// precompiled headers. bool DisablePCHValidation; @@ -73,6 +76,10 @@ class PreprocessorOptions { /// If given, a PTH cache file to use for speeding up header parsing. std::string TokenCache; + /// \brief True if the SourceManager should report the original file name for + /// contents of files that were remapped to other files. Defaults to true. + bool RemappedFilesKeepOriginalName; + /// \brief The set of file remappings, which take existing files on /// the system (the first part of each pair) and gives them the /// contents of other files on the system (the second part of each @@ -132,6 +139,7 @@ class PreprocessorOptions { DisablePCHValidation(false), DisableStatCache(false), DumpDeserializedPCHDecls(false), PrecompiledPreambleBytes(0, true), + RemappedFilesKeepOriginalName(true), RetainRemappedFileBuffers(false) { } void addMacroDef(llvm::StringRef Name) { diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def deleted file mode 100644 index 8a859e6898b1..000000000000 --- a/contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def +++ /dev/null @@ -1,520 +0,0 @@ -//===-- StmtXML.def - Metadata about Stmt XML nodes ------------*- 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 XML statement database structure as written in -// sub-nodes of the XML document. -// The semantics of the attributes and enums are mostly self-documenting -// by looking at the appropriate internally used functions and values. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// statement of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that statement -// node and possible sub-nodes follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a -// string, which value uniquely identify that statement. Other nodes may refer -// by reference attributes to this value (currently used only for Label). -// -// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an -// expression by a "type" attribute. FN is internally used by clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally -// used by clang. A boolean attribute have the values "0" or "1". -// -// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves -// a special handling. See the appropriate documentations. -// -// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of -// a statement in the source file(s). -// -// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. -// Optional attributes are omitted for boolean types, if the value is false, -// for integral types, if the value is null and for strings, -// if the value is the empty string. FN is internally used by clang. -// -// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the -// empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is -// internally used by clang. -// -// END_ENUM_XML - Closes the enumeration definition of the current attribute. -// -// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or -// its sub-classes. -// -//===----------------------------------------------------------------------===// - -#ifndef ATTRIBUTE_FILE_LOCATION_XML -# define ATTRIBUTE_FILE_LOCATION_XML \ - ATTRIBUTE_XML(getFilename(), "file") \ - ATTRIBUTE_XML(getLine(), "line") \ - ATTRIBUTE_XML(getColumn(), "col") \ - ATTRIBUTE_OPT_XML(getFilename(), "endfile") \ - ATTRIBUTE_OPT_XML(getLine(), "endline") \ - ATTRIBUTE_OPT_XML(getColumn(), "endcol") -#endif - -#ifndef TYPE_ATTRIBUTE_XML -# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#endif - -#ifndef CONTEXT_ATTRIBUTE_XML -# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#endif - -NODE_XML(Stmt, "Stmt_Unsupported") // fallback for unsupproted statements - ATTRIBUTE_FILE_LOCATION_XML -END_NODE_XML - -NODE_XML(NullStmt, "NullStmt") - ATTRIBUTE_FILE_LOCATION_XML -END_NODE_XML - -NODE_XML(CompoundStmt, "CompoundStmt") - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(size(), "num_stmts") - SUB_NODE_SEQUENCE_XML(Stmt) -END_NODE_XML - -NODE_XML(CaseStmt, "CaseStmt") // case expr: body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Stmt) // body - SUB_NODE_XML(Expr) // expr - SUB_NODE_XML(Expr) // rhs expr in gc extension: case expr .. expr: body; -END_NODE_XML - -NODE_XML(DefaultStmt, "DefaultStmt") // default: body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(LabelStmt, "LabelStmt") // Label: body; - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getName(), "name") // string - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(IfStmt, "IfStmt") // if (cond) stmt1; else stmt2; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Stmt) // stmt1 - SUB_NODE_XML(Stmt) // stmt2 -END_NODE_XML - -NODE_XML(SwitchStmt, "SwitchStmt") // switch (cond) body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(WhileStmt, "WhileStmt") // while (cond) body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(DoStmt, "DoStmt") // do body while (cond); - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(ForStmt, "ForStmt") // for (init; cond; inc) body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Stmt) // init - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Expr) // inc - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(GotoStmt, "GotoStmt") // goto label; - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getLabel()->getName(), "name") // informal string - ATTRIBUTE_XML(getLabel(), "ref") // id string -END_NODE_XML - -NODE_XML(IndirectGotoStmt, "IndirectGotoStmt") // goto expr; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(ContinueStmt, "ContinueStmt") // continue - ATTRIBUTE_FILE_LOCATION_XML -END_NODE_XML - -NODE_XML(BreakStmt, "BreakStmt") // break - ATTRIBUTE_FILE_LOCATION_XML -END_NODE_XML - -NODE_XML(ReturnStmt, "ReturnStmt") // return expr; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(AsmStmt, "AsmStmt") // GNU inline-assembly statement extension - ATTRIBUTE_FILE_LOCATION_XML - // FIXME -END_NODE_XML - -NODE_XML(DeclStmt, "DeclStmt") // a declaration statement - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_SEQUENCE_XML(Decl) -END_NODE_XML - -// C++ statements -NODE_XML(CXXTryStmt, "CXXTryStmt") // try CompoundStmt CXXCatchStmt1 CXXCatchStmt2 .. - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getNumHandlers(), "num_handlers") - SUB_NODE_XML(CompoundStmt) - SUB_NODE_SEQUENCE_XML(CXXCatchStmt) -END_NODE_XML - -NODE_XML(CXXCatchStmt, "CXXCatchStmt") // catch (decl) Stmt - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(VarDecl) - SUB_NODE_XML(Stmt) -END_NODE_XML - -// Expressions -NODE_XML(PredefinedExpr, "PredefinedExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_XML(getIdentType(), "kind") - ENUM_XML(PredefinedExpr::Func, "__func__") - ENUM_XML(PredefinedExpr::Function, "__FUNCTION__") - ENUM_XML(PredefinedExpr::PrettyFunction, "__PRETTY_FUNCTION__") - END_ENUM_XML -END_NODE_XML - -NODE_XML(DeclRefExpr, "DeclRefExpr") // an expression referring to a declared entity - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getDecl(), "ref") // id string of the declaration - ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // informal - //ATTRIBUTE_ENUM_XML(getDecl()->getKind(), "kind") // really needed here? -END_NODE_XML - -NODE_XML(IntegerLiteral, "IntegerLiteral") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getValue(), "value") // (signed) integer -END_NODE_XML - -NODE_XML(CharacterLiteral, "CharacterLiteral") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getValue(), "value") // unsigned -END_NODE_XML - -NODE_XML(FloatingLiteral, "FloatingLiteral") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - // FIXME: output float as written in source (no approximation or the like) - //ATTRIBUTE_XML(getValueAsApproximateDouble(), "value") // float -END_NODE_XML - -NODE_XML(StringLiteral, "StringLiteral") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_SPECIAL_XML(getStrData(), "value") // string, special handling for escaping needed - ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean -END_NODE_XML - -NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_XML(getOpcode(), "kind") - ENUM_XML(UO_PostInc, "postinc") - ENUM_XML(UO_PostDec, "postdec") - ENUM_XML(UO_PreInc, "preinc") - ENUM_XML(UO_PreDec, "predec") - ENUM_XML(UO_AddrOf, "addrof") - ENUM_XML(UO_Deref, "deref") - ENUM_XML(UO_Plus, "plus") - ENUM_XML(UO_Minus, "minus") - ENUM_XML(UO_Not, "not") // bitwise not - ENUM_XML(UO_LNot, "lnot") // boolean not - ENUM_XML(UO_Real, "__real") - ENUM_XML(UO_Imag, "__imag") - ENUM_XML(UO_Extension, "__extension__") - END_ENUM_XML - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_XML(getOpcode(), "kind") - ENUM_XML(BO_PtrMemD , "ptrmemd") - ENUM_XML(BO_PtrMemI , "ptrmemi") - ENUM_XML(BO_Mul , "mul") - ENUM_XML(BO_Div , "div") - ENUM_XML(BO_Rem , "rem") - ENUM_XML(BO_Add , "add") - ENUM_XML(BO_Sub , "sub") - ENUM_XML(BO_Shl , "shl") - ENUM_XML(BO_Shr , "shr") - ENUM_XML(BO_LT , "lt") - ENUM_XML(BO_GT , "gt") - ENUM_XML(BO_LE , "le") - ENUM_XML(BO_GE , "ge") - ENUM_XML(BO_EQ , "eq") - ENUM_XML(BO_NE , "ne") - ENUM_XML(BO_And , "and") // bitwise and - ENUM_XML(BO_Xor , "xor") - ENUM_XML(BO_Or , "or") // bitwise or - ENUM_XML(BO_LAnd , "land") // boolean and - ENUM_XML(BO_LOr , "lor") // boolean or - ENUM_XML(BO_Assign , "assign") - ENUM_XML(BO_MulAssign, "mulassign") - ENUM_XML(BO_DivAssign, "divassign") - ENUM_XML(BO_RemAssign, "remassign") - ENUM_XML(BO_AddAssign, "addassign") - ENUM_XML(BO_SubAssign, "subassign") - ENUM_XML(BO_ShlAssign, "shlassign") - ENUM_XML(BO_ShrAssign, "shrassign") - ENUM_XML(BO_AndAssign, "andassign") - ENUM_XML(BO_XorAssign, "xorassign") - ENUM_XML(BO_OrAssign , "orassign") - ENUM_XML(BO_Comma , "comma") - END_ENUM_XML - SUB_NODE_XML(Expr) // expr1 - SUB_NODE_XML(Expr) // expr2 -END_NODE_XML - -// FIXME: is there a special class needed or is BinaryOperator sufficient? -//NODE_XML(CompoundAssignOperator, "CompoundAssignOperator") - -NODE_XML(ConditionalOperator, "ConditionalOperator") // expr1 ? expr2 : expr3 - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr1 - SUB_NODE_XML(Expr) // expr2 - SUB_NODE_XML(Expr) // expr3 -END_NODE_XML - -NODE_XML(OffsetOfExpr, "OffsetOfExpr") // offsetof(basetype, components) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getTypeSourceInfo()->getType()) - ATTRIBUTE_XML(getNumComponents(), "num_components") - SUB_NODE_SEQUENCE_XML(OffsetOfExpr::OffsetOfNode) -END_NODE_XML - -NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(isSizeOf(), "is_sizeof") - ATTRIBUTE_XML(isArgumentType(), "is_type") // "1" if expr denotes a type - ATTRIBUTE_SPECIAL_XML(getArgumentType(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getArgumentType() could assert - SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0" -END_NODE_XML - -NODE_XML(ArraySubscriptExpr, "ArraySubscriptExpr") // expr1[expr2] - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr1 - SUB_NODE_XML(Expr) // expr2 -END_NODE_XML - -NODE_XML(CallExpr, "CallExpr") // fnexpr(arg1, arg2, ...) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned - SUB_NODE_XML(Expr) // fnexpr - SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN -END_NODE_XML - -NODE_XML(MemberExpr, "MemberExpr") // expr->F or expr.F - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(isArrow(), "is_deref") - ATTRIBUTE_XML(getMemberDecl(), "ref") // refers to F - ATTRIBUTE_XML(getMemberDecl()->getNameAsString(), "name") // informal - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(CStyleCastExpr, "CStyleCastExpr") // (type)expr - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(ImplicitCastExpr, "ImplicitCastExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) -END_NODE_XML - -NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5] - SUB_NODE_XML(Expr) // init -END_NODE_XML - -NODE_XML(ExtVectorElementExpr, "ExtVectorElementExpr") - SUB_NODE_XML(Expr) // base -END_NODE_XML - -NODE_XML(InitListExpr, "InitListExpr") // struct foo x = { expr1, { expr2, expr3 } }; - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id - ATTRIBUTE_XML(getNumInits(), "num_inits") // unsigned - SUB_NODE_SEQUENCE_XML(Expr) // expr1..exprN -END_NODE_XML - -NODE_XML(DesignatedInitExpr, "DesignatedInitExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -NODE_XML(ImplicitValueInitExpr, "ImplicitValueInitExpr") // Implicit value initializations occur within InitListExpr - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -NODE_XML(VAArgExpr, "VAArgExpr") // used for the builtin function __builtin_va_start(expr) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(ParenExpr, "ParenExpr") // this represents a parethesized expression "(expr)". Only formed if full location information is requested. - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -// GNU Extensions -NODE_XML(AddrLabelExpr, "AddrLabelExpr") // the GNU address of label extension, representing &&label. - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getLabel(), "ref") // id string - SUB_NODE_XML(LabelStmt) // expr -END_NODE_XML - -NODE_XML(StmtExpr, "StmtExpr") // StmtExpr contains a single CompoundStmt node, which it evaluates and takes the value of the last subexpression. - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(CompoundStmt) -END_NODE_XML - -NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr1 - SUB_NODE_XML(Expr) // expr2 - SUB_NODE_XML(Expr) // expr3 -END_NODE_XML - -NODE_XML(GNUNullExpr, "GNUNullExpr") // GNU __null extension - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -// C++ Expressions -NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, ...) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned - SUB_NODE_XML(Expr) // fnexpr - SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN -END_NODE_XML - -NODE_XML(CXXConstructExpr, "CXXConstructExpr") // ctor(arg1, arg2, ...) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned - SUB_NODE_XML(Expr) // fnexpr - SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN -END_NODE_XML - -NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast(expr) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_XML(getStmtClass(), "kind") - ENUM_XML(Stmt::CXXStaticCastExprClass, "static_cast") - ENUM_XML(Stmt::CXXDynamicCastExprClass, "dynamic_cast") - ENUM_XML(Stmt::CXXReinterpretCastExprClass, "reinterpret_cast") - ENUM_XML(Stmt::CXXConstCastExprClass, "const_cast") - END_ENUM_XML - ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(CXXMemberCallExpr, "CXXMemberCallExpr") // fnexpr(arg1, arg2, ...) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned - SUB_NODE_XML(Expr) // fnexpr - SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN -END_NODE_XML - -NODE_XML(CXXBoolLiteralExpr, "CXXBoolLiteralExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getValue(), "value") // boolean -END_NODE_XML - -NODE_XML(CXXNullPtrLiteralExpr, "CXXNullPtrLiteralExpr") // [C++0x 2.14.7] C++ Pointer Literal - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -NODE_XML(CXXTypeidExpr, "CXXTypeidExpr") // typeid(expr) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(isTypeOperand(), "is_type") // "1" if expr denotes a type - ATTRIBUTE_SPECIAL_XML(getTypeOperand(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getTypeOperand() could assert - SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0" -END_NODE_XML - -NODE_XML(CXXThisExpr, "CXXThisExpr") // this - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -NODE_XML(CXXThrowExpr, "CXXThrowExpr") // throw (expr); - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // NULL in case of "throw;" -END_NODE_XML - -NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration) -END_NODE_XML - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef TYPE_ATTRIBUTE_XML -#undef ATTRIBUTE_XML -#undef ATTRIBUTE_SPECIAL_XML -#undef ATTRIBUTE_OPT_XML -#undef ATTRIBUTE_ENUM_XML -#undef ATTRIBUTE_ENUM_OPT_XML -#undef ATTRIBUTE_FILE_LOCATION_XML -#undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML -#undef SUB_NODE_XML -#undef SUB_NODE_SEQUENCE_XML -#undef SUB_NODE_OPT_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h index f5302947a593..d7d2692cb547 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h @@ -53,7 +53,8 @@ class TextDiagnosticPrinter : public DiagnosticClient { LangOpts = 0; } - void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM); + void PrintIncludeStack(Diagnostic::Level Level, SourceLocation Loc, + const SourceManager &SM); void HighlightRange(const CharSourceRange &R, const SourceManager &SrcMgr, @@ -61,7 +62,7 @@ class TextDiagnosticPrinter : public DiagnosticClient { std::string &CaretLine, const std::string &SourceLine); - void EmitCaretDiagnostic(SourceLocation Loc, + void EmitCaretDiagnostic(Diagnostic::Level Level, SourceLocation Loc, CharSourceRange *Ranges, unsigned NumRanges, const SourceManager &SM, const FixItHint *Hints, @@ -71,7 +72,7 @@ class TextDiagnosticPrinter : public DiagnosticClient { unsigned MacroSkipStart, unsigned MacroSkipEnd); - virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + virtual void HandleDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info); }; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def deleted file mode 100644 index b78e70f5aa86..000000000000 --- a/contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def +++ /dev/null @@ -1,304 +0,0 @@ -//===-- TypeXML.def - Metadata about Type XML nodes ------------*- 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 XML type info database as written in the -// / sub-nodes of the XML document. Type nodes -// are referred by "type" reference attributes throughout the document. -// A type node never contains sub-nodes. -// The semantics of the attributes and enums are mostly self-documenting -// by looking at the appropriate internally used functions and values. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// type of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that type -// node follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Each type node has an "id" attribute containing a -// string, which value uniquely identify the type. Other nodes may refer -// by "type" reference attributes to this value. -// -// TYPE_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of other type -// nodes by a "type" attribute. FN is internally used by clang. -// -// CONTEXT_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of their -// declaration contexts by a "context" attribute. FN is internally used by -// clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally -// used by clang. A boolean attribute have the values "0" or "1". -// -// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. -// Optional attributes are omitted for boolean types, if the value is false, -// for integral types, if the value is null and for strings, -// if the value is the empty string. FN is internally used by clang. -// -// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the -// empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is -// internally used by clang. -// -// END_ENUM_XML - Closes the enumeration definition of the current attribute. -// -//===----------------------------------------------------------------------===// - -#ifndef TYPE_ATTRIBUTE_XML -# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#endif - -#ifndef CONTEXT_ATTRIBUTE_XML -# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#endif - -NODE_XML(Type, "FIXME_Type") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getTypeClassName(), "unhandled_type_name") -END_NODE_XML - -NODE_XML(QualType, "CvQualifiedType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getTypePtr()) // the qualified type, e.g. for 'T* const' it's 'T*' - ATTRIBUTE_OPT_XML(isLocalConstQualified(), "const") // boolean - ATTRIBUTE_OPT_XML(isLocalVolatileQualified(), "volatile") // boolean - ATTRIBUTE_OPT_XML(isLocalRestrictQualified(), "restrict") // boolean - ATTRIBUTE_OPT_XML(getObjCGCAttr(), "objc_gc") // Qualifiers::GC - ATTRIBUTE_OPT_XML(getAddressSpace(), "address_space") // unsigned -END_NODE_XML - -NODE_XML(BuiltinType, "FundamentalType") - ID_ATTRIBUTE_XML - ATTRIBUTE_ENUM_XML(getKind(), "kind") - ENUM_XML(BuiltinType::Void, "void") - ENUM_XML(BuiltinType::Bool, "bool") - ENUM_XML(BuiltinType::Char_U, "char") // not explicitely qualified char, depends on target platform - ENUM_XML(BuiltinType::Char_S, "char") // not explicitely qualified char, depends on target platform - ENUM_XML(BuiltinType::SChar, "signed char") - ENUM_XML(BuiltinType::Short, "short"); - ENUM_XML(BuiltinType::Int, "int"); - ENUM_XML(BuiltinType::Long, "long"); - ENUM_XML(BuiltinType::LongLong, "long long"); - ENUM_XML(BuiltinType::Int128, "__int128_t"); - ENUM_XML(BuiltinType::UChar, "unsigned char"); - ENUM_XML(BuiltinType::UShort, "unsigned short"); - ENUM_XML(BuiltinType::UInt, "unsigned int"); - ENUM_XML(BuiltinType::ULong, "unsigned long"); - ENUM_XML(BuiltinType::ULongLong, "unsigned long long"); - ENUM_XML(BuiltinType::UInt128, "__uint128_t"); - ENUM_XML(BuiltinType::Float, "float"); - ENUM_XML(BuiltinType::Double, "double"); - ENUM_XML(BuiltinType::LongDouble, "long double"); - ENUM_XML(BuiltinType::WChar_U, "wchar_t"); - ENUM_XML(BuiltinType::WChar_S, "wchar_t"); - ENUM_XML(BuiltinType::Char16, "char16_t"); - ENUM_XML(BuiltinType::Char32, "char32_t"); - ENUM_XML(BuiltinType::NullPtr, "nullptr_t"); // This is the type of C++0x 'nullptr'. - ENUM_XML(BuiltinType::Overload, "overloaded"); - ENUM_XML(BuiltinType::Dependent, "dependent"); - END_ENUM_XML -END_NODE_XML - -NODE_XML(PointerType, "PointerType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) -END_NODE_XML - -NODE_XML(LValueReferenceType, "ReferenceType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) -END_NODE_XML - -NODE_XML(RValueReferenceType, "ReferenceType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) -END_NODE_XML - -NODE_XML(FunctionNoProtoType, "FunctionNoProtoType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(FunctionProtoType, "FunctionType") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getResultType(), "result_type") - ATTRIBUTE_OPT_XML(isVariadic(), "variadic") - ATTRIBUTE_ENUM_XML(getCallConv(), "call_conv") - ENUM_XML(CC_Default, "") - ENUM_XML(CC_C, "C") - ENUM_XML(CC_X86StdCall, "X86StdCall") - ENUM_XML(CC_X86FastCall, "X86FastCall") - ENUM_XML(CC_X86ThisCall, "X86ThisCall") - END_ENUM_XML -END_NODE_XML - -NODE_XML(TypedefType, "Typedef") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getDecl()->getUnderlyingType()) - ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string - CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) -END_NODE_XML - -NODE_XML(ComplexType, "ComplexType") // C99 complex types (_Complex float etc) - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) -END_NODE_XML - -NODE_XML(BlockPointerType, "BlockPointerType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) // alway refers to a function type -END_NODE_XML - -NODE_XML(MemberPointerType, "MemberPointerType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) - ATTRIBUTE_XML(getClass(), "class_type") // refers to the class type id of which the pointee is a member -END_NODE_XML - -NODE_XML(ConstantArrayType, "ArrayType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - ATTRIBUTE_XML(getSize(), "size") // unsigned - ATTRIBUTE_ENUM_OPT_XML(getSizeModifier(), "size_modifier") - ENUM_XML(ArrayType::Normal, "") - ENUM_XML(ArrayType::Static, "static") - ENUM_XML(ArrayType::Star, "star") - END_ENUM_XML - ATTRIBUTE_OPT_XML(getIndexTypeCVRQualifiers(), "index_type_qualifier") // unsigned -END_NODE_XML - -NODE_XML(IncompleteArrayType, "IncompleteArrayType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) -END_NODE_XML - -NODE_XML(VariableArrayType, "VariableArrayType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - // note: the size expression is print at the point of declaration -END_NODE_XML - -NODE_XML(DependentSizedArrayType, "DependentSizedArrayType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - // FIXME: how to deal with size expression? -END_NODE_XML - -NODE_XML(VectorType, "VectorType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - ATTRIBUTE_XML(getNumElements(), "size") // unsigned -END_NODE_XML - -NODE_XML(ExtVectorType, "ExtVectorType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - ATTRIBUTE_XML(getNumElements(), "size") // unsigned -END_NODE_XML - -NODE_XML(TypeOfExprType, "TypeOfExprType") - ID_ATTRIBUTE_XML - // note: the typeof expression is print at the point of use -END_NODE_XML - -NODE_XML(TypeOfType, "TypeOfType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getUnderlyingType()) -END_NODE_XML - - -NODE_XML(RecordType, "Record") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string - ATTRIBUTE_ENUM_XML(getDecl()->getTagKind(), "kind") - ENUM_XML(TTK_Struct, "struct") - ENUM_XML(TTK_Union, "union") - ENUM_XML(TTK_Class, "class") - END_ENUM_XML - CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) -END_NODE_XML - -NODE_XML(EnumType, "Enum") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string - CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) -END_NODE_XML - -NODE_XML(TemplateTypeParmType, "TemplateTypeParmType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(TemplateSpecializationType, "TemplateSpecializationType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(ElaboratedType, "ElaboratedType") - ID_ATTRIBUTE_XML - ATTRIBUTE_ENUM_XML(getKeyword(), "keyword") - ENUM_XML(ETK_None, "none") - ENUM_XML(ETK_Typename, "typename") - ENUM_XML(ETK_Struct, "struct") - ENUM_XML(ETK_Union, "union") - ENUM_XML(ETK_Class, "class") - ENUM_XML(ETK_Enum, "enum") - END_ENUM_XML - TYPE_ATTRIBUTE_XML(getNamedType()) -END_NODE_XML - -NODE_XML(InjectedClassNameType, "InjectedClassNameType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(DependentNameType, "DependentNameType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(DependentTemplateSpecializationType, - "DependentTemplateSpecializationType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(ObjCInterfaceType, "ObjCInterfaceType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(ObjCObjectPointerType, "ObjCObjectPointerType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(SubstTemplateTypeParmType, "SubstTemplateTypeParm") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(DependentSizedExtVectorType, "DependentSizedExtVector") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(UnresolvedUsingType, "UnresolvedUsing") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(DecltypeType, "Decltype") - ID_ATTRIBUTE_XML -END_NODE_XML - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef TYPE_ATTRIBUTE_XML -#undef CONTEXT_ATTRIBUTE_XML -#undef ATTRIBUTE_XML -#undef ATTRIBUTE_OPT_XML -#undef ATTRIBUTE_ENUM_XML -#undef ATTRIBUTE_ENUM_OPT_XML -#undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h index 02342c1a4710..e4997165cd11 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h @@ -14,7 +14,10 @@ #ifndef LLVM_CLANG_FRONTEND_UTILS_H #define LLVM_CLANG_FRONTEND_UTILS_H +#include "clang/Basic/Diagnostic.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -24,6 +27,7 @@ class Triple; namespace clang { class ASTConsumer; class CompilerInstance; +class CompilerInvocation; class Decl; class DependencyOutputOptions; class Diagnostic; @@ -85,12 +89,23 @@ void AttachDependencyFileGen(Preprocessor &PP, /// \param OutputPath - If non-empty, a path to write the header include /// information to, instead of writing to stderr. void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false, - llvm::StringRef OutputPath = ""); + llvm::StringRef OutputPath = "", + bool ShowDepth = true); /// CacheTokens - Cache tokens for use with PCH. Note that this requires /// a seekable stream. void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS); +/// createInvocationFromCommandLine - Construct a compiler invocation object for +/// a command line argument vector. +/// +/// \return A CompilerInvocation, or 0 if none was built for the given +/// argument vector. +CompilerInvocation * +createInvocationFromCommandLine(llvm::ArrayRef Args, + llvm::IntrusiveRefCntPtr Diags = + llvm::IntrusiveRefCntPtr()); + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h index 64687a18e2b6..1ee6953a12b2 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h @@ -18,6 +18,7 @@ namespace llvm { class StringRef; + template class SmallVectorImpl; } namespace clang { class HeaderMap; @@ -121,11 +122,26 @@ class DirectoryLookup { /// LookupFile - Lookup the specified file in this search path, returning it /// if it exists or returning null if not. - const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS) const; + /// + /// \param Filename The file to look up relative to the search paths. + /// + /// \param HS The header search instance to search with. + /// + /// \param SearchPath If not NULL, will be set to the search path relative + /// to which the file was found. + /// + /// \param RelativePath If not NULL, will be set to the path relative to + /// SearchPath at which the file was found. This only differs from the + /// Filename for framework includes. + const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) const; private: - const FileEntry *DoFrameworkLookup(llvm::StringRef Filename, - HeaderSearch &HS) const; + const FileEntry *DoFrameworkLookup( + llvm::StringRef Filename, HeaderSearch &HS, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) const; }; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h index 8a5c83ecf495..e333840b6a9d 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h @@ -17,6 +17,7 @@ namespace llvm { class MemoryBuffer; class StringRef; + template class SmallVectorImpl; } namespace clang { class FileEntry; @@ -47,6 +48,10 @@ class HeaderMap { /// LookupFile - Check to see if the specified relative filename is located in /// this HeaderMap. If so, open it and return its FileEntry. + /// If RawPath is not NULL and the file is found, RawPath will be set to the + /// raw path at which the file was found in the file system. For example, + /// for a search path ".." and a filename "../file.h" this would be + /// "../../file.h". const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM) const; /// getFileName - Return the filename of the headermap. diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h index 30bd4f58549c..fec4dad1e73b 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h @@ -104,7 +104,7 @@ class HeaderSearch { /// consequtively. Requests for search the current dir first, then each /// directory in SearchDirs, starting at SystemDirIdx, consequtively. If /// NoCurDirSearch is true, then the check for the file in the current - /// directory is supressed. + /// directory is suppressed. std::vector SearchDirs; unsigned SystemDirIdx; bool NoCurDirSearch; @@ -182,25 +182,43 @@ class HeaderSearch { } /// LookupFile - Given a "foo" or reference, look up the indicated file, - /// return null on failure. isAngled indicates whether the file reference is - /// a <> reference. If successful, this returns 'UsedDir', the - /// DirectoryLookup member the file was found in, or null if not applicable. - /// If CurDir is non-null, the file was found in the specified directory - /// search location. This is used to implement #include_next. CurFileEnt, if - /// non-null, indicates where the #including file is, in case a relative - /// search is needed. + /// return null on failure. + /// + /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member + /// the file was found in, or null if not applicable. + /// + /// \param isAngled indicates whether the file reference is a <> reference. + /// + /// \param CurDir If non-null, the file was found in the specified directory + /// search location. This is used to implement #include_next. + /// + /// \param CurFileEnt If non-null, indicates where the #including file is, in + /// case a relative search is needed. + /// + /// \param SearchPath If non-null, will be set to the search path relative + /// to which the file was found. If the include path is absolute, SearchPath + /// will be set to an empty string. + /// + /// \param RelativePath If non-null, will be set to the path relative to + /// SearchPath at which the file was found. This only differs from the + /// Filename for framework includes. const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, - const FileEntry *CurFileEnt); + const FileEntry *CurFileEnt, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath); /// LookupSubframeworkHeader - Look up a subframework for the specified /// #include file. For example, if #include'ing from /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox /// is a subframework within Carbon.framework. If so, return the FileEntry /// for the designated file, otherwise return null. - const FileEntry *LookupSubframeworkHeader(llvm::StringRef Filename, - const FileEntry *RelativeFileEnt); + const FileEntry *LookupSubframeworkHeader( + llvm::StringRef Filename, + const FileEntry *RelativeFileEnt, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath); /// LookupFrameworkCache - Look up the specified framework name in our /// framework cache, returning the DirectoryEntry it is in if we know, @@ -261,6 +279,17 @@ class HeaderSearch { // Used by ASTReader. void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID); + // Used by external tools + typedef std::vector::const_iterator search_dir_iterator; + search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); } + search_dir_iterator search_dir_end() const { return SearchDirs.end(); } + unsigned search_dir_size() const { return SearchDirs.size(); } + + search_dir_iterator system_dir_begin() const { + return SearchDirs.begin() + SystemDirIdx; + } + search_dir_iterator system_dir_end() const { return SearchDirs.end(); } + void PrintStats(); private: diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h index 5fcb8eb2d1a4..7d2eb89c50bc 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define LEXSTART #include "clang/Basic/DiagnosticLexKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h index fc9a8de43482..7c3d863bd3d3 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h @@ -18,7 +18,6 @@ #include "clang/Basic/LangOptions.h" #include "llvm/ADT/SmallVector.h" #include -#include #include namespace clang { @@ -236,6 +235,20 @@ class Lexer : public PreprocessorLexer { const SourceManager &SourceMgr, const LangOptions &Features, bool *Invalid = 0); + + /// getSpelling - This method is used to get the spelling of the + /// token at the given source location. If, as is usually true, it + /// is not necessary to copy any data, then the returned string may + /// not point into the provided buffer. + /// + /// This method lexes at the instantiation depth of the given + /// location and does not jump to the instantiation or spelling + /// location. + static llvm::StringRef getSpelling(SourceLocation loc, + llvm::SmallVectorImpl &buffer, + const SourceManager &SourceMgr, + const LangOptions &Features, + bool *invalid = 0); /// MeasureTokenLength - Relex the token at the specified location and return /// its length in bytes in the input file. If the token needs cleaning (e.g. diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h index bf2c06becdbf..dcaf4457cfa8 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h @@ -19,7 +19,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Support/DataTypes.h" #include -#include namespace clang { diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h index 717c3008eca9..7c4cfb007233 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h @@ -17,7 +17,6 @@ #include "clang/Lex/Token.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" -#include #include namespace clang { diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h index 5d5d67329059..95b00dfcf366 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h @@ -47,7 +47,7 @@ class MultipleIncludeOpt { TheMacro = 0; } - /// Invalidate - Permenantly mark this file as not being suitable for the + /// Invalidate - Permanently mark this file as not being suitable for the /// include-file optimization. void Invalidate() { // If we have read tokens but have no controlling macro, the state-machine diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h index b2a80a62985f..fd07a29f8e9d 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h @@ -75,12 +75,26 @@ class PPCallbacks { /// /// \param EndLoc The location of the last token within the inclusion /// directive. + /// + /// \param SearchPath Contains the search path which was used to find the file + /// in the file system. If the file was found via an absolute include path, + /// SearchPath will be empty. For framework includes, the SearchPath and + /// RelativePath will be split up. For example, if an include of "Some/Some.h" + /// is found via the framework path + /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be + /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be + /// "Some.h". + /// + /// \param RelativePath The path relative to SearchPath, at which the include + /// file was found. This is equal to FileName except for framework includes. virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, llvm::StringRef FileName, bool IsAngled, const FileEntry *File, - SourceLocation EndLoc) { + SourceLocation EndLoc, + llvm::StringRef SearchPath, + llvm::StringRef RelativePath) { } /// EndOfMainFile - This callback is invoked when the end of the main file is @@ -188,11 +202,13 @@ class PPChainedCallbacks : public PPCallbacks { llvm::StringRef FileName, bool IsAngled, const FileEntry *File, - SourceLocation EndLoc) { - First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc); - Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc); + SourceLocation EndLoc, + llvm::StringRef SearchPath, + llvm::StringRef RelativePath) { + First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, + EndLoc, SearchPath, RelativePath); + Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, + EndLoc, SearchPath, RelativePath); } virtual void EndOfMainFile() { diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h index 0b5a76ccfd6e..f6a97a0a90a4 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h @@ -15,7 +15,6 @@ #define LLVM_CLANG_PTHLEXER_H #include "clang/Lex/PreprocessorLexer.h" -#include namespace clang { diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h index 8bd22369476e..c6ab35c19c1e 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h @@ -17,7 +17,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include -#include namespace clang { class Preprocessor; diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h index afd7ae1187cc..7be845549d4a 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h @@ -341,7 +341,9 @@ namespace clang { llvm::StringRef FileName, bool IsAngled, const FileEntry *File, - SourceLocation EndLoc); + SourceLocation EndLoc, + llvm::StringRef SearchPath, + llvm::StringRef RelativePath); }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h index 9005adc6ade6..616507a914a8 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h @@ -25,6 +25,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" @@ -53,7 +54,7 @@ class PreprocessingRecord; /// single source file, and don't know anything about preprocessor-level issues /// like the #include stack, token expansion, etc. /// -class Preprocessor { +class Preprocessor : public llvm::RefCountedBase { Diagnostic *Diags; LangOptions Features; const TargetInfo &Target; @@ -217,6 +218,10 @@ class Preprocessor { /// previous macro value. llvm::DenseMap > PragmaPushMacroInfo; + /// \brief Instantiation source location for the last macro that expanded + /// to no tokens. + SourceLocation LastEmptyMacroInstantiationLoc; + // Various statistics we track for performance analysis. unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma; unsigned NumIf, NumElse, NumEndif; @@ -365,6 +370,12 @@ class Preprocessor { macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; + /// \brief Instantiation source location for the last macro that expanded + /// to no tokens. + SourceLocation getLastEmptyMacroInstantiationLoc() const { + return LastEmptyMacroInstantiationLoc; + } + const std::string &getPredefines() const { return Predefines; } /// setPredefines - Set the predefines for this Preprocessor. These /// predefines are automatically injected when parsing the main file. @@ -644,13 +655,26 @@ class Preprocessor { return Diags->Report(Tok.getLocation(), DiagID); } + /// getSpelling() - Return the 'spelling' of the token at the given + /// location; does not go up to the spelling location or down to the + /// instantiation location. + /// + /// \param buffer A buffer which will be used only if the token requires + /// "cleaning", e.g. if it contains trigraphs or escaped newlines + /// \param invalid If non-null, will be set \c true if an error occurs. + llvm::StringRef getSpelling(SourceLocation loc, + llvm::SmallVectorImpl &buffer, + bool *invalid = 0) const { + return Lexer::getSpelling(loc, buffer, SourceMgr, Features, invalid); + } + /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a /// token is the characters used to represent the token in the source file /// after trigraph expansion and escaped-newline folding. In particular, this /// wants to get the true, uncanonicalized, spelling of things like digraphs /// UCNs, etc. /// - /// \param Invalid If non-NULL, will be set \c true if an error occurs. + /// \param Invalid If non-null, will be set \c true if an error occurs. std::string getSpelling(const Token &Tok, bool *Invalid = 0) const { return Lexer::getSpelling(Tok, SourceMgr, Features, Invalid); } @@ -759,6 +783,38 @@ class Preprocessor { /// updating the token kind accordingly. IdentifierInfo *LookUpIdentifierInfo(Token &Identifier) const; +private: + llvm::DenseMap PoisonReasons; + +public: + + // SetPoisonReason - Call this function to indicate the reason for + // poisoning an identifier. If that identifier is accessed while + // poisoned, then this reason will be used instead of the default + // "poisoned" diagnostic. + void SetPoisonReason(IdentifierInfo *II, unsigned DiagID); + + // HandlePoisonedIdentifier - Display reason for poisoned + // identifier. + void HandlePoisonedIdentifier(Token & Tok); + + void MaybeHandlePoisonedIdentifier(Token & Identifier) { + if(IdentifierInfo * II = Identifier.getIdentifierInfo()) { + if(II->isPoisoned()) { + HandlePoisonedIdentifier(Identifier); + } + } + } + +private: + /// Identifiers used for SEH handling in Borland. These are only + /// allowed in particular circumstances + IdentifierInfo *Ident__exception_code, *Ident___exception_code, *Ident_GetExceptionCode; // __except block + IdentifierInfo *Ident__exception_info, *Ident___exception_info, *Ident_GetExceptionInfo; // __except filter expression + IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; // __finally +public: + void PoisonSEHIdentifiers(bool Poison = true); // Borland + /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier and has filled in the tokens IdentifierInfo member. This /// callback potentially macro expands it or turns it into a named token (like @@ -782,13 +838,13 @@ class Preprocessor { /// read is the correct one. void HandleDirective(Token &Result); - /// CheckEndOfDirective - Ensure that the next token is a tok::eom token. If - /// not, emit a diagnostic and consume up until the eom. If EnableMacros is + /// CheckEndOfDirective - Ensure that the next token is a tok::eod token. If + /// not, emit a diagnostic and consume up until the eod. If EnableMacros is /// true, then we consider macros that expand to zero tokens as being ok. void CheckEndOfDirective(const char *Directive, bool EnableMacros = false); /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the - /// current line until the tok::eom token is found. + /// current line until the tok::eod token is found. void DiscardUntilEndOfDirective(); /// SawDateOrTime - This returns true if the preprocessor has seen a use of @@ -819,7 +875,9 @@ class Preprocessor { /// for system #include's or not (i.e. using <> instead of ""). const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, - const DirectoryLookup *&CurDir); + const DirectoryLookup *&CurDir, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath); /// GetCurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to @@ -839,12 +897,12 @@ class Preprocessor { /// /// This code concatenates and consumes tokens up to the '>' token. It /// returns false if the > was found, otherwise it returns true if it finds - /// and consumes the EOM marker. + /// and consumes the EOD marker. bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer, SourceLocation &End); /// LexOnOffSwitch - Lex an on-off-switch (C99 6.10.6p2) and verify that it is - /// followed by EOM. Return true if the token is not a valid on-off-switch. + /// followed by EOD. Return true if the token is not a valid on-off-switch. bool LexOnOffSwitch(tok::OnOffSwitch &OOS); private: @@ -875,7 +933,7 @@ class Preprocessor { void ReleaseMacroInfo(MacroInfo* MI); /// ReadMacroName - Lex and validate a macro name, which occurs after a - /// #define or #undef. This emits a diagnostic, sets the token kind to eom, + /// #define or #undef. This emits a diagnostic, sets the token kind to eod, /// and discards the rest of the macro line if the macro name is invalid. void ReadMacroName(Token &MacroNameTok, char isDefineUndef = 0); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h index d8332938a7ed..7bf041df974f 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h @@ -17,7 +17,6 @@ #include "clang/Lex/MultipleIncludeOpt.h" #include "clang/Lex/Token.h" #include "llvm/ADT/SmallVector.h" -#include namespace clang { @@ -36,7 +35,7 @@ class PreprocessorLexer { //===--------------------------------------------------------------------===// /// ParsingPreprocessorDirective - This is true when parsing #XXX. This turns - /// '\n' into a tok::eom token. + /// '\n' into a tok::eod token. bool ParsingPreprocessorDirective; /// ParsingFilename - True after #include: this turns into a @@ -131,7 +130,7 @@ class PreprocessorLexer { /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and /// (potentially) macro expand the filename. If the sequence parsed is not - /// lexically legal, emit a diagnostic and return a result EOM token. + /// lexically legal, emit a diagnostic and return a result EOD token. void LexIncludeFilename(Token &Result); /// setParsingPreprocessorDirective - Inform the lexer whether or not diff --git a/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h index f640b37c1982..c50ac92f6e8d 100644 --- a/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define PARSESTART #include "clang/Basic/DiagnosticParseKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h index 758792097639..3fd9844368ee 100644 --- a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h +++ b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h @@ -22,7 +22,6 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/ADT/OwningPtr.h" #include -#include namespace clang { class PragmaHandler; @@ -33,6 +32,8 @@ namespace clang { class PragmaUnusedHandler; class ColonProtectionRAIIObject; class InMessageExpressionRAIIObject; + class PoisonSEHIdentifiersRAIIObject; + class VersionTuple; /// PrettyStackTraceParserEntry - If a crash happens while the parser is active, /// an entry is printed for it. @@ -75,8 +76,8 @@ class Parser : public CodeCompletionHandler { friend class PragmaUnusedHandler; friend class ColonProtectionRAIIObject; friend class InMessageExpressionRAIIObject; + friend class PoisonSEHIdentifiersRAIIObject; friend class ParenBraceBracketBalancer; - PrettyStackTraceParserEntry CrashInfo; Preprocessor &PP; @@ -103,6 +104,12 @@ class Parser : public CodeCompletionHandler { unsigned NumCachedScopes; Scope *ScopeCache[ScopeCacheSize]; + /// Identifiers used for SEH handling in Borland. These are only + /// allowed in particular circumstances + IdentifierInfo *Ident__exception_code, *Ident___exception_code, *Ident_GetExceptionCode; // __except block + IdentifierInfo *Ident__exception_info, *Ident___exception_info, *Ident_GetExceptionInfo; // __except filter expression + IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; // __finally + /// Ident_super - IdentifierInfo for "super", to support fast /// comparison. IdentifierInfo *Ident_super; @@ -112,6 +119,18 @@ class Parser : public CodeCompletionHandler { IdentifierInfo *Ident_vector; IdentifierInfo *Ident_pixel; + /// \brief Identifier for "introduced". + IdentifierInfo *Ident_introduced; + + /// \brief Identifier for "deprecated". + IdentifierInfo *Ident_deprecated; + + /// \brief Identifier for "obsoleted". + IdentifierInfo *Ident_obsoleted; + + /// \brief Identifier for "unavailable". + IdentifierInfo *Ident_unavailable; + /// C++0x contextual keywords. mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_override; @@ -120,6 +139,7 @@ class Parser : public CodeCompletionHandler { llvm::OwningPtr GCCVisibilityHandler; llvm::OwningPtr OptionsHandler; llvm::OwningPtr PackHandler; + llvm::OwningPtr MSStructHandler; llvm::OwningPtr UnusedHandler; llvm::OwningPtr WeakHandler; llvm::OwningPtr FPContractHandler; @@ -137,7 +157,7 @@ class Parser : public CodeCompletionHandler { /// ColonProtectionRAIIObject RAII object. bool ColonIsSacred; - /// \brief When true, we are directly inside an Ojective-C messsage + /// \brief When true, we are directly inside an Objective-C messsage /// send expression. /// /// This is managed by the \c InMessageExpressionRAIIObject class, and @@ -148,7 +168,7 @@ class Parser : public CodeCompletionHandler { unsigned TemplateParameterDepth; /// Factory object for creating AttributeList objects. - AttributeList::Factory AttrFactory; + AttributeFactory AttrFactory; public: Parser(Preprocessor &PP, Sema &Actions); @@ -380,6 +400,24 @@ class Parser : public CodeCompletionHandler { static void setTypeAnnotation(Token &Tok, ParsedType T) { Tok.setAnnotationValue(T.getAsOpaquePtr()); } + + /// \brief Read an already-translated primary expression out of an annotation + /// token. + static ExprResult getExprAnnotation(Token &Tok) { + if (Tok.getAnnotationValue()) + return ExprResult((Expr *)Tok.getAnnotationValue()); + + return ExprResult(true); + } + + /// \brief Set the primary expression corresponding to the given annotation + /// token. + static void setExprAnnotation(Token &Tok, ExprResult ER) { + if (ER.isInvalid()) + Tok.setAnnotationValue(0); + else + Tok.setAnnotationValue(ER.get()); + } /// TryAnnotateTypeOrScopeToken - If the current token position is on a /// typename (possibly qualified in C++) or a C++ scope specifier not followed @@ -678,7 +716,7 @@ class Parser : public CodeCompletionHandler { /// LateParsedDeclarationsContainer - During parsing of a top (non-nested) /// C++ class, its method declarations that contain parts that won't be - /// parsed until after the definiton is completed (C++ [class.mem]p2), + /// parsed until after the definition is completed (C++ [class.mem]p2), /// the method declarations and possibly attached inline definitions /// will be stored here with the tokens that will be parsed to create those entities. typedef llvm::SmallVector LateParsedDeclarationsContainer; @@ -792,10 +830,9 @@ class Parser : public CodeCompletionHandler { ParsingDeclRAIIObject ParsingRAII; public: - ParsingDeclSpec(Parser &P) : ParsingRAII(P) {} - ParsingDeclSpec(ParsingDeclRAIIObject &RAII) : ParsingRAII(RAII) {} + ParsingDeclSpec(Parser &P) : DeclSpec(P.AttrFactory), ParsingRAII(P) {} ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII) - : ParsingRAII(P, RAII) {} + : DeclSpec(P.AttrFactory), ParsingRAII(P, RAII) {} void complete(Decl *D) { ParsingRAII.complete(D); @@ -908,6 +945,27 @@ class Parser : public CodeCompletionHandler { SourceRange getSourceRange() const; }; + /// \brief Contains a late templated function. + /// Will be parsed at the end of the translation unit. + struct LateParsedTemplatedFunction { + explicit LateParsedTemplatedFunction(Parser* P, Decl *MD) + : D(MD) {} + + CachedTokens Toks; + + /// \brief The template function declaration to be late parsed. + Decl *D; + }; + + void LexTemplateFunctionForLateParsing(CachedTokens &Toks); + void ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT); + typedef llvm::DenseMap + LateParsedTemplateMapT; + LateParsedTemplateMapT LateParsedTemplateMap; + + static void LateTemplateParserCallback(void *P, const FunctionDecl *FD); + void LateTemplateParser(const FunctionDecl *FD); + Sema::ParsingClassState PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass); void DeallocateParsedClasses(ParsingClass *Class); @@ -934,6 +992,9 @@ class Parser : public CodeCompletionHandler { //===--------------------------------------------------------------------===// // C99 6.9: External Definitions. struct ParsedAttributesWithRange : ParsedAttributes { + ParsedAttributesWithRange(AttributeFactory &factory) + : ParsedAttributes(factory) {} + SourceRange Range; }; @@ -992,13 +1053,21 @@ class Parser : public CodeCompletionHandler { bool isTokIdentifier_in() const; - ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter); + /// \brief The context in which we are parsing an Objective-C type name. + enum ObjCTypeNameContext { + OTN_ResultType, + OTN_ParameterType + }; + + ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, ObjCTypeNameContext Context); void ParseObjCMethodRequirement(); Decl *ParseObjCMethodPrototype(Decl *classOrCat, - tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); + tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword, + bool MethodDefinition = true); Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, Decl *classDecl, - tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); + tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword, + bool MethodDefinition=true); void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl); Decl *ParseObjCMethodDefinition(); @@ -1016,14 +1085,14 @@ class Parser : public CodeCompletionHandler { ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); ExprResult ParseRHSOfBinaryExpression(ExprResult LHS, - prec::Level MinPrec); + prec::Level MinPrec); ExprResult ParseCastExpression(bool isUnaryExpression, - bool isAddressOfOperand, - bool &NotCastExpr, - ParsedType TypeOfCast); + bool isAddressOfOperand, + bool &NotCastExpr, + ParsedType TypeOfCast); ExprResult ParseCastExpression(bool isUnaryExpression, - bool isAddressOfOperand = false, - ParsedType TypeOfCast = ParsedType()); + bool isAddressOfOperand = false, + ParsedType TypeOfCast = ParsedType()); /// Returns true if the next token would start a postfix-expression /// suffix. @@ -1035,10 +1104,10 @@ class Parser : public CodeCompletionHandler { } ExprResult ParsePostfixExpressionSuffix(ExprResult LHS); - ExprResult ParseSizeofAlignofExpression(); + ExprResult ParseUnaryExprOrTypeTraitExpression(); ExprResult ParseBuiltinPrimaryExpression(); - ExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, + ExprResult ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, bool &isCastExpr, ParsedType &CastTy, SourceRange &CastRange); @@ -1079,6 +1148,8 @@ class Parser : public CodeCompletionHandler { ExprResult ParseStringLiteralExpression(); + ExprResult ParseGenericSelectionExpression(); + //===--------------------------------------------------------------------===// // C++ Expressions ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); @@ -1086,7 +1157,8 @@ class Parser : public CodeCompletionHandler { bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ParsedType ObjectType, bool EnteringContext, - bool *MayBePseudoDestructor = 0); + bool *MayBePseudoDestructor = 0, + bool IsTypename = false); //===--------------------------------------------------------------------===// // C++ 5.2p1: C++ Casts @@ -1114,11 +1186,18 @@ class Parser : public CodeCompletionHandler { //===--------------------------------------------------------------------===// // C++ 15: C++ Throw Expression ExprResult ParseThrowExpression(); + + ExceptionSpecificationType MaybeParseExceptionSpecification( + SourceRange &SpecificationRange, + llvm::SmallVectorImpl &DynamicExceptions, + llvm::SmallVectorImpl &DynamicExceptionRanges, + ExprResult &NoexceptExpr); + // EndLoc is filled with the location of the last token of the specification. - bool ParseExceptionSpecification(SourceLocation &EndLoc, - llvm::SmallVectorImpl &Exns, - llvm::SmallVectorImpl &Ranges, - bool &hasAnyExceptionSpec); + ExceptionSpecificationType ParseDynamicExceptionSpecification( + SourceRange &SpecificationRange, + llvm::SmallVectorImpl &Exceptions, + llvm::SmallVectorImpl &Ranges); //===--------------------------------------------------------------------===// // C++0x 8: Function declaration trailing-return-type @@ -1205,11 +1284,14 @@ class Parser : public CodeCompletionHandler { } StmtResult ParseStatementOrDeclaration(StmtVector& Stmts, bool OnlyStatement = false); + StmtResult ParseExprStatement(ParsedAttributes &Attrs); StmtResult ParseLabeledStatement(ParsedAttributes &Attr); - StmtResult ParseCaseStatement(ParsedAttributes &Attr); + StmtResult ParseCaseStatement(ParsedAttributes &Attr, + bool MissingCase = false, + ExprResult Expr = ExprResult()); StmtResult ParseDefaultStatement(ParsedAttributes &Attr); StmtResult ParseCompoundStatement(ParsedAttributes &Attr, - bool isStmtExpr = false); + bool isStmtExpr = false); StmtResult ParseCompoundStatementBody(bool isStmtExpr = false); bool ParseParenExprOrCondition(ExprResult &ExprResult, Decl *&DeclResult, @@ -1237,6 +1319,14 @@ class Parser : public CodeCompletionHandler { StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc); StmtResult ParseCXXCatchBlock(); + //===--------------------------------------------------------------------===// + // MS: SEH Statements and Blocks + + StmtResult ParseSEHTryBlock(ParsedAttributes &Attr); + StmtResult ParseSEHTryBlockCommon(SourceLocation Loc); + StmtResult ParseSEHExceptBlock(SourceLocation Loc); + StmtResult ParseSEHFinallyBlock(SourceLocation Loc); + //===--------------------------------------------------------------------===// // Objective-C Statements @@ -1258,6 +1348,15 @@ class Parser : public CodeCompletionHandler { DSC_top_level // top-level/namespace declaration context }; + /// Information on a C++0x for-range-initializer found while parsing a + /// declaration which turns out to be a for-range-declaration. + struct ForRangeInit { + SourceLocation ColonLoc; + ExprResult RangeExpr; + + bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); } + }; + DeclGroupPtrTy ParseDeclaration(StmtVector &Stmts, unsigned Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs); @@ -1265,14 +1364,19 @@ class Parser : public CodeCompletionHandler { unsigned Context, SourceLocation &DeclEnd, ParsedAttributes &attrs, - bool RequireSemi); + bool RequireSemi, + ForRangeInit *FRI = 0); DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, - SourceLocation *DeclEnd = 0); + SourceLocation *DeclEnd = 0, + ForRangeInit *FRI = 0); Decl *ParseDeclarationAfterDeclarator(Declarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); - Decl *ParseFunctionStatementBody(Decl *Decl); - Decl *ParseFunctionTryBlock(Decl *Decl); + bool ParseAttributesAfterDeclarator(Declarator &D); + Decl *ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); + Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope); + Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope); /// \brief When in code-completion, skip parsing of the function/method body /// unless the body contains the code-completion point. @@ -1296,7 +1400,8 @@ class Parser : public CodeCompletionHandler { void ParseSpecifierQualifierList(DeclSpec &DS); - void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter); + void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, + ObjCTypeNameContext Context); void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), @@ -1470,7 +1575,7 @@ class Parser : public CodeCompletionHandler { TypeResult ParseTypeName(SourceRange *Range = 0, Declarator::TheContext Context - = Declarator::TypeNameContext); + = Declarator::TypeNameContext); void ParseBlockId(); void ProhibitAttributes(ParsedAttributesWithRange &attrs) { @@ -1481,10 +1586,10 @@ class Parser : public CodeCompletionHandler { void MaybeParseGNUAttributes(Declarator &D) { if (Tok.is(tok::kw___attribute)) { - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); SourceLocation endLoc; ParseGNUAttributes(attrs, &endLoc); - D.addAttributes(attrs.getList(), endLoc); + D.takeAttributes(attrs, endLoc); } } void MaybeParseGNUAttributes(ParsedAttributes &attrs, @@ -1497,18 +1602,18 @@ class Parser : public CodeCompletionHandler { void MaybeParseCXX0XAttributes(Declarator &D) { if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); SourceLocation endLoc; ParseCXX0XAttributes(attrs, &endLoc); - D.addAttributes(attrs.getList(), endLoc); + D.takeAttributes(attrs, endLoc); } } void MaybeParseCXX0XAttributes(ParsedAttributes &attrs, SourceLocation *endLoc = 0) { if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { - ParsedAttributesWithRange attrsWithRange; + ParsedAttributesWithRange attrsWithRange(AttrFactory); ParseCXX0XAttributes(attrsWithRange, endLoc); - attrs.append(attrsWithRange.getList()); + attrs.takeAllFrom(attrsWithRange); } } void MaybeParseCXX0XAttributes(ParsedAttributesWithRange &attrs, @@ -1530,6 +1635,13 @@ class Parser : public CodeCompletionHandler { void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs); void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLAttributes(ParsedAttributes &attrs); + void ParseOpenCLQualifiers(DeclSpec &DS); + + VersionTuple ParseVersionTuple(SourceRange &Range); + void ParseAvailabilityAttribute(IdentifierInfo &Availability, + SourceLocation AvailabilityLoc, + ParsedAttributes &attrs, + SourceLocation *endLoc); void ParseTypeofSpecifier(DeclSpec &DS); void ParseDecltypeSpecifier(DeclSpec &DS); @@ -1539,8 +1651,7 @@ class Parser : public CodeCompletionHandler { VirtSpecifiers::Specifier isCXX0XVirtSpecifier() const; void ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS); - ClassVirtSpecifiers::Specifier isCXX0XClassVirtSpecifier() const; - void ParseOptionalCXX0XClassVirtSpecifierSeq(ClassVirtSpecifiers &CVS); + bool isCXX0XFinalKeyword() const; /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to /// enter a new C++ declarator scope and exit it when the function is @@ -1624,8 +1735,7 @@ class Parser : public CodeCompletionHandler { //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. - TypeResult ParseClassName(SourceLocation &EndLocation, - CXXScopeSpec *SS = 0); + TypeResult ParseClassName(SourceLocation &EndLocation, CXXScopeSpec &SS); void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), @@ -1696,18 +1806,18 @@ class Parser : public CodeCompletionHandler { bool ParseTemplateIdAfterTemplateName(TemplateTy Template, SourceLocation TemplateNameLoc, - const CXXScopeSpec *SS, + const CXXScopeSpec &SS, bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, SourceLocation &RAngleLoc); bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, - const CXXScopeSpec *SS, + CXXScopeSpec &SS, UnqualifiedId &TemplateName, SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); - void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); + void AnnotateTemplateIdTokenAsType(); bool IsTemplateArgumentList(unsigned Skip = 0); bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); ParsedTemplateArgument ParseTemplateTemplateArgument(); @@ -1721,6 +1831,11 @@ class Parser : public CodeCompletionHandler { ExprResult ParseUnaryTypeTrait(); ExprResult ParseBinaryTypeTrait(); + //===--------------------------------------------------------------------===// + // Embarcadero: Arary and Expression Traits + ExprResult ParseArrayTypeTrait(); + ExprResult ParseExpressionTrait(); + //===--------------------------------------------------------------------===// // Preprocessor code-completion pass-through virtual void CodeCompleteDirective(bool InConditional); diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h index 2b5f88ccee9d..6b33183166f8 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h @@ -11,8 +11,6 @@ #define LLVM_CLANG_REWRITE_FRONTENDACTIONS_H #include "clang/Frontend/FrontendAction.h" -#include -#include namespace clang { class FixItRewriter; diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h index b3d4035628ee..7861e9992891 100644 --- a/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h +++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h @@ -22,7 +22,6 @@ #include #include #include -#include namespace llvm { class raw_ostream; } @@ -58,7 +57,8 @@ class RewriteBuffer { llvm::raw_ostream &write(llvm::raw_ostream &) const; /// RemoveText - Remove the specified text. - void RemoveText(unsigned OrigOffset, unsigned Size); + void RemoveText(unsigned OrigOffset, unsigned Size, + bool removeLineIfEmpty = false); /// InsertText - Insert some text at the specified point, where the offset in /// the buffer is specified relative to the original SourceBuffer. The @@ -129,6 +129,23 @@ class Rewriter { const LangOptions *LangOpts; std::map RewriteBuffers; public: + struct RewriteOptions { + /// \brief Given a source range, true to include previous inserts at the + /// beginning of the range as part of the range itself (true by default). + bool IncludeInsertsAtBeginOfRange; + /// \brief Given a source range, true to include previous inserts at the + /// end of the range as part of the range itself (true by default). + bool IncludeInsertsAtEndOfRange; + /// \brief If true and removing some text leaves a blank line + /// also remove the empty line (false by default). + bool RemoveLineIfEmpty; + + RewriteOptions() + : IncludeInsertsAtBeginOfRange(true), + IncludeInsertsAtEndOfRange(true), + RemoveLineIfEmpty(false) { } + }; + typedef std::map::iterator buffer_iterator; explicit Rewriter(SourceManager &SM, const LangOptions &LO) @@ -150,8 +167,10 @@ class Rewriter { /// getRangeSize - Return the size in bytes of the specified range if they /// are in the same file. If not, this returns -1. - int getRangeSize(SourceRange Range) const; - int getRangeSize(const CharSourceRange &Range) const; + int getRangeSize(SourceRange Range, + RewriteOptions opts = RewriteOptions()) const; + int getRangeSize(const CharSourceRange &Range, + RewriteOptions opts = RewriteOptions()) const; /// getRewrittenText - Return the rewritten form of the text in the specified /// range. If the start or end of the range was unrewritable or if they are @@ -176,6 +195,10 @@ class Rewriter { return InsertText(Loc, Str); } + /// \brief Insert the specified string after the token in the + /// specified location. + bool InsertTextAfterToken(SourceLocation Loc, llvm::StringRef Str); + /// InsertText - Insert the specified string at the specified location in the /// original buffer. This method returns true (and does nothing) if the input /// location was not rewritable, false otherwise. Text is @@ -186,7 +209,19 @@ class Rewriter { } /// RemoveText - Remove the specified text region. - bool RemoveText(SourceLocation Start, unsigned Length); + bool RemoveText(SourceLocation Start, unsigned Length, + RewriteOptions opts = RewriteOptions()); + + /// \brief Remove the specified text region. + bool RemoveText(CharSourceRange range, + RewriteOptions opts = RewriteOptions()) { + return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); + } + + /// \brief Remove the specified text region. + bool RemoveText(SourceRange range, RewriteOptions opts = RewriteOptions()) { + return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); + } /// ReplaceText - This method replaces a range of characters in the input /// buffer with a new string. This is effectively a combined "remove/insert" @@ -194,11 +229,37 @@ class Rewriter { bool ReplaceText(SourceLocation Start, unsigned OrigLength, llvm::StringRef NewStr); + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + bool ReplaceText(SourceRange range, llvm::StringRef NewStr) { + return ReplaceText(range.getBegin(), getRangeSize(range), NewStr); + } + + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + bool ReplaceText(SourceRange range, SourceRange replacementRange); + /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty /// printer to generate the replacement code. This returns true if the input /// could not be rewritten, or false if successful. bool ReplaceStmt(Stmt *From, Stmt *To); + /// \brief Increase indentation for the lines between the given source range. + /// To determine what the indentation should be, 'parentIndent' is used + /// that should be at a source location with an indentation one degree + /// lower than the given range. + bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent); + bool IncreaseIndentation(SourceRange range, SourceLocation parentIndent) { + return IncreaseIndentation(CharSourceRange::getTokenRange(range), + parentIndent); + } + + /// ConvertToString converts statement 'From' to a string using the + /// pretty printer. + std::string ConvertToString(Stmt *From); + /// getEditBuffer - This is like getRewriteBufferFor, but always returns a /// buffer, and allows you to write on it directly. This is useful if you /// want efficient low-level access to apis for scribbling on one specific diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h index 45ee579a02d3..72cd47589f91 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h @@ -16,14 +16,33 @@ #define LLVM_CLANG_SEMA_ATTRLIST_H #include "llvm/Support/Allocator.h" -#include "clang/Sema/Ownership.h" +#include "llvm/ADT/SmallVector.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/VersionTuple.h" #include namespace clang { + class ASTContext; class IdentifierInfo; class Expr; +/// \brief Represents information about a change in availability for +/// an entity, which is part of the encoding of the 'availability' +/// attribute. +struct AvailabilityChange { + /// \brief The location of the keyword indicating the kind of change. + SourceLocation KeywordLoc; + + /// \brief The version number at which the change occurred. + VersionTuple Version; + + /// \brief The source range covering the version number. + SourceRange VersionRange; + + /// \brief Determine whether this availability change is valid. + bool isValid() const { return !Version.empty(); } +}; + /// AttributeList - Represents GCC's __attribute__ declaration. There are /// 4 forms of this construct...they are: /// @@ -32,52 +51,102 @@ namespace clang { /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. /// -class AttributeList { -public: - class Factory; +class AttributeList { // TODO: This should really be called ParsedAttribute private: IdentifierInfo *AttrName; - SourceLocation AttrLoc; IdentifierInfo *ScopeName; - SourceLocation ScopeLoc; IdentifierInfo *ParmName; + SourceLocation AttrLoc; + SourceLocation ScopeLoc; SourceLocation ParmLoc; - Expr **Args; - unsigned NumArgs; - AttributeList *Next; - bool DeclspecAttribute, CXX0XAttribute; + + /// The number of expression arguments this attribute has. + /// The expressions themselves are stored after the object. + unsigned NumArgs : 16; + + /// True if Microsoft style: declspec(foo). + unsigned DeclspecAttribute : 1; + + /// True if C++0x-style: [[foo]]. + unsigned CXX0XAttribute : 1; /// True if already diagnosed as invalid. - mutable bool Invalid; + mutable unsigned Invalid : 1; + + /// True if this has the extra information associated with an + /// availability attribute. + unsigned IsAvailability : 1; + + /// \brief The location of the 'unavailable' keyword in an + /// availability attribute. + SourceLocation UnavailableLoc; + + /// The next attribute in the current position. + AttributeList *NextInPosition; + + /// The next attribute allocated in the current Pool. + AttributeList *NextInPool; + + Expr **getArgsBuffer() { + return reinterpret_cast(this+1); + } + Expr * const *getArgsBuffer() const { + return reinterpret_cast(this+1); + } + + enum AvailabilitySlot { + IntroducedSlot, DeprecatedSlot, ObsoletedSlot + }; + + AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { + return reinterpret_cast(this+1)[index]; + } + const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const { + return reinterpret_cast(this+1)[index]; + } AttributeList(const AttributeList &); // DO NOT IMPLEMENT void operator=(const AttributeList &); // DO NOT IMPLEMENT void operator delete(void *); // DO NOT IMPLEMENT ~AttributeList(); // DO NOT IMPLEMENT - AttributeList(llvm::BumpPtrAllocator &Alloc, - IdentifierInfo *AttrName, SourceLocation AttrLoc, - IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - IdentifierInfo *ParmName, SourceLocation ParmLoc, - Expr **args, unsigned numargs, - bool declspec, bool cxx0x); + + size_t allocated_size() const; + + AttributeList(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + Expr **args, unsigned numArgs, + bool declspec, bool cxx0x) + : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), + AttrLoc(attrLoc), ScopeLoc(scopeLoc), ParmLoc(parmLoc), + NumArgs(numArgs), + DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false), + IsAvailability(false), NextInPosition(0), NextInPool(0) { + if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); + } + + AttributeList(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, + bool declspec, bool cxx0x) + : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), + AttrLoc(attrLoc), ScopeLoc(scopeLoc), ParmLoc(parmLoc), + NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), + Invalid(false), IsAvailability(true), UnavailableLoc(unavailable), + NextInPosition(0), NextInPool(0) { + new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); + new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); + new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); + } + + friend class AttributePool; + friend class AttributeFactory; + public: - class Factory { - llvm::BumpPtrAllocator Alloc; - public: - Factory() {} - ~Factory() {} - AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc, - IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - IdentifierInfo *ParmName, SourceLocation ParmLoc, - Expr **args, unsigned numargs, bool declspec = false, bool cxx0x = false) { - AttributeList *Mem = Alloc.Allocate(); - new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc, - ParmName, ParmLoc, args, numargs, - declspec, cxx0x); - return Mem; - } - }; - enum Kind { // Please keep this list alphabetized. AT_IBAction, // Clang-specific. AT_IBOutlet, // Clang-specific. @@ -88,6 +157,7 @@ class AttributeList { AT_always_inline, AT_analyzer_noreturn, AT_annotate, + AT_availability, // Clang-specific AT_base_check, AT_blocks, AT_carries_dependency, @@ -125,6 +195,7 @@ class AttributeList { AT_nothrow, AT_nsobject, AT_objc_exception, + AT_objc_method_family, AT_cf_returns_not_retained, // Clang-specific. AT_cf_returns_retained, // Clang-specific. AT_ns_returns_not_retained, // Clang-specific. @@ -134,6 +205,7 @@ class AttributeList { AT_ns_consumed, // Clang-specific. AT_ns_consumes_self, // Clang-specific. AT_objc_gc, + AT_opencl_image_access, // OpenCL-specific. AT_opencl_kernel_function, // OpenCL-specific. AT_overloadable, // Clang-specific. AT_ownership_holds, // Clang-specific. @@ -141,6 +213,7 @@ class AttributeList { AT_ownership_takes, // Clang-specific. AT_packed, AT_pascal, + AT_pcs, // ARM specific AT_pure, AT_regparm, AT_section, @@ -162,6 +235,7 @@ class AttributeList { AT_weak_import, AT_reqd_wg_size, AT_init_priority, + AT_MsStruct, IgnoredAttribute, UnknownAttribute }; @@ -185,23 +259,27 @@ class AttributeList { Kind getKind() const { return getKind(getName()); } static Kind getKind(const IdentifierInfo *Name); - AttributeList *getNext() const { return Next; } - void setNext(AttributeList *N) { Next = N; } + AttributeList *getNext() const { return NextInPosition; } + void setNext(AttributeList *N) { NextInPosition = N; } /// getNumArgs - Return the number of actual arguments to this attribute. unsigned getNumArgs() const { return NumArgs; } + /// hasParameterOrArguments - Return true if this attribute has a parameter, + /// or has a non empty argument expression list. + bool hasParameterOrArguments() const { return ParmName || NumArgs; } + /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return Args[Arg]; + return getArgsBuffer()[Arg]; } class arg_iterator { - Expr** X; + Expr * const *X; unsigned Idx; public: - arg_iterator(Expr** x, unsigned idx) : X(x), Idx(idx) {} + arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {} arg_iterator& operator++() { ++Idx; @@ -228,12 +306,165 @@ class AttributeList { }; arg_iterator arg_begin() const { - return arg_iterator(Args, 0); + return arg_iterator(getArgsBuffer(), 0); } arg_iterator arg_end() const { - return arg_iterator(Args, NumArgs); + return arg_iterator(getArgsBuffer(), NumArgs); } + + const AvailabilityChange &getAvailabilityIntroduced() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return getAvailabilitySlot(IntroducedSlot); + } + + const AvailabilityChange &getAvailabilityDeprecated() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return getAvailabilitySlot(DeprecatedSlot); + } + + const AvailabilityChange &getAvailabilityObsoleted() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return getAvailabilitySlot(ObsoletedSlot); + } + + SourceLocation getUnavailableLoc() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return UnavailableLoc; + } +}; + +/// A factory, from which one makes pools, from which one creates +/// individual attributes which are deallocated with the pool. +/// +/// Note that it's tolerably cheap to create and destroy one of +/// these as long as you don't actually allocate anything in it. +class AttributeFactory { +public: + enum { + /// The required allocation size of an availability attribute, + /// which we want to ensure is a multiple of sizeof(void*). + AvailabilityAllocSize = + sizeof(AttributeList) + + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1) + / sizeof(void*) * sizeof(void*)) + }; + +private: + enum { + /// The number of free lists we want to be sure to support + /// inline. This is just enough that availability attributes + /// don't surpass it. It's actually very unlikely we'll see an + /// attribute that needs more than that; on x86-64 you'd need 10 + /// expression arguments, and on i386 you'd need 19. + InlineFreeListsCapacity = + 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) + }; + + llvm::BumpPtrAllocator Alloc; + + /// Free lists. The index is determined by the following formula: + /// (size - sizeof(AttributeList)) / sizeof(void*) + llvm::SmallVector FreeLists; + + // The following are the private interface used by AttributePool. + friend class AttributePool; + + /// Allocate an attribute of the given size. + void *allocate(size_t size); + + /// Reclaim all the attributes in the given pool chain, which is + /// non-empty. Note that the current implementation is safe + /// against reclaiming things which were not actually allocated + /// with the allocator, although of course it's important to make + /// sure that their allocator lives at least as long as this one. + void reclaimPool(AttributeList *head); + +public: + AttributeFactory(); + ~AttributeFactory(); +}; + +class AttributePool { + AttributeFactory &Factory; + AttributeList *Head; + + void *allocate(size_t size) { + return Factory.allocate(size); + } + + AttributeList *add(AttributeList *attr) { + // We don't care about the order of the pool. + attr->NextInPool = Head; + Head = attr; + return attr; + } + + void takePool(AttributeList *pool); + +public: + /// Create a new pool for a factory. + AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {} + + /// Move the given pool's allocations to this pool. + AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { + pool.Head = 0; + } + + AttributeFactory &getFactory() const { return Factory; } + + void clear() { + if (Head) { + Factory.reclaimPool(Head); + Head = 0; + } + } + + /// Take the given pool's allocations and add them to this pool. + void takeAllFrom(AttributePool &pool) { + if (pool.Head) { + takePool(pool.Head); + pool.Head = 0; + } + } + + ~AttributePool() { + if (Head) Factory.reclaimPool(Head); + } + + AttributeList *create(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + Expr **args, unsigned numArgs, + bool declspec = false, bool cxx0x = false) { + void *memory = allocate(sizeof(AttributeList) + + numArgs * sizeof(Expr*)); + return add(new (memory) AttributeList(attrName, attrLoc, + scopeName, scopeLoc, + parmName, parmLoc, + args, numArgs, + declspec, cxx0x)); + } + + AttributeList *create(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, + bool declspec = false, bool cxx0x = false) { + void *memory = allocate(AttributeFactory::AvailabilityAllocSize); + return add(new (memory) AttributeList(attrName, attrLoc, + scopeName, scopeLoc, + parmName, parmLoc, + introduced, deprecated, obsoleted, + unavailable, + declspec, cxx0x)); + } + + AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, + SourceLocation TokLoc, int Arg); }; /// addAttributeLists - Add two AttributeLists together @@ -278,7 +509,16 @@ struct CXX0XAttributeList { /// is that this will become significantly more serious. class ParsedAttributes { public: - ParsedAttributes() : list(0) {} + ParsedAttributes(AttributeFactory &factory) + : pool(factory), list(0) { + } + + ParsedAttributes(ParsedAttributes &attrs) + : pool(attrs.pool), list(attrs.list) { + attrs.list = 0; + } + + AttributePool &getPool() const { return pool; } bool empty() const { return list == 0; } @@ -289,7 +529,7 @@ class ParsedAttributes { list = newAttr; } - void append(AttributeList *newList) { + void addAll(AttributeList *newList) { if (!newList) return; AttributeList *lastInNewList = newList; @@ -304,14 +544,59 @@ class ParsedAttributes { list = newList; } - void clear() { list = 0; } + void takeAllFrom(ParsedAttributes &attrs) { + addAll(attrs.list); + attrs.list = 0; + pool.takeAllFrom(attrs.pool); + } + + void clear() { list = 0; pool.clear(); } AttributeList *getList() const { return list; } /// Returns a reference to the attribute list. Try not to introduce /// dependencies on this method, it may not be long-lived. AttributeList *&getListRef() { return list; } + + AttributeList *addNew(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + Expr **args, unsigned numArgs, + bool declspec = false, bool cxx0x = false) { + AttributeList *attr = + pool.create(attrName, attrLoc, scopeName, scopeLoc, parmName, parmLoc, + args, numArgs, declspec, cxx0x); + add(attr); + return attr; + } + + AttributeList *addNew(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, + bool declspec = false, bool cxx0x = false) { + AttributeList *attr = + pool.create(attrName, attrLoc, scopeName, scopeLoc, parmName, parmLoc, + introduced, deprecated, obsoleted, unavailable, + declspec, cxx0x); + add(attr); + return attr; + } + + AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name, + SourceLocation loc, int arg) { + AttributeList *attr = + pool.createIntegerAttribute(C, name, loc, arg); + add(attr); + return attr; + } + + private: + mutable AttributePool pool; AttributeList *list; }; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h index 64126bd4d80a..708c9b2084b0 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h @@ -22,7 +22,9 @@ #include "clang/Sema/AttributeList.h" #include "clang/Sema/Ownership.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/Lex/Token.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/SmallVector.h" @@ -54,32 +56,10 @@ namespace clang { /// /// The actual scope is described by getScopeRep(). class CXXScopeSpec { - SourceRange Range; - NestedNameSpecifier *ScopeRep; - - /// \brief Buffer used to store source-location information for the - /// nested-name-specifier. - /// - /// Note that we explicitly manage the buffer (rather than using a - /// SmallVector) because \c Declarator expects it to be possible to memcpy() - /// a \c CXXScopeSpec. - char *Buffer; - - /// \brief The size of the buffer used to store source-location information - /// for the nested-name-specifier. - unsigned BufferSize; - - /// \brief The capacity of the buffer used to store source-location - /// information for the nested-name-specifier. - unsigned BufferCapacity; + SourceRange Range; + NestedNameSpecifierLocBuilder Builder; public: - CXXScopeSpec() : Range(), ScopeRep(), Buffer(0), BufferSize(0), - BufferCapacity(0) { } - CXXScopeSpec(const CXXScopeSpec &Other); - CXXScopeSpec &operator=(const CXXScopeSpec &Other); - ~CXXScopeSpec(); - const SourceRange &getRange() const { return Range; } void setRange(const SourceRange &R) { Range = R; } void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } @@ -87,7 +67,10 @@ class CXXScopeSpec { SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } - NestedNameSpecifier *getScopeRep() const { return ScopeRep; } + /// \brief Retrieve the representation of the nested-name-specifier. + NestedNameSpecifier *getScopeRep() const { + return Builder.getRepresentation(); + } /// \brief Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'type::'. @@ -175,10 +158,10 @@ class CXXScopeSpec { /// A scope specifier is present, but may be valid or invalid. bool isNotEmpty() const { return !isEmpty(); } - /// An error occured during parsing of the scope specifier. - bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; } + /// An error occurred during parsing of the scope specifier. + bool isInvalid() const { return isNotEmpty() && getScopeRep() == 0; } /// A scope specifier is present, and it refers to a real scope. - bool isValid() const { return isNotEmpty() && ScopeRep != 0; } + bool isValid() const { return isNotEmpty() && getScopeRep() != 0; } /// \brief Indicate that this nested-name-specifier is invalid. void SetInvalid(SourceRange R) { @@ -186,24 +169,24 @@ class CXXScopeSpec { if (Range.getBegin().isInvalid()) Range.setBegin(R.getBegin()); Range.setEnd(R.getEnd()); - ScopeRep = 0; + Builder.Clear(); } /// Deprecated. Some call sites intend isNotEmpty() while others intend /// isValid(). - bool isSet() const { return ScopeRep != 0; } + bool isSet() const { return getScopeRep() != 0; } void clear() { Range = SourceRange(); - ScopeRep = 0; + Builder.Clear(); } /// \brief Retrieve the data associated with the source-location information. - char *location_data() const { return Buffer; } + char *location_data() const { return Builder.getBuffer().first; } /// \brief Retrieve the size of the data associated with source-location /// information. - unsigned location_size() const { return BufferSize; } + unsigned location_size() const { return Builder.getBuffer().second; } }; /// DeclSpec - This class captures information about "declaration specifiers", @@ -267,6 +250,7 @@ class DeclSpec { static const TST TST_typeofExpr = clang::TST_typeofExpr; static const TST TST_decltype = clang::TST_decltype; static const TST TST_auto = clang::TST_auto; + static const TST TST_unknown_anytype = clang::TST_unknown_anytype; static const TST TST_error = clang::TST_error; // type-qualifiers @@ -288,7 +272,6 @@ class DeclSpec { }; private: - // storage-class-specifier /*SCS*/unsigned StorageClassSpec : 3; unsigned SCS_thread_specified : 1; @@ -346,6 +329,11 @@ class DeclSpec { SourceLocation StorageClassSpecLoc, SCS_threadLoc; SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc, AltiVecLoc; + /// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union, + /// typename, then this is the location of the named type (if present); + /// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and + /// TSTNameLoc provides source range info for tag types. + SourceLocation TSTNameLoc; SourceRange TypeofParensRange; SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; @@ -370,7 +358,7 @@ class DeclSpec { void operator=(const DeclSpec&); // DO NOT IMPLEMENT public: - DeclSpec() + DeclSpec(AttributeFactory &attrFactory) : StorageClassSpec(SCS_unspecified), SCS_thread_specified(false), SCS_extern_in_linkage_spec(false), @@ -389,6 +377,7 @@ class DeclSpec { Friend_specified(false), Constexpr_specified(false), StorageClassSpecAsWritten(SCS_unspecified), + Attrs(attrFactory), ProtocolQualifiers(0), NumProtocolQualifiers(0), ProtocolLocs(0), @@ -448,6 +437,11 @@ class DeclSpec { SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } SourceLocation getAltiVecLoc() const { return AltiVecLoc; } + SourceLocation getTypeSpecTypeNameLoc() const { + assert(isDeclRep((TST) TypeSpecType) || TypeSpecType == TST_typename); + return TSTNameLoc; + } + SourceRange getTypeofParensRange() const { return TypeofParensRange; } void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; } @@ -539,6 +533,13 @@ class DeclSpec { unsigned &DiagID, ParsedType Rep); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, Decl *Rep, bool Owned); + bool SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, const char *&PrevSpec, + unsigned &DiagID, ParsedType Rep); + bool SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, const char *&PrevSpec, + unsigned &DiagID, Decl *Rep, bool Owned); + bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, Expr *Rep); bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, @@ -581,6 +582,10 @@ class DeclSpec { bool isConstexprSpecified() const { return Constexpr_specified; } SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; } + AttributePool &getAttributePool() const { + return Attrs.getPool(); + } + /// AddAttributes - contatenates two attribute lists. /// The GCC attribute syntax allows for the following: /// @@ -594,9 +599,9 @@ class DeclSpec { /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; /// void addAttributes(AttributeList *AL) { - Attrs.append(AL); + Attrs.addAll(AL); } - void aetAttributes(AttributeList *AL) { + void setAttributes(AttributeList *AL) { Attrs.set(AL); } @@ -608,14 +613,12 @@ class DeclSpec { /// TakeAttributes - Return the current attribute list and remove them from /// the DeclSpec so that it doesn't own them. ParsedAttributes takeAttributes() { - ParsedAttributes saved = Attrs; - Attrs.clear(); - return saved; + // The non-const "copy" constructor clears the operand automatically. + return Attrs; } void takeAttributesFrom(ParsedAttributes &attrs) { - Attrs.append(attrs.getList()); - attrs.clear(); + Attrs.takeAllFrom(attrs); } typedef Decl * const *ProtocolQualifierListTy; @@ -649,7 +652,12 @@ class DeclSpec { /// "declaration specifiers" specific to objective-c class ObjCDeclSpec { public: - /// ObjCDeclQualifier - Qualifier used on types in method declarations + /// ObjCDeclQualifier - Qualifier used on types in method + /// declarations. Not all combinations are sensible. Parameters + /// can be one of { in, out, inout } with one of { bycopy, byref }. + /// Returns can either be { oneway } or not. + /// + /// This should be kept in sync with Decl::ObjCDeclQualifier. enum ObjCDeclQualifier { DQ_None = 0x0, DQ_In = 0x1, @@ -661,7 +669,8 @@ class ObjCDeclSpec { }; /// PropertyAttributeKind - list of property attributes. - enum ObjCPropertyAttributeKind { DQ_PR_noattr = 0x0, + enum ObjCPropertyAttributeKind { + DQ_PR_noattr = 0x0, DQ_PR_readonly = 0x01, DQ_PR_getter = 0x02, DQ_PR_assign = 0x04, @@ -1037,11 +1046,8 @@ struct DeclaratorChunk { /// The qualifier bitmask values are the same as in QualType. unsigned TypeQuals : 3; - /// hasExceptionSpec - True if the function has an exception specification. - unsigned hasExceptionSpec : 1; - - /// hasAnyExceptionSpec - True if the function has a throw(...) specifier. - unsigned hasAnyExceptionSpec : 1; + /// ExceptionSpecType - An ExceptionSpecificationType value. + unsigned ExceptionSpecType : 3; /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. unsigned DeleteArgInfo : 1; @@ -1053,28 +1059,34 @@ struct DeclaratorChunk { /// declarator. unsigned NumArgs; - /// NumExceptions - This is the number of types in the exception-decl, if - /// the function has one. + /// NumExceptions - This is the number of types in the dynamic-exception- + /// decl, if the function has one. unsigned NumExceptions; /// \brief The location of the ref-qualifier, if any. /// /// If this is an invalid location, there is no ref-qualifier. unsigned RefQualifierLoc; - - /// ThrowLoc - When hasExceptionSpec is true, the location of the throw + + /// \brief When ExceptionSpecType isn't EST_None, the location of the /// keyword introducing the spec. - unsigned ThrowLoc; + unsigned ExceptionSpecLoc; /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that /// describe the arguments for this function declarator. This is null if /// there are no arguments specified. ParamInfo *ArgInfo; - /// Exceptions - This is a pointer to a new[]'d array of TypeAndRange - /// objects that contain the types in the function's exception - /// specification and their locations. - TypeAndRange *Exceptions; + union { + /// \brief Pointer to a new[]'d array of TypeAndRange objects that + /// contain the types in the function's dynamic exception specification + /// and their locations, if there is one. + TypeAndRange *Exceptions; + + /// \brief Pointer to the expression in the noexcept-specifier of this + /// function, if it has one. + Expr *NoexceptExpr; + }; /// TrailingReturnType - If this isn't null, it's the trailing return type /// specified. This is actually a ParsedType, but stored as void* to @@ -1094,7 +1106,8 @@ struct DeclaratorChunk { void destroy() { if (DeleteArgInfo) delete[] ArgInfo; - delete[] Exceptions; + if (getExceptionSpecType() == EST_Dynamic) + delete[] Exceptions; } /// isKNRPrototype - Return true if this is a K&R style identifier list, @@ -1107,18 +1120,23 @@ struct DeclaratorChunk { SourceLocation getEllipsisLoc() const { return SourceLocation::getFromRawEncoding(EllipsisLoc); } - SourceLocation getThrowLoc() const { - return SourceLocation::getFromRawEncoding(ThrowLoc); + SourceLocation getExceptionSpecLoc() const { + return SourceLocation::getFromRawEncoding(ExceptionSpecLoc); } - + /// \brief Retrieve the location of the ref-qualifier, if any. SourceLocation getRefQualifierLoc() const { return SourceLocation::getFromRawEncoding(RefQualifierLoc); } - + /// \brief Determine whether this function declaration contains a /// ref-qualifier. bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); } + + /// \brief Get the type of exception specification this function has. + ExceptionSpecificationType getExceptionSpecType() const { + return static_cast(ExceptionSpecType); + } }; struct BlockPointerTypeInfo : TypeInfoCommon { @@ -1188,8 +1206,7 @@ struct DeclaratorChunk { static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, SourceLocation ConstQualLoc, SourceLocation VolatileQualLoc, - SourceLocation RestrictQualLoc, - const ParsedAttributes &attrs) { + SourceLocation RestrictQualLoc) { DeclaratorChunk I; I.Kind = Pointer; I.Loc = Loc; @@ -1197,35 +1214,33 @@ struct DeclaratorChunk { I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding(); I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding(); I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); - I.Ptr.AttrList = attrs.getList(); + I.Ptr.AttrList = 0; return I; } /// getReference - Return a DeclaratorChunk for a reference. /// static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc, - const ParsedAttributes &attrs, bool lvalue) { DeclaratorChunk I; I.Kind = Reference; I.Loc = Loc; I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; I.Ref.LValueRef = lvalue; - I.Ref.AttrList = attrs.getList(); + I.Ref.AttrList = 0; return I; } /// getArray - Return a DeclaratorChunk for an array. /// static DeclaratorChunk getArray(unsigned TypeQuals, - const ParsedAttributes &attrs, bool isStatic, bool isStar, Expr *NumElts, SourceLocation LBLoc, SourceLocation RBLoc) { DeclaratorChunk I; I.Kind = Array; I.Loc = LBLoc; I.EndLoc = RBLoc; - I.Arr.AttrList = attrs.getList(); + I.Arr.AttrList = 0; I.Arr.TypeQuals = TypeQuals; I.Arr.hasStatic = isStatic; I.Arr.isStar = isStar; @@ -1235,44 +1250,44 @@ struct DeclaratorChunk { /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. - static DeclaratorChunk getFunction(const ParsedAttributes &attrs, - bool hasProto, bool isVariadic, + static DeclaratorChunk getFunction(bool hasProto, bool isVariadic, SourceLocation EllipsisLoc, ParamInfo *ArgInfo, unsigned NumArgs, unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, - bool hasExceptionSpec, - SourceLocation ThrowLoc, - bool hasAnyExceptionSpec, + ExceptionSpecificationType ESpecType, + SourceLocation ESpecLoc, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, - SourceLocation LPLoc, SourceLocation RPLoc, + Expr *NoexceptExpr, + SourceLocation LocalRangeBegin, + SourceLocation LocalRangeEnd, Declarator &TheDeclarator, - ParsedType TrailingReturnType = ParsedType()); + ParsedType TrailingReturnType = + ParsedType()); /// getBlockPointer - Return a DeclaratorChunk for a block. /// - static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc, - const ParsedAttributes &attrs) { + static DeclaratorChunk getBlockPointer(unsigned TypeQuals, + SourceLocation Loc) { DeclaratorChunk I; I.Kind = BlockPointer; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = attrs.getList(); + I.Cls.AttrList = 0; return I; } static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS, unsigned TypeQuals, - SourceLocation Loc, - const ParsedAttributes &attrs) { + SourceLocation Loc) { DeclaratorChunk I; I.Kind = MemberPointer; I.Loc = Loc; I.Mem.TypeQuals = TypeQuals; - I.Mem.AttrList = attrs.getList(); + I.Mem.AttrList = 0; new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS); return I; } @@ -1306,6 +1321,7 @@ class Declarator { enum TheContext { FileContext, // File scope declaration. PrototypeContext, // Within a function prototype. + ObjCPrototypeContext,// Within a method prototype. KNRTypeListContext, // K&R type definition list for formals. TypeNameContext, // Abstract declarator for types. MemberContext, // Struct/Union field. @@ -1315,7 +1331,8 @@ class Declarator { TemplateParamContext,// Within a template parameter list. CXXCatchContext, // C++ catch exception-declaration BlockLiteralContext, // Block literal declarator. - TemplateTypeArgContext // Template type argument. + TemplateTypeArgContext, // Template type argument. + AliasDeclContext // C++0x alias-declaration. }; private: @@ -1340,8 +1357,8 @@ class Declarator { /// GroupingParens - Set by Parser::ParseParenDeclarator(). bool GroupingParens : 1; - /// AttrList - Attributes. - AttributeList *AttrList; + /// Attrs - Attributes. + ParsedAttributes Attrs; /// AsmLabel - The asm label, if specified. Expr *AsmLabel; @@ -1365,8 +1382,8 @@ class Declarator { Declarator(const DeclSpec &ds, TheContext C) : DS(ds), Range(ds.getSourceRange()), Context(C), InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), - GroupingParens(false), AttrList(0), AsmLabel(0), - InlineParamsUsed(false), Extension(false) { + GroupingParens(false), Attrs(ds.getAttributePool().getFactory()), + AsmLabel(0), InlineParamsUsed(false), Extension(false) { } ~Declarator() { @@ -1384,6 +1401,10 @@ class Declarator { /// be shared or when in error recovery etc. DeclSpec &getMutableDeclSpec() { return const_cast(DS); } + AttributePool &getAttributePool() const { + return Attrs.getPool(); + } + /// getCXXScopeSpec - Return the C++ scope specifier (global scope or /// nested-name-specifier) that is part of the declarator-id. const CXXScopeSpec &getCXXScopeSpec() const { return SS; } @@ -1394,6 +1415,10 @@ class Declarator { TheContext getContext() const { return Context; } + bool isPrototypeContext() const { + return (Context == PrototypeContext || Context == ObjCPrototypeContext); + } + /// getSourceRange - Get the source range that spans this declarator. const SourceRange &getSourceRange() const { return Range; } @@ -1429,7 +1454,7 @@ class Declarator { for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) DeclTypeInfo[i].destroy(); DeclTypeInfo.clear(); - AttrList = 0; + Attrs.clear(); AsmLabel = 0; InlineParamsUsed = false; } @@ -1438,26 +1463,79 @@ class Declarator { /// not allowed. This is true for typenames, prototypes, and template /// parameter lists. bool mayOmitIdentifier() const { - return Context == TypeNameContext || Context == PrototypeContext || - Context == TemplateParamContext || Context == CXXCatchContext || - Context == BlockLiteralContext || Context == TemplateTypeArgContext; + switch (Context) { + case FileContext: + case KNRTypeListContext: + case MemberContext: + case BlockContext: + case ForContext: + case ConditionContext: + return false; + + case TypeNameContext: + case AliasDeclContext: + case PrototypeContext: + case ObjCPrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + case BlockLiteralContext: + case TemplateTypeArgContext: + return true; + } + llvm_unreachable("unknown context kind!"); } /// mayHaveIdentifier - Return true if the identifier is either optional or /// required. This is true for normal declarators and prototypes, but not /// typenames. bool mayHaveIdentifier() const { - return Context != TypeNameContext && Context != BlockLiteralContext && - Context != TemplateTypeArgContext; + switch (Context) { + case FileContext: + case KNRTypeListContext: + case MemberContext: + case BlockContext: + case ForContext: + case ConditionContext: + case PrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + return true; + + case TypeNameContext: + case AliasDeclContext: + case ObjCPrototypeContext: + case BlockLiteralContext: + case TemplateTypeArgContext: + return false; + } + llvm_unreachable("unknown context kind!"); } /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be /// followed by a C++ direct initializer, e.g. "int x(1);". bool mayBeFollowedByCXXDirectInit() const { - return !hasGroupingParens() && - (Context == FileContext || - Context == BlockContext || - Context == ForContext); + if (hasGroupingParens()) return false; + + switch (Context) { + case FileContext: + case BlockContext: + case ForContext: + return true; + + case KNRTypeListContext: + case MemberContext: + case ConditionContext: + case PrototypeContext: + case ObjCPrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + case TypeNameContext: + case AliasDeclContext: + case BlockLiteralContext: + case TemplateTypeArgContext: + return false; + } + llvm_unreachable("unknown context kind!"); } /// isPastIdentifier - Return true if we have parsed beyond the point where @@ -1486,8 +1564,13 @@ class Declarator { /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to /// EndLoc, which should be the last token of the chunk. - void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { + void AddTypeInfo(const DeclaratorChunk &TI, + ParsedAttributes &attrs, + SourceLocation EndLoc) { DeclTypeInfo.push_back(TI); + DeclTypeInfo.back().getAttrListRef() = attrs.getList(); + getAttributePool().takeAllFrom(attrs.getPool()); + if (!EndLoc.isInvalid()) SetRangeEnd(EndLoc); } @@ -1567,28 +1650,26 @@ class Declarator { return const_cast(this)->getFunctionTypeInfo(); } - /// AddAttributes - simply adds the attribute list to the Declarator. + /// takeAttributes - Takes attributes from the given parsed-attributes + /// set and add them to this declarator. + /// /// These examples both add 3 attributes to "var": /// short int var __attribute__((aligned(16),common,deprecated)); /// short int x, __attribute__((aligned(16)) var /// __attribute__((common,deprecated)); /// /// Also extends the range of the declarator. - void addAttributes(AttributeList *alist, SourceLocation LastLoc) { - AttrList = addAttributeLists(AttrList, alist); + void takeAttributes(ParsedAttributes &attrs, SourceLocation lastLoc) { + Attrs.takeAllFrom(attrs); - if (!LastLoc.isInvalid()) - SetRangeEnd(LastLoc); + if (!lastLoc.isInvalid()) + SetRangeEnd(lastLoc); } - void addAttributes(const ParsedAttributes &attrs) { - addAttributes(attrs.getList(), SourceLocation()); - } + const AttributeList *getAttributes() const { return Attrs.getList(); } + AttributeList *getAttributes() { return Attrs.getList(); } - const AttributeList *getAttributes() const { return AttrList; } - AttributeList *getAttributes() { return AttrList; } - - AttributeList *&getAttrListRef() { return AttrList; } + AttributeList *&getAttrListRef() { return Attrs.getListRef(); } /// hasAttributes - do we contain any attributes? bool hasAttributes() const { @@ -1634,8 +1715,7 @@ class VirtSpecifiers { enum Specifier { VS_None = 0, VS_Override = 1, - VS_Final = 2, - VS_New = 4 + VS_Final = 2 }; VirtSpecifiers() : Specifiers(0) { } @@ -1649,45 +1729,17 @@ class VirtSpecifiers { bool isFinalSpecified() const { return Specifiers & VS_Final; } SourceLocation getFinalLoc() const { return VS_finalLoc; } - bool isNewSpecified() const { return Specifiers & VS_New; } - SourceLocation getNewLoc() const { return VS_newLoc; } - void clear() { Specifiers = 0; } static const char *getSpecifierName(Specifier VS); + SourceLocation getLastLocation() const { return LastLocation; } + private: unsigned Specifiers; - SourceLocation VS_overrideLoc, VS_finalLoc, VS_newLoc; -}; - -/// ClassVirtSpecifiers - Represents a C++0x class-virt-specifier-seq. -class ClassVirtSpecifiers { -public: - enum Specifier { - CVS_None = 0, - CVS_Final = 1, - CVS_Explicit = 2 - }; - - ClassVirtSpecifiers() : Specifiers(0) { } - - bool SetSpecifier(Specifier CVS, SourceLocation Loc, - const char *&PrevSpec); - - bool isFinalSpecified() const { return Specifiers & CVS_Final; } - SourceLocation getFinalLoc() const { return CVS_finalLoc; } - - bool isExplicitSpecified() const { return Specifiers & CVS_Explicit; } - SourceLocation getExplicitLoc() const { return CVS_explicitLoc; } - - static const char *getSpecifierName(Specifier CVS); - -private: - unsigned Specifiers; - - SourceLocation CVS_finalLoc, CVS_explicitLoc; + SourceLocation VS_overrideLoc, VS_finalLoc; + SourceLocation LastLocation; }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h index 6e808de9a147..8395138ab612 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h @@ -119,25 +119,11 @@ class DelayedDiagnostic { SourceLocation Loc; - void destroy() { - switch (Kind) { - case Access: getAccessData().~AccessedEntity(); break; - case Deprecation: break; - } - } + void Destroy(); static DelayedDiagnostic makeDeprecation(SourceLocation Loc, const NamedDecl *D, - llvm::StringRef Msg) { - DelayedDiagnostic DD; - DD.Kind = Deprecation; - DD.Triggered = false; - DD.Loc = Loc; - DD.DeprecationData.Decl = D; - DD.DeprecationData.Message = Msg.data(); - DD.DeprecationData.MessageLen = Msg.size(); - return DD; - } + llvm::StringRef Msg); static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity) { diff --git a/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h index 7e9d338293ee..8d79fc09f292 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h @@ -28,7 +28,7 @@ class Scope; /// IdentifierResolver - Keeps track of shadowed decls on enclosing /// scopes. It manages the shadowing chains of declaration names and -/// implements efficent decl lookup based on a declaration name. +/// implements efficient decl lookup based on a declaration name. class IdentifierResolver { /// IdDeclInfo - Keeps track of information about decls associated @@ -53,6 +53,11 @@ class IdentifierResolver { /// declaration was not found, returns false. bool ReplaceDecl(NamedDecl *Old, NamedDecl *New); + /// \brief Insert the given declaration at the given position in the list. + void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) { + Decls.insert(Pos, D); + } + private: DeclsTy Decls; }; @@ -146,8 +151,13 @@ class IdentifierResolver { /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns /// true if 'D' belongs to the given declaration context. + /// + /// \param ExplicitInstantiationOrSpecialization When true, we are checking + /// whether the declaration is in scope for the purposes of explicit template + /// instantiation or specialization. The default is false. bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context, - Scope *S = 0) const; + Scope *S = 0, + bool ExplicitInstantiationOrSpecialization = false) const; /// AddDecl - Link the decl to its shadowed decl chain. void AddDecl(NamedDecl *D); @@ -161,6 +171,10 @@ class IdentifierResolver { /// (and, therefore, replaced). bool ReplaceDecl(NamedDecl *Old, NamedDecl *New); + /// \brief Insert the given declaration after the given iterator + /// position. + void InsertDeclAfter(iterator Pos, NamedDecl *D); + /// \brief Link the declaration into the chain of declarations for /// the given identifier. /// diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h index bdf0d8e7b602..e83e5c0ccfda 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h @@ -64,6 +64,8 @@ class InitializedEntity { EK_Temporary, /// \brief The entity being initialized is a base member subobject. EK_Base, + /// \brief The initialization is being done by a delegating constructor. + EK_Delegating, /// \brief The entity being initialized is an element of a vector. /// or vector. EK_VectorElement, @@ -210,6 +212,11 @@ class InitializedEntity { static InitializedEntity InitializeBase(ASTContext &Context, CXXBaseSpecifier *Base, bool IsInheritedVirtualBase); + + /// \brief Create the initialization entity for a delegated constructor. + static InitializedEntity InitializeDelegation(QualType Type) { + return InitializedEntity(EK_Delegating, SourceLocation(), Type); + } /// \brief Create the initialization entity for a member subobject. static InitializedEntity InitializeMember(FieldDecl *Member, @@ -234,7 +241,7 @@ class InitializedEntity { EntityKind getKind() const { return Kind; } /// \brief Retrieve the parent of the entity being initialized, when - /// the initialization itself is occuring within the context of a + /// the initialization itself is occurring within the context of a /// larger initialization. const InitializedEntity *getParent() const { return Parent; } @@ -590,6 +597,8 @@ class InitializationSequence { FK_ReferenceInitFailed, /// \brief Implicit conversion failed. FK_ConversionFailed, + /// \brief Implicit conversion failed. + FK_ConversionFromPropertyFailed, /// \brief Too many initializers for scalar FK_TooManyInitsForScalar, /// \brief Reference initialization from an initializer list @@ -655,7 +664,7 @@ class InitializationSequence { /// \param Kind the kind of initialization being performed. /// /// \param Args the argument(s) provided for initialization, ownership of - /// which is transfered into the routine. + /// which is transferred into the routine. /// /// \param ResultType if non-NULL, will be set to the type of the /// initialized object, which is the type of the declaration in most diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h index aa58d14fac73..400a7cc9194d 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h @@ -439,6 +439,7 @@ class LookupResult { Decls.clear(); if (Paths) deletePaths(Paths); Paths = NULL; + NamingClass = 0; } /// \brief Clears out any current state and re-initializes for a diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h index 3ce3513c21ae..e196e83a0e26 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h @@ -76,6 +76,7 @@ namespace clang { ICK_Vector_Splat, ///< A vector splat from an arithmetic type ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7) ICK_Block_Pointer_Conversion, ///< Block Pointer conversions + ICK_TransparentUnionConversion, /// Transparent Union Conversions ICK_Num_Conversion_Kinds ///< The number of conversion kinds }; @@ -647,8 +648,6 @@ namespace clang { /// \brief Clear out all of the candidates. void clear(); - - ~OverloadCandidateSet() { clear(); } /// Find the best viable function on this overload set, if it exists. OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h index 5f2f0eba7124..cef93fe5832f 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h @@ -383,11 +383,18 @@ namespace clang { template T **takeAs() { return reinterpret_cast(take()); } }; + /// An opaque type for threading parsed type information through the + /// parser. + typedef OpaquePtr ParsedType; + typedef UnionOpaquePtr UnionParsedType; + /// A SmallVector of statements, with stack size 32 (as that is the only one /// used.) typedef ASTOwningVector StmtVector; /// A SmallVector of expressions, with stack size 12 (the maximum used.) typedef ASTOwningVector ExprVector; + /// A SmallVector of types. + typedef ASTOwningVector TypeVector; template inline ASTMultiPtr move_arg(ASTOwningVector &vec) { @@ -421,11 +428,6 @@ namespace clang { static const bool value = true; }; - /// An opaque type for threading parsed type information through the - /// parser. - typedef OpaquePtr ParsedType; - typedef UnionOpaquePtr UnionParsedType; - typedef ActionResult ExprResult; typedef ActionResult StmtResult; typedef ActionResult TypeResult; @@ -440,6 +442,7 @@ namespace clang { typedef ASTMultiPtr MultiExprArg; typedef ASTMultiPtr MultiStmtArg; + typedef ASTMultiPtr MultiTypeArg; typedef ASTMultiPtr MultiTemplateParamsArg; inline ExprResult ExprError() { return ExprResult(true); } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h index 9e1a6165b194..1f572e5df4f3 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h @@ -139,6 +139,9 @@ namespace clang { /// tokens. All of the information about template arguments is allocated /// directly after this structure. struct TemplateIdAnnotation { + /// \brief The nested-name-specifier that precedes the template name. + CXXScopeSpec SS; + /// TemplateNameLoc - The location of the template name within the /// source. SourceLocation TemplateNameLoc; @@ -174,10 +177,13 @@ namespace clang { static TemplateIdAnnotation* Allocate(unsigned NumArgs) { TemplateIdAnnotation *TemplateId - = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + + = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + sizeof(ParsedTemplateArgument) * NumArgs); TemplateId->NumArgs = NumArgs; + // Default-construct nested-name-specifier. + new (&TemplateId->SS) CXXScopeSpec(); + // Default-construct parsed template arguments. ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs(); for (unsigned I = 0; I != NumArgs; ++I) @@ -186,7 +192,10 @@ namespace clang { return TemplateId; } - void Destroy() { free(this); } + void Destroy() { + SS.~CXXScopeSpec(); + free(this); + } }; /// Retrieves the range of the given template parameter lists. diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h index d7fda35cdb87..6588a1d92dfa 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h @@ -16,6 +16,7 @@ #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" namespace clang { @@ -75,7 +76,10 @@ class Scope { /// ObjCMethodScope - This scope corresponds to an Objective-C method body. /// It always has FnScope and DeclScope set as well. - ObjCMethodScope = 0x400 + ObjCMethodScope = 0x400, + + /// SwitchScope - This is a scope that corresponds to a switch statement. + SwitchScope = 0x800 }; private: /// The parent scope for this scope. This is null for the translation-unit @@ -90,17 +94,25 @@ class Scope { /// interrelates with other control flow statements. unsigned short Flags; + /// PrototypeDepth - This is the number of function prototype scopes + /// enclosing this scope, including this scope. + unsigned short PrototypeDepth; + + /// PrototypeIndex - This is the number of parameters currently + /// declared in this scope. + unsigned short PrototypeIndex; + /// FnParent - If this scope has a parent scope that is a function body, this /// pointer is non-null and points to it. This is used for label processing. Scope *FnParent; /// BreakParent/ContinueParent - This is a direct link to the immediately - /// preceeding BreakParent/ContinueParent if this scope is not one, or null if + /// preceding BreakParent/ContinueParent if this scope is not one, or null if /// there is no containing break/continue scope. Scope *BreakParent, *ContinueParent; /// ControlParent - This is a direct link to the immediately - /// preceeding ControlParent if this scope is not one, or null if + /// preceding ControlParent if this scope is not one, or null if /// there is no containing control scope. Scope *ControlParent; @@ -193,6 +205,19 @@ class Scope { Scope *getTemplateParamParent() { return TemplateParamParent; } const Scope *getTemplateParamParent() const { return TemplateParamParent; } + /// Returns the number of function prototype scopes in this scope + /// chain. + unsigned getFunctionPrototypeDepth() const { + return PrototypeDepth; + } + + /// Return the number of parameters declared in this function + /// prototype, increasing it by one for the next call. + unsigned getNextFunctionPrototypeIndex() { + assert(isFunctionPrototypeScope()); + return PrototypeIndex++; + } + typedef DeclSetTy::iterator decl_iterator; decl_iterator decl_begin() const { return DeclsInScope.begin(); } decl_iterator decl_end() const { return DeclsInScope.end(); } @@ -260,6 +285,20 @@ class Scope { return getFlags() & Scope::AtCatchScope; } + /// isSwitchScope - Return true if this scope is a switch scope. + bool isSwitchScope() const { + for (const Scope *S = this; S; S = S->getParent()) { + if (S->getFlags() & Scope::SwitchScope) + return true; + else if (S->getFlags() & (Scope::FnScope | Scope::ClassScope | + Scope::BlockScope | Scope::TemplateParamScope | + Scope::FunctionPrototypeScope | + Scope::AtCatchScope | Scope::ObjCMethodScope)) + return false; + } + return false; + } + typedef UsingDirectivesTy::iterator udir_iterator; typedef UsingDirectivesTy::const_iterator const_udir_iterator; @@ -285,36 +324,7 @@ class Scope { /// Init - This is used by the parser to implement scope caching. /// - void Init(Scope *Parent, unsigned ScopeFlags) { - AnyParent = Parent; - Depth = AnyParent ? AnyParent->Depth+1 : 0; - Flags = ScopeFlags; - - if (AnyParent) { - FnParent = AnyParent->FnParent; - BreakParent = AnyParent->BreakParent; - ContinueParent = AnyParent->ContinueParent; - ControlParent = AnyParent->ControlParent; - BlockParent = AnyParent->BlockParent; - TemplateParamParent = AnyParent->TemplateParamParent; - } else { - FnParent = BreakParent = ContinueParent = BlockParent = 0; - ControlParent = 0; - TemplateParamParent = 0; - } - - // If this scope is a function or contains breaks/continues, remember it. - if (Flags & FnScope) FnParent = this; - if (Flags & BreakScope) BreakParent = this; - if (Flags & ContinueScope) ContinueParent = this; - if (Flags & ControlScope) ControlParent = this; - if (Flags & BlockScope) BlockParent = this; - if (Flags & TemplateParamScope) TemplateParamParent = this; - DeclsInScope.clear(); - UsingDirectives.clear(); - Entity = 0; - ErrorTrap.reset(); - } + void Init(Scope *parent, unsigned flags); }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h index a93739892cfe..07a14d2dca3b 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h @@ -27,6 +27,7 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TypeTraits.h" +#include "clang/Basic/ExpressionTraits.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -43,6 +44,7 @@ namespace clang { class ADLResult; class ASTConsumer; class ASTContext; + class ASTMutationListener; class ArrayType; class AttributeList; class BlockDecl; @@ -110,6 +112,7 @@ namespace clang { class ObjCPropertyDecl; class ObjCProtocolDecl; class OverloadCandidateSet; + class OverloadExpr; class ParenListExpr; class ParmVarDecl; class Preprocessor; @@ -128,7 +131,9 @@ namespace clang { class TemplatePartialOrderingContext; class TemplateTemplateParmDecl; class Token; + class TypeAliasDecl; class TypedefDecl; + class TypedefNameDecl; class TypeLoc; class UnqualifiedId; class UnresolvedLookupExpr; @@ -236,6 +241,8 @@ class Sema { /// PackContext - Manages the stack for #pragma pack. An alignment /// of 0 indicates default alignment. void *PackContext; // Really a "PragmaPackStack*" + + bool MSStructPragmaOn; // True when #pragma ms_struct on /// VisContext - Manages the stack for #pragma GCC visibility. void *VisContext; // Really a "PragmaVisStack*" @@ -255,7 +262,7 @@ class Sema { /// ExtVectorDecls - This is a list all the extended vector types. This allows /// us to associate a raw vector type with one of the ext_vector type names. /// This is only necessary for issuing pretty diagnostics. - llvm::SmallVector ExtVectorDecls; + llvm::SmallVector ExtVectorDecls; /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. llvm::OwningPtr FieldCollector; @@ -305,6 +312,16 @@ class Sema { /// and must warn if not used. Only contains the first declaration. llvm::SmallVector UnusedFileScopedDecls; + /// \brief Callback to the parser to parse templated functions when needed. + typedef void LateTemplateParserCB(void *P, const FunctionDecl *FD); + LateTemplateParserCB *LateTemplateParser; + void *OpaqueParser; + + void SetLateTemplateParser(LateTemplateParserCB *LTP, void *P) { + LateTemplateParser = LTP; + OpaqueParser = P; + } + class DelayedDiagnostics; class ParsingDeclState { @@ -645,6 +662,7 @@ class Sema { Preprocessor &getPreprocessor() const { return PP; } ASTContext &getASTContext() const { return Context; } ASTConsumer &getASTConsumer() const { return Consumer; } + ASTMutationListener *getASTMutationListener() const; /// \brief Helper class that creates diagnostics with optional /// template instantiation stacks. @@ -678,6 +696,8 @@ class Sema { /// \brief Build a partial diagnostic. PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h + bool findMacroSpelling(SourceLocation &loc, llvm::StringRef name); + ExprResult Owned(Expr* E) { return E; } ExprResult Owned(ExprResult R) { return R; } StmtResult Owned(Stmt* S) { return S; } @@ -755,7 +775,9 @@ class Sema { const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc, bool *MissingExceptionSpecification = 0, - bool *MissingEmptyExceptionSpecification = 0); + bool *MissingEmptyExceptionSpecification = 0, + bool AllowNoexceptAllMatchWithNoSpec = false, + bool IsOperatorNew = false); bool CheckExceptionSpecSubset( const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Superset, SourceLocation SuperLoc, @@ -792,14 +814,117 @@ class Sema { Scope *S, CXXScopeSpec *SS = 0, bool isClassName = false, bool HasTrailingDot = false, - ParsedType ObjectType = ParsedType()); + ParsedType ObjectType = ParsedType(), + bool WantNontrivialTypeSourceInfo = false); TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); + bool isMicrosoftMissingTypename(const CXXScopeSpec *SS); bool DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, CXXScopeSpec *SS, ParsedType &SuggestedType); + /// \brief Describes the result of the name lookup and resolution performed + /// by \c ClassifyName(). + enum NameClassificationKind { + NC_Unknown, + NC_Error, + NC_Keyword, + NC_Type, + NC_Expression, + NC_NestedNameSpecifier, + NC_TypeTemplate, + NC_FunctionTemplate + }; + + class NameClassification { + NameClassificationKind Kind; + ExprResult Expr; + TemplateName Template; + ParsedType Type; + const IdentifierInfo *Keyword; + + explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {} + + public: + NameClassification(ExprResult Expr) : Kind(NC_Expression), Expr(Expr) {} + + NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {} + + NameClassification(const IdentifierInfo *Keyword) + : Kind(NC_Keyword), Keyword(Keyword) { } + + static NameClassification Error() { + return NameClassification(NC_Error); + } + + static NameClassification Unknown() { + return NameClassification(NC_Unknown); + } + + static NameClassification NestedNameSpecifier() { + return NameClassification(NC_NestedNameSpecifier); + } + + static NameClassification TypeTemplate(TemplateName Name) { + NameClassification Result(NC_TypeTemplate); + Result.Template = Name; + return Result; + } + + static NameClassification FunctionTemplate(TemplateName Name) { + NameClassification Result(NC_FunctionTemplate); + Result.Template = Name; + return Result; + } + + NameClassificationKind getKind() const { return Kind; } + + ParsedType getType() const { + assert(Kind == NC_Type); + return Type; + } + + ExprResult getExpression() const { + assert(Kind == NC_Expression); + return Expr; + } + + TemplateName getTemplateName() const { + assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate); + return Template; + } + + TemplateNameKind getTemplateNameKind() const { + assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate); + return Kind == NC_TypeTemplate? TNK_Type_template : TNK_Function_template; + } +}; + + /// \brief Perform name lookup on the given name, classifying it based on + /// the results of name lookup and the following token. + /// + /// This routine is used by the parser to resolve identifiers and help direct + /// parsing. When the identifier cannot be found, this routine will attempt + /// to correct the typo and classify based on the resulting name. + /// + /// \param S The scope in which we're performing name lookup. + /// + /// \param SS The nested-name-specifier that precedes the name. + /// + /// \param Name The identifier. If typo correction finds an alternative name, + /// this pointer parameter will be updated accordingly. + /// + /// \param NameLoc The location of the identifier. + /// + /// \param NextToken The token following the identifier. Used to help + /// disambiguate the name. + NameClassification ClassifyName(Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *&Name, + SourceLocation NameLoc, + const Token &NextToken); + Decl *ActOnDeclarator(Scope *S, Declarator &D); Decl *HandleDeclarator(Scope *S, Declarator &D, @@ -808,6 +933,7 @@ class Sema { void RegisterLocallyScopedExternCDecl(NamedDecl *ND, const LookupResult &Previous, Scope *S); + bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); void DiagnoseFunctionSpecifiers(Declarator& D); void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); void CheckShadow(Scope *S, VarDecl *D); @@ -815,6 +941,8 @@ class Sema { NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, bool &Redeclaration); + NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D, + LookupResult &Previous, bool &Redeclaration); NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -840,12 +968,10 @@ class Sema { ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T); - ParmVarDecl *CheckParameter(DeclContext *DC, - TypeSourceInfo *TSInfo, QualType T, - IdentifierInfo *Name, - SourceLocation NameLoc, - StorageClass SC, - StorageClass SCAsWritten); + ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc, + SourceLocation NameLoc, IdentifierInfo *Name, + QualType T, TypeSourceInfo *TSInfo, + StorageClass SC, StorageClass SCAsWritten); void ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, Expr *defarg); @@ -860,6 +986,7 @@ class Sema { bool TypeMayContainAuto); void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto); void ActOnInitializerError(Decl *Dcl); + void ActOnCXXForRangeDecl(Decl *D); void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); void FinalizeDeclaration(Decl *D); DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, @@ -869,6 +996,7 @@ class Sema { bool TypeMayContainAuto = true); void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls); + void CheckForFunctionRedefinition(FunctionDecl *FD); Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D); Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D); void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); @@ -890,7 +1018,9 @@ class Sema { NamedDecl *D); void DiagnoseInvalidJumps(Stmt *Body); - Decl *ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr); + Decl *ActOnFileScopeAsmDecl(Expr *expr, + SourceLocation AsmLoc, + SourceLocation RParenLoc); /// Scope actions. void ActOnPopScope(SourceLocation Loc, Scope *S); @@ -994,7 +1124,7 @@ class Sema { /// C++ record definition's base-specifiers clause and are starting its /// member declarations. void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl, - ClassVirtSpecifiers &CVS, + SourceLocation FinalLoc, SourceLocation LBraceLoc); /// ActOnTagFinishDefinition - Invoked once we have finished parsing @@ -1055,7 +1185,12 @@ class Sema { /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns /// true if 'D' belongs to the given declaration context. - bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0); + /// + /// \param ExplicitInstantiationOrSpecialization When true, we are checking + /// whether the declaration is in scope for the purposes of explicit template + /// instantiation or specialization. The default is false. + bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0, + bool ExplicitInstantiationOrSpecialization = false); /// Finds the scope corresponding to the given decl context, if it /// happens to be an enclosing scope. Otherwise return NULL. @@ -1064,11 +1199,13 @@ class Sema { /// Subroutines of ActOnDeclarator(). TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, TypeSourceInfo *TInfo); - void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls); + void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls); bool MergeFunctionDecl(FunctionDecl *New, Decl *Old); bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old); - void MergeVarDeclTypes(VarDecl *New, VarDecl *Old); + void mergeObjCMethodDecls(ObjCMethodDecl *New, const ObjCMethodDecl *Old); void MergeVarDecl(VarDecl *New, LookupResult &OldDecls); + void MergeVarDeclTypes(VarDecl *New, VarDecl *Old); + void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old); // AssignmentAction - This is used by all the assignment diagnostic functions @@ -1149,13 +1286,13 @@ class Sema { ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init); - bool PerformObjectArgumentInitialization(Expr *&From, - NestedNameSpecifier *Qualifier, - NamedDecl *FoundDecl, - CXXMethodDecl *Method); + ExprResult PerformObjectArgumentInitialization(Expr *From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + CXXMethodDecl *Method); - bool PerformContextuallyConvertToBool(Expr *&From); - bool PerformContextuallyConvertToObjCId(Expr *&From); + ExprResult PerformContextuallyConvertToBool(Expr *From); + ExprResult PerformContextuallyConvertToObjCId(Expr *From); ExprResult ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE, @@ -1167,10 +1304,10 @@ class Sema { const PartialDiagnostic &AmbigNote, const PartialDiagnostic &ConvDiag); - bool PerformObjectMemberConversion(Expr *&From, - NestedNameSpecifier *Qualifier, - NamedDecl *FoundDecl, - NamedDecl *Member); + ExprResult PerformObjectMemberConversion(Expr *From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + NamedDecl *Member); // Members have to be NamespaceDecl* or TranslationUnitDecl*. // TODO: make this is a typesafe union. @@ -1208,7 +1345,7 @@ class Sema { void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, Expr **Args, unsigned NumArgs, @@ -1216,7 +1353,7 @@ class Sema { bool SuppressUserConversions = false); void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); @@ -1253,9 +1390,10 @@ class Sema { void AddArgumentDependentLookupCandidates(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, - bool PartialOverloading = false); + bool PartialOverloading = false, + bool StdNamespaceIsAssociated = false); // Emit as a 'note' the specific overload candidate void NoteOverloadCandidate(FunctionDecl *Fn); @@ -1276,10 +1414,18 @@ class Sema { bool Complain, DeclAccessPair &Found); - FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From, + FunctionDecl *ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, bool Complain = false, DeclAccessPair* Found = 0); + ExprResult ResolveAndFixSingleFunctionTemplateSpecialization( + Expr *SrcExpr, bool DoFunctionPointerConverion = false, + bool Complain = false, + const SourceRange& OpRangeForComplaining = SourceRange(), + QualType DestTypeForComplaining = QualType(), + unsigned DiagIDForComplaining = 0); + + Expr *FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl, FunctionDecl *Fn); @@ -1444,15 +1590,16 @@ class Sema { QualType T1, QualType T2, UnresolvedSetImpl &Functions); - LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, - bool isLocalLabel = false); - + LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc, + SourceLocation GnuLabelLoc = SourceLocation()); + DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class); CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); void ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - ADLResult &Functions); + ADLResult &Functions, + bool StdNamespaceIsAssociated = false); void LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer, @@ -1695,6 +1842,7 @@ class Sema { /// initialization. void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, llvm::SmallVectorImpl &Ivars); + //===--------------------------------------------------------------------===// // Statement Parsing Callbacks: SemaStmt.cpp. public: @@ -1734,7 +1882,7 @@ class Sema { StmtResult ActOnExprStmt(FullExprArg Expr); StmtResult ActOnNullStmt(SourceLocation SemiLoc, - bool LeadingEmptyMacro = false); + SourceLocation LeadingEmptyMacroLoc = SourceLocation()); StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, MultiStmtArg Elts, bool isStmtExpr); @@ -1782,6 +1930,17 @@ class Sema { SourceLocation LParenLoc, Stmt *First, Expr *Second, SourceLocation RParenLoc, Stmt *Body); + StmtResult ActOnCXXForRangeStmt(SourceLocation ForLoc, + SourceLocation LParenLoc, Stmt *LoopVar, + SourceLocation ColonLoc, Expr *Collection, + SourceLocation RParenLoc); + StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc, + SourceLocation ColonLoc, + Stmt *RangeDecl, Stmt *BeginEndDecl, + Expr *Cond, Expr *Inc, + Stmt *LoopVarDecl, + SourceLocation RParenLoc); + StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body); StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, @@ -1811,7 +1970,8 @@ class Sema { VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, - IdentifierInfo *Name, SourceLocation NameLoc, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, bool Invalid = false); Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D); @@ -1831,16 +1991,29 @@ class Sema { Expr *SynchExpr, Stmt *SynchBody); - VarDecl *BuildExceptionDeclaration(Scope *S, - TypeSourceInfo *TInfo, - IdentifierInfo *Name, - SourceLocation Loc); + VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, + SourceLocation StartLoc, + SourceLocation IdLoc, + IdentifierInfo *Id); Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D); StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, Stmt *HandlerBlock); StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg Handlers); + + StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ? + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); + + StmtResult ActOnSEHExceptBlock(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block); + + StmtResult ActOnSEHFinallyBlock(SourceLocation Loc, + Stmt *Block); + void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock); bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const; @@ -1870,7 +2043,8 @@ class Sema { } void EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message, - SourceLocation Loc, bool UnknownObjCClass=false); + SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass=0); void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); @@ -1878,7 +2052,8 @@ class Sema { // Expression Parsing Callbacks: SemaExpr.cpp. bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, - bool UnknownObjCClass=false); + const ObjCInterfaceDecl *UnknownObjCClass=0); + std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD); bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, ObjCMethodDecl *Getter, SourceLocation Loc); @@ -1906,6 +2081,10 @@ class Sema { // Primary Expressions. SourceRange getExprRange(Expr *E) const; + ObjCIvarDecl *SynthesizeProvisionalIvar(LookupResult &Lookup, + IdentifierInfo *II, + SourceLocation NameLoc); + ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name, bool HasTrailingLParen, bool IsAddressOfOperand); @@ -1971,6 +2150,20 @@ class Sema { /// fragments (e.g. "foo" "bar" L"baz"). ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks); + ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + MultiTypeArg Types, + MultiExprArg Exprs); + ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + TypeSourceInfo **Types, + Expr **Exprs, + unsigned NumAssocs); + // Binary/Unary Operators. 'Tok' is the token for the operator. ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputArg); @@ -1979,19 +2172,25 @@ class Sema { ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input); - ExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T, - SourceLocation OpLoc, - bool isSizeOf, SourceRange R); - ExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, - bool isSizeOf, SourceRange R); + ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *T, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R); + ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R); ExprResult - ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, - void *TyOrEx, const SourceRange &ArgRange); + ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + bool isType, void *TyOrEx, + const SourceRange &ArgRange); - ExprResult CheckPlaceholderExpr(Expr *E, SourceLocation Loc); + ExprResult CheckPlaceholderExpr(Expr *E); + bool CheckVecStepExpr(Expr *E, SourceLocation OpLoc, SourceRange R); - bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc, - SourceRange R, bool isSizeof); + bool CheckUnaryExprOrTypeTraitOperand(QualType type, SourceLocation OpLoc, + SourceRange R, + UnaryExprOrTypeTrait ExprKind); ExprResult ActOnSizeofParameterPackExpr(Scope *S, SourceLocation OpLoc, IdentifierInfo &Name, @@ -2020,7 +2219,7 @@ class Sema { const TemplateArgumentListInfo *TemplateArgs, bool SuppressQualifierCheck = false); - ExprResult LookupMemberExpr(LookupResult &R, Expr *&Base, + ExprResult LookupMemberExpr(LookupResult &R, ExprResult &Base, bool &IsArrow, SourceLocation OpLoc, CXXScopeSpec &SS, Decl *ObjCImpDecl, @@ -2163,6 +2362,8 @@ class Sema { // __null ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc); + bool CheckCaseExpression(Expr *expr); + //===------------------------- "Block" Extension ------------------------===// /// ActOnBlockStart - This callback is invoked when a block literal is @@ -2186,6 +2387,7 @@ class Sema { // Act on C++ namespaces Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc, + SourceLocation NamespaceLoc, SourceLocation IdentLoc, IdentifierInfo *Ident, SourceLocation LBrace, @@ -2250,6 +2452,11 @@ class Sema { AttributeList *AttrList, bool IsTypeName, SourceLocation TypenameLoc); + Decl *ActOnAliasDeclaration(Scope *CurScope, + AccessSpecifier AS, + SourceLocation UsingLoc, + UnqualifiedId &Name, + TypeResult Type); /// AddCXXDirectInitializerToDecl - This action is called immediately after /// ActOnDeclarator, when a C++ direct initializer is present. @@ -2444,7 +2651,7 @@ class Sema { //// ActOnCXXThrow - Parse throw expressions. ExprResult ActOnCXXThrow(SourceLocation OpLoc, Expr *expr); - bool CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E); + ExprResult CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E); /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. /// Can be interpreted either as function-style casting ("int(x)") @@ -2542,6 +2749,32 @@ class Sema { TypeSourceInfo *RhsT, SourceLocation RParen); + /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support + /// pseudo-functions. + ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + ParsedType LhsTy, + Expr *DimExpr, + SourceLocation RParen); + + ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + TypeSourceInfo *TSInfo, + Expr *DimExpr, + SourceLocation RParen); + + /// ActOnExpressionTrait - Parsed one of the unary type trait support + /// pseudo-functions. + ExprResult ActOnExpressionTrait(ExpressionTrait OET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen); + + ExprResult BuildExpressionTrait(ExpressionTrait OET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen); + ExprResult ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, @@ -2659,25 +2892,41 @@ class Sema { ParsedType ObjectType, bool EnteringContext); - /// \brief The parser has parsed a nested-name-specifier 'type::'. + /// \brief The parser has parsed a nested-name-specifier + /// 'template[opt] template-name < template-args >::'. /// /// \param S The scope in which this nested-name-specifier occurs. /// - /// \param Type The type, which will be a template specialization - /// type, preceding the '::'. - /// - /// \param CCLoc The location of the '::'. + /// \param TemplateLoc The location of the 'template' keyword, if any. /// /// \param SS The nested-name-specifier, which is both an input /// parameter (the nested-name-specifier before this type) and an /// output parameter (containing the full nested-name-specifier, /// including this new type). + /// + /// \param TemplateLoc the location of the 'template' keyword, if any. + /// \param TemplateName The template name. + /// \param TemplateNameLoc The location of the template name. + /// \param LAngleLoc The location of the opening angle bracket ('<'). + /// \param TemplateArgs The template arguments. + /// \param RAngleLoc The location of the closing angle bracket ('>'). + /// \param CCLoc The location of the '::'. + + /// \param EnteringContext Whether we're entering the context of the + /// nested-name-specifier. + /// /// /// \returns true if an error occurred, false otherwise. bool ActOnCXXNestedNameSpecifier(Scope *S, - ParsedType Type, + SourceLocation TemplateLoc, + CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, SourceLocation CCLoc, - CXXScopeSpec &SS); + bool EnteringContext); /// \brief Given a C++ nested-name-specifier, produce an annotation value /// that the parser can use later to reconstruct the given @@ -2818,10 +3067,13 @@ class Sema { MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr **Args, unsigned NumArgs, + SourceLocation BaseLoc, SourceLocation RParenLoc, SourceLocation LParenLoc, - CXXRecordDecl *ClassDecl, - SourceLocation EllipsisLoc); + CXXRecordDecl *ClassDecl); + + bool SetDelegatingInitializer(CXXConstructorDecl *Constructor, + CXXCtorInitializer *Initializer); bool SetCtorInitializers(CXXConstructorDecl *Constructor, CXXCtorInitializer **Initializers, @@ -2887,15 +3139,19 @@ class Sema { AttributeList *AttrList); void ActOnReenterTemplateScope(Scope *S, Decl *Template); + void ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D); void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record); void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method); void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param); void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method); void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record); + void MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag = true); + bool IsInsideALocalClassWithinATemplateFunction(); - Decl *ActOnStaticAssertDeclaration(SourceLocation AssertLoc, + Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, Expr *AssertExpr, - Expr *AssertMessageExpr); + Expr *AssertMessageExpr, + SourceLocation RParenLoc); FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc, TypeSourceInfo *TSInfo); @@ -3071,18 +3327,21 @@ class Sema { //===--------------------------------------------------------------------===// // C++ Templates [C++ 14] // + void FilterAcceptableTemplateNames(LookupResult &R); + bool hasAnyAcceptableTemplateNames(LookupResult &R); + void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType, bool EnteringContext, bool &MemberOfUnknownSpecialization); TemplateNameKind isTemplateName(Scope *S, - CXXScopeSpec &SS, - bool hasTemplateKeyword, - UnqualifiedId &Name, - ParsedType ObjectType, - bool EnteringContext, - TemplateTy &Template, - bool &MemberOfUnknownSpecialization); + CXXScopeSpec &SS, + bool hasTemplateKeyword, + UnqualifiedId &Name, + ParsedType ObjectType, + bool EnteringContext, + TemplateTy &Template, + bool &MemberOfUnknownSpecialization); bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, SourceLocation IILoc, @@ -3155,27 +3414,41 @@ class Sema { IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, TemplateParameterList *TemplateParams, - AccessSpecifier AS); + AccessSpecifier AS, + unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists); void translateTemplateArguments(const ASTTemplateArgsPtr &In, TemplateArgumentListInfo &Out); + void NoteAllFoundTemplates(TemplateName Name); + QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &TemplateArgs); + TemplateArgumentListInfo &TemplateArgs); TypeResult - ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc, + ActOnTemplateIdType(CXXScopeSpec &SS, + TemplateTy Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc); - TypeResult ActOnTagTemplateIdType(CXXScopeSpec &SS, - TypeResult Type, - TagUseKind TUK, + /// \brief Parsed an elaborated-type-specifier that refers to a template-id, + /// such as \c class T::template apply. + /// + /// \param TUK + TypeResult ActOnTagTemplateIdType(TagUseKind TUK, TypeSpecifierType TagSpec, - SourceLocation TagLoc); + SourceLocation TagLoc, + CXXScopeSpec &SS, + TemplateTy TemplateD, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc); + ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, LookupResult &R, bool RequiresADL, @@ -3225,7 +3498,7 @@ class Sema { LookupResult &Previous); bool CheckFunctionTemplateSpecialization(FunctionDecl *FD, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous); bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); @@ -3291,9 +3564,30 @@ class Sema { llvm::SmallVectorImpl &Converted, CheckTemplateArgumentKind CTAK = CTAK_Specified); + /// \brief Check that the given template arguments can be be provided to + /// the given template, converting the arguments along the way. + /// + /// \param Template The template to which the template arguments are being + /// provided. + /// + /// \param TemplateLoc The location of the template name in the source. + /// + /// \param TemplateArgs The list of template arguments. If the template is + /// a template template parameter, this function may extend the set of + /// template arguments to also include substituted, defaulted template + /// arguments. + /// + /// \param PartialTemplateArgs True if the list of template arguments is + /// intentionally partial, e.g., because we're checking just the initial + /// set of template arguments. + /// + /// \param Converted Will receive the converted, canonicalized template + /// arguments. + /// + /// \returns True if an error occurred, false otherwise. bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &TemplateArgs, + TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, llvm::SmallVectorImpl &Converted); @@ -3305,10 +3599,10 @@ class Sema { TypeSourceInfo *Arg); bool CheckTemplateArgumentPointerToMember(Expr *Arg, TemplateArgument &Converted); - bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param, - QualType InstantiatedParamType, Expr *&Arg, - TemplateArgument &Converted, - CheckTemplateArgumentKind CTAK = CTAK_Specified); + ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param, + QualType InstantiatedParamType, Expr *Arg, + TemplateArgument &Converted, + CheckTemplateArgumentKind CTAK = CTAK_Specified); bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, const TemplateArgumentLoc &Arg); @@ -3384,17 +3678,25 @@ class Sema { /// \param TypenameLoc the location of the 'typename' keyword /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). /// \param TemplateLoc the location of the 'template' keyword, if any. - /// \param Ty the type that the typename specifier refers to. + /// \param TemplateName The template name. + /// \param TemplateNameLoc The location of the template name. + /// \param LAngleLoc The location of the opening angle bracket ('<'). + /// \param TemplateArgs The template arguments. + /// \param RAngleLoc The location of the closing angle bracket ('>'). TypeResult ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, SourceLocation TemplateLoc, - ParsedType Ty); + const CXXScopeSpec &SS, + SourceLocation TemplateLoc, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc); QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo &II, SourceLocation KeywordLoc, - SourceRange NNSRange, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo &II, SourceLocation IILoc); TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, @@ -3480,7 +3782,7 @@ class Sema { /// \param T The type that is being checked for unexpanded parameter /// packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, UnexpandedParameterPackContext UPPC); @@ -3490,7 +3792,7 @@ class Sema { /// \param E The expression that is being checked for unexpanded /// parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(Expr *E, UnexpandedParameterPackContext UPPC = UPPC_Expression); @@ -3500,7 +3802,7 @@ class Sema { /// \param SS The nested-name-specifier that is being checked for /// unexpanded parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, UnexpandedParameterPackContext UPPC); @@ -3510,7 +3812,7 @@ class Sema { /// \param NameInfo The name (with source location information) that /// is being checked for unexpanded parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, UnexpandedParameterPackContext UPPC); @@ -3522,7 +3824,7 @@ class Sema { /// \param Template The template name that is being checked for unexpanded /// parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TemplateName Template, UnexpandedParameterPackContext UPPC); @@ -3533,7 +3835,7 @@ class Sema { /// \param Arg The template argument that is being checked for unexpanded /// parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, UnexpandedParameterPackContext UPPC); @@ -3751,7 +4053,7 @@ class Sema { TemplateDeductionResult SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo &ExplicitTemplateArgs, + TemplateArgumentListInfo &ExplicitTemplateArgs, llvm::SmallVectorImpl &Deduced, llvm::SmallVectorImpl &ParamTypes, QualType *FunctionType, @@ -3766,14 +4068,14 @@ class Sema { TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info); @@ -3786,11 +4088,12 @@ class Sema { TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info); - bool DeduceAutoType(QualType AutoType, Expr *Initializer, QualType &Result); + bool DeduceAutoType(TypeSourceInfo *AutoType, Expr *Initializer, + TypeSourceInfo *&Result); FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, @@ -4204,7 +4507,7 @@ class Sema { /// types, static variables, enumerators, etc. std::deque PendingLocalImplicitInstantiations; - void PerformPendingInstantiations(bool LocalOnly = false); + bool PerformPendingInstantiations(bool LocalOnly = false); TypeSourceInfo *SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, @@ -4224,6 +4527,7 @@ class Sema { DeclarationName Entity); ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, + int indexAdjustment, llvm::Optional NumExpansions); bool SubstParmTypes(SourceLocation Loc, ParmVarDecl **Params, unsigned NumParams, @@ -4289,11 +4593,6 @@ class Sema { ClassTemplateSpecializationDecl *ClassTemplateSpec, TemplateSpecializationKind TSK); - NestedNameSpecifier * - SubstNestedNameSpecifier(NestedNameSpecifier *NNS, - SourceRange Range, - const MultiLevelTemplateArgumentList &TemplateArgs); - NestedNameSpecifierLoc SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -4302,7 +4601,8 @@ class Sema { SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, const MultiLevelTemplateArgumentList &TemplateArgs); TemplateName - SubstTemplateName(TemplateName Name, SourceLocation Loc, + SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name, + SourceLocation Loc, const MultiLevelTemplateArgumentList &TemplateArgs); bool Subst(const TemplateArgumentLoc *Args, unsigned NumArgs, TemplateArgumentListInfo &Result, @@ -4475,7 +4775,7 @@ class Sema { ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, - bool isVariadic = false); + bool isVariadic, bool MethodDefinition); // Helper method for ActOnClassMethod/ActOnInstanceMethod. // Will search "local" class/category implementations for a method decl. @@ -4485,6 +4785,9 @@ class Sema { ObjCInterfaceDecl *CDecl); ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel, ObjCInterfaceDecl *ClassDecl); + ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, + const ObjCObjectPointerType *OPT, + bool IsInstance); ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, @@ -4586,6 +4889,11 @@ class Sema { PPK_Pop // #pragma pack(pop, [identifier], [n]) }; + enum PragmaMSStructKind { + PMSST_OFF, // #pragms ms_struct off + PMSST_ON // #pragms ms_struct on + }; + /// ActOnPragmaPack - Called on well formed #pragma pack(...). void ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, @@ -4593,6 +4901,9 @@ class Sema { SourceLocation PragmaLoc, SourceLocation LParenLoc, SourceLocation RParenLoc); + + /// ActOnPragmaMSStruct - Called on well formed #pragms ms_struct [on|off]. + void ActOnPragmaMSStruct(PragmaMSStructKind Kind); /// ActOnPragmaUnused - Called on well-formed '#pragma unused'. void ActOnPragmaUnused(const Token &Identifier, @@ -4626,6 +4937,9 @@ class Sema { /// a the record decl, to handle '#pragma pack' and '#pragma options align'. void AddAlignmentAttributesForRecord(RecordDecl *RD); + /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record. + void AddMsStructLayoutForRecord(RecordDecl *RD); + /// FreePackedContext - Deallocate and null out PackContext. void FreePackedContext(); @@ -4655,38 +4969,42 @@ class Sema { /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit /// cast. If there is already an implicit cast, merge into the existing one. /// If isLvalue, the result of the cast is an lvalue. - void ImpCastExprToType(Expr *&Expr, QualType Type, CastKind CK, - ExprValueKind VK = VK_RValue, - const CXXCastPath *BasePath = 0); + ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, + ExprValueKind VK = VK_RValue, + const CXXCastPath *BasePath = 0); + + /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding + /// to the conversion from scalar type ScalarTy to the Boolean type. + static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy); /// IgnoredValueConversions - Given that an expression's result is /// syntactically ignored, perform any conversions that are /// required. - void IgnoredValueConversions(Expr *&expr); + ExprResult IgnoredValueConversions(Expr *E); // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts // functions and arrays to their respective pointers (C99 6.3.2.1). - Expr *UsualUnaryConversions(Expr *&expr); + ExprResult UsualUnaryConversions(Expr *E); // DefaultFunctionArrayConversion - converts functions and arrays // to their respective pointers (C99 6.3.2.1). - void DefaultFunctionArrayConversion(Expr *&expr); + ExprResult DefaultFunctionArrayConversion(Expr *E); // DefaultFunctionArrayLvalueConversion - converts functions and // arrays to their respective pointers and performs the // lvalue-to-rvalue conversion. - void DefaultFunctionArrayLvalueConversion(Expr *&expr); + ExprResult DefaultFunctionArrayLvalueConversion(Expr *E); // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on // the operand. This is DefaultFunctionArrayLvalueConversion, // except that it assumes the operand isn't of function or array // type. - void DefaultLvalueConversion(Expr *&expr); + ExprResult DefaultLvalueConversion(Expr *E); // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that // do not have a prototype. Integer promotions are performed on each // argument, and arguments that have type float are promoted to double. - void DefaultArgumentPromotion(Expr *&Expr); + ExprResult DefaultArgumentPromotion(Expr *E); // Used for emitting the right warning by DefaultVariadicArgumentPromotion enum VariadicCallType { @@ -4709,15 +5027,15 @@ class Sema { // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but // will warn if the resulting type is not a POD type. - bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, - FunctionDecl *FDecl); + ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, + FunctionDecl *FDecl); // UsualArithmeticConversions - performs the UsualUnaryConversions on it's // operands and then handles various conversions that are common to binary // operators (C99 6.3.1.8). If both operands aren't arithmetic, this // routine returns the first non-arithmetic type found. The client is // responsible for emitting appropriate error diagnostics. - QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr, + QualType UsualArithmeticConversions(ExprResult &lExpr, ExprResult &rExpr, bool isCompAssign = false); /// AssignConvertType - All of the 'assignment' semantic checks return this @@ -4805,94 +5123,102 @@ class Sema { /// Check assignment constraints and prepare for a conversion of the /// RHS to the LHS type. - AssignConvertType CheckAssignmentConstraints(QualType lhs, Expr *&rhs, + AssignConvertType CheckAssignmentConstraints(QualType lhs, ExprResult &rhs, CastKind &Kind); // CheckSingleAssignmentConstraints - Currently used by // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking, // this routine performs the default function/array converions. AssignConvertType CheckSingleAssignmentConstraints(QualType lhs, - Expr *&rExpr); + ExprResult &rExprRes); // \brief If the lhs type is a transparent union, check whether we // can initialize the transparent union with the given expression. AssignConvertType CheckTransparentUnionArgumentConstraints(QualType lhs, - Expr *&rExpr); + ExprResult &rExpr); bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType); bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType); - bool PerformImplicitConversion(Expr *&From, QualType ToType, - AssignmentAction Action, - bool AllowExplicit = false); - bool PerformImplicitConversion(Expr *&From, QualType ToType, - AssignmentAction Action, - bool AllowExplicit, - ImplicitConversionSequence& ICS); - bool PerformImplicitConversion(Expr *&From, QualType ToType, - const ImplicitConversionSequence& ICS, - AssignmentAction Action, - bool CStyle = false); - bool PerformImplicitConversion(Expr *&From, QualType ToType, - const StandardConversionSequence& SCS, - AssignmentAction Action, - bool CStyle); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, + bool AllowExplicit = false); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, + bool AllowExplicit, + ImplicitConversionSequence& ICS); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + const ImplicitConversionSequence& ICS, + AssignmentAction Action, + bool CStyle = false); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + const StandardConversionSequence& SCS, + AssignmentAction Action, + bool CStyle); /// the following "Check" methods will return a valid/converted QualType /// or a null QualType (indicating an error diagnostic was issued). /// type checking binary operators (subroutines of CreateBuiltinBinOp). - QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex); + QualType InvalidOperands(SourceLocation l, ExprResult &lex, ExprResult &rex); QualType CheckPointerToMemberOperands( // C++ 5.5 - Expr *&lex, Expr *&rex, ExprValueKind &VK, + ExprResult &lex, ExprResult &rex, ExprValueKind &VK, SourceLocation OpLoc, bool isIndirect); QualType CheckMultiplyDivideOperands( // C99 6.5.5 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign, + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, bool isCompAssign, bool isDivide); QualType CheckRemainderOperands( // C99 6.5.5 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, bool isCompAssign = false); QualType CheckAdditionOperands( // C99 6.5.6 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); QualType CheckSubtractionOperands( // C99 6.5.6 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); QualType CheckShiftOperands( // C99 6.5.7 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, unsigned Opc, bool isCompAssign = false); QualType CheckCompareOperands( // C99 6.5.8/9 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, unsigned Opc, bool isRelational); QualType CheckBitwiseOperands( // C99 6.5.[10...12] - Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, bool isCompAssign = false); QualType CheckLogicalOperands( // C99 6.5.[13,14] - Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, unsigned Opc); // CheckAssignmentOperands is used for both simple and compound assignment. // For simple assignment, pass both expressions and a null converted type. // For compound assignment, pass both expressions and the converted type. QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] - Expr *lex, Expr *&rex, SourceLocation OpLoc, QualType convertedType); + Expr *lex, ExprResult &rex, SourceLocation OpLoc, QualType convertedType); - void ConvertPropertyForRValue(Expr *&E); - void ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType& LHSTy); + void ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS, QualType& LHSTy); + ExprResult ConvertPropertyForRValue(Expr *E); QualType CheckConditionalOperands( // C99 6.5.15 - Expr *&cond, Expr *&lhs, Expr *&rhs, + ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); QualType CXXCheckConditionalOperands( // C++ 5.16 - Expr *&cond, Expr *&lhs, Expr *&rhs, + ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, bool *NonStandardCompositeType = 0); + QualType FindCompositePointerType(SourceLocation Loc, ExprResult &E1, ExprResult &E2, + bool *NonStandardCompositeType = 0) { + Expr *E1Tmp = E1.take(), *E2Tmp = E2.take(); + QualType Composite = FindCompositePointerType(Loc, E1Tmp, E2Tmp, NonStandardCompositeType); + E1 = Owned(E1Tmp); + E2 = Owned(E2Tmp); + return Composite; + } - QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, + QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, SourceLocation questionLoc); bool DiagnoseConditionalForNull(Expr *LHS, Expr *RHS, SourceLocation QuestionLoc); /// type checking for vector binary operators. - QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex); - QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx, + QualType CheckVectorOperands(SourceLocation l, ExprResult &lex, ExprResult &rex); + QualType CheckVectorCompareOperands(ExprResult &lex, ExprResult &rx, SourceLocation l, bool isRel); /// type checking declaration initializers (C99 6.7.8) @@ -4930,9 +5256,13 @@ class Sema { /// CheckCastTypes - Check type constraints for casting between types under /// C semantics, or forward to CXXCheckCStyleCast in C++. - bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr, - CastKind &Kind, ExprValueKind &VK, CXXCastPath &BasePath, - bool FunctionalStyle = false); + ExprResult CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *CastExpr, + CastKind &Kind, ExprValueKind &VK, CXXCastPath &BasePath, + bool FunctionalStyle = false); + + ExprResult checkUnknownAnyCast(SourceRange TyRange, QualType castType, + Expr *castExpr, CastKind &castKind, + ExprValueKind &valueKind, CXXCastPath &BasePath); // CheckVectorCast - check type constraints for vectors. // Since vectors are an extension, there are no C standard reference for this. @@ -4945,15 +5275,15 @@ class Sema { // Since vectors are an extension, there are no C standard reference for this. // We allow casting between vectors and integer datatypes of the same size, // or vectors and the element type of that vector. - // returns true if the cast is invalid - bool CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *&CastExpr, - CastKind &Kind); + // returns the cast expr + ExprResult CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *CastExpr, + CastKind &Kind); /// CXXCheckCStyleCast - Check constraints of a C-style or function-style /// cast under C++ semantics. - bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, - Expr *&CastExpr, CastKind &Kind, - CXXCastPath &BasePath, bool FunctionalStyle); + ExprResult CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, + Expr *CastExpr, CastKind &Kind, + CXXCastPath &BasePath, bool FunctionalStyle); /// CheckMessageArgumentTypes - Check types in an Obj-C message send. /// \param Method - May be null. @@ -4972,7 +5302,7 @@ class Sema { /// \param Loc - A location associated with the condition, e.g. the /// 'if' keyword. /// \return true iff there were any errors - bool CheckBooleanCondition(Expr *&CondExpr, SourceLocation Loc); + ExprResult CheckBooleanCondition(Expr *CondExpr, SourceLocation Loc); ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, Expr *SubExpr); @@ -4986,7 +5316,7 @@ class Sema { void DiagnoseEqualityWithExtraParens(ParenExpr *parenE); /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. - bool CheckCXXBooleanCondition(Expr *&CondExpr); + ExprResult CheckCXXBooleanCondition(Expr *CondExpr); /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have /// the specified width and sign. If an overflow occurs, detect it and emit @@ -5174,7 +5504,7 @@ class Sema { unsigned ByteNo) const; private: - void CheckArrayAccess(const ArraySubscriptExpr *E); + void CheckArrayAccess(const Expr *E); bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall); bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall); @@ -5210,12 +5540,15 @@ class Sema { bool isPrintf); void CheckNonNullArguments(const NonNullAttr *NonNull, - const CallExpr *TheCall); + const Expr * const *ExprArgs, + SourceLocation CallSiteLoc); void CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, bool isPrintf); + void CheckMemsetArguments(const CallExpr *Call); + void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, SourceLocation ReturnLoc); void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex); diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h index ae5aa33db766..83c0999ad49c 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define SEMASTART #include "clang/Basic/DiagnosticSemaKinds.inc" #undef DIAG diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Template.h b/contrib/llvm/tools/clang/include/clang/Sema/Template.h index 53f4a9d8c8fa..4d97f9bef802 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Template.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Template.h @@ -335,7 +335,9 @@ namespace clang { Decl *VisitLabelDecl(LabelDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); + Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias); Decl *VisitTypedefDecl(TypedefDecl *D); + Decl *VisitTypeAliasDecl(TypeAliasDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); Decl *VisitFieldDecl(FieldDecl *D); diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h index 7cc35713aace..c66697963e0d 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h @@ -56,7 +56,7 @@ class TemplateDeductionInfo { } /// \brief Returns the location at which template argument is - /// occuring. + /// occurring. SourceLocation getLocation() const { return Loc; } diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h index 68fd91d4c069..1cfd458a3864 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h @@ -490,7 +490,11 @@ namespace clang { /// \brief The ObjC 'Class' type. PREDEF_TYPE_OBJC_CLASS = 27, /// \brief The ObjC 'SEL' type. - PREDEF_TYPE_OBJC_SEL = 28 + PREDEF_TYPE_OBJC_SEL = 28, + /// \brief The 'unknown any' placeholder type. + PREDEF_TYPE_UNKNOWN_ANY = 29, + /// \brief The placeholder type for bound member functions. + PREDEF_TYPE_BOUND_MEMBER = 30 }; /// \brief The number of predefined type IDs that are reserved for @@ -622,7 +626,11 @@ namespace clang { /// \brief NSConstantString type SPECIAL_TYPE_NS_CONSTANT_STRING = 15, /// \brief Whether __[u]int128_t identifier is installed. - SPECIAL_TYPE_INT128_INSTALLED = 16 + SPECIAL_TYPE_INT128_INSTALLED = 16, + /// \brief Cached "auto" deduction type. + SPECIAL_TYPE_AUTO_DEDUCT = 17, + /// \brief Cached "auto &&" deduction type. + SPECIAL_TYPE_AUTO_RREF_DEDUCT = 18 }; /// \brief Record codes for each kind of declaration. @@ -636,6 +644,8 @@ namespace clang { DECL_TRANSLATION_UNIT = 50, /// \brief A TypedefDecl record. DECL_TYPEDEF, + /// \brief A TypeAliasDecl record. + DECL_TYPEALIAS, /// \brief An EnumDecl record. DECL_ENUM, /// \brief A RecordDecl record. @@ -872,6 +882,8 @@ namespace clang { EXPR_BLOCK, /// \brief A BlockDeclRef record. EXPR_BLOCK_DECL_REF, + /// \brief A GenericSelectionExpr record. + EXPR_GENERIC_SELECTION, // Objective-C @@ -913,6 +925,8 @@ namespace clang { STMT_CXX_CATCH, /// \brief A CXXTryStmt record. STMT_CXX_TRY, + /// \brief A CXXForRangeStmt record. + STMT_CXX_FOR_RANGE, /// \brief A CXXOperatorCallExpr record. EXPR_CXX_OPERATOR_CALL, @@ -958,11 +972,13 @@ namespace clang { EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr + EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr EXPR_OPAQUE_VALUE, // OpaqueValueExpr EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr + EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr EXPR_PACK_EXPANSION, // PackExpansionExpr EXPR_SIZEOF_PACK, // SizeOfPackExpr diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h index 424e78c391bc..da018ab99e65 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h @@ -69,6 +69,7 @@ class ASTStmtReader; class ASTIdentifierLookupTrait; class TypeLocReader; struct HeaderFileInfo; +class VersionTuple; struct PCHPredefinesBlock { /// \brief The file ID for this predefines buffer in a PCH file. @@ -213,6 +214,10 @@ class ASTReader /// \brief The AST consumer. ASTConsumer *Consumer; + /// \brief AST buffers for chained PCHs created and stored in memory. + /// First (not depending on another) PCH in chain is in front. + std::vector ASTBuffers; + /// \brief Information that is needed for every module. struct PerFileData { PerFileData(ASTFileType Ty); @@ -806,7 +811,9 @@ class ASTReader /// /// This routine should only be used for fatal errors that have to /// do with non-routine failures (e.g., corrupted AST file). - void Error(const char *Msg); + void Error(llvm::StringRef Msg); + void Error(unsigned DiagID, llvm::StringRef Arg1 = llvm::StringRef(), + llvm::StringRef Arg2 = llvm::StringRef()); ASTReader(const ASTReader&); // do not implement ASTReader &operator=(const ASTReader &); // do not implement @@ -886,6 +893,13 @@ class ASTReader /// \brief Sets and initializes the given Context. void InitializeContext(ASTContext &Context); + /// \brief Set AST buffers for chained PCHs created and stored in memory. + /// First (not depending on another) PCH in chain is first in array. + void setASTMemoryBuffers(llvm::MemoryBuffer **bufs, unsigned numBufs) { + ASTBuffers.clear(); + ASTBuffers.insert(ASTBuffers.begin(), bufs, bufs + numBufs); + } + /// \brief Retrieve the name of the named (primary) AST file const std::string &getFileName() const { return Chain[0]->FileName; } @@ -1052,6 +1066,10 @@ class ASTReader /// \brief Print some statistics about AST usage. virtual void PrintStats(); + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; + /// \brief Initialize the semantic source with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. @@ -1108,7 +1126,7 @@ class ASTReader } /// \brief Read the source location entry with index ID. - virtual void ReadSLocEntry(unsigned ID); + virtual bool ReadSLocEntry(unsigned ID); Selector DecodeSelector(unsigned Idx); @@ -1197,6 +1215,9 @@ class ASTReader // \brief Read a string std::string ReadString(const RecordData &Record, unsigned &Idx); + /// \brief Read a version tuple. + VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx); + CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx); /// \brief Reads attributes from the current stream position. diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h index 04ad93fa7c1a..1a79b31d26b4 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h @@ -56,6 +56,7 @@ class Sema; class SourceManager; class SwitchCase; class TargetInfo; +class VersionTuple; /// \brief Writes an AST file containing the contents of a translation unit. /// @@ -322,6 +323,7 @@ class ASTWriter : public ASTDeserializationListener, void WriteHeaderSearch(HeaderSearch &HS, const char* isysroot); void WritePreprocessorDetail(PreprocessingRecord &PPRec); void WritePragmaDiagnosticMappings(const Diagnostic &Diag); + void WriteCXXBaseSpecifiersOffsets(); void WriteType(QualType T); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); @@ -513,6 +515,9 @@ class ASTWriter : public ASTDeserializationListener, /// \brief Add a string to the given record. void AddString(llvm::StringRef Str, RecordDataImpl &Record); + /// \brief Add a version tuple to the given record + void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record); + /// \brief Mark a declaration context as needing an update. void AddUpdatedDeclContext(const DeclContext *DC) { UpdatedDeclContexts.insert(DC); @@ -581,6 +586,10 @@ class ASTWriter : public ASTDeserializationListener, virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D); virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D); + virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D); + virtual void CompletedImplicitDefinition(const FunctionDecl *D); + virtual void StaticDataMemberInstantiated(const VarDecl *D); }; /// \brief AST and semantic-analysis consumer that generates a diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ChainedIncludesSource.h b/contrib/llvm/tools/clang/include/clang/Serialization/ChainedIncludesSource.h new file mode 100644 index 000000000000..0c3e86faf414 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ChainedIncludesSource.h @@ -0,0 +1,76 @@ +//===- ChainedIncludesSource.h - Chained PCHs in Memory ---------*- 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 ChainedIncludesSource class, which converts headers +// to chained PCHs in memory, mainly used for testing. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SERIALIZATION_CHAINEDINCLUDESSOURCE_H +#define LLVM_CLANG_SERIALIZATION_CHAINEDINCLUDESSOURCE_H + +#include "clang/Sema/ExternalSemaSource.h" +#include + +namespace clang { + class CompilerInstance; + +class ChainedIncludesSource : public ExternalSemaSource { +public: + virtual ~ChainedIncludesSource(); + + static ChainedIncludesSource *create(CompilerInstance &CI); + +private: + ExternalSemaSource &getFinalReader() const { return *FinalReader; } + + std::vector CIs; + llvm::OwningPtr FinalReader; + + +protected: + +//===----------------------------------------------------------------------===// +// ExternalASTSource interface. +//===----------------------------------------------------------------------===// + + virtual Decl *GetExternalDecl(uint32_t ID); + virtual Selector GetExternalSelector(uint32_t ID); + virtual uint32_t GetNumExternalSelectors(); + virtual Stmt *GetExternalDeclStmt(uint64_t Offset); + virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); + virtual DeclContextLookupResult + FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); + virtual void MaterializeVisibleDecls(const DeclContext *DC); + virtual bool FindExternalLexicalDecls(const DeclContext *DC, + bool (*isKindWeWant)(Decl::Kind), + llvm::SmallVectorImpl &Result); + virtual void CompleteType(TagDecl *Tag); + virtual void CompleteType(ObjCInterfaceDecl *Class); + virtual void StartedDeserializing(); + virtual void FinishedDeserializing(); + virtual void StartTranslationUnit(ASTConsumer *Consumer); + virtual void PrintStats(); + + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; + +//===----------------------------------------------------------------------===// +// ExternalSemaSource interface. +//===----------------------------------------------------------------------===// + + virtual void InitializeSema(Sema &S); + virtual void ForgetSema(); + virtual std::pair ReadMethodPool(Selector Sel); + virtual bool LookupUnqualified(LookupResult &R, Scope *S); +}; + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td index e452ccfb6ceb..11f1e5d4bd51 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td @@ -11,18 +11,19 @@ // //===----------------------------------------------------------------------===// -class Package { - string PackageName = name; - bit Hidden = 0; - Package ParentPackage; -} -class InPackage { Package ParentPackage = P; } - class CheckerGroup { string GroupName = name; } class InGroup { CheckerGroup Group = G; } +class Package { + string PackageName = name; + bit Hidden = 0; + Package ParentPackage; + CheckerGroup Group; +} +class InPackage { Package ParentPackage = P; } + // All checkers are an indirect subclass of this. class Checker { string CheckerName = name; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h index afba12dc0620..2a3d43e22325 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h @@ -39,8 +39,6 @@ class ExprEngine; TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled, const LangOptions& lopts); -void RegisterExperimentalChecks(ExprEngine &Eng); - void RegisterCallInliner(ExprEngine &Eng); } // end GR namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 93d795831d3c..3acbcd685bc0 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -126,7 +126,7 @@ class BugReport : public BugReporterVisitor { /// getLocation - Return the "definitive" location of the reported bug. /// While a bug can span an entire path, usually there is a specific - /// location that can be used to identify where the key issue occured. + /// location that can be used to identify where the key issue occurred. /// This location is used by clients rendering diagnostics. virtual SourceLocation getLocation() const; @@ -219,6 +219,18 @@ class RangedBugReport : public BugReport { virtual std::pair getRanges() const { return std::make_pair(Ranges.begin(), Ranges.end()); } + + virtual void Profile(llvm::FoldingSetNodeID& hash) const { + BugReport::Profile(hash); + for (llvm::SmallVectorImpl::const_iterator I = + Ranges.begin(), E = Ranges.end(); I != E; ++I) { + const SourceRange range = *I; + if (!range.isValid()) + continue; + hash.AddInteger(range.getBegin().getRawEncoding()); + hash.AddInteger(range.getEnd().getRawEncoding()); + } + } }; class EnhancedBugReport : public RangedBugReport { diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h similarity index 69% rename from contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h rename to contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h index e080d190ab75..8c2ffc690887 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h @@ -1,4 +1,4 @@ -//== CheckerV2.h - Registration mechanism for checkers -----------*- C++ -*--=// +//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,15 @@ // //===----------------------------------------------------------------------===// // -// This file defines CheckerV2, used to create and register checkers. +// This file defines Checker, used to create and register checkers. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SA_CORE_CHECKERV2 -#define LLVM_CLANG_SA_CORE_CHECKERV2 +#ifndef LLVM_CLANG_SA_CORE_CHECKER +#define LLVM_CLANG_SA_CORE_CHECKER #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/Support/Casting.h" namespace clang { @@ -145,6 +146,21 @@ class Location { } }; +class Bind { + template + static void _checkBind(void *checker, const SVal &location, const SVal &val, + CheckerContext &C) { + ((const CHECKER *)checker)->checkBind(location, val, C); + } + +public: + template + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForBind( + CheckerManager::CheckBindFunc(checker, _checkBind)); + } +}; + class EndAnalysis { template static void _checkEndAnalysis(void *checker, ExplodedGraph &G, @@ -175,6 +191,22 @@ class EndPath { } }; +class BranchCondition { + template + static void _checkBranchCondition(void *checker, const Stmt *condition, + BranchNodeBuilder &B, ExprEngine &Eng) { + ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng); + } + +public: + template + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForBranchCondition( + CheckerManager::CheckBranchConditionFunc(checker, + _checkBranchCondition)); + } +}; + class LiveSymbols { template static void _checkLiveSymbols(void *checker, const GRState *state, @@ -228,10 +260,39 @@ class RegionChanges { } }; +template +class Event { + template + static void _checkEvent(void *checker, const void *event) { + ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); + } +public: + template + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerListenerForEvent( + CheckerManager::CheckEventFunc(checker, _checkEvent)); + } +}; + } // end check namespace namespace eval { +class Assume { + template + static const GRState *_evalAssume(void *checker, const GRState *state, + const SVal &cond, bool assumption) { + return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); + } + +public: + template + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEvalAssume( + CheckerManager::EvalAssumeFunc(checker, _evalAssume)); + } +}; + class Call { template static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { @@ -254,25 +315,58 @@ template -class CheckerV2 { +class Checker; + +template <> +class Checker { +public: + static void _register(void *checker, CheckerManager &mgr) { } +}; + +template +class Checker + : public CHECK1, + public Checker { public: template static void _register(CHECKER *checker, CheckerManager &mgr) { CHECK1::_register(checker, mgr); - CHECK2::_register(checker, mgr); - CHECK3::_register(checker, mgr); - CHECK4::_register(checker, mgr); - CHECK5::_register(checker, mgr); - CHECK6::_register(checker, mgr); - CHECK7::_register(checker, mgr); - CHECK8::_register(checker, mgr); - CHECK9::_register(checker, mgr); - CHECK10::_register(checker, mgr); - CHECK11::_register(checker, mgr); - CHECK12::_register(checker, mgr); + Checker::_register(checker, mgr); } }; +template +class EventDispatcher { + CheckerManager *Mgr; +public: + EventDispatcher() : Mgr(0) { } + + template + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerDispatcherForEvent(); + static_cast *>(checker)->Mgr = &mgr; + } + + void dispatchEvent(const EVENT &event) const { + Mgr->_dispatchEvent(event); + } +}; + +/// \brief We dereferenced a location that may be null. +struct ImplicitNullDerefEvent { + SVal Location; + bool IsLoad; + ExplodedNode *SinkNode; + BugReporter *BR; +}; + } // end ento namespace } // end clang namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h index 276819549d1a..92ec0388e500 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -37,6 +37,7 @@ namespace ento { class ExplodedGraph; class GRState; class EndOfFunctionNodeBuilder; + class BranchNodeBuilder; class MemRegion; class SymbolReaper; @@ -46,47 +47,46 @@ class GraphExpander { virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0; }; -struct VoidCheckerFnParm {}; -template -class CheckerFn { - typedef void (*Func)(void *, P1, P2, P3, P4); +template class CheckerFn; + +template +class CheckerFn { + typedef RET (*Func)(void *, P1, P2, P3); Func Fn; public: void *Checker; CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } - void operator()(P1 p1, P2 p2, P3 p3, P4 p4) { Fn(Checker, p1, p2, p3, p4); } + RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); } }; -template -class CheckerFn { - typedef void (*Func)(void *, P1, P2, P3); +template +class CheckerFn { + typedef RET (*Func)(void *, P1, P2); Func Fn; public: void *Checker; CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } - void operator()(P1 p1, P2 p2, P3 p3) { Fn(Checker, p1, p2, p3); } + RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); } }; -template -class CheckerFn { - typedef void (*Func)(void *, P1, P2); +template +class CheckerFn { + typedef RET (*Func)(void *, P1); Func Fn; public: void *Checker; CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } - void operator()(P1 p1, P2 p2) { Fn(Checker, p1, p2); } + RET operator()(P1 p1) const { return Fn(Checker, p1); } }; -template <> -class CheckerFn { - typedef void (*Func)(void *); +template +class CheckerFn { + typedef RET (*Func)(void *); Func Fn; public: void *Checker; CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } - void operator()() { Fn(Checker); } + RET operator()() const { return Fn(Checker); } }; class CheckerManager { @@ -96,21 +96,35 @@ class CheckerManager { CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { } ~CheckerManager(); + bool hasPathSensitiveCheckers() const; + + void finishedCheckerRegistration(); + const LangOptions &getLangOptions() const { return LangOpts; } typedef void *CheckerRef; - typedef CheckerFn<> CheckerDtor; + typedef void *CheckerTag; + typedef CheckerFn CheckerDtor; //===----------------------------------------------------------------------===// // registerChecker //===----------------------------------------------------------------------===// /// \brief Used to register checkers. + /// + /// \returns a pointer to the checker object. template - void registerChecker() { + CHECKER *registerChecker() { + CheckerTag tag = getTag(); + CheckerRef &ref = CheckerTags[tag]; + if (ref) + return static_cast(ref); // already registered. + CHECKER *checker = new CHECKER(); CheckerDtors.push_back(CheckerDtor(checker, destruct)); CHECKER::_register(checker, *this); + ref = checker; + return checker; } //===----------------------------------------------------------------------===// @@ -179,6 +193,12 @@ class CheckerManager { const Stmt *S, ExprEngine &Eng); + /// \brief Run checkers for binding of a value to a location. + void runCheckersForBind(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + SVal location, SVal val, + const Stmt *S, ExprEngine &Eng); + /// \brief Run checkers for end of analysis. void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng); @@ -186,6 +206,10 @@ class CheckerManager { /// \brief Run checkers for end of path. void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng); + /// \brief Run checkers for branch condition. + void runCheckersForBranchCondition(const Stmt *condition, + BranchNodeBuilder &B, ExprEngine &Eng); + /// \brief Run checkers for live symbols. void runCheckersForLiveSymbols(const GRState *state, SymbolReaper &SymReaper); @@ -204,6 +228,10 @@ class CheckerManager { const MemRegion * const *Begin, const MemRegion * const *End); + /// \brief Run checkers for handling assumptions on symbolic values. + const GRState *runCheckersForEvalAssume(const GRState *state, + SVal Cond, bool Assumption); + /// \brief Run checkers for evaluating a call. void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, @@ -217,9 +245,8 @@ class CheckerManager { // Functions used by the registration mechanism, checkers should not touch // these directly. - typedef CheckerFn + typedef CheckerFn CheckDeclFunc; - typedef CheckerFn CheckStmtFunc; typedef bool (*HandlesDeclFunc)(const Decl *D); void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); @@ -230,14 +257,44 @@ class CheckerManager { // Internal registration functions for path-sensitive checking. //===----------------------------------------------------------------------===// - typedef CheckerFn CheckObjCMessageFunc; - typedef CheckerFn + typedef CheckerFn CheckStmtFunc; + + typedef CheckerFn + CheckObjCMessageFunc; + + typedef CheckerFn CheckLocationFunc; - typedef CheckerFn + + typedef CheckerFn CheckBindFunc; + + typedef CheckerFn CheckEndAnalysisFunc; - typedef CheckerFn CheckEndPathFunc; - typedef CheckerFn CheckDeadSymbolsFunc; - typedef CheckerFn CheckLiveSymbolsFunc; + + typedef CheckerFn + CheckEndPathFunc; + + typedef CheckerFn + CheckBranchConditionFunc; + + typedef CheckerFn + CheckDeadSymbolsFunc; + + typedef CheckerFn CheckLiveSymbolsFunc; + + typedef CheckerFn + CheckRegionChangesFunc; + + typedef CheckerFn WantsRegionChangeUpdateFunc; + + typedef CheckerFn + EvalAssumeFunc; + + typedef CheckerFn + EvalCallFunc; typedef bool (*HandlesStmtFunc)(const Stmt *D); void _registerForPreStmt(CheckStmtFunc checkfn, @@ -250,57 +307,54 @@ class CheckerManager { void _registerForLocation(CheckLocationFunc checkfn); + void _registerForBind(CheckBindFunc checkfn); + void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); void _registerForEndPath(CheckEndPathFunc checkfn); + void _registerForBranchCondition(CheckBranchConditionFunc checkfn); + void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); - class CheckRegionChangesFunc { - typedef const GRState * (*Func)(void *, const GRState *, - const MemRegion * const *, - const MemRegion * const *); - Func Fn; - public: - void *Checker; - CheckRegionChangesFunc(void *checker, Func fn) : Fn(fn), Checker(checker) {} - const GRState *operator()(const GRState *state, - const MemRegion * const *begin, - const MemRegion * const *end) { - return Fn(Checker, state, begin, end); - } - }; - - class WantsRegionChangeUpdateFunc { - typedef bool (*Func)(void *, const GRState *); - Func Fn; - public: - void *Checker; - WantsRegionChangeUpdateFunc(void *checker, Func fn) - : Fn(fn), Checker(checker) { } - bool operator()(const GRState *state) { - return Fn(Checker, state); - } - }; - void _registerForRegionChanges(CheckRegionChangesFunc checkfn, WantsRegionChangeUpdateFunc wantUpdateFn); - class EvalCallFunc { - typedef bool (*Func)(void *, const CallExpr *, CheckerContext &); - Func Fn; - public: - void *Checker; - EvalCallFunc(void *checker, Func fn) : Fn(fn), Checker(checker) { } - bool operator()(const CallExpr *CE, CheckerContext &C) { - return Fn(Checker, CE, C); - } - }; + void _registerForEvalAssume(EvalAssumeFunc checkfn); void _registerForEvalCall(EvalCallFunc checkfn); +//===----------------------------------------------------------------------===// +// Internal registration functions for events. +//===----------------------------------------------------------------------===// + + typedef void *EventTag; + typedef CheckerFn CheckEventFunc; + + template + void _registerListenerForEvent(CheckEventFunc checkfn) { + EventInfo &info = Events[getTag()]; + info.Checkers.push_back(checkfn); + } + + template + void _registerDispatcherForEvent() { + EventInfo &info = Events[getTag()]; + info.HasDispatcher = true; + } + + template + void _dispatchEvent(const EVENT &event) const { + EventsTy::const_iterator I = Events.find(getTag()); + if (I == Events.end()) + return; + const EventInfo &info = I->second; + for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i) + info.Checkers[i](&event); + } + //===----------------------------------------------------------------------===// // Implementation details. //===----------------------------------------------------------------------===// @@ -309,6 +363,11 @@ class CheckerManager { template static void destruct(void *obj) { delete static_cast(obj); } + template + static void *getTag() { static int tag; return &tag; } + + llvm::DenseMap CheckerTags; + std::vector CheckerDtors; struct DeclCheckerInfo { @@ -365,10 +424,14 @@ class CheckerManager { std::vector LocationCheckers; + std::vector BindCheckers; + std::vector EndAnalysisCheckers; std::vector EndPathCheckers; + std::vector BranchConditionCheckers; + std::vector LiveSymbolsCheckers; std::vector DeadSymbolsCheckers; @@ -379,7 +442,18 @@ class CheckerManager { }; std::vector RegionChangesCheckers; + std::vector EvalAssumeCheckers; + std::vector EvalCallCheckers; + + struct EventInfo { + llvm::SmallVector Checkers; + bool HasDispatcher; + EventInfo() : HasDispatcher(false) { } + }; + + typedef llvm::DenseMap EventsTy; + EventsTy Events; }; } // end ento namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h index 40b838e75886..b8aaaa1a04c0 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h @@ -15,7 +15,6 @@ #define LLVM_CLANG_SA_CORE_CHECKERPROVIDER_H #include "llvm/ADT/StringRef.h" -#include namespace llvm { class raw_ostream; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h index 2713e31fc0d1..d02228fa30dd 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H -#define LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLiENTS_H +#define LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H #include diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index a4327e127f5f..65fbfcc912f9 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -16,6 +16,7 @@ #ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H #define LLVM_CLANG_GR_BASICVALUEFACTORY_H +#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/AST/ASTContext.h" #include "llvm/ADT/FoldingSet.h" @@ -47,16 +48,17 @@ class CompoundValData : public llvm::FoldingSetNode { }; class LazyCompoundValData : public llvm::FoldingSetNode { - const void *store; + StoreRef store; const TypedRegion *region; public: - LazyCompoundValData(const void *st, const TypedRegion *r) + LazyCompoundValData(const StoreRef &st, const TypedRegion *r) : store(st), region(r) {} - const void *getStore() const { return store; } + const void *getStore() const { return store.getStore(); } const TypedRegion *getRegion() const { return region; } - static void Profile(llvm::FoldingSetNodeID& ID, const void *store, + static void Profile(llvm::FoldingSetNodeID& ID, + const StoreRef &store, const TypedRegion *region); void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); } @@ -170,7 +172,7 @@ class BasicValueFactory { const CompoundValData *getCompoundValData(QualType T, llvm::ImmutableList Vals); - const LazyCompoundValData *getLazyCompoundValData(const void *store, + const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store, const TypedRegion *region); llvm::ImmutableList getEmptySValList() { diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h deleted file mode 100644 index 627bc0ab3516..000000000000 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h +++ /dev/null @@ -1,166 +0,0 @@ -//== Checker.h - Abstract interface for checkers -----------------*- 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 Checker and CheckerVisitor, classes used for creating -// domain-specific checks. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_GR_CHECKER -#define LLVM_CLANG_GR_CHECKER - -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" - -//===----------------------------------------------------------------------===// -// Checker interface. -//===----------------------------------------------------------------------===// - -namespace clang { - -namespace ento { - -class Checker { -private: - friend class ExprEngine; - - // FIXME: Remove the 'tag' option. - void GR_Visit(ExplodedNodeSet &Dst, - StmtNodeBuilder &Builder, - ExprEngine &Eng, - const Stmt *S, - ExplodedNode *Pred, void *tag, bool isPrevisit, - bool& respondsToCallback) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, - isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind, &respondsToCallback, S); - if (isPrevisit) - _PreVisit(C, S); - else - _PostVisit(C, S); - } - - void GR_visitObjCMessage(ExplodedNodeSet &Dst, - StmtNodeBuilder &Builder, - ExprEngine &Eng, - const ObjCMessage &msg, - ExplodedNode *Pred, void *tag, bool isPrevisit) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, - isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind, 0, msg.getOriginExpr()); - if (isPrevisit) - preVisitObjCMessage(C, msg); - else - postVisitObjCMessage(C, msg); - } - - bool GR_evalNilReceiver(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder, - ExprEngine &Eng, const ObjCMessage &msg, - ExplodedNode *Pred, const GRState *state, void *tag) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, - 0, msg.getOriginExpr(), state); - return evalNilReceiver(C, msg); - } - - bool GR_evalCallExpr(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder, - ExprEngine &Eng, const CallExpr *CE, - ExplodedNode *Pred, void *tag) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, - 0, CE); - return evalCallExpr(C, CE); - } - - // FIXME: Remove the 'tag' option. - void GR_VisitBind(ExplodedNodeSet &Dst, - StmtNodeBuilder &Builder, ExprEngine &Eng, - const Stmt *StoreE, ExplodedNode *Pred, void *tag, - SVal location, SVal val, - bool isPrevisit) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, - isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind, 0, StoreE); - assert(isPrevisit && "Only previsit supported for now."); - PreVisitBind(C, StoreE, location, val); - } - - // FIXME: Remove the 'tag' option. - void GR_visitLocation(ExplodedNodeSet &Dst, - StmtNodeBuilder &Builder, - ExprEngine &Eng, - const Stmt *S, - ExplodedNode *Pred, const GRState *state, - SVal location, - void *tag, bool isLoad) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, - isLoad ? ProgramPoint::PreLoadKind : - ProgramPoint::PreStoreKind, 0, S, state); - visitLocation(C, S, location, isLoad); - } - - void GR_evalDeadSymbols(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder, - ExprEngine &Eng, const Stmt *S, ExplodedNode *Pred, - SymbolReaper &SymReaper, void *tag) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, - ProgramPoint::PostPurgeDeadSymbolsKind, 0, S); - evalDeadSymbols(C, SymReaper); - } - -public: - virtual ~Checker(); - virtual void _PreVisit(CheckerContext &C, const Stmt *S) {} - virtual void _PostVisit(CheckerContext &C, const Stmt *S) {} - virtual void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {} - virtual void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {} - virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location, - bool isLoad) {} - virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE, - SVal location, SVal val) {} - virtual void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {} - virtual void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, - ExprEngine &Eng) {} - - virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {} - - virtual void VisitBranchCondition(BranchNodeBuilder &Builder, - ExprEngine &Eng, - const Stmt *Condition, void *tag) {} - - virtual bool evalNilReceiver(CheckerContext &C, ObjCMessage msg) { - return false; - } - - virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE) { - return false; - } - - virtual const GRState *evalAssume(const GRState *state, SVal Cond, - bool Assumption, bool *respondsToCallback) { - *respondsToCallback = false; - return state; - } - - virtual bool wantsRegionChangeUpdate(const GRState *state) { return false; } - - virtual const GRState *EvalRegionChanges(const GRState *state, - const MemRegion * const *Begin, - const MemRegion * const *End, - bool *respondsToCallback) { - *respondsToCallback = false; - return state; - } - - virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, - ExprEngine &Eng) {} -}; - -} // end GR namespace - -} // end clang namespace - -#endif - diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def deleted file mode 100644 index 9b3c263e7d53..000000000000 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def +++ /dev/null @@ -1,48 +0,0 @@ -//===-- CheckerVisitor.def - Metadata for CheckerVisitor ----------------*-===// -// -// 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 AST nodes accepted by the CheckerVisitor class. -// -//===---------------------------------------------------------------------===// - -#ifndef PREVISIT -#define PREVISIT(NODE, FALLBACK) -#endif - -#ifndef POSTVISIT -#define POSTVISIT(NODE, FALLBACK) -#endif - -PREVISIT(ArraySubscriptExpr, Stmt) -PREVISIT(BinaryOperator, Stmt) -PREVISIT(CallExpr, GenericCall) -PREVISIT(CompoundAssignOperator, BinaryOperator) -PREVISIT(CStyleCastExpr, CastExpr) -PREVISIT(CXXConstCastExpr, CastExpr) -PREVISIT(CXXDynamicCastExpr, CastExpr) -PREVISIT(CXXFunctionalCastExpr, CastExpr) -PREVISIT(CXXOperatorCallExpr, GenericCall) -PREVISIT(CXXMemberCallExpr, GenericCall) -PREVISIT(CXXReinterpretCastExpr, CastExpr) -PREVISIT(CXXStaticCastExpr, CastExpr) -PREVISIT(DeclStmt, Stmt) -PREVISIT(ImplicitCastExpr, CastExpr) -PREVISIT(ObjCAtSynchronizedStmt, Stmt) -PREVISIT(ReturnStmt, Stmt) - -POSTVISIT(BlockExpr, Stmt) -POSTVISIT(BinaryOperator, Stmt) -POSTVISIT(CallExpr, GenericCall) -POSTVISIT(CompoundAssignOperator, BinaryOperator) -POSTVISIT(CXXOperatorCallExpr, GenericCall) -POSTVISIT(CXXMemberCallExpr, GenericCall) -POSTVISIT(ObjCIvarRefExpr, Stmt) - -#undef PREVISIT -#undef POSTVISIT diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h deleted file mode 100644 index dc76c9604741..000000000000 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h +++ /dev/null @@ -1,103 +0,0 @@ -//== CheckerVisitor.h - Abstract visitor for checkers ------------*- 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 CheckerVisitor. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_GR_CHECKERVISITOR -#define LLVM_CLANG_GR_CHECKERVISITOR -#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" - -namespace clang { - -namespace ento { - -//===----------------------------------------------------------------------===// -// Checker visitor interface. Used by subclasses of Checker to specify their -// own checker visitor logic. -//===----------------------------------------------------------------------===// - -/// CheckerVisitor - This class implements a simple visitor for Stmt subclasses. -/// Since Expr derives from Stmt, this also includes support for visiting Exprs. -template -class CheckerVisitor : public Checker { -public: - virtual void _PreVisit(CheckerContext &C, const Stmt *S) { - PreVisit(C, S); - } - - virtual void _PostVisit(CheckerContext &C, const Stmt *S) { - PostVisit(C, S); - } - - void PreVisit(CheckerContext &C, const Stmt *S) { - switch (S->getStmtClass()) { - default: - assert(false && "Unsupport statement."); - return; - -#define PREVISIT(NAME, FALLBACK) \ -case Stmt::NAME ## Class:\ -static_cast(this)->PreVisit ## NAME(C,static_cast(S));\ -break; -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def" - } - } - - void PostVisit(CheckerContext &C, const Stmt *S) { - switch (S->getStmtClass()) { - default: - assert(false && "Unsupport statement."); - return; - -#define POSTVISIT(NAME, FALLBACK) \ -case Stmt::NAME ## Class:\ -static_cast(this)->\ -PostVisit ## NAME(C,static_cast(S));\ -break; -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def" - } - } - - void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE) { - static_cast(this)->PreVisitStmt(C, CE); - } - void PostVisitGenericCall(CheckerContext &C, const CallExpr *CE) { - static_cast(this)->PostVisitStmt(C, CE); - } - - void PreVisitStmt(CheckerContext &C, const Stmt *S) { - *C.respondsToCallback = false; - } - - void PostVisitStmt(CheckerContext &C, const Stmt *S) { - *C.respondsToCallback = false; - } - - void PreVisitCastExpr(CheckerContext &C, const CastExpr *E) { - static_cast(this)->PreVisitStmt(C, E); - } - -#define PREVISIT(NAME, FALLBACK) \ -void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\ - static_cast(this)->PreVisit ## FALLBACK(C, S);\ -} -#define POSTVISIT(NAME, FALLBACK) \ -void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\ - static_cast(this)->PostVisit ## FALLBACK(C, S);\ -} -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def" -}; - -} // end GR namespace - -} // end clang namespace - -#endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 25c644734232..2c1d07c59b68 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -47,7 +47,11 @@ class CoreEngine { public: typedef std::vector > + BlocksExhausted; + + typedef std::vector > BlocksAborted; + private: SubEngine& SubEng; @@ -67,6 +71,10 @@ class CoreEngine { /// The locations where we stopped doing work because we visited a location /// too many times. + BlocksExhausted blocksExhausted; + + /// The locations where we stopped because the engine aborted analysis, + /// usually because it could not reason about something. BlocksAborted blocksAborted; void generateNode(const ProgramPoint& Loc, const GRState* State, @@ -110,7 +118,7 @@ class CoreEngine { ExplodedGraph& getGraph() { return *G.get(); } /// takeGraph - Returns the exploded graph. Ownership of the graph is - /// transfered to the caller. + /// transferred to the caller. ExplodedGraph* takeGraph() { return G.take(); } /// ExecuteWorkList - Run the worklist algorithm for a maximum number of @@ -123,10 +131,25 @@ class CoreEngine { // Functions for external checking of whether we have unfinished work bool wasBlockAborted() const { return !blocksAborted.empty(); } - bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); } + bool wasBlocksExhausted() const { return !blocksExhausted.empty(); } + bool hasWorkRemaining() const { return wasBlocksExhausted() || + WList->hasWork() || + wasBlockAborted(); } + /// Inform the CoreEngine that a basic block was aborted because + /// it could not be completely analyzed. + void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) { + blocksAborted.push_back(std::make_pair(block, node)); + } + WorkList *getWorkList() const { return WList; } + BlocksExhausted::const_iterator blocks_exhausted_begin() const { + return blocksExhausted.begin(); + } + BlocksExhausted::const_iterator blocks_exhausted_end() const { + return blocksExhausted.end(); + } BlocksAborted::const_iterator blocks_aborted_begin() const { return blocksAborted.begin(); } @@ -219,11 +242,8 @@ class StmtNodeBuilder { /// getStmt - Return the current block-level expression associated with /// this builder. const Stmt* getStmt() const { - CFGStmt CS = B[Idx].getAs(); - if (CS) - return CS.getStmt(); - else - return 0; + const CFGStmt *CS = B[Idx].getAs(); + return CS ? CS->getStmt() : 0; } /// getBlock - Return the CFGBlock associated with the block-level expression @@ -287,6 +307,8 @@ class BranchNodeBuilder { BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} + ExplodedNode* generateNode(const Stmt *Condition, const GRState* State); + ExplodedNode* generateNode(const GRState* State, bool branch); const CFGBlock* getTargetBlock(bool branch) const { diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index 732a40cb2145..193056e6b030 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -51,9 +51,10 @@ class Environment { iterator end() const { return ExprBindings.end(); } - /// GetSVal - Fetches the current binding of the expression in the + /// getSVal - Fetches the current binding of the expression in the /// Environment. - SVal getSVal(const Stmt* Ex, SValBuilder& svalBuilder) const; + SVal getSVal(const Stmt* Ex, SValBuilder& svalBuilder, + bool useOnlyDirectBindings = false) const; /// Profile - Profile the contents of an Environment object for use /// in a FoldingSet. diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 16f54ee7468d..8cd743f68f56 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -34,7 +34,6 @@ class ObjCForCollectionStmt; namespace ento { class AnalysisManager; -class Checker; class ExprEngine : public SubEngine { AnalysisManager &AMgr; @@ -74,39 +73,6 @@ class ExprEngine : public SubEngine { Selector* NSExceptionInstanceRaiseSelectors; Selector RaiseSel; - enum CallbackKind { - PreVisitStmtCallback, - PostVisitStmtCallback, - processAssumeCallback, - EvalRegionChangesCallback - }; - - typedef uint32_t CallbackTag; - - /// GetCallbackTag - Create a tag for a certain kind of callback. The 'Sub' - /// argument can be used to differentiate callbacks that depend on another - /// value from a small set of possibilities, such as statement classes. - static inline CallbackTag GetCallbackTag(CallbackKind K, uint32_t Sub = 0) { - assert(Sub == ((Sub << 8) >> 8) && "Tag sub-kind must fit into 24 bits"); - return K | (Sub << 8); - } - - typedef llvm::DenseMap CheckerMap; - typedef std::vector > CheckersOrdered; - typedef llvm::DenseMap CheckersOrderedCache; - - /// A registration map from checker tag to the index into the - /// ordered checkers vector. - CheckerMap CheckerM; - - /// An ordered vector of checkers that are called when evaluating - /// various expressions and statements. - CheckersOrdered Checkers; - - /// A map used for caching the checkers that respond to the callback for - /// a particular callback tag. - CheckersOrderedCache COCache; - /// The BugReporter associated with this engine. It is important that /// this object be placed at the very end of member variables so that its /// destructor is called before the rest of the ExprEngine is destroyed. @@ -165,21 +131,6 @@ class ExprEngine : public SubEngine { ExplodedGraph& getGraph() { return G; } const ExplodedGraph& getGraph() const { return G; } - template - void registerCheck(CHECKER *check) { - unsigned entry = Checkers.size(); - void *tag = CHECKER::getTag(); - Checkers.push_back(std::make_pair(tag, check)); - CheckerM[tag] = entry; - } - - Checker *lookupChecker(void *tag) const; - - template - CHECKER *getChecker() const { - return static_cast(lookupChecker(CHECKER::getTag())); - } - /// processCFGElement - Called by CoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a CFG element. void processCFGElement(const CFGElement E, StmtNodeBuilder& builder); @@ -262,11 +213,9 @@ class ExprEngine : public SubEngine { const SymbolManager& getSymbolManager() const { return SymMgr; } // Functions for external checking of whether we have unfinished work - bool wasBlockAborted() const { return Engine.wasBlockAborted(); } + bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); } bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); } - bool hasWorkRemaining() const { - return wasBlockAborted() || Engine.getWorkList()->hasWork(); - } + bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); } const CoreEngine &getCoreEngine() const { return Engine; } @@ -281,27 +230,6 @@ class ExprEngine : public SubEngine { ProgramPoint::Kind K = ProgramPoint::PostStmtKind, const void *tag = 0); - /// CheckerVisit - Dispatcher for performing checker-specific logic - /// at specific statements. - void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, - CallbackKind Kind); - - void CheckerVisitObjCMessage(const ObjCMessage &msg, ExplodedNodeSet &Dst, - ExplodedNodeSet &Src, bool isPrevisit); - - bool CheckerEvalCall(const CallExpr *CE, - ExplodedNodeSet &Dst, - ExplodedNode *Pred); - - void CheckerEvalNilReceiver(const ObjCMessage &msg, - ExplodedNodeSet &Dst, - const GRState *state, - ExplodedNode *Pred); - - void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst, - ExplodedNodeSet &Src, SVal location, SVal val, - bool isPrevisit); - /// Visit - Transfer function logic for all statements. Dispatches to /// other functions that handle specific kinds of statements. void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst); @@ -334,10 +262,8 @@ class ExprEngine : public SubEngine { /// VisitCall - Transfer function for function calls. - void VisitCall(const CallExpr* CE, ExplodedNode* Pred, - CallExpr::const_arg_iterator AI, - CallExpr::const_arg_iterator AE, - ExplodedNodeSet& Dst); + void VisitCallExpr(const CallExpr* CE, ExplodedNode* Pred, + ExplodedNodeSet& Dst); /// VisitCast - Transfer function logic for all casts (implicit and explicit). void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, @@ -358,11 +284,6 @@ class ExprEngine : public SubEngine { /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose void VisitGuardedExpr(const Expr* Ex, const Expr* L, const Expr* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); - - /// VisitCondInit - Transfer function for handling the initialization - /// of a condition variable in an IfStmt, SwitchStmt, etc. - void VisitCondInit(const VarDecl *VD, const Stmt *S, ExplodedNode *Pred, - ExplodedNodeSet& Dst); void VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred, ExplodedNodeSet& Dst); @@ -409,9 +330,9 @@ class ExprEngine : public SubEngine { void VisitOffsetOfExpr(const OffsetOfExpr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst); - /// VisitSizeOfAlignOfExpr - Transfer function for sizeof. - void VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, ExplodedNode* Pred, - ExplodedNodeSet& Dst); + /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof. + void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr* Ex, + ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitUnaryOperator - Transfer function logic for unary operators. void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred, @@ -432,12 +353,6 @@ class ExprEngine : public SubEngine { const MemRegion *Dest, const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, - ExplodedNodeSet &Dst); - - void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C, - ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -463,12 +378,10 @@ class ExprEngine : public SubEngine { const FunctionProtoType *FnType, ExplodedNode *Pred, ExplodedNodeSet &Dst, bool FstArgAsLValue = false); - - /// Evaluate method call itself. Used for CXXMethodCallExpr and - /// CXXOperatorCallExpr. - void evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD, - const Expr *ThisExpr, ExplodedNode *Pred, - ExplodedNodeSet &Src, ExplodedNodeSet &Dst); + + /// Evaluate callee expression (for a function call). + void evalCallee(const CallExpr *callExpr, const ExplodedNodeSet &src, + ExplodedNodeSet &dest); /// evalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h index 37694da6573c..a957c897b92a 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h @@ -35,7 +35,6 @@ class ASTContext; namespace ento { class GRStateManager; -class Checker; typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&, SubEngine&); @@ -261,7 +260,7 @@ class GRState : public llvm::FoldingSetNode { const llvm::APSInt *getSymVal(SymbolRef sym) const; /// Returns the SVal bound to the statement 'S' in the state's environment. - SVal getSVal(const Stmt* S) const; + SVal getSVal(const Stmt* S, bool useOnlyDirectBindings = false) const; SVal getSValAsScalarOrLoc(const Stmt *Ex) const; @@ -274,8 +273,6 @@ class GRState : public llvm::FoldingSetNode { SVal getSValAsScalarOrLoc(const MemRegion *R) const; - const llvm::APSInt *getSymVal(SymbolRef sym); - bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const; bool scanReachableSymbols(const SVal *I, const SVal *E, @@ -627,10 +624,6 @@ class GRStateManager { // Out-of-line method definitions for GRState. //===----------------------------------------------------------------------===// -inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) { - return getStateManager().getSymVal(this, sym); -} - inline const VarRegion* GRState::getRegion(const VarDecl *D, const LocationContext *LC) const { return getStateManager().getRegionManager().getVarRegion(D, LC); @@ -690,14 +683,15 @@ inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const { return getStateManager().getSymVal(this, sym); } -inline SVal GRState::getSVal(const Stmt* Ex) const { - return Env.getSVal(Ex, *getStateManager().svalBuilder); +inline SVal GRState::getSVal(const Stmt* Ex, bool useOnlyDirectBindings) const{ + return Env.getSVal(Ex, *getStateManager().svalBuilder, + useOnlyDirectBindings); } inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const { if (const Expr *Ex = dyn_cast(S)) { QualType T = Ex->getType(); - if (Loc::isLocType(T) || T->isIntegerType()) + if (Ex->isLValue() || Loc::isLocType(T) || T->isIntegerType()) return getSVal(S); } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 8d19b5199274..db7a930b556e 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -769,7 +769,7 @@ class ObjCIvarRegion : public DeclRegion { } }; //===----------------------------------------------------------------------===// -// Auxillary data classes for use with MemRegions. +// Auxiliary data classes for use with MemRegions. //===----------------------------------------------------------------------===// class ElementRegion; @@ -960,7 +960,7 @@ class MemRegionManager { getCompoundLiteralRegion(const CompoundLiteralExpr* CL, const LocationContext *LC); - /// getCXXThisRegion - Retrieve the [artifical] region associated with the + /// getCXXThisRegion - Retrieve the [artificial] region associated with the /// parameter 'this'. const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy, const LocationContext *LC); diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h index 710fc6b84f9e..6d8fc89a4839 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h @@ -72,6 +72,8 @@ class ObjCMessage { return getType(ctx); } + ObjCMethodFamily getMethodFamily() const; + Selector getSelector() const; const Expr *getInstanceReceiver() const { @@ -169,14 +171,23 @@ class CallOrObjCMessage { const CallExpr *CallE; ObjCMessage Msg; const GRState *State; - public: CallOrObjCMessage(const CallExpr *callE, const GRState *state) - : CallE(callE), State(state) { } + : CallE(callE), State(state) {} CallOrObjCMessage(const ObjCMessage &msg, const GRState *state) - : CallE(0), Msg(msg), State(state) { } + : CallE(0), Msg(msg), State(state) {} QualType getResultType(ASTContext &ctx) const; + + bool isFunctionCall() const { + return (bool) CallE; + } + + bool isCXXCall() const { + return CallE && isa(CallE); + } + + SVal getCXXCallee() const; unsigned getNumArgs() const { if (CallE) return CallE->getNumArgs(); @@ -185,7 +196,8 @@ class CallOrObjCMessage { SVal getArgSVal(unsigned i) const { assert(i < getNumArgs()); - if (CallE) return State->getSVal(CallE->getArg(i)); + if (CallE) + return State->getSVal(CallE->getArg(i)); return Msg.getArgSVal(i, State); } @@ -193,13 +205,15 @@ class CallOrObjCMessage { const Expr *getArg(unsigned i) const { assert(i < getNumArgs()); - if (CallE) return CallE->getArg(i); + if (CallE) + return CallE->getArg(i); return Msg.getArgExpr(i); } SourceRange getArgSourceRange(unsigned i) const { assert(i < getNumArgs()); - if (CallE) return CallE->getArg(i)->getSourceRange(); + if (CallE) + return CallE->getArg(i)->getSourceRange(); return Msg.getArgSourceRange(i); } }; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index fc2b76e04a66..0f9e56aa2ff8 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -49,10 +49,10 @@ class SValBuilder { const unsigned ArrayIndexWidth; public: - // FIXME: Make these protected again one RegionStoreManager correctly - // handles loads from differening bound value types. - virtual SVal evalCastNL(NonLoc val, QualType castTy) = 0; - virtual SVal evalCastL(Loc val, QualType castTy) = 0; + // FIXME: Make these protected again once RegionStoreManager correctly + // handles loads from different bound value types. + virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy) = 0; + virtual SVal evalCastFromLoc(Loc val, QualType castTy) = 0; public: SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, @@ -66,30 +66,30 @@ class SValBuilder { virtual ~SValBuilder() {} - SVal evalCast(SVal V, QualType castTy, QualType originalType); + SVal evalCast(SVal val, QualType castTy, QualType originalType); virtual SVal evalMinus(NonLoc val) = 0; virtual SVal evalComplement(NonLoc val) = 0; - virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode Op, + virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy) = 0; - virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode Op, + virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode op, Loc lhs, Loc rhs, QualType resultTy) = 0; - virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode Op, + virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy) = 0; /// getKnownValue - evaluates a given SVal. If the SVal has only one possible /// (integer) value, that value is returned. Otherwise, returns NULL. - virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V) = 0; + virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal val) = 0; - SVal evalBinOp(const GRState *ST, BinaryOperator::Opcode Op, - SVal L, SVal R, QualType T); + SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op, + SVal lhs, SVal rhs, QualType type); - DefinedOrUnknownSVal evalEQ(const GRState *ST, DefinedOrUnknownSVal L, - DefinedOrUnknownSVal R); + DefinedOrUnknownSVal evalEQ(const GRState *state, DefinedOrUnknownSVal lhs, + DefinedOrUnknownSVal rhs); ASTContext &getContext() { return Context; } const ASTContext &getContext() const { return Context; } @@ -115,46 +115,48 @@ class SValBuilder { // Forwarding methods to SymbolManager. - const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T, - unsigned VisitCount, - const void* SymbolTag = 0) { - return SymMgr.getConjuredSymbol(E, T, VisitCount, SymbolTag); + const SymbolConjured* getConjuredSymbol(const Stmt* stmt, QualType type, + unsigned visitCount, + const void* symbolTag = 0) { + return SymMgr.getConjuredSymbol(stmt, type, visitCount, symbolTag); } - const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount, - const void* SymbolTag = 0) { - return SymMgr.getConjuredSymbol(E, VisitCount, SymbolTag); + const SymbolConjured* getConjuredSymbol(const Expr* expr, unsigned visitCount, + const void* symbolTag = 0) { + return SymMgr.getConjuredSymbol(expr, visitCount, symbolTag); } /// makeZeroVal - Construct an SVal representing '0' for the specified type. - DefinedOrUnknownSVal makeZeroVal(QualType T); + DefinedOrUnknownSVal makeZeroVal(QualType type); - /// getRegionValueSymbolVal - make a unique symbol for value of R. - DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedRegion *R); + /// getRegionValueSymbolVal - make a unique symbol for value of region. + DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedRegion *region); - DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, - const Expr *E, unsigned Count); - DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, - const Expr *E, QualType T, - unsigned Count); + DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag, + const Expr *expr, unsigned count); + DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag, + const Expr *expr, QualType type, + unsigned count); - DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, - const TypedRegion *R); + DefinedOrUnknownSVal getDerivedRegionValueSymbolVal( + SymbolRef parentSymbol, const TypedRegion *region); - DefinedSVal getMetadataSymbolVal(const void *SymbolTag, const MemRegion *MR, - const Expr *E, QualType T, unsigned Count); + DefinedSVal getMetadataSymbolVal( + const void *symbolTag, const MemRegion *region, + const Expr *expr, QualType type, unsigned count); - DefinedSVal getFunctionPointer(const FunctionDecl *FD); + DefinedSVal getFunctionPointer(const FunctionDecl *func); - DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy, - const LocationContext *LC); + DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy, + const LocationContext *locContext); - NonLoc makeCompoundVal(QualType T, llvm::ImmutableList Vals) { - return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); + NonLoc makeCompoundVal(QualType type, llvm::ImmutableList vals) { + return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals)); } - NonLoc makeLazyCompoundVal(const void *store, const TypedRegion *R) { - return nonloc::LazyCompoundVal(BasicVals.getLazyCompoundValData(store, R)); + NonLoc makeLazyCompoundVal(const StoreRef &store, const TypedRegion *region) { + return nonloc::LazyCompoundVal( + BasicVals.getLazyCompoundValData(store, region)); } NonLoc makeZeroArrayIndex() { @@ -165,60 +167,63 @@ class SValBuilder { return nonloc::ConcreteInt(BasicVals.getValue(idx, ArrayIndexTy)); } - SVal convertToArrayIndex(SVal V); + SVal convertToArrayIndex(SVal val); - nonloc::ConcreteInt makeIntVal(const IntegerLiteral* I) { - return nonloc::ConcreteInt(BasicVals.getValue(I->getValue(), - I->getType()->isUnsignedIntegerType())); + nonloc::ConcreteInt makeIntVal(const IntegerLiteral* integer) { + return nonloc::ConcreteInt( + BasicVals.getValue(integer->getValue(), + integer->getType()->isUnsignedIntegerType())); } - nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *E) { - return makeTruthVal(E->getValue()); + nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean) { + return makeTruthVal(boolean->getValue()); } - nonloc::ConcreteInt makeIntVal(const llvm::APSInt& V) { - return nonloc::ConcreteInt(BasicVals.getValue(V)); + nonloc::ConcreteInt makeIntVal(const llvm::APSInt& integer) { + return nonloc::ConcreteInt(BasicVals.getValue(integer)); } - loc::ConcreteInt makeIntLocVal(const llvm::APSInt &v) { - return loc::ConcreteInt(BasicVals.getValue(v)); + loc::ConcreteInt makeIntLocVal(const llvm::APSInt &integer) { + return loc::ConcreteInt(BasicVals.getValue(integer)); } - NonLoc makeIntVal(const llvm::APInt& V, bool isUnsigned) { - return nonloc::ConcreteInt(BasicVals.getValue(V, isUnsigned)); + NonLoc makeIntVal(const llvm::APInt& integer, bool isUnsigned) { + return nonloc::ConcreteInt(BasicVals.getValue(integer, isUnsigned)); } - DefinedSVal makeIntVal(uint64_t X, QualType T) { - if (Loc::isLocType(T)) - return loc::ConcreteInt(BasicVals.getValue(X, T)); + DefinedSVal makeIntVal(uint64_t integer, QualType type) { + if (Loc::isLocType(type)) + return loc::ConcreteInt(BasicVals.getValue(integer, type)); - return nonloc::ConcreteInt(BasicVals.getValue(X, T)); + return nonloc::ConcreteInt(BasicVals.getValue(integer, type)); } - NonLoc makeIntVal(uint64_t X, bool isUnsigned) { - return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned)); + NonLoc makeIntVal(uint64_t integer, bool isUnsigned) { + return nonloc::ConcreteInt(BasicVals.getIntValue(integer, isUnsigned)); } - NonLoc makeIntValWithPtrWidth(uint64_t X, bool isUnsigned) { - return nonloc::ConcreteInt(BasicVals.getIntWithPtrWidth(X, isUnsigned)); + NonLoc makeIntValWithPtrWidth(uint64_t integer, bool isUnsigned) { + return nonloc::ConcreteInt( + BasicVals.getIntWithPtrWidth(integer, isUnsigned)); } - NonLoc makeIntVal(uint64_t X, unsigned BitWidth, bool isUnsigned) { - return nonloc::ConcreteInt(BasicVals.getValue(X, BitWidth, isUnsigned)); + NonLoc makeIntVal(uint64_t integer, unsigned bitWidth, bool isUnsigned) { + return nonloc::ConcreteInt( + BasicVals.getValue(integer, bitWidth, isUnsigned)); } - NonLoc makeLocAsInteger(Loc V, unsigned Bits) { - return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(V, Bits)); + NonLoc makeLocAsInteger(Loc loc, unsigned bits) { + return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(loc, bits)); } NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt& rhs, QualType T); + const llvm::APSInt& rhs, QualType type); NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, - const SymExpr *rhs, QualType T); + const SymExpr *rhs, QualType type); - nonloc::ConcreteInt makeTruthVal(bool b, QualType T) { - return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T)); + nonloc::ConcreteInt makeTruthVal(bool b, QualType type) { + return nonloc::ConcreteInt(BasicVals.getTruthValue(b, type)); } nonloc::ConcreteInt makeTruthVal(bool b) { @@ -229,20 +234,20 @@ class SValBuilder { return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth()); } - Loc makeLoc(SymbolRef Sym) { - return loc::MemRegionVal(MemMgr.getSymbolicRegion(Sym)); + Loc makeLoc(SymbolRef sym) { + return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); } - Loc makeLoc(const MemRegion* R) { - return loc::MemRegionVal(R); + Loc makeLoc(const MemRegion* region) { + return loc::MemRegionVal(region); } - Loc makeLoc(const AddrLabelExpr *E) { - return loc::GotoLabel(E->getLabel()); + Loc makeLoc(const AddrLabelExpr *expr) { + return loc::GotoLabel(expr->getLabel()); } - Loc makeLoc(const llvm::APSInt& V) { - return loc::ConcreteInt(BasicVals.getValue(V)); + Loc makeLoc(const llvm::APSInt& integer) { + return loc::ConcreteInt(BasicVals.getValue(integer)); } }; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 0251311c27ae..21c6ae760cc8 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_GR_STORE_H #define LLVM_CLANG_GR_STORE_H +#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" #include "llvm/ADT/DenseSet.h" @@ -28,36 +29,10 @@ class StackFrameContext; namespace ento { -/// Store - This opaque type encapsulates an immutable mapping from -/// locations to values. At a high-level, it represents the symbolic -/// memory model. Different subclasses of StoreManager may choose -/// different types to represent the locations and values. -typedef const void* Store; - class GRState; class GRStateManager; class SubRegionMap; -class StoreManager; - -class StoreRef { - Store store; - StoreManager &mgr; -public: - StoreRef(Store, StoreManager &); - StoreRef(const StoreRef &); - StoreRef &operator=(StoreRef const &); - - bool operator==(const StoreRef &x) const { - assert(&mgr == &x.mgr); - return x.store == store; - } - bool operator!=(const StoreRef &x) const { return !operator==(x); } - ~StoreRef(); - - Store getStore() const { return store; } -}; - class StoreManager { protected: SValBuilder &svalBuilder; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h new file mode 100644 index 000000000000..0662eadc93c3 --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h @@ -0,0 +1,50 @@ +//== StoreRef.h - Smart pointer for store objects ---------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the type StoreRef. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_GR_STOREREF_H +#define LLVM_CLANG_GR_STOREREF_H + +#include + +namespace clang { +namespace ento { + +/// Store - This opaque type encapsulates an immutable mapping from +/// locations to values. At a high-level, it represents the symbolic +/// memory model. Different subclasses of StoreManager may choose +/// different types to represent the locations and values. +typedef const void* Store; + +class StoreManager; + +class StoreRef { + Store store; + StoreManager &mgr; +public: + StoreRef(Store, StoreManager &); + StoreRef(const StoreRef &); + StoreRef &operator=(StoreRef const &); + + bool operator==(const StoreRef &x) const { + assert(&mgr == &x.mgr); + return x.store == store; + } + bool operator!=(const StoreRef &x) const { return !operator==(x); } + + ~StoreRef(); + + Store getStore() const { return store; } +}; + +}} +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h new file mode 100644 index 000000000000..6ccccd0bff0c --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h @@ -0,0 +1,81 @@ +//===--- Tooling.h - Framework for standalone Clang tools -------*- 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 functions to run clang tools standalone instead +// of running them as a plugin. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TOOLING_H +#define LLVM_CLANG_TOOLING_TOOLING_H + +#include "llvm/ADT/StringRef.h" +#include +#include + +namespace clang { + +class FrontendAction; + +namespace tooling { + +/// \brief Runs (and deletes) the tool on 'Code' with the -fsynatx-only flag. +/// +/// \param ToolAction The action to run over the code. +/// \param Code C++ code. +/// +/// \return - True if 'ToolAction' was successfully executed. +bool RunSyntaxOnlyToolOnCode( + clang::FrontendAction *ToolAction, llvm::StringRef Code); + +/// \brief Runs (and deletes) the tool with the given Clang flags. +/// +/// \param ToolAction The action to run over the code. +/// \param Argc The number of elements in Argv. +/// \param Argv The command line arguments, including the path the binary +/// was started with (Argv[0]). +bool RunToolWithFlags( + clang::FrontendAction* ToolAction, int Argc, char *Argv[]); + +/// \brief Converts a vector into a vector suitable to pass +/// to main-style functions taking (int Argc, char *Argv[]). +std::vector CommandLineToArgv(const std::vector* Command); + +/// \brief Specifies the working directory and command of a compilation. +struct CompileCommand { + /// \brief The working directory the command was executed from. + std::string Directory; + + /// \brief The command line that was executed. + std::vector CommandLine; +}; + +/// \brief Looks up the compile command for 'FileName' in 'JsonDatabase'. +/// +/// \param FileName The path to an input file for which we want the compile +/// command line. If the 'JsonDatabase' was created by CMake, this must be +/// an absolute path inside the CMake source directory which does not have +/// symlinks resolved. +/// +/// \param JsonDatabase A JSON formatted list of compile commands. This lookup +/// command supports only a subset of the JSON standard as written by CMake. +/// +/// \param ErrorMessage If non-empty, an error occurred and 'ErrorMessage' will +/// be set to contain the error message. In this case CompileCommand will +/// contain an empty directory and command line. +/// +/// \see JsonCompileCommandLineDatabase +CompileCommand FindCompileArgsInJsonDatabase( + llvm::StringRef FileName, llvm::StringRef JsonDatabase, + std::string &ErrorMessage); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_TOOLING_H diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 9c2455034d68..8316ea68e9e4 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -107,7 +107,9 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( if (TemplateTypeParmDecl *TTP = dyn_cast(*P)) CanonParams.push_back( TemplateTypeParmDecl::Create(*this, getTranslationUnitDecl(), - SourceLocation(), TTP->getDepth(), + SourceLocation(), + SourceLocation(), + TTP->getDepth(), TTP->getIndex(), 0, false, TTP->isParameterPack())); else if (NonTypeTemplateParmDecl *NTTP @@ -125,7 +127,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( } Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(), - SourceLocation(), + SourceLocation(), + SourceLocation(), NTTP->getDepth(), NTTP->getPosition(), 0, T, @@ -135,7 +138,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( ExpandedTInfos.data()); } else { Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(), - SourceLocation(), + SourceLocation(), + SourceLocation(), NTTP->getDepth(), NTTP->getPosition(), 0, T, @@ -186,11 +190,28 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { return 0; } +static const LangAS::Map &getAddressSpaceMap(const TargetInfo &T, + const LangOptions &LOpts) { + if (LOpts.FakeAddressSpaceMap) { + // The fake address space map must have a distinct entry for each + // language-specific address space. + static const unsigned FakeAddrSpaceMap[] = { + 1, // opencl_global + 2, // opencl_local + 3 // opencl_constant + }; + return FakeAddrSpaceMap; + } else { + return T.getAddressSpaceMap(); + } +} + ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, unsigned size_reserve) : + FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), GlobalNestedNameSpecifier(0), IsInt128Installed(false), @@ -199,7 +220,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0), NullTypeSourceInfo(QualType()), - SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)), Target(t), + SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)), + AddrSpaceMap(getAddressSpaceMap(t, LOpts)), Target(t), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), @@ -353,7 +375,7 @@ void ASTContext::InitBuiltinTypes() { InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); if (LangOpts.CPlusPlus) { // C++ 3.9.1p5 - if (!LangOpts.ShortWChar) + if (TargetInfo::isTypeSigned(Target.getWCharType())) InitBuiltinType(WCharTy, BuiltinType::WChar_S); else // -fshort-wchar makes wchar_t be unsigned. InitBuiltinType(WCharTy, BuiltinType::WChar_U); @@ -380,6 +402,12 @@ void ASTContext::InitBuiltinTypes() { // Placeholder type for functions. InitBuiltinType(OverloadTy, BuiltinType::Overload); + // Placeholder type for bound members. + InitBuiltinType(BoundMemberTy, BuiltinType::BoundMember); + + // "any" type; useful for debugger-like clients. + InitBuiltinType(UnknownAnyTy, BuiltinType::UnknownAny); + // C99 6.2.5p11. FloatComplexTy = getComplexType(FloatTy); DoubleComplexTy = getComplexType(DoubleTy); @@ -429,7 +457,6 @@ void ASTContext::eraseDeclAttrs(const Decl *D) { } } - MemberSpecializationInfo * ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) { assert(Var->isStaticDataMember() && "Not a static data member"); @@ -509,6 +536,20 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, InstantiatedFromUnnamedFieldDecl[Inst] = Tmpl; } +bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const { + return (FD->isBitField() && LastFD && !LastFD->isBitField() && + FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0); + +} + +bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const { + return (FD->isBitField() && LastFD && LastFD->isBitField() && + FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0); + +} + ASTContext::overridden_cxx_method_iterator ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const { llvm::DenseMap::const_iterator Pos @@ -697,6 +738,7 @@ ASTContext::getTypeInfo(const Type *T) const { std::pair EltInfo = getTypeInfo(CAT->getElementType()); Width = EltInfo.first*CAT->getSize().getZExtValue(); Align = EltInfo.second; + Width = llvm::RoundUpToAlignment(Width, Align); break; } case Type::ExtVector: @@ -801,7 +843,8 @@ ASTContext::getTypeInfo(const Type *T) const { Align = Target.getPointerAlign(0); break; case Type::BlockPointer: { - unsigned AS = cast(T)->getPointeeType().getAddressSpace(); + unsigned AS = getTargetAddressSpace( + cast(T)->getPointeeType()); Width = Target.getPointerWidth(AS); Align = Target.getPointerAlign(AS); break; @@ -810,13 +853,14 @@ ASTContext::getTypeInfo(const Type *T) const { case Type::RValueReference: { // alignof and sizeof should never enter this code path here, so we go // the pointer route. - unsigned AS = cast(T)->getPointeeType().getAddressSpace(); + unsigned AS = getTargetAddressSpace( + cast(T)->getPointeeType()); Width = Target.getPointerWidth(AS); Align = Target.getPointerAlign(AS); break; } case Type::Pointer: { - unsigned AS = cast(T)->getPointeeType().getAddressSpace(); + unsigned AS = getTargetAddressSpace(cast(T)->getPointeeType()); Width = Target.getPointerWidth(AS); Align = Target.getPointerAlign(AS); break; @@ -852,8 +896,8 @@ ASTContext::getTypeInfo(const Type *T) const { const TagType *TT = cast(T); if (TT->getDecl()->isInvalidDecl()) { - Width = 1; - Align = 1; + Width = 8; + Align = 8; break; } @@ -881,7 +925,7 @@ ASTContext::getTypeInfo(const Type *T) const { return getTypeInfo(cast(T)->getInnerType().getTypePtr()); case Type::Typedef: { - const TypedefDecl *Typedef = cast(T)->getDecl(); + const TypedefNameDecl *Typedef = cast(T)->getDecl(); std::pair Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); // If the typedef has an aligned attribute on it, it overrides any computed @@ -1463,7 +1507,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, // the target. llvm::APInt ArySize(ArySizeIn); ArySize = - ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace())); + ArySize.zextOrTrunc(Target.getPointerWidth(getTargetAddressSpace(EltTy))); llvm::FoldingSetNodeID ID; ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals); @@ -1862,7 +1906,9 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const { - const CallingConv CallConv = Info.getCC(); + const CallingConv DefaultCC = Info.getCC(); + const CallingConv CallConv = (LangOpts.MRTD && DefaultCC == CC_Default) ? + CC_X86StdCall : DefaultCC; // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; @@ -1886,8 +1932,9 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } + FunctionProtoType::ExtInfo newInfo = Info.withCallingConv(CallConv); FunctionNoProtoType *New = new (*this, TypeAlignment) - FunctionNoProtoType(ResultTy, Canonical, Info); + FunctionNoProtoType(ResultTy, Canonical, newInfo); Types.push_back(New); FunctionNoProtoTypes.InsertNode(New, InsertPos); return QualType(New, 0); @@ -1902,7 +1949,7 @@ ASTContext::getFunctionType(QualType ResultTy, // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; - FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI); + FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI, *this); void *InsertPos = 0; if (FunctionProtoType *FTP = @@ -1910,12 +1957,14 @@ ASTContext::getFunctionType(QualType ResultTy, return QualType(FTP, 0); // Determine whether the type being created is already canonical or not. - bool isCanonical = !EPI.HasExceptionSpec && ResultTy.isCanonical(); + bool isCanonical= EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical(); for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; - const CallingConv CallConv = EPI.ExtInfo.getCC(); + const CallingConv DefaultCC = EPI.ExtInfo.getCC(); + const CallingConv CallConv = (LangOpts.MRTD && DefaultCC == CC_Default) ? + CC_X86StdCall : DefaultCC; // If this type isn't canonical, get the canonical version of it. // The exception spec is not part of the canonical type. @@ -1927,11 +1976,8 @@ ASTContext::getFunctionType(QualType ResultTy, CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i])); FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI; - if (CanonicalEPI.HasExceptionSpec) { - CanonicalEPI.HasExceptionSpec = false; - CanonicalEPI.HasAnyExceptionSpec = false; - CanonicalEPI.NumExceptions = 0; - } + CanonicalEPI.ExceptionSpecType = EST_None; + CanonicalEPI.NumExceptions = 0; CanonicalEPI.ExtInfo = CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv)); @@ -1947,12 +1993,19 @@ ASTContext::getFunctionType(QualType ResultTy, // FunctionProtoType objects are allocated with extra bytes after them // for two variable size arrays (for parameter and exception types) at the - // end of them. + // end of them. Instead of the exception types, there could be a noexcept + // expression and a context pointer. size_t Size = sizeof(FunctionProtoType) + - NumArgs * sizeof(QualType) + - EPI.NumExceptions * sizeof(QualType); + NumArgs * sizeof(QualType); + if (EPI.ExceptionSpecType == EST_Dynamic) + Size += EPI.NumExceptions * sizeof(QualType); + else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + Size += sizeof(Expr*); + } FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); - new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, EPI); + FunctionProtoType::ExtProtoInfo newEPI = EPI; + newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv); + new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, newEPI); Types.push_back(FTP); FunctionProtoTypes.InsertNode(FTP, InsertPos); return QualType(FTP, 0); @@ -1997,7 +2050,7 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { assert(Decl && "Passed null for Decl param"); assert(!Decl->TypeForDecl && "TypeForDecl present in slow case"); - if (const TypedefDecl *Typedef = dyn_cast(Decl)) + if (const TypedefNameDecl *Typedef = dyn_cast(Decl)) return getTypedefType(Typedef); assert(!isa(Decl) && @@ -2024,9 +2077,10 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { } /// getTypedefType - Return the unique reference to the type for the -/// specified typename decl. +/// specified typedef name decl. QualType -ASTContext::getTypedefType(const TypedefDecl *Decl, QualType Canonical) const { +ASTContext::getTypedefType(const TypedefNameDecl *Decl, + QualType Canonical) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); if (Canonical.isNull()) @@ -2149,9 +2203,9 @@ QualType ASTContext::getSubstTemplateTypeParmPackType( /// name. QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name) const { + TemplateTypeParmDecl *TTPDecl) const { llvm::FoldingSetNodeID ID; - TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, Name); + TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, TTPDecl); void *InsertPos = 0; TemplateTypeParmType *TypeParm = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -2159,10 +2213,9 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, if (TypeParm) return QualType(TypeParm, 0); - if (Name) { + if (TTPDecl) { QualType Canon = getTemplateTypeParmType(Depth, Index, ParameterPack); - TypeParm = new (*this, TypeAlignment) - TemplateTypeParmType(Depth, Index, ParameterPack, Name, Canon); + TypeParm = new (*this, TypeAlignment) TemplateTypeParmType(TTPDecl, Canon); TemplateTypeParmType *TypeCheck = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -2183,6 +2236,8 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, SourceLocation NameLoc, const TemplateArgumentListInfo &Args, QualType CanonType) const { + assert(!Name.getAsDependentTemplateName() && + "No dependent template names here!"); QualType TST = getTemplateSpecializationType(Name, Args, CanonType); TypeSourceInfo *DI = CreateTypeSourceInfo(TST); @@ -2200,6 +2255,9 @@ QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgumentListInfo &Args, QualType Canon) const { + assert(!Template.getAsDependentTemplateName() && + "No dependent template names here!"); + unsigned NumArgs = Args.size(); llvm::SmallVector ArgVec; @@ -2216,6 +2274,12 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, unsigned NumArgs, QualType Canon) const { + assert(!Template.getAsDependentTemplateName() && + "No dependent template names here!"); + // Look through qualified template names. + if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Template = TemplateName(QTN->getTemplateDecl()); + if (!Canon.isNull()) Canon = getCanonicalType(Canon); else @@ -2240,6 +2304,12 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, unsigned NumArgs) const { + assert(!Template.getAsDependentTemplateName() && + "No dependent template names here!"); + // Look through qualified template names. + if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Template = TemplateName(QTN->getTemplateDecl()); + // Build the canonical template specialization type. TemplateName CanonTemplate = getCanonicalTemplateName(Template); llvm::SmallVector CanonArgs; @@ -2377,7 +2447,8 @@ ASTContext::getDependentTemplateSpecializationType( const IdentifierInfo *Name, unsigned NumArgs, const TemplateArgument *Args) const { - assert(NNS->isDependent() && "nested-name-specifier must be dependent"); + assert((!NNS || NNS->isDependent()) && + "nested-name-specifier must be dependent"); llvm::FoldingSetNodeID ID; DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS, @@ -2701,6 +2772,22 @@ QualType ASTContext::getAutoType(QualType DeducedType) const { return QualType(AT, 0); } +/// getAutoDeductType - Get type pattern for deducing against 'auto'. +QualType ASTContext::getAutoDeductType() const { + if (AutoDeductTy.isNull()) + AutoDeductTy = getAutoType(QualType()); + assert(!AutoDeductTy.isNull() && "can't build 'auto' pattern"); + return AutoDeductTy; +} + +/// getAutoRRefDeductType - Get type pattern for deducing against 'auto &&'. +QualType ASTContext::getAutoRRefDeductType() const { + if (AutoRRefDeductTy.isNull()) + AutoRRefDeductTy = getRValueReferenceType(getAutoDeductType()); + assert(!AutoRRefDeductTy.isNull() && "can't build 'auto &&' pattern"); + return AutoRRefDeductTy; +} + /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. QualType ASTContext::getTagDeclType(const TagDecl *Decl) const { @@ -3014,10 +3101,11 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { = T->getAs()) { NestedNameSpecifier *Prefix = getCanonicalNestedNameSpecifier(DTST->getQualifier()); - TemplateName Name - = getDependentTemplateName(Prefix, DTST->getIdentifier()); - T = getTemplateSpecializationType(Name, - DTST->getArgs(), DTST->getNumArgs()); + + T = getDependentTemplateSpecializationType(DTST->getKeyword(), + Prefix, DTST->getIdentifier(), + DTST->getNumArgs(), + DTST->getArgs()); T = getCanonicalType(T); } @@ -3334,19 +3422,20 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { } static RecordDecl * -CreateRecordDecl(const ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id) { +CreateRecordDecl(const ASTContext &Ctx, RecordDecl::TagKind TK, + DeclContext *DC, IdentifierInfo *Id) { + SourceLocation Loc; if (Ctx.getLangOptions().CPlusPlus) - return CXXRecordDecl::Create(Ctx, TK, DC, L, Id); + return CXXRecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id); else - return RecordDecl::Create(Ctx, TK, DC, L, Id); + return RecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id); } - + // getCFConstantStringType - Return the type used for constant CFStrings. QualType ASTContext::getCFConstantStringType() const { if (!CFConstantStringTypeDecl) { CFConstantStringTypeDecl = - CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), + CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("NSConstantString")); CFConstantStringTypeDecl->startDefinition(); @@ -3364,6 +3453,7 @@ QualType ASTContext::getCFConstantStringType() const { // Create fields for (unsigned i = 0; i < 4; ++i) { FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl, + SourceLocation(), SourceLocation(), 0, FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, @@ -3388,7 +3478,7 @@ void ASTContext::setCFConstantStringType(QualType T) { QualType ASTContext::getNSConstantStringType() const { if (!NSConstantStringTypeDecl) { NSConstantStringTypeDecl = - CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), + CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("__builtin_NSString")); NSConstantStringTypeDecl->startDefinition(); @@ -3404,6 +3494,7 @@ QualType ASTContext::getNSConstantStringType() const { // Create fields for (unsigned i = 0; i < 3; ++i) { FieldDecl *Field = FieldDecl::Create(*this, NSConstantStringTypeDecl, + SourceLocation(), SourceLocation(), 0, FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, @@ -3427,7 +3518,7 @@ void ASTContext::setNSConstantStringType(QualType T) { QualType ASTContext::getObjCFastEnumerationStateType() const { if (!ObjCFastEnumerationStateTypeDecl) { ObjCFastEnumerationStateTypeDecl = - CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), + CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("__objcFastEnumerationState")); ObjCFastEnumerationStateTypeDecl->startDefinition(); @@ -3442,6 +3533,7 @@ QualType ASTContext::getObjCFastEnumerationStateType() const { for (size_t i = 0; i < 4; ++i) { FieldDecl *Field = FieldDecl::Create(*this, ObjCFastEnumerationStateTypeDecl, + SourceLocation(), SourceLocation(), 0, FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, @@ -3462,7 +3554,7 @@ QualType ASTContext::getBlockDescriptorType() const { RecordDecl *T; // FIXME: Needs the FlagAppleBlock bit. - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), + T = CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("__block_descriptor")); T->startDefinition(); @@ -3477,8 +3569,7 @@ QualType ASTContext::getBlockDescriptorType() const { }; for (size_t i = 0; i < 2; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, - T, + FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), SourceLocation(), &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/0, @@ -3507,7 +3598,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { RecordDecl *T; // FIXME: Needs the FlagAppleBlock bit. - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), + T = CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("__block_descriptor_withcopydispose")); T->startDefinition(); @@ -3526,8 +3617,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { }; for (size_t i = 0; i < 4; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, - T, + FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), SourceLocation(), &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/0, @@ -3586,8 +3676,7 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const { llvm::raw_svector_ostream(Name) << "__Block_byref_" << ++UniqueBlockByRefTypeID << '_' << DeclName; RecordDecl *T; - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), - &Idents.get(Name.str())); + T = CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get(Name.str())); T->startDefinition(); QualType Int32Ty = IntTy; assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported"); @@ -3615,6 +3704,7 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const { if (!HasCopyAndDispose && i >=4 && i <= 5) continue; FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), + SourceLocation(), &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/0, /*BitWidth=*/0, /*Mutable=*/false); @@ -4367,6 +4457,8 @@ TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateDecl *Template) const { + assert(NNS && "Missing nested-name-specifier in qualified template name"); + // FIXME: Canonicalization? llvm::FoldingSetNodeID ID; QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template); @@ -4503,7 +4595,7 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const { /// bool ASTContext::isObjCNSObjectType(QualType Ty) const { if (const TypedefType *TDT = dyn_cast(Ty)) { - if (TypedefDecl *TD = TDT->getDecl()) + if (TypedefNameDecl *TD = TDT->getDecl()) if (TD->getAttr()) return true; } @@ -4795,13 +4887,14 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, } /// canAssignObjCInterfacesInBlockPointer - This routine is specifically written -/// for providing type-safty for objective-c pointers used to pass/return +/// for providing type-safety for objective-c pointers used to pass/return /// arguments in block literals. When passed as arguments, passing 'A*' where /// 'id' is expected is not OK. Passing 'Sub *" where 'Super *" is expected is /// not OK. For the return type, the opposite is not OK. bool ASTContext::canAssignObjCInterfacesInBlockPointer( const ObjCObjectPointerType *LHSOPT, - const ObjCObjectPointerType *RHSOPT) { + const ObjCObjectPointerType *RHSOPT, + bool BlockReturnType) { if (RHSOPT->isObjCBuiltinType() || LHSOPT->isObjCIdType()) return true; @@ -4819,9 +4912,9 @@ bool ASTContext::canAssignObjCInterfacesInBlockPointer( if (LHS && RHS) { // We have 2 user-defined types. if (LHS != RHS) { if (LHS->getDecl()->isSuperClassOf(RHS->getDecl())) - return false; + return BlockReturnType; if (RHS->getDecl()->isSuperClassOf(LHS->getDecl())) - return true; + return !BlockReturnType; } else return true; @@ -4887,10 +4980,10 @@ QualType ASTContext::areCommonBaseCompatible( const ObjCObjectType *RHS = Rptr->getObjectType(); const ObjCInterfaceDecl* LDecl = LHS->getInterface(); const ObjCInterfaceDecl* RDecl = RHS->getInterface(); - if (!LDecl || !RDecl) + if (!LDecl || !RDecl || (LDecl == RDecl)) return QualType(); - while ((LDecl = LDecl->getSuperClass())) { + do { LHS = cast(getObjCInterfaceType(LDecl)); if (canAssignObjCInterfaces(LHS, RHS)) { llvm::SmallVector Protocols; @@ -4902,7 +4995,7 @@ QualType ASTContext::areCommonBaseCompatible( Result = getObjCObjectPointerType(Result); return Result; } - } + } while ((LDecl = LDecl->getSuperClass())); return QualType(); } @@ -4922,10 +5015,47 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, if (LHS->getNumProtocols() == 0) return true; - // Okay, we know the LHS has protocol qualifiers. If the RHS doesn't, then it - // isn't a superset. - if (RHS->getNumProtocols() == 0) - return true; // FIXME: should return false! + // Okay, we know the LHS has protocol qualifiers. If the RHS doesn't, + // more detailed analysis is required. + if (RHS->getNumProtocols() == 0) { + // OK, if LHS is a superclass of RHS *and* + // this superclass is assignment compatible with LHS. + // false otherwise. + bool IsSuperClass = + LHS->getInterface()->isSuperClassOf(RHS->getInterface()); + if (IsSuperClass) { + // OK if conversion of LHS to SuperClass results in narrowing of types + // ; i.e., SuperClass may implement at least one of the protocols + // in LHS's protocol list. Example, SuperObj = lhs is ok. + // But not SuperObj = lhs. + llvm::SmallPtrSet SuperClassInheritedProtocols; + CollectInheritedProtocols(RHS->getInterface(), SuperClassInheritedProtocols); + // If super class has no protocols, it is not a match. + if (SuperClassInheritedProtocols.empty()) + return false; + + for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(), + LHSPE = LHS->qual_end(); + LHSPI != LHSPE; LHSPI++) { + bool SuperImplementsProtocol = false; + ObjCProtocolDecl *LHSProto = (*LHSPI); + + for (llvm::SmallPtrSet::iterator I = + SuperClassInheritedProtocols.begin(), + E = SuperClassInheritedProtocols.end(); I != E; ++I) { + ObjCProtocolDecl *SuperClassProto = (*I); + if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) { + SuperImplementsProtocol = true; + break; + } + } + if (!SuperImplementsProtocol) + return false; + } + return true; + } + return false; + } for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(), LHSPE = LHS->qual_end(); @@ -5045,7 +5175,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, bool UnqualifiedResult = Unqualified; if (!UnqualifiedResult) UnqualifiedResult = (!RHS.hasQualifiers() && LHS.hasQualifiers()); - retType = mergeTypes(RHS, LHS, true, UnqualifiedResult); + retType = mergeTypes(LHS, RHS, true, UnqualifiedResult, true); } else retType = mergeTypes(lbase->getResultType(), rbase->getResultType(), false, @@ -5079,6 +5209,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, return QualType(); // Regparm is part of the calling convention. + if (lbaseInfo.getHasRegParm() != rbaseInfo.getHasRegParm()) + return QualType(); if (lbaseInfo.getRegParm() != rbaseInfo.getRegParm()) return QualType(); @@ -5091,6 +5223,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, allRTypes = false; FunctionType::ExtInfo einfo(NoReturn, + lbaseInfo.getHasRegParm(), lbaseInfo.getRegParm(), lbaseInfo.getCC()); @@ -5185,7 +5318,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, - bool Unqualified) { + bool Unqualified, bool BlockReturnType) { // C++ [expr]: If an expression initially has the type "reference to T", the // type is adjusted to "T" prior to any further analysis, the expression // designates the object or function denoted by the reference, and the @@ -5419,7 +5552,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, if (OfBlockPointer) { if (canAssignObjCInterfacesInBlockPointer( LHS->getAs(), - RHS->getAs())) + RHS->getAs(), + BlockReturnType)) return LHS; return QualType(); } @@ -5557,10 +5691,6 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) { } } -ExternalASTSource::~ExternalASTSource() { } - -void ExternalASTSource::PrintStats() { } - ASTMutationListener::~ASTMutationListener() { } @@ -6015,3 +6145,19 @@ MangleContext *ASTContext::createMangleContext() { } CXXABI::~CXXABI() {} + +size_t ASTContext::getSideTableAllocatedMemory() const { + size_t bytes = 0; + bytes += ASTRecordLayouts.getMemorySize(); + bytes += ObjCLayouts.getMemorySize(); + bytes += KeyFunctions.getMemorySize(); + bytes += ObjCImpls.getMemorySize(); + bytes += BlockVarCopyInits.getMemorySize(); + bytes += DeclAttrs.getMemorySize(); + bytes += InstantiatedFromStaticDataMember.getMemorySize(); + bytes += InstantiatedFromUsingDecl.getMemorySize(); + bytes += InstantiatedFromUsingShadowDecl.getMemorySize(); + bytes += InstantiatedFromUnnamedFieldDecl.getMemorySize(); + return bytes; +} + diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 5bf8a38199b6..897b4a4c1f27 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -43,6 +43,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { QT = ST->desugar(); continue; } + // ...or an attributed type... + if (const AttributedType *AT = dyn_cast(Ty)) { + QT = AT->desugar(); + continue; + } // ... or an auto type. if (const AutoType *AT = dyn_cast(Ty)) { if (!AT->isSugared()) @@ -95,7 +100,7 @@ break; \ // Don't desugar through the primary typedef of an anonymous type. if (const TagType *UTT = Underlying->getAs()) if (const TypedefType *QTT = dyn_cast(QT)) - if (UTT->getDecl()->getTypedefForAnonDecl() == QTT->getDecl()) + if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl()) break; // Record that we actually looked through an opaque type here. diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index 21f10fb7ad99..dc881ba86960 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -97,7 +97,9 @@ namespace { bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); Decl *VisitDecl(Decl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); + Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); Decl *VisitTypedefDecl(TypedefDecl *D); + Decl *VisitTypeAliasDecl(TypeAliasDecl *D); Decl *VisitEnumDecl(EnumDecl *D); Decl *VisitRecordDecl(RecordDecl *D); Decl *VisitEnumConstantDecl(EnumConstantDecl *D); @@ -139,7 +141,7 @@ namespace { Expr *VisitCharacterLiteral(CharacterLiteral *E); Expr *VisitParenExpr(ParenExpr *E); Expr *VisitUnaryOperator(UnaryOperator *E); - Expr *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); + Expr *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); Expr *VisitBinaryOperator(BinaryOperator *E); Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E); Expr *VisitImplicitCastExpr(ImplicitCastExpr *E); @@ -521,16 +523,21 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } if (Proto1->isVariadic() != Proto2->isVariadic()) return false; - if (Proto1->hasExceptionSpec() != Proto2->hasExceptionSpec()) + if (Proto1->getExceptionSpecType() != Proto2->getExceptionSpecType()) return false; - if (Proto1->hasAnyExceptionSpec() != Proto2->hasAnyExceptionSpec()) - return false; - if (Proto1->getNumExceptions() != Proto2->getNumExceptions()) - return false; - for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) { + if (Proto1->getExceptionSpecType() == EST_Dynamic) { + if (Proto1->getNumExceptions() != Proto2->getNumExceptions()) + return false; + for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, + Proto1->getExceptionType(I), + Proto2->getExceptionType(I))) + return false; + } + } else if (Proto1->getExceptionSpecType() == EST_ComputedNoexcept) { if (!IsStructurallyEquivalent(Context, - Proto1->getExceptionType(I), - Proto2->getExceptionType(I))) + Proto1->getNoexceptExpr(), + Proto2->getNoexceptExpr())) return false; } if (Proto1->getTypeQuals() != Proto2->getTypeQuals()) @@ -830,7 +837,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; } // If one is a class template specialization and the other is not, these - // structures are diferent. + // structures are different. else if (Spec1 || Spec2) return false; @@ -1189,11 +1196,11 @@ bool StructuralEquivalenceContext::Finish() { if (RecordDecl *Record2 = dyn_cast(D2)) { // Check for equivalent structure names. IdentifierInfo *Name1 = Record1->getIdentifier(); - if (!Name1 && Record1->getTypedefForAnonDecl()) - Name1 = Record1->getTypedefForAnonDecl()->getIdentifier(); + if (!Name1 && Record1->getTypedefNameForAnonDecl()) + Name1 = Record1->getTypedefNameForAnonDecl()->getIdentifier(); IdentifierInfo *Name2 = Record2->getIdentifier(); - if (!Name2 && Record2->getTypedefForAnonDecl()) - Name2 = Record2->getTypedefForAnonDecl()->getIdentifier(); + if (!Name2 && Record2->getTypedefNameForAnonDecl()) + Name2 = Record2->getTypedefNameForAnonDecl()->getIdentifier(); if (!::IsStructurallyEquivalent(Name1, Name2) || !::IsStructurallyEquivalent(*this, Record1, Record2)) Equivalent = false; @@ -1205,11 +1212,11 @@ bool StructuralEquivalenceContext::Finish() { if (EnumDecl *Enum2 = dyn_cast(D2)) { // Check for equivalent enum names. IdentifierInfo *Name1 = Enum1->getIdentifier(); - if (!Name1 && Enum1->getTypedefForAnonDecl()) - Name1 = Enum1->getTypedefForAnonDecl()->getIdentifier(); + if (!Name1 && Enum1->getTypedefNameForAnonDecl()) + Name1 = Enum1->getTypedefNameForAnonDecl()->getIdentifier(); IdentifierInfo *Name2 = Enum2->getIdentifier(); - if (!Name2 && Enum2->getTypedefForAnonDecl()) - Name2 = Enum2->getTypedefForAnonDecl()->getIdentifier(); + if (!Name2 && Enum2->getTypedefNameForAnonDecl()) + Name2 = Enum2->getTypedefNameForAnonDecl()->getIdentifier(); if (!::IsStructurallyEquivalent(Name1, Name2) || !::IsStructurallyEquivalent(*this, Enum1, Enum2)) Equivalent = false; @@ -1217,8 +1224,8 @@ bool StructuralEquivalenceContext::Finish() { // Enum/non-enum mismatch Equivalent = false; } - } else if (TypedefDecl *Typedef1 = dyn_cast(D1)) { - if (TypedefDecl *Typedef2 = dyn_cast(D2)) { + } else if (TypedefNameDecl *Typedef1 = dyn_cast(D1)) { + if (TypedefNameDecl *Typedef2 = dyn_cast(D2)) { if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(), Typedef2->getIdentifier()) || !::IsStructurallyEquivalent(*this, @@ -1355,6 +1362,8 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { case BuiltinType::Overload: return Importer.getToContext().OverloadTy; case BuiltinType::Dependent: return Importer.getToContext().DependentTy; + case BuiltinType::UnknownAny: return Importer.getToContext().UnknownAnyTy; + case BuiltinType::BoundMember: return Importer.getToContext().BoundMemberTy; case BuiltinType::ObjCId: // FIXME: Make sure that the "to" context supports Objective-C! @@ -1530,8 +1539,8 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { } QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { - TypedefDecl *ToDecl - = dyn_cast_or_null(Importer.Import(T->getDecl())); + TypedefNameDecl *ToDecl + = dyn_cast_or_null(Importer.Import(T->getDecl())); if (!ToDecl) return QualType(); @@ -1967,8 +1976,9 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Create the "to" namespace, if needed. NamespaceDecl *ToNamespace = MergeWithNamespace; if (!ToNamespace) { - ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo()); + ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getLocStart()), + Loc, Name.getAsIdentifierInfo()); ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDecl(ToNamespace); @@ -1988,7 +1998,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { return ToNamespace; } -Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { +Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Import the major distinguishing characteristics of this typedef. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -2007,7 +2017,8 @@ Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { ++Lookup.first) { if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) continue; - if (TypedefDecl *FoundTypedef = dyn_cast(*Lookup.first)) { + if (TypedefNameDecl *FoundTypedef = + dyn_cast(*Lookup.first)) { if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) return Importer.Imported(D, FoundTypedef); @@ -2032,9 +2043,18 @@ Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { // Create the new typedef node. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - TypedefDecl *ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC, - Loc, Name.getAsIdentifierInfo(), - TInfo); + SourceLocation StartL = Importer.Import(D->getLocStart()); + TypedefNameDecl *ToTypedef; + if (IsAlias) + ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC, + StartL, Loc, + Name.getAsIdentifierInfo(), + TInfo); + else + ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, + StartL, Loc, + Name.getAsIdentifierInfo(), + TInfo); ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToTypedef); @@ -2043,6 +2063,14 @@ Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { return ToTypedef; } +Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { + return VisitTypedefNameDecl(D, /*IsAlias=*/false); +} + +Decl *ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) { + return VisitTypedefNameDecl(D, /*IsAlias=*/true); +} + Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Import the major distinguishing characteristics of this enum. DeclContext *DC, *LexicalDC; @@ -2054,8 +2082,8 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Figure out what enum name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; - if (!SearchName && D->getTypedefForAnonDecl()) { - SearchName = Importer.Import(D->getTypedefForAnonDecl()->getDeclName()); + if (!SearchName && D->getTypedefNameForAnonDecl()) { + SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName()); IDNS = Decl::IDNS_Ordinary; } else if (Importer.getToContext().getLangOptions().CPlusPlus) IDNS |= Decl::IDNS_Ordinary; @@ -2070,7 +2098,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { continue; Decl *Found = *Lookup.first; - if (TypedefDecl *Typedef = dyn_cast(Found)) { + if (TypedefNameDecl *Typedef = dyn_cast(Found)) { if (const TagType *Tag = Typedef->getUnderlyingType()->getAs()) Found = Tag->getDecl(); } @@ -2091,9 +2119,9 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { } // Create the enum declaration. - EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), - Importer.Import(D->getTagKeywordLoc()), 0, + EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getLocStart()), + Loc, Name.getAsIdentifierInfo(), 0, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); // Import the qualifier, if any. @@ -2155,8 +2183,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // Figure out what structure name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; - if (!SearchName && D->getTypedefForAnonDecl()) { - SearchName = Importer.Import(D->getTypedefForAnonDecl()->getDeclName()); + if (!SearchName && D->getTypedefNameForAnonDecl()) { + SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName()); IDNS = Decl::IDNS_Ordinary; } else if (Importer.getToContext().getLangOptions().CPlusPlus) IDNS |= Decl::IDNS_Ordinary; @@ -2172,7 +2200,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { continue; Decl *Found = *Lookup.first; - if (TypedefDecl *Typedef = dyn_cast(Found)) { + if (TypedefNameDecl *Typedef = dyn_cast(Found)) { if (const TagType *Tag = Typedef->getUnderlyingType()->getAs()) Found = Tag->getDecl(); } @@ -2206,20 +2234,18 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // Create the record declaration. RecordDecl *D2 = AdoptDecl; + SourceLocation StartLoc = Importer.Import(D->getLocStart()); if (!D2) { if (isa(D)) { CXXRecordDecl *D2CXX = CXXRecordDecl::Create(Importer.getToContext(), D->getTagKind(), - DC, Loc, - Name.getAsIdentifierInfo(), - Importer.Import(D->getTagKeywordLoc())); + DC, StartLoc, Loc, + Name.getAsIdentifierInfo()); D2 = D2CXX; D2->setAccess(D->getAccess()); } else { D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), - DC, Loc, - Name.getAsIdentifierInfo(), - Importer.Import(D->getTagKeywordLoc())); + DC, StartLoc, Loc, Name.getAsIdentifierInfo()); } D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); @@ -2367,6 +2393,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (CXXConstructorDecl *FromConstructor = dyn_cast(D)) { ToFunction = CXXConstructorDecl::Create(Importer.getToContext(), cast(DC), + D->getInnerLocStart(), NameInfo, T, TInfo, FromConstructor->isExplicit(), D->isInlineSpecified(), @@ -2374,6 +2401,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } else if (isa(D)) { ToFunction = CXXDestructorDecl::Create(Importer.getToContext(), cast(DC), + D->getInnerLocStart(), NameInfo, T, TInfo, D->isInlineSpecified(), D->isImplicit()); @@ -2381,18 +2409,23 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { = dyn_cast(D)) { ToFunction = CXXConversionDecl::Create(Importer.getToContext(), cast(DC), + D->getInnerLocStart(), NameInfo, T, TInfo, D->isInlineSpecified(), - FromConversion->isExplicit()); + FromConversion->isExplicit(), + Importer.Import(D->getLocEnd())); } else if (CXXMethodDecl *Method = dyn_cast(D)) { ToFunction = CXXMethodDecl::Create(Importer.getToContext(), cast(DC), + D->getInnerLocStart(), NameInfo, T, TInfo, Method->isStatic(), Method->getStorageClassAsWritten(), - Method->isInlineSpecified()); + Method->isInlineSpecified(), + Importer.Import(D->getLocEnd())); } else { ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, + D->getInnerLocStart(), NameInfo, T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten(), D->isInlineSpecified(), @@ -2457,7 +2490,8 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { if (!BitWidth && D->getBitWidth()) return 0; - FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC, + FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, BitWidth, D->isMutable()); ToField->setAccess(D->getAccess()); @@ -2542,6 +2576,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), cast(DC), + Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), BitWidth, D->getSynthesize()); @@ -2650,8 +2685,10 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { // Create the imported variable. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), T, TInfo, + VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), + Loc, Name.getAsIdentifierInfo(), + T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten()); ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); @@ -2718,6 +2755,7 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { // Create the imported parameter. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten(), @@ -3444,6 +3482,7 @@ Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { // FIXME: Import default argument. return TemplateTypeParmDecl::Create(Importer.getToContext(), Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getLocStart()), Importer.Import(D->getLocation()), D->getDepth(), D->getIndex(), @@ -3476,6 +3515,7 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { return NonTypeTemplateParmDecl::Create(Importer.getToContext(), Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getInnerLocStart()), Loc, D->getDepth(), D->getPosition(), Name.getAsIdentifierInfo(), T, D->isParameterPack(), TInfo); @@ -3567,12 +3607,12 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *DTemplated = D->getTemplatedDecl(); // Create the declaration that is being templated. + SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart()); + SourceLocation IdLoc = Importer.Import(DTemplated->getLocation()); CXXRecordDecl *D2Templated = CXXRecordDecl::Create(Importer.getToContext(), DTemplated->getTagKind(), - DC, - Importer.Import(DTemplated->getLocation()), - Name.getAsIdentifierInfo(), - Importer.Import(DTemplated->getTagKeywordLoc())); + DC, StartLoc, IdLoc, + Name.getAsIdentifierInfo()); D2Templated->setAccess(DTemplated->getAccess()); D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc())); D2Templated->setLexicalDeclContext(LexicalDC); @@ -3637,7 +3677,8 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( } // Import the location of this declaration. - SourceLocation Loc = Importer.Import(D->getLocation()); + SourceLocation StartLoc = Importer.Import(D->getLocStart()); + SourceLocation IdLoc = Importer.Import(D->getLocation()); // Import template arguments. llvm::SmallVector TemplateArgs; @@ -3669,7 +3710,8 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Create a new specialization. D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(), D->getTagKind(), DC, - Loc, ClassTemplate, + StartLoc, IdLoc, + ClassTemplate, TemplateArgs.data(), TemplateArgs.size(), /*PrevDecl=*/0); @@ -3713,26 +3755,27 @@ Expr *ASTNodeImporter::VisitExpr(Expr *E) { } Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { - NestedNameSpecifier *Qualifier = 0; - if (E->getQualifier()) { - Qualifier = Importer.Import(E->getQualifier()); - if (!E->getQualifier()) - return 0; - } - ValueDecl *ToD = cast_or_null(Importer.Import(E->getDecl())); if (!ToD) return 0; + + NamedDecl *FoundD = 0; + if (E->getDecl() != E->getFoundDecl()) { + FoundD = cast_or_null(Importer.Import(E->getFoundDecl())); + if (!FoundD) + return 0; + } QualType T = Importer.Import(E->getType()); if (T.isNull()) return 0; - return DeclRefExpr::Create(Importer.getToContext(), Qualifier, - Importer.Import(E->getQualifierRange()), + return DeclRefExpr::Create(Importer.getToContext(), + Importer.Import(E->getQualifierLoc()), ToD, Importer.Import(E->getLocation()), T, E->getValueKind(), + FoundD, /*FIXME:TemplateArgs=*/0); } @@ -3782,7 +3825,8 @@ Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { Importer.Import(E->getOperatorLoc())); } -Expr *ASTNodeImporter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { +Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr( + UnaryExprOrTypeTraitExpr *E) { QualType ResultType = Importer.Import(E->getType()); if (E->isArgumentType()) { @@ -3790,8 +3834,8 @@ Expr *ASTNodeImporter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { if (!TInfo) return 0; - return new (Importer.getToContext()) SizeOfAlignOfExpr(E->isSizeOf(), - TInfo, ResultType, + return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(), + TInfo, ResultType, Importer.Import(E->getOperatorLoc()), Importer.Import(E->getRParenLoc())); } @@ -3800,8 +3844,8 @@ Expr *ASTNodeImporter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { if (!SubExpr) return 0; - return new (Importer.getToContext()) SizeOfAlignOfExpr(E->isSizeOf(), - SubExpr, ResultType, + return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(), + SubExpr, ResultType, Importer.Import(E->getOperatorLoc()), Importer.Import(E->getRParenLoc())); } @@ -3854,7 +3898,7 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { Importer.Import(E->getOperatorLoc())); } -bool ImportCastPath(CastExpr *E, CXXCastPath &Path) { +static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) { if (E->path_empty()) return false; // TODO: import cast paths @@ -3973,19 +4017,19 @@ Decl *ASTImporter::Import(Decl *FromD) { if (TagDecl *FromTag = dyn_cast(FromD)) { // Keep track of anonymous tags that have an associated typedef. - if (FromTag->getTypedefForAnonDecl()) + if (FromTag->getTypedefNameForAnonDecl()) AnonTagsWithPendingTypedefs.push_back(FromTag); - } else if (TypedefDecl *FromTypedef = dyn_cast(FromD)) { + } else if (TypedefNameDecl *FromTypedef = dyn_cast(FromD)) { // When we've finished transforming a typedef, see whether it was the // typedef for an anonymous tag. for (llvm::SmallVector::iterator FromTag = AnonTagsWithPendingTypedefs.begin(), FromTagEnd = AnonTagsWithPendingTypedefs.end(); FromTag != FromTagEnd; ++FromTag) { - if ((*FromTag)->getTypedefForAnonDecl() == FromTypedef) { + if ((*FromTag)->getTypedefNameForAnonDecl() == FromTypedef) { if (TagDecl *ToTag = cast_or_null(Import(*FromTag))) { // We found the typedef for an anonymous tag; link them. - ToTag->setTypedefForAnonDecl(cast(ToD)); + ToTag->setTypedefNameForAnonDecl(cast(ToD)); AnonTagsWithPendingTypedefs.erase(FromTag); break; } @@ -4034,7 +4078,46 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { if (!FromNNS) return 0; - // FIXME: Implement! + NestedNameSpecifier *prefix = Import(FromNNS->getPrefix()); + + switch (FromNNS->getKind()) { + case NestedNameSpecifier::Identifier: + if (IdentifierInfo *II = Import(FromNNS->getAsIdentifier())) { + return NestedNameSpecifier::Create(ToContext, prefix, II); + } + return 0; + + case NestedNameSpecifier::Namespace: + if (NamespaceDecl *NS = + cast(Import(FromNNS->getAsNamespace()))) { + return NestedNameSpecifier::Create(ToContext, prefix, NS); + } + return 0; + + case NestedNameSpecifier::NamespaceAlias: + if (NamespaceAliasDecl *NSAD = + cast(Import(FromNNS->getAsNamespaceAlias()))) { + return NestedNameSpecifier::Create(ToContext, prefix, NSAD); + } + return 0; + + case NestedNameSpecifier::Global: + return NestedNameSpecifier::GlobalSpecifier(ToContext); + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + QualType T = Import(QualType(FromNNS->getAsType(), 0u)); + if (!T.isNull()) { + bool bTemplate = FromNNS->getKind() == + NestedNameSpecifier::TypeSpecWithTemplate; + return NestedNameSpecifier::Create(ToContext, prefix, + bTemplate, T.getTypePtr()); + } + } + return 0; + } + + llvm_unreachable("Invalid nested name specifier kind"); return 0; } @@ -4156,12 +4239,12 @@ FileID ASTImporter::Import(FileID FromID) { // Map the FileID for to the "to" source manager. FileID ToID; const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); - if (Cache->Entry) { + if (Cache->OrigEntry) { // FIXME: We probably want to use getVirtualFile(), so we don't hit the // disk again // FIXME: We definitely want to re-use the existing MemoryBuffer, rather // than mmap the files several times. - const FileEntry *Entry = ToFileManager.getFile(Cache->Entry->getName()); + const FileEntry *Entry = ToFileManager.getFile(Cache->OrigEntry->getName()); ToID = ToSM.createFileID(Entry, ToIncludeLoc, FromSLoc.getFile().getFileCharacteristic()); } else { diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index ca9ec18b3997..9ffe1f865689 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -415,7 +415,7 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, Path.Decls.first != Path.Decls.second; ++Path.Decls.first) { // FIXME: Refactor the "is it a nested-name-specifier?" check - if (isa(*Path.Decls.first) || + if (isa(*Path.Decls.first) || (*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag)) return true; } diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 73fe117b1e4e..b21ba9a65e76 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -25,6 +25,7 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -33,53 +34,33 @@ using namespace clang; // NamedDecl Implementation //===----------------------------------------------------------------------===// -static const VisibilityAttr *GetExplicitVisibility(const Decl *d) { - // Use the most recent declaration of a variable. - if (const VarDecl *var = dyn_cast(d)) - return var->getMostRecentDeclaration()->getAttr(); +static llvm::Optional getVisibilityOf(const Decl *D) { + // If this declaration has an explicit visibility attribute, use it. + if (const VisibilityAttr *A = D->getAttr()) { + switch (A->getVisibility()) { + case VisibilityAttr::Default: + return DefaultVisibility; + case VisibilityAttr::Hidden: + return HiddenVisibility; + case VisibilityAttr::Protected: + return ProtectedVisibility; + } - // Use the most recent declaration of a function, and also handle - // function template specializations. - if (const FunctionDecl *fn = dyn_cast(d)) { - if (const VisibilityAttr *attr - = fn->getMostRecentDeclaration()->getAttr()) - return attr; - - // If the function is a specialization of a template with an - // explicit visibility attribute, use that. - if (FunctionTemplateSpecializationInfo *templateInfo - = fn->getTemplateSpecializationInfo()) - return templateInfo->getTemplate()->getTemplatedDecl() - ->getAttr(); - - return 0; - } - - // Otherwise, just check the declaration itself first. - if (const VisibilityAttr *attr = d->getAttr()) - return attr; - - // If there wasn't explicit visibility there, and this is a - // specialization of a class template, check for visibility - // on the pattern. - if (const ClassTemplateSpecializationDecl *spec - = dyn_cast(d)) - return spec->getSpecializedTemplate()->getTemplatedDecl() - ->getAttr(); - - return 0; -} - -static Visibility GetVisibilityFromAttr(const VisibilityAttr *A) { - switch (A->getVisibility()) { - case VisibilityAttr::Default: return DefaultVisibility; - case VisibilityAttr::Hidden: - return HiddenVisibility; - case VisibilityAttr::Protected: - return ProtectedVisibility; } - return DefaultVisibility; + + // If we're on Mac OS X, an 'availability' for Mac OS X attribute + // implies visibility(default). + if (D->getASTContext().Target.getTriple().isOSDarwin()) { + for (specific_attr_iterator + A = D->specific_attr_begin(), + AEnd = D->specific_attr_end(); + A != AEnd; ++A) + if ((*A)->getPlatform()->getName().equals("macosx")) + return DefaultVisibility; + } + + return llvm::Optional(); } typedef NamedDecl::LinkageInfo LinkageInfo; @@ -100,9 +81,11 @@ namespace { struct LVFlags { bool ConsiderGlobalVisibility; bool ConsiderVisibilityAttributes; + bool ConsiderTemplateParameterTypes; LVFlags() : ConsiderGlobalVisibility(true), - ConsiderVisibilityAttributes(true) { + ConsiderVisibilityAttributes(true), + ConsiderTemplateParameterTypes(true) { } /// \brief Returns a set of flags that is only useful for computing the @@ -111,6 +94,7 @@ struct LVFlags { LVFlags F; F.ConsiderGlobalVisibility = false; F.ConsiderVisibilityAttributes = false; + F.ConsiderTemplateParameterTypes = false; return F; } @@ -120,6 +104,7 @@ struct LVFlags { LVFlags F = *this; F.ConsiderGlobalVisibility = false; F.ConsiderVisibilityAttributes = false; + F.ConsiderTemplateParameterTypes = false; return F; } }; @@ -282,8 +267,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { LinkageInfo LV; if (F.ConsiderVisibilityAttributes) { - if (const VisibilityAttr *VA = GetExplicitVisibility(D)) { - LV.setVisibility(GetVisibilityFromAttr(VA), true); + if (llvm::Optional Vis = D->getExplicitVisibility()) { + LV.setVisibility(*Vis, true); F.ConsiderGlobalVisibility = false; } else { // If we're declared in a namespace with a visibility attribute, @@ -292,9 +277,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { !isa(DC); DC = DC->getParent()) { if (!isa(DC)) continue; - if (const VisibilityAttr *VA = - cast(DC)->getAttr()) { - LV.setVisibility(GetVisibilityFromAttr(VA), false); + if (llvm::Optional Vis + = cast(DC)->getExplicitVisibility()) { + LV.setVisibility(*Vis, false); F.ConsiderGlobalVisibility = false; break; } @@ -420,7 +405,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // has the typedef name for linkage purposes (7.1.3); or } else if (const TagDecl *Tag = dyn_cast(D)) { // Unnamed tags have no linkage. - if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl()) + if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) return LinkageInfo::none(); // If this is a class template specialization, consider the @@ -451,8 +436,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // - a template, unless it is a function template that has // internal linkage (Clause 14); - } else if (const TemplateDecl *Template = dyn_cast(D)) { - LV.merge(getLVForTemplateParameterList(Template->getTemplateParameters())); + } else if (const TemplateDecl *temp = dyn_cast(D)) { + if (F.ConsiderTemplateParameterTypes) + LV.merge(getLVForTemplateParameterList(temp->getTemplateParameters())); // - a namespace (7.3), unless it is declared within an unnamed // namespace. @@ -491,7 +477,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { isa(D) || isa(D) || (isa(D) && - (D->getDeclName() || cast(D)->getTypedefForAnonDecl())))) + (D->getDeclName() || cast(D)->getTypedefNameForAnonDecl())))) return LinkageInfo::none(); LinkageInfo LV; @@ -501,8 +487,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { // If we have an explicit visibility attribute, merge that in. if (F.ConsiderVisibilityAttributes) { - if (const VisibilityAttr *VA = GetExplicitVisibility(D)) { - LV.mergeVisibility(GetVisibilityFromAttr(VA), true); + if (llvm::Optional Vis = D->getExplicitVisibility()) { + LV.mergeVisibility(*Vis, true); // Ignore global visibility later, but not this attribute. F.ConsiderGlobalVisibility = false; @@ -536,7 +522,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { if (FunctionTemplateSpecializationInfo *Spec = MD->getTemplateSpecializationInfo()) { LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments, F)); - LV.merge(getLVForTemplateParameterList( + if (F.ConsiderTemplateParameterTypes) + LV.merge(getLVForTemplateParameterList( Spec->getTemplate()->getTemplateParameters())); TSK = Spec->getTemplateSpecializationKind(); @@ -571,7 +558,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { // Merge template argument/parameter information for member // class template specializations. LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs(), F)); - LV.merge(getLVForTemplateParameterList( + if (F.ConsiderTemplateParameterTypes) + LV.merge(getLVForTemplateParameterList( Spec->getSpecializedTemplate()->getTemplateParameters())); } @@ -632,10 +620,12 @@ void NamedDecl::ClearLinkageCache() { // Clear cached linkage for function template decls, too. if (FunctionTemplateDecl *temp = - dyn_cast(const_cast(this))) + dyn_cast(const_cast(this))) { + temp->getTemplatedDecl()->ClearLinkageCache(); for (FunctionTemplateDecl::spec_iterator i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) i->ClearLinkageCache(); + } } @@ -660,6 +650,41 @@ LinkageInfo NamedDecl::getLinkageAndVisibility() const { return LI; } +llvm::Optional NamedDecl::getExplicitVisibility() const { + // Use the most recent declaration of a variable. + if (const VarDecl *var = dyn_cast(this)) + return getVisibilityOf(var->getMostRecentDeclaration()); + + // Use the most recent declaration of a function, and also handle + // function template specializations. + if (const FunctionDecl *fn = dyn_cast(this)) { + if (llvm::Optional V + = getVisibilityOf(fn->getMostRecentDeclaration())) + return V; + + // If the function is a specialization of a template with an + // explicit visibility attribute, use that. + if (FunctionTemplateSpecializationInfo *templateInfo + = fn->getTemplateSpecializationInfo()) + return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl()); + + return llvm::Optional(); + } + + // Otherwise, just check the declaration itself first. + if (llvm::Optional V = getVisibilityOf(this)) + return V; + + // If there wasn't explicit visibility there, and this is a + // specialization of a class template, check for visibility + // on the pattern. + if (const ClassTemplateSpecializationDecl *spec + = dyn_cast(this)) + return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl()); + + return llvm::Optional(); +} + static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { // Objective-C: treat all Objective-C declarations as having external // linkage. @@ -713,8 +738,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { LinkageInfo LV; if (Flags.ConsiderVisibilityAttributes) { - if (const VisibilityAttr *VA = GetExplicitVisibility(Function)) - LV.setVisibility(GetVisibilityFromAttr(VA)); + if (llvm::Optional Vis = Function->getExplicitVisibility()) + LV.setVisibility(*Vis); } if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) { @@ -736,8 +761,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { if (Var->getStorageClass() == SC_PrivateExtern) LV.setVisibility(HiddenVisibility); else if (Flags.ConsiderVisibilityAttributes) { - if (const VisibilityAttr *VA = GetExplicitVisibility(Var)) - LV.setVisibility(GetVisibilityFromAttr(VA)); + if (llvm::Optional Vis = Var->getExplicitVisibility()) + LV.setVisibility(*Vis); } if (const VarDecl *Prev = Var->getPreviousDeclaration()) { @@ -954,28 +979,97 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). if (hasExtInfo()) { - // Save type source info pointer. - TypeSourceInfo *savedTInfo = getExtInfo()->TInfo; - // Deallocate the extended decl info. - getASTContext().Deallocate(getExtInfo()); - // Restore savedTInfo into (non-extended) decl info. - DeclInfo = savedTInfo; + if (getExtInfo()->NumTemplParamLists == 0) { + // Save type source info pointer. + TypeSourceInfo *savedTInfo = getExtInfo()->TInfo; + // Deallocate the extended decl info. + getASTContext().Deallocate(getExtInfo()); + // Restore savedTInfo into (non-extended) decl info. + DeclInfo = savedTInfo; + } + else + getExtInfo()->QualifierLoc = QualifierLoc; } } } +void +DeclaratorDecl::setTemplateParameterListsInfo(ASTContext &Context, + unsigned NumTPLists, + TemplateParameterList **TPLists) { + assert(NumTPLists > 0); + // Make sure the extended decl info is allocated. + if (!hasExtInfo()) { + // Save (non-extended) type source info pointer. + TypeSourceInfo *savedTInfo = DeclInfo.get(); + // Allocate external info struct. + DeclInfo = new (getASTContext()) ExtInfo; + // Restore savedTInfo into (extended) decl info. + getExtInfo()->TInfo = savedTInfo; + } + // Set the template parameter lists info. + getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); +} + SourceLocation DeclaratorDecl::getOuterLocStart() const { return getTemplateOrInnerLocStart(this); } +namespace { + +// Helper function: returns true if QT is or contains a type +// having a postfix component. +bool typeIsPostfix(clang::QualType QT) { + while (true) { + const Type* T = QT.getTypePtr(); + switch (T->getTypeClass()) { + default: + return false; + case Type::Pointer: + QT = cast(T)->getPointeeType(); + break; + case Type::BlockPointer: + QT = cast(T)->getPointeeType(); + break; + case Type::MemberPointer: + QT = cast(T)->getPointeeType(); + break; + case Type::LValueReference: + case Type::RValueReference: + QT = cast(T)->getPointeeType(); + break; + case Type::PackExpansion: + QT = cast(T)->getPattern(); + break; + case Type::Paren: + case Type::ConstantArray: + case Type::DependentSizedArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::FunctionProto: + case Type::FunctionNoProto: + return true; + } + } +} + +} // namespace + +SourceRange DeclaratorDecl::getSourceRange() const { + SourceLocation RangeEnd = getLocation(); + if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { + if (typeIsPostfix(TInfo->getType())) + RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); + } + return SourceRange(getOuterLocStart(), RangeEnd); +} + void QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, TemplateParameterList **TPLists) { assert((NumTPLists == 0 || TPLists != 0) && "Empty array of template parameters with positive size!"); - assert((NumTPLists == 0 || QualifierLoc) && - "Nonempty array of template parameters with no qualifier!"); // Free previous template parameters (if any). if (NumTemplParamLists > 0) { @@ -1010,10 +1104,11 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { return 0; } -VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, +VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartL, SourceLocation IdL, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten) { - return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S, SCAsWritten); + return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S, SCAsWritten); } void VarDecl::setStorageClass(StorageClass SC) { @@ -1021,20 +1116,13 @@ void VarDecl::setStorageClass(StorageClass SC) { if (getStorageClass() != SC) ClearLinkageCache(); - SClass = SC; -} - -SourceLocation VarDecl::getInnerLocStart() const { - SourceLocation Start = getTypeSpecStartLoc(); - if (Start.isInvalid()) - Start = getLocation(); - return Start; + VarDeclBits.SClass = SC; } SourceRange VarDecl::getSourceRange() const { if (getInit()) return SourceRange(getOuterLocStart(), getInit()->getLocEnd()); - return SourceRange(getOuterLocStart(), getLocation()); + return DeclaratorDecl::getSourceRange(); } bool VarDecl::isExternC() const { @@ -1250,11 +1338,12 @@ void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, //===----------------------------------------------------------------------===// ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, Expr *DefArg) { - return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, TInfo, + return new (C) ParmVarDecl(ParmVar, DC, StartLoc, IdLoc, Id, T, TInfo, S, SCAsWritten, DefArg); } @@ -1324,7 +1413,7 @@ bool FunctionDecl::isVariadic() const { bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { - if (I->Body) { + if (I->Body || I->IsLateTemplateParsed) { Definition = *I; return true; } @@ -1338,6 +1427,9 @@ Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { if (I->Body) { Definition = *I; return I->Body.get(getASTContext().getExternalSource()); + } else if (I->IsLateTemplateParsed) { + Definition = *I; + return 0; } } @@ -1804,7 +1896,7 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, // Insert this function template specialization into the set of known // function template specializations. if (InsertPos) - Template->getSpecializations().InsertNode(Info, InsertPos); + Template->addSpecialization(Info, InsertPos); else { // Try to insert the new node. If there is an existing node, leave it, the // set will contain the canonical decls while @@ -1925,14 +2017,20 @@ bool FunctionDecl::isOutOfLine() const { return false; } +SourceRange FunctionDecl::getSourceRange() const { + return SourceRange(getOuterLocStart(), EndRangeLoc); +} + //===----------------------------------------------------------------------===// // FieldDecl Implementation //===----------------------------------------------------------------------===// FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, QualType T, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable) { - return new (C) FieldDecl(Decl::Field, DC, L, Id, T, TInfo, BW, Mutable); + return new (C) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo, + BW, Mutable); } bool FieldDecl::isAnonymousStructOrUnion() const { @@ -1949,13 +2047,25 @@ unsigned FieldDecl::getFieldIndex() const { if (CachedFieldIndex) return CachedFieldIndex - 1; unsigned index = 0; - RecordDecl::field_iterator - i = getParent()->field_begin(), e = getParent()->field_end(); + const RecordDecl *RD = getParent(); + const FieldDecl *LastFD = 0; + bool IsMsStruct = RD->hasAttr(); + + RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); while (true) { assert(i != e && "failed to find field in parent!"); if (*i == this) break; + if (IsMsStruct) { + // Zero-length bitfields following non-bitfield members are ignored. + if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD) || + getASTContext().ZeroBitfieldFollowsBitfield((*i), LastFD)) { + ++i; + continue; + } + LastFD = (*i); + } ++i; ++index; } @@ -1964,6 +2074,12 @@ unsigned FieldDecl::getFieldIndex() const { return index; } +SourceRange FieldDecl::getSourceRange() const { + if (isBitField()) + return SourceRange(getInnerLocStart(), BitWidth->getLocEnd()); + return DeclaratorDecl::getSourceRange(); +} + //===----------------------------------------------------------------------===// // TagDecl Implementation //===----------------------------------------------------------------------===// @@ -1981,8 +2097,8 @@ TagDecl* TagDecl::getCanonicalDecl() { return getFirstDeclaration(); } -void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) { - TypedefDeclOrQualifier = TDD; +void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { + TypedefNameDeclOrQualifier = TDD; if (TypeForDecl) const_cast(TypeForDecl)->ClearLinkageCache(); ClearLinkageCache(); @@ -2030,35 +2146,52 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (QualifierLoc) { // Make sure the extended qualifier info is allocated. if (!hasExtInfo()) - TypedefDeclOrQualifier = new (getASTContext()) ExtInfo; + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; } else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). if (hasExtInfo()) { - getASTContext().Deallocate(getExtInfo()); - TypedefDeclOrQualifier = (TypedefDecl*) 0; + if (getExtInfo()->NumTemplParamLists == 0) { + getASTContext().Deallocate(getExtInfo()); + TypedefNameDeclOrQualifier = (TypedefNameDecl*) 0; + } + else + getExtInfo()->QualifierLoc = QualifierLoc; } } } +void TagDecl::setTemplateParameterListsInfo(ASTContext &Context, + unsigned NumTPLists, + TemplateParameterList **TPLists) { + assert(NumTPLists > 0); + // Make sure the extended decl info is allocated. + if (!hasExtInfo()) + // Allocate external info struct. + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; + // Set the template parameter lists info. + getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); +} + //===----------------------------------------------------------------------===// // EnumDecl Implementation //===----------------------------------------------------------------------===// -EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, SourceLocation TKL, +EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed) { - EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL, + EnumDecl *Enum = new (C) EnumDecl(DC, StartLoc, IdLoc, Id, PrevDecl, IsScoped, IsScopedUsingClassTag, IsFixed); C.getTypeDeclType(Enum, PrevDecl); return Enum; } EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation(), + return new (C) EnumDecl(0, SourceLocation(), SourceLocation(), 0, 0, false, false, false); } @@ -2079,10 +2212,10 @@ void EnumDecl::completeDefinition(QualType NewType, // RecordDecl Implementation //===----------------------------------------------------------------------===// -RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, RecordDecl *PrevDecl, - SourceLocation TKL) - : TagDecl(DK, TK, DC, L, Id, PrevDecl, TKL) { +RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, RecordDecl *PrevDecl) + : TagDecl(DK, TK, DC, IdLoc, Id, PrevDecl, StartLoc) { HasFlexibleArrayMember = false; AnonymousStructOrUnion = false; HasObjectMember = false; @@ -2091,17 +2224,17 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, } RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL, RecordDecl* PrevDecl) { - - RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id, PrevDecl, TKL); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, RecordDecl* PrevDecl) { + RecordDecl* R = new (C) RecordDecl(Record, TK, DC, StartLoc, IdLoc, Id, + PrevDecl); C.getTypeDeclType(R, PrevDecl); return R; } RecordDecl *RecordDecl::Create(const ASTContext &C, EmptyShell Empty) { - return new (C) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), 0, 0, - SourceLocation()); + return new (C) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), + SourceLocation(), 0, 0); } bool RecordDecl::isInjectedClassName() const { @@ -2200,14 +2333,22 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { } LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *II) { - return new (C) LabelDecl(DC, L, II, 0); + SourceLocation IdentL, IdentifierInfo *II) { + return new (C) LabelDecl(DC, IdentL, II, 0, IdentL); +} + +LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation IdentL, IdentifierInfo *II, + SourceLocation GnuLabelL) { + assert(GnuLabelL != IdentL && "Use this only for GNU local labels"); + return new (C) LabelDecl(DC, IdentL, II, 0, GnuLabelL); } NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id) { - return new (C) NamespaceDecl(DC, L, Id); + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id) { + return new (C) NamespaceDecl(DC, StartLoc, IdLoc, Id); } NamespaceDecl *NamespaceDecl::getNextNamespace() { @@ -2216,20 +2357,22 @@ NamespaceDecl *NamespaceDecl::getNextNamespace() { } ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation loc, - IdentifierInfo *name, - QualType type) { - return new (C) ImplicitParamDecl(DC, loc, name, type); + SourceLocation IdLoc, + IdentifierInfo *Id, + QualType Type) { + return new (C) ImplicitParamDecl(DC, IdLoc, Id, Type); } FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass S, StorageClass SCAsWritten, + StorageClass SC, StorageClass SCAsWritten, bool isInlineSpecified, bool hasWrittenPrototype) { - FunctionDecl *New = new (C) FunctionDecl(Function, DC, NameInfo, T, TInfo, - S, SCAsWritten, isInlineSpecified); + FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo, + T, TInfo, SC, SCAsWritten, + isInlineSpecified); New->HasWrittenPrototype = hasWrittenPrototype; return New; } @@ -2260,13 +2403,37 @@ SourceRange EnumConstantDecl::getSourceRange() const { } TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - TypeSourceInfo *TInfo) { - return new (C) TypedefDecl(DC, L, Id, TInfo); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) { + return new (C) TypedefDecl(DC, StartLoc, IdLoc, Id, TInfo); +} + +TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + TypeSourceInfo *TInfo) { + return new (C) TypeAliasDecl(DC, StartLoc, IdLoc, Id, TInfo); +} + +SourceRange TypedefDecl::getSourceRange() const { + SourceLocation RangeEnd = getLocation(); + if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { + if (typeIsPostfix(TInfo->getType())) + RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); + } + return SourceRange(getLocStart(), RangeEnd); +} + +SourceRange TypeAliasDecl::getSourceRange() const { + SourceLocation RangeEnd = getLocStart(); + if (TypeSourceInfo *TInfo = getTypeSourceInfo()) + RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); + return SourceRange(getLocStart(), RangeEnd); } FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - StringLiteral *Str) { - return new (C) FileScopeAsmDecl(DC, L, Str); + StringLiteral *Str, + SourceLocation AsmLoc, + SourceLocation RParenLoc) { + return new (C) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 81df00d6c7e8..6d517c544089 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -25,11 +25,11 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" #include #include -#include using namespace clang; //===----------------------------------------------------------------------===// @@ -173,9 +173,6 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const { Decl::~Decl() { } void Decl::setDeclContext(DeclContext *DC) { - if (isOutOfSemaDC()) - delete getMultipleDC(); - DeclCtx = DC; } @@ -244,6 +241,177 @@ bool Decl::isUsed(bool CheckUsedAttr) const { return false; } +bool Decl::isReferenced() const { + if (Referenced) + return true; + + // Check redeclarations. + for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) + if (I->Referenced) + return true; + + return false; +} + +/// \brief Determine the availability of the given declaration based on +/// the target platform. +/// +/// When it returns an availability result other than \c AR_Available, +/// if the \p Message parameter is non-NULL, it will be set to a +/// string describing why the entity is unavailable. +/// +/// FIXME: Make these strings localizable, since they end up in +/// diagnostics. +static AvailabilityResult CheckAvailability(ASTContext &Context, + const AvailabilityAttr *A, + std::string *Message) { + llvm::StringRef TargetPlatform = Context.Target.getPlatformName(); + llvm::StringRef PrettyPlatformName + = AvailabilityAttr::getPrettyPlatformName(TargetPlatform); + if (PrettyPlatformName.empty()) + PrettyPlatformName = TargetPlatform; + + VersionTuple TargetMinVersion = Context.Target.getPlatformMinVersion(); + if (TargetMinVersion.empty()) + return AR_Available; + + // Match the platform name. + if (A->getPlatform()->getName() != TargetPlatform) + return AR_Available; + + // Make sure that this declaration has not been marked 'unavailable'. + if (A->getUnavailable()) { + if (Message) { + Message->clear(); + llvm::raw_string_ostream Out(*Message); + Out << "not available on " << PrettyPlatformName; + } + + return AR_Unavailable; + } + + // Make sure that this declaration has already been introduced. + if (!A->getIntroduced().empty() && + TargetMinVersion < A->getIntroduced()) { + if (Message) { + Message->clear(); + llvm::raw_string_ostream Out(*Message); + Out << "introduced in " << PrettyPlatformName << ' ' + << A->getIntroduced(); + } + + return AR_NotYetIntroduced; + } + + // Make sure that this declaration hasn't been obsoleted. + if (!A->getObsoleted().empty() && TargetMinVersion >= A->getObsoleted()) { + if (Message) { + Message->clear(); + llvm::raw_string_ostream Out(*Message); + Out << "obsoleted in " << PrettyPlatformName << ' ' + << A->getObsoleted(); + } + + return AR_Unavailable; + } + + // Make sure that this declaration hasn't been deprecated. + if (!A->getDeprecated().empty() && TargetMinVersion >= A->getDeprecated()) { + if (Message) { + Message->clear(); + llvm::raw_string_ostream Out(*Message); + Out << "first deprecated in " << PrettyPlatformName << ' ' + << A->getDeprecated(); + } + + return AR_Deprecated; + } + + return AR_Available; +} + +AvailabilityResult Decl::getAvailability(std::string *Message) const { + AvailabilityResult Result = AR_Available; + std::string ResultMessage; + + for (attr_iterator A = attr_begin(), AEnd = attr_end(); A != AEnd; ++A) { + if (DeprecatedAttr *Deprecated = dyn_cast(*A)) { + if (Result >= AR_Deprecated) + continue; + + if (Message) + ResultMessage = Deprecated->getMessage(); + + Result = AR_Deprecated; + continue; + } + + if (UnavailableAttr *Unavailable = dyn_cast(*A)) { + if (Message) + *Message = Unavailable->getMessage(); + return AR_Unavailable; + } + + if (AvailabilityAttr *Availability = dyn_cast(*A)) { + AvailabilityResult AR = CheckAvailability(getASTContext(), Availability, + Message); + + if (AR == AR_Unavailable) + return AR_Unavailable; + + if (AR > Result) { + Result = AR; + if (Message) + ResultMessage.swap(*Message); + } + continue; + } + } + + if (Message) + Message->swap(ResultMessage); + return Result; +} + +bool Decl::canBeWeakImported(bool &IsDefinition) const { + IsDefinition = false; + if (const VarDecl *Var = dyn_cast(this)) { + if (!Var->hasExternalStorage() || Var->getInit()) { + IsDefinition = true; + return false; + } + } else if (const FunctionDecl *FD = dyn_cast(this)) { + if (FD->hasBody()) { + IsDefinition = true; + return false; + } + } else if (isa(this) || isa(this)) + return false; + else if (!(getASTContext().getLangOptions().ObjCNonFragileABI && + isa(this))) + return false; + + return true; +} + +bool Decl::isWeakImported() const { + bool IsDefinition; + if (!canBeWeakImported(IsDefinition)) + return false; + + for (attr_iterator A = attr_begin(), AEnd = attr_end(); A != AEnd; ++A) { + if (isa(*A)) + return true; + + if (AvailabilityAttr *Availability = dyn_cast(*A)) { + if (CheckAvailability(getASTContext(), Availability, 0) + == AR_NotYetIntroduced) + return true; + } + } + + return false; +} unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { switch (DeclKind) { @@ -270,6 +438,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { return IDNS_Ordinary | IDNS_Type; case Typedef: + case TypeAlias: case UnresolvedUsingTypename: case TemplateTypeParm: return IDNS_Ordinary | IDNS_Type; @@ -960,7 +1129,7 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) { // FIXME: This feels like a hack. Should DeclarationName support // template-ids, or is there a better way to keep specializations // from being visible? - if (isa(D)) + if (isa(D) || D->isTemplateParameter()) return; if (FunctionDecl *FD = dyn_cast(D)) if (FD->isFunctionTemplateSpecialization()) @@ -999,7 +1168,7 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) { // FIXME: This feels like a hack. Should DeclarationName support // template-ids, or is there a better way to keep specializations // from being visible? - if (isa(D)) + if (isa(D) || D->isTemplateParameter()) return; ASTContext *C = 0; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index 46768c12d879..9099cd524f1a 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -31,9 +31,13 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false), Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), - Abstract(false), HasTrivialConstructor(true), - HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true), - HasTrivialDestructor(true), ComputedVisibleConversions(false), + Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), + HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), + HasTrivialConstructor(true), HasConstExprNonCopyMoveConstructor(false), + HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true), + HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true), + HasTrivialDestructor(true), HasNonLiteralTypeFieldsOrBases(false), + ComputedVisibleConversions(false), DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), DeclaredCopyAssignment(false), DeclaredDestructor(false), NumBases(0), NumVBases(0), Bases(), VBases(), @@ -41,20 +45,19 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) } CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - CXXRecordDecl *PrevDecl, - SourceLocation TKL) - : RecordDecl(K, TK, DC, L, Id, PrevDecl, TKL), + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, CXXRecordDecl *PrevDecl) + : RecordDecl(K, TK, DC, StartLoc, IdLoc, Id, PrevDecl), DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0), TemplateOrInstantiation() { } CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, - DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, SourceLocation TKL, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl* PrevDecl, bool DelayTypeCreation) { - CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, L, Id, - PrevDecl, TKL); + CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, StartLoc, IdLoc, + Id, PrevDecl); // FIXME: DelayTypeCreation seems like such a hack if (!DelayTypeCreation) @@ -63,8 +66,8 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, } CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, EmptyShell Empty) { - return new (C) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), 0, 0, - SourceLocation()); + return new (C) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), + SourceLocation(), 0, 0); } void @@ -109,14 +112,38 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // A class with a non-empty base class is not empty. // FIXME: Standard ref? - if (!BaseClassDecl->isEmpty()) + if (!BaseClassDecl->isEmpty()) { + if (!data().Empty) { + // C++0x [class]p7: + // A standard-layout class is a class that: + // [...] + // -- either has no non-static data members in the most derived + // class and at most one base class with non-static data members, + // or has no base classes with non-static data members, and + // If this is the second non-empty base, then neither of these two + // clauses can be true. + data().IsStandardLayout = false; + } + data().Empty = false; + data().HasNoNonEmptyBases = false; + } // C++ [class.virtual]p1: // A class that declares or inherits a virtual function is called a // polymorphic class. if (BaseClassDecl->isPolymorphic()) data().Polymorphic = true; + + // C++0x [class]p7: + // A standard-layout class is a class that: [...] + // -- has no non-standard-layout base classes + if (!BaseClassDecl->isStandardLayout()) + data().IsStandardLayout = false; + + // Record if this base is the first non-literal field or base. + if (!hasNonLiteralTypeFieldsOrBases() && !BaseType->isLiteralType()) + data().HasNonLiteralTypeFieldsOrBases = true; // Now go through all virtual bases of this base and add them. for (CXXRecordDecl::base_class_iterator VBase = @@ -140,16 +167,25 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // C++ [class.ctor]p5: // A constructor is trivial if its class has no virtual base classes. data().HasTrivialConstructor = false; - - // C++ [class.copy]p6: - // A copy constructor is trivial if its class has no virtual base - // classes. + + // C++0x [class.copy]p13: + // A copy/move constructor for class X is trivial if it is neither + // user-provided nor deleted and if + // -- class X has no virtual functions and no virtual base classes, and data().HasTrivialCopyConstructor = false; - - // C++ [class.copy]p11: - // A copy assignment operator is trivial if its class has no virtual - // base classes. + data().HasTrivialMoveConstructor = false; + + // C++0x [class.copy]p27: + // A copy/move assignment operator for class X is trivial if it is + // neither user-provided nor deleted and if + // -- class X has no virtual functions and no virtual base classes, and data().HasTrivialCopyAssignment = false; + data().HasTrivialMoveAssignment = false; + + // C++0x [class]p7: + // A standard-layout class is a class that: [...] + // -- has [...] no virtual base classes + data().IsStandardLayout = false; } else { // C++ [class.ctor]p5: // A constructor is trivial if all the direct base classes of its @@ -157,17 +193,29 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (!BaseClassDecl->hasTrivialConstructor()) data().HasTrivialConstructor = false; - // C++ [class.copy]p6: - // A copy constructor is trivial if all the direct base classes of its - // class have trivial copy constructors. + // C++0x [class.copy]p13: + // A copy/move constructor for class X is trivial if [...] + // [...] + // -- the constructor selected to copy/move each direct base class + // subobject is trivial, and + // FIXME: C++0x: We need to only consider the selected constructor + // instead of all of them. if (!BaseClassDecl->hasTrivialCopyConstructor()) data().HasTrivialCopyConstructor = false; - - // C++ [class.copy]p11: - // A copy assignment operator is trivial if all the direct base classes - // of its class have trivial copy assignment operators. + if (!BaseClassDecl->hasTrivialMoveConstructor()) + data().HasTrivialMoveConstructor = false; + + // C++0x [class.copy]p27: + // A copy/move assignment operator for class X is trivial if [...] + // [...] + // -- the assignment operator selected to copy/move each direct base + // class subobject is trivial, and + // FIXME: C++0x: We need to only consider the selected operator instead + // of all of them. if (!BaseClassDecl->hasTrivialCopyAssignment()) data().HasTrivialCopyAssignment = false; + if (!BaseClassDecl->hasTrivialMoveAssignment()) + data().HasTrivialMoveAssignment = false; } // C++ [class.ctor]p3: @@ -218,6 +266,23 @@ bool CXXRecordDecl::hasConstCopyConstructor(const ASTContext &Context) const { return getCopyConstructor(Context, Qualifiers::Const) != 0; } +bool CXXRecordDecl::isTriviallyCopyable() const { + // C++0x [class]p5: + // A trivially copyable class is a class that: + // -- has no non-trivial copy constructors, + if (!hasTrivialCopyConstructor()) return false; + // -- has no non-trivial move constructors, + if (!hasTrivialMoveConstructor()) return false; + // -- has no non-trivial copy assignment operators, + if (!hasTrivialCopyAssignment()) return false; + // -- has no non-trivial move assignment operators, and + if (!hasTrivialMoveAssignment()) return false; + // -- has a trivial destructor. + if (!hasTrivialDestructor()) return false; + + return true; +} + /// \brief Perform a simplistic form of overload resolution that only considers /// cv-qualifiers on a single parameter, and return the best overload candidate /// (if there is one). @@ -231,11 +296,11 @@ GetBestOverloadCandidateSimple( unsigned Best = 0, N = Cands.size(); for (unsigned I = 1; I != N; ++I) - if (Cands[Best].second.isSupersetOf(Cands[I].second)) + if (Cands[Best].second.compatiblyIncludes(Cands[I].second)) Best = I; for (unsigned I = 1; I != N; ++I) - if (Cands[Best].second.isSupersetOf(Cands[I].second)) + if (Cands[Best].second.compatiblyIncludes(Cands[I].second)) return 0; return Cands[Best].first; @@ -358,9 +423,24 @@ void CXXRecordDecl::addedMember(Decl *D) { // None of the special member functions are trivial. data().HasTrivialConstructor = false; + + // C++0x [class.copy]p13: + // A copy/move constructor for class X is trivial if [...] + // -- class X has no virtual functions [...] data().HasTrivialCopyConstructor = false; + data().HasTrivialMoveConstructor = false; + + // C++0x [class.copy]p27: + // A copy/move assignment operator for class X is trivial if [...] + // -- class X has no virtual functions [...] data().HasTrivialCopyAssignment = false; + data().HasTrivialMoveAssignment = false; // FIXME: Destructor? + + // C++0x [class]p7: + // A standard-layout class is a class that: [...] + // -- has no virtual functions + data().IsStandardLayout = false; } } @@ -423,18 +503,33 @@ void CXXRecordDecl::addedMember(Decl *D) { // FIXME: C++0x: don't do this for "= default" default constructors. data().HasTrivialConstructor = false; - // Note when we have a user-declared copy constructor, which will - // suppress the implicit declaration of a copy constructor. - if (!FunTmpl && Constructor->isCopyConstructor()) { - data().UserDeclaredCopyConstructor = true; - data().DeclaredCopyConstructor = true; - - // C++ [class.copy]p6: - // A copy constructor is trivial if it is implicitly declared. - // FIXME: C++0x: don't do this for "= default" copy constructors. - data().HasTrivialCopyConstructor = false; + // Note when we have a user-declared copy or move constructor, which will + // suppress the implicit declaration of those constructors. + if (!FunTmpl) { + if (Constructor->isCopyConstructor()) { + data().UserDeclaredCopyConstructor = true; + data().DeclaredCopyConstructor = true; + + // C++0x [class.copy]p13: + // A copy/move constructor for class X is trivial if it is neither + // user-provided nor deleted + // FIXME: C++0x: don't do this for "= default" copy constructors. + data().HasTrivialCopyConstructor = false; + } else if (Constructor->isMoveConstructor()) { + // C++0x [class.copy]p13: + // A copy/move constructor for class X is trivial if it is neither + // user-provided nor deleted + // FIXME: C++0x: don't do this for "= default" move constructors. + data().HasTrivialMoveConstructor = false; + } } - + if (Constructor->isConstExpr() && + !Constructor->isCopyOrMoveConstructor()) { + // Record if we see any constexpr constructors which are niether copy + // nor move constructors. + data().HasConstExprNonCopyMoveConstructor = true; + } + return; } @@ -472,35 +567,53 @@ void CXXRecordDecl::addedMember(Decl *D) { return; ASTContext &Context = getASTContext(); - QualType ArgType = FnType->getArgType(0); - if (const LValueReferenceType *Ref =ArgType->getAs()) - ArgType = Ref->getPointeeType(); - - ArgType = ArgType.getUnqualifiedType(); QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( const_cast(this))); - + + bool isRValueRefArg = false; + QualType ArgType = FnType->getArgType(0); + if (const LValueReferenceType *Ref = + ArgType->getAs()) { + ArgType = Ref->getPointeeType(); + } else if (const RValueReferenceType *Ref = + ArgType->getAs()) { + ArgType = Ref->getPointeeType(); + isRValueRefArg = true; + } if (!Context.hasSameUnqualifiedType(ClassType, ArgType)) return; - - // This is a copy assignment operator. - // FIXME: Move assignment operators. - - // Suppress the implicit declaration of a copy constructor. - data().UserDeclaredCopyAssignment = true; - data().DeclaredCopyAssignment = true; - - // C++ [class.copy]p11: - // A copy assignment operator is trivial if it is implicitly declared. - // FIXME: C++0x: don't do this for "= default" copy operators. - data().HasTrivialCopyAssignment = false; - + // C++ [class]p4: - // A POD-struct is an aggregate class that [...] has no user-defined copy - // assignment operator [...]. + // A POD-struct is an aggregate class that [...] has no user-defined + // copy assignment operator [...]. + // FIXME: This should be probably determined dynamically in terms of + // other more precise attributes to correctly model how it is specified + // in C++0x. Setting it here happens to do the right thing. data().PlainOldData = false; + + if (!isRValueRefArg) { + // This is a copy assignment operator. + + // Suppress the implicit declaration of a copy constructor. + data().UserDeclaredCopyAssignment = true; + data().DeclaredCopyAssignment = true; + + // C++0x [class.copy]p27: + // A copy/move assignment operator for class X is trivial if it is + // neither user-provided nor deleted [...] + // FIXME: C++0x: don't do this for "= default" copy operators. + data().HasTrivialCopyAssignment = false; + } else { + // This is a move assignment operator. + + // C++0x [class.copy]p27: + // A copy/move assignment operator for class X is trivial if it is + // neither user-provided nor deleted [...] + // FIXME: C++0x: don't do this for "= default" copy operators. + data().HasTrivialMoveAssignment = false; + } } - + // Keep the list of conversion functions up-to-date. if (CXXConversionDecl *Conversion = dyn_cast(D)) { // We don't record specializations. @@ -539,8 +652,22 @@ void CXXRecordDecl::addedMember(Decl *D) { data().Aggregate = false; data().PlainOldData = false; } - - // C++ [class]p9: + + // C++0x [class]p7: + // A standard-layout class is a class that: + // [...] + // -- has the same access control for all non-static data members, + switch (D->getAccess()) { + case AS_private: data().HasPrivateFields = true; break; + case AS_protected: data().HasProtectedFields = true; break; + case AS_public: data().HasPublicFields = true; break; + case AS_none: assert(0 && "Invalid access specifier"); + }; + if ((data().HasPrivateFields + data().HasProtectedFields + + data().HasPublicFields) > 1) + data().IsStandardLayout = false; + + // C++0x [class]p9: // A POD struct is a class that is both a trivial class and a // standard-layout class, and has no non-static data members of type // non-POD struct, non-POD union (or array of such types). @@ -548,23 +675,98 @@ void CXXRecordDecl::addedMember(Decl *D) { QualType T = Context.getBaseElementType(Field->getType()); if (!T->isPODType()) data().PlainOldData = false; - if (T->isReferenceType()) + if (T->isReferenceType()) { data().HasTrivialConstructor = false; - + + // C++0x [class]p7: + // A standard-layout class is a class that: + // -- has no non-static data members of type [...] reference, + data().IsStandardLayout = false; + } + + // Record if this field is the first non-literal field or base. + if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) + data().HasNonLiteralTypeFieldsOrBases = true; + if (const RecordType *RecordTy = T->getAs()) { CXXRecordDecl* FieldRec = cast(RecordTy->getDecl()); if (FieldRec->getDefinition()) { if (!FieldRec->hasTrivialConstructor()) data().HasTrivialConstructor = false; + + // C++0x [class.copy]p13: + // A copy/move constructor for class X is trivial if [...] + // [...] + // -- for each non-static data member of X that is of class type (or + // an array thereof), the constructor selected to copy/move that + // member is trivial; + // FIXME: C++0x: We don't correctly model 'selected' constructors. if (!FieldRec->hasTrivialCopyConstructor()) data().HasTrivialCopyConstructor = false; + if (!FieldRec->hasTrivialMoveConstructor()) + data().HasTrivialMoveConstructor = false; + + // C++0x [class.copy]p27: + // A copy/move assignment operator for class X is trivial if [...] + // [...] + // -- for each non-static data member of X that is of class type (or + // an array thereof), the assignment operator selected to + // copy/move that member is trivial; + // FIXME: C++0x: We don't correctly model 'selected' operators. if (!FieldRec->hasTrivialCopyAssignment()) data().HasTrivialCopyAssignment = false; + if (!FieldRec->hasTrivialMoveAssignment()) + data().HasTrivialMoveAssignment = false; + if (!FieldRec->hasTrivialDestructor()) data().HasTrivialDestructor = false; + + // C++0x [class]p7: + // A standard-layout class is a class that: + // -- has no non-static data members of type non-standard-layout + // class (or array of such types) [...] + if (!FieldRec->isStandardLayout()) + data().IsStandardLayout = false; + + // C++0x [class]p7: + // A standard-layout class is a class that: + // [...] + // -- has no base classes of the same type as the first non-static + // data member. + // We don't want to expend bits in the state of the record decl + // tracking whether this is the first non-static data member so we + // cheat a bit and use some of the existing state: the empty bit. + // Virtual bases and virtual methods make a class non-empty, but they + // also make it non-standard-layout so we needn't check here. + // A non-empty base class may leave the class standard-layout, but not + // if we have arrived here, and have at least on non-static data + // member. If IsStandardLayout remains true, then the first non-static + // data member must come through here with Empty still true, and Empty + // will subsequently be set to false below. + if (data().IsStandardLayout && data().Empty) { + for (CXXRecordDecl::base_class_const_iterator BI = bases_begin(), + BE = bases_end(); + BI != BE; ++BI) { + if (Context.hasSameUnqualifiedType(BI->getType(), T)) { + data().IsStandardLayout = false; + break; + } + } + } } } - + + // C++0x [class]p7: + // A standard-layout class is a class that: + // [...] + // -- either has no non-static data members in the most derived + // class and at most one base class with non-static data members, + // or has no base classes with non-static data members, and + // At this point we know that we have a non-static data member, so the last + // clause holds. + if (!data().HasNoNonEmptyBases) + data().IsStandardLayout = false; + // If this is not a zero-length bit-field, then the class is not empty. if (data().Empty) { if (!Field->getBitWidth()) @@ -814,8 +1016,6 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { return 0; CXXDestructorDecl *Dtor = cast(*I); - assert(++I == E && "Found more than one destructor!"); - return Dtor; } @@ -884,11 +1084,13 @@ bool CXXRecordDecl::mayBeAbstract() const { CXXMethodDecl * CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic, StorageClass SCAsWritten, bool isInline) { - return new (C) CXXMethodDecl(CXXMethod, RD, NameInfo, T, TInfo, - isStatic, SCAsWritten, isInline); + bool isStatic, StorageClass SCAsWritten, bool isInline, + SourceLocation EndLocation) { + return new (C) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo, + isStatic, SCAsWritten, isInline, EndLocation); } bool CXXMethodDecl::isUsualDeallocationFunction() const { @@ -1032,6 +1234,16 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, { } +CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, + SourceLocation D, SourceLocation L, + CXXConstructorDecl *Target, Expr *Init, + SourceLocation R) + : Initializee(Target), MemberOrEllipsisLocation(D), Init(Init), + LParenLoc(L), RParenLoc(R), IsVirtual(false), + IsWritten(false), SourceOrderOrNumArrayIndices(0) +{ +} + CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, @@ -1076,7 +1288,7 @@ const Type *CXXCtorInitializer::getBaseClass() const { } SourceLocation CXXCtorInitializer::getSourceLocation() const { - if (isAnyMemberInitializer()) + if (isAnyMemberInitializer() || isDelegatingInitializer()) return getMemberLocation(); return getBaseClassLoc().getLocalSourceRange().getBegin(); @@ -1088,12 +1300,13 @@ SourceRange CXXCtorInitializer::getSourceRange() const { CXXConstructorDecl * CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) CXXConstructorDecl(0, DeclarationNameInfo(), + return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationNameInfo(), QualType(), 0, false, false, false); } CXXConstructorDecl * CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicit, @@ -1102,8 +1315,8 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); - return new (C) CXXConstructorDecl(RD, NameInfo, T, TInfo, isExplicit, - isInline, isImplicitlyDeclared); + return new (C) CXXConstructorDecl(RD, StartLoc, NameInfo, T, TInfo, + isExplicit, isInline, isImplicitlyDeclared); } bool CXXConstructorDecl::isDefaultConstructor() const { @@ -1222,12 +1435,13 @@ CXXConstructorDecl::setInheritedConstructor(const CXXConstructorDecl *BaseCtor){ CXXDestructorDecl * CXXDestructorDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) CXXDestructorDecl(0, DeclarationNameInfo(), + return new (C) CXXDestructorDecl(0, SourceLocation(), DeclarationNameInfo(), QualType(), 0, false, false); } CXXDestructorDecl * CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, @@ -1235,33 +1449,38 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, assert(NameInfo.getName().getNameKind() == DeclarationName::CXXDestructorName && "Name must refer to a destructor"); - return new (C) CXXDestructorDecl(RD, NameInfo, T, TInfo, isInline, + return new (C) CXXDestructorDecl(RD, StartLoc, NameInfo, T, TInfo, isInline, isImplicitlyDeclared); } CXXConversionDecl * CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) CXXConversionDecl(0, DeclarationNameInfo(), - QualType(), 0, false, false); + return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(), + QualType(), 0, false, false, + SourceLocation()); } CXXConversionDecl * CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicit) { + bool isInline, bool isExplicit, + SourceLocation EndLocation) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConversionFunctionName && "Name must refer to a conversion function"); - return new (C) CXXConversionDecl(RD, NameInfo, T, TInfo, - isInline, isExplicit); + return new (C) CXXConversionDecl(RD, StartLoc, NameInfo, T, TInfo, + isInline, isExplicit, EndLocation); } LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - LanguageIDs Lang, bool Braces) { - return new (C) LinkageSpecDecl(DC, L, Lang, Braces); + SourceLocation ExternLoc, + SourceLocation LangLoc, + LanguageIDs Lang, + SourceLocation RBraceLoc) { + return new (C) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, RBraceLoc); } UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, @@ -1364,9 +1583,12 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, } StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, Expr *AssertExpr, - StringLiteral *Message) { - return new (C) StaticAssertDecl(DC, L, AssertExpr, Message); + SourceLocation StaticAssertLoc, + Expr *AssertExpr, + StringLiteral *Message, + SourceLocation RParenLoc) { + return new (C) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message, + RParenLoc); } static const char *getAccessName(AccessSpecifier AS) { diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index 45f5188d4043..24d281e8b66d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -398,6 +398,64 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { return this; } +ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { + ObjCMethodFamily family = static_cast(Family); + if (family != static_cast(InvalidObjCMethodFamily)) + return family; + + // Check for an explicit attribute. + if (const ObjCMethodFamilyAttr *attr = getAttr()) { + // The unfortunate necessity of mapping between enums here is due + // to the attributes framework. + switch (attr->getFamily()) { + case ObjCMethodFamilyAttr::OMF_None: family = OMF_None; break; + case ObjCMethodFamilyAttr::OMF_alloc: family = OMF_alloc; break; + case ObjCMethodFamilyAttr::OMF_copy: family = OMF_copy; break; + case ObjCMethodFamilyAttr::OMF_init: family = OMF_init; break; + case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break; + case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break; + } + Family = static_cast(family); + return family; + } + + family = getSelector().getMethodFamily(); + switch (family) { + case OMF_None: break; + + // init only has a conventional meaning for an instance method, and + // it has to return an object. + case OMF_init: + if (!isInstanceMethod() || !getResultType()->isObjCObjectPointerType()) + family = OMF_None; + break; + + // alloc/copy/new have a conventional meaning for both class and + // instance methods, but they require an object return. + case OMF_alloc: + case OMF_copy: + case OMF_mutableCopy: + case OMF_new: + if (!getResultType()->isObjCObjectPointerType()) + family = OMF_None; + break; + + // These selectors have a conventional meaning only for instance methods. + case OMF_dealloc: + case OMF_retain: + case OMF_release: + case OMF_autorelease: + case OMF_retainCount: + if (!isInstanceMethod()) + family = OMF_None; + break; + } + + // Cache the result. + Family = static_cast(family); + return family; +} + void ObjCMethodDecl::createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *OID) { QualType selfTy; @@ -614,7 +672,8 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, //===----------------------------------------------------------------------===// ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, - SourceLocation L, IdentifierInfo *Id, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, bool synthesized) { @@ -651,7 +710,8 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, ID->setIvarList(0); } - return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW, synthesized); + return new (C) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, + ac, BW, synthesized); } const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { @@ -684,9 +744,10 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { //===----------------------------------------------------------------------===// ObjCAtDefsFieldDecl -*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, +*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW) { - return new (C) ObjCAtDefsFieldDecl(DC, L, Id, T, BW); + return new (C) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW); } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index c6ae128e42b5..2fd88d7c808d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -45,6 +45,7 @@ namespace { void VisitTranslationUnitDecl(TranslationUnitDecl *D); void VisitTypedefDecl(TypedefDecl *D); + void VisitTypeAliasDecl(TypeAliasDecl *D); void VisitEnumDecl(EnumDecl *D); void VisitRecordDecl(RecordDecl *D); void VisitEnumConstantDecl(EnumConstantDecl *D); @@ -54,12 +55,13 @@ namespace { void VisitLabelDecl(LabelDecl *D); void VisitParmVarDecl(ParmVarDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); + void VisitStaticAssertDecl(StaticAssertDecl *D); void VisitNamespaceDecl(NamespaceDecl *D); void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitCXXRecordDecl(CXXRecordDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); - void VisitTemplateDecl(TemplateDecl *D); + void VisitTemplateDecl(const TemplateDecl *D); void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCClassDecl(ObjCClassDecl *D); void VisitObjCImplementationDecl(ObjCImplementationDecl *D); @@ -109,7 +111,7 @@ static QualType GetBaseType(QualType T) { } static QualType getDeclType(Decl* D) { - if (TypedefDecl* TDD = dyn_cast(D)) + if (TypedefNameDecl* TDD = dyn_cast(D)) return TDD->getUnderlyingType(); if (ValueDecl* VD = dyn_cast(D)) return VD->getType(); @@ -307,6 +309,11 @@ void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { Out << S; } +void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { + Out << "using " << D->getNameAsString() << " = " + << D->getUnderlyingType().getAsString(Policy); +} + void DeclPrinter::VisitEnumDecl(EnumDecl *D) { Out << "enum "; if (D->isScoped()) { @@ -412,22 +419,32 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (TypeQuals & Qualifiers::Restrict) Proto += " restrict"; } - - if (FT && FT->hasExceptionSpec()) { + + if (FT && FT->hasDynamicExceptionSpec()) { Proto += " throw("; - if (FT->hasAnyExceptionSpec()) + if (FT->getExceptionSpecType() == EST_MSAny) Proto += "..."; else for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { if (I) Proto += ", "; - - + std::string ExceptionType; FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy); Proto += ExceptionType; } Proto += ")"; + } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) { + Proto += " noexcept"; + if (FT->getExceptionSpecType() == EST_ComputedNoexcept) { + Proto += "("; + llvm::raw_string_ostream EOut(Proto); + FT->getNoexceptExpr()->printPretty(EOut, Context, 0, SubPolicy, + Indentation); + EOut.flush(); + Proto += EOut.str(); + Proto += ")"; + } } if (D->hasAttr()) @@ -556,7 +573,8 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { T = Parm->getOriginalType(); T.getAsStringInternal(Name, Policy); Out << Name; - if (Expr *Init = D->getInit()) { + Expr *Init = D->getInit(); + if (!Policy.SuppressInitializers && Init) { if (D->hasCXXDirectInitializer()) Out << "("; else { @@ -580,6 +598,14 @@ void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { Out << ")"; } +void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { + Out << "static_assert("; + D->getAssertExpr()->printPretty(Out, Context, 0, Policy, Indentation); + Out << ", "; + D->getMessage()->printPretty(Out, Context, 0, Policy, Indentation); + Out << ")"; +} + //---------------------------------------------------------------------------- // C++ declarations //---------------------------------------------------------------------------- @@ -624,6 +650,9 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { if (AS != AS_none) Print(AS); Out << " " << Base->getType().getAsString(Policy); + + if (Base->isPackExpansion()) + Out << "..."; } } @@ -654,7 +683,7 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { Visit(*D->decls_begin()); } -void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { +void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { Out << "template <"; TemplateParameterList *Params = D->getTemplateParameters(); @@ -666,9 +695,6 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { if (const TemplateTypeParmDecl *TTP = dyn_cast(Param)) { - QualType ParamType = - Context.getTypeDeclType(const_cast(TTP)); - if (TTP->wasDeclaredWithTypename()) Out << "typename "; else @@ -677,7 +703,7 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { if (TTP->isParameterPack()) Out << "... "; - Out << ParamType.getAsString(Policy); + Out << TTP->getNameAsString(); if (TTP->hasDefaultArgument()) { Out << " = "; @@ -700,12 +726,17 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy, Indentation); } + } else if (const TemplateTemplateParmDecl *TTPD = + dyn_cast(Param)) { + VisitTemplateDecl(TTPD); + // FIXME: print the default argument, if present. } } Out << "> "; - if (TemplateTemplateParmDecl *TTP = dyn_cast(D)) { + if (const TemplateTemplateParmDecl *TTP = + dyn_cast(D)) { Out << "class "; if (TTP->isParameterPack()) Out << "..."; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index a73deeab3a61..6272340691bf 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -95,6 +95,18 @@ unsigned TemplateParameterList::getDepth() const { return cast(FirstParm)->getDepth(); } +static void AdoptTemplateParameterList(TemplateParameterList *Params, + DeclContext *Owner) { + for (TemplateParameterList::iterator P = Params->begin(), + PEnd = Params->end(); + P != PEnd; ++P) { + (*P)->setDeclContext(Owner); + + if (TemplateTemplateParmDecl *TTP = dyn_cast(*P)) + AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner); + } +} + //===----------------------------------------------------------------------===// // RedeclarableTemplateDecl Implementation //===----------------------------------------------------------------------===// @@ -151,6 +163,49 @@ RedeclarableTemplateDecl::findSpecializationImpl( return Entry ? SETraits::getMostRecentDeclaration(Entry) : 0; } +/// \brief Generate the injected template arguments for the given template +/// parameter list, e.g., for the injected-class-name of a class template. +static void GenerateInjectedTemplateArgs(ASTContext &Context, + TemplateParameterList *Params, + TemplateArgument *Args) { + for (TemplateParameterList::iterator Param = Params->begin(), + ParamEnd = Params->end(); + Param != ParamEnd; ++Param) { + TemplateArgument Arg; + if (TemplateTypeParmDecl *TTP = dyn_cast(*Param)) { + QualType ArgType = Context.getTypeDeclType(TTP); + if (TTP->isParameterPack()) + ArgType = Context.getPackExpansionType(ArgType, + llvm::Optional()); + + Arg = TemplateArgument(ArgType); + } else if (NonTypeTemplateParmDecl *NTTP = + dyn_cast(*Param)) { + Expr *E = new (Context) DeclRefExpr(NTTP, + NTTP->getType().getNonLValueExprType(Context), + Expr::getValueKindForType(NTTP->getType()), + NTTP->getLocation()); + + if (NTTP->isParameterPack()) + E = new (Context) PackExpansionExpr(Context.DependentTy, E, + NTTP->getLocation(), + llvm::Optional()); + Arg = TemplateArgument(E); + } else { + TemplateTemplateParmDecl *TTP = cast(*Param); + if (TTP->isParameterPack()) + Arg = TemplateArgument(TemplateName(TTP), llvm::Optional()); + else + Arg = TemplateArgument(TemplateName(TTP)); + } + + if ((*Param)->isTemplateParameterPack()) + Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1); + + *Args++ = Arg; + } +} + //===----------------------------------------------------------------------===// // FunctionTemplateDecl Implementation //===----------------------------------------------------------------------===// @@ -165,9 +220,15 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) { + AdoptTemplateParameterList(Params, cast(Decl)); return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); } +FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, EmptyShell) { + return new (C) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(), + 0, 0); +} + RedeclarableTemplateDecl::CommonBase * FunctionTemplateDecl::newCommon(ASTContext &C) { Common *CommonPtr = new (C) Common; @@ -181,6 +242,27 @@ FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args, return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos); } +void FunctionTemplateDecl::addSpecialization( + FunctionTemplateSpecializationInfo *Info, void *InsertPos) { + getSpecializations().InsertNode(Info, InsertPos); + if (ASTMutationListener *L = getASTMutationListener()) + L->AddedCXXTemplateSpecialization(this, Info->Function); +} + +std::pair +FunctionTemplateDecl::getInjectedTemplateArgs() { + TemplateParameterList *Params = getTemplateParameters(); + Common *CommonPtr = getCommonPtr(); + if (!CommonPtr->InjectedArgs) { + CommonPtr->InjectedArgs + = new (getASTContext()) TemplateArgument [Params->size()]; + GenerateInjectedTemplateArgs(getASTContext(), Params, + CommonPtr->InjectedArgs); + } + + return std::make_pair(CommonPtr->InjectedArgs, Params->size()); +} + //===----------------------------------------------------------------------===// // ClassTemplateDecl Implementation //===----------------------------------------------------------------------===// @@ -196,11 +278,16 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, TemplateParameterList *Params, NamedDecl *Decl, ClassTemplateDecl *PrevDecl) { + AdoptTemplateParameterList(Params, cast(Decl)); ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl); New->setPreviousDeclaration(PrevDecl); return New; } +ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, EmptyShell Empty) { + return new (C) ClassTemplateDecl(Empty); +} + void ClassTemplateDecl::LoadLazySpecializations() { Common *CommonPtr = getCommonPtr(); if (CommonPtr->LazySpecializations) { @@ -320,44 +407,8 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { ASTContext &Context = getASTContext(); TemplateParameterList *Params = getTemplateParameters(); llvm::SmallVector TemplateArgs; - TemplateArgs.reserve(Params->size()); - for (TemplateParameterList::iterator Param = Params->begin(), - ParamEnd = Params->end(); - Param != ParamEnd; ++Param) { - TemplateArgument Arg; - if (TemplateTypeParmDecl *TTP = dyn_cast(*Param)) { - QualType ArgType = Context.getTypeDeclType(TTP); - if (TTP->isParameterPack()) - ArgType = Context.getPackExpansionType(ArgType, - llvm::Optional()); - - Arg = TemplateArgument(ArgType); - } else if (NonTypeTemplateParmDecl *NTTP = - dyn_cast(*Param)) { - Expr *E = new (Context) DeclRefExpr(NTTP, - NTTP->getType().getNonLValueExprType(Context), - Expr::getValueKindForType(NTTP->getType()), - NTTP->getLocation()); - - if (NTTP->isParameterPack()) - E = new (Context) PackExpansionExpr(Context.DependentTy, E, - NTTP->getLocation(), - llvm::Optional()); - Arg = TemplateArgument(E); - } else { - TemplateTemplateParmDecl *TTP = cast(*Param); - if (TTP->isParameterPack()) - Arg = TemplateArgument(TemplateName(TTP), llvm::Optional()); - else - Arg = TemplateArgument(TemplateName(TTP)); - } - - if ((*Param)->isTemplateParameterPack()) - Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1); - - TemplateArgs.push_back(Arg); - } - + TemplateArgs.resize(Params->size()); + GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data()); CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(TemplateName(this), &TemplateArgs[0], @@ -371,21 +422,34 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { TemplateTypeParmDecl * TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, unsigned P, - IdentifierInfo *Id, bool Typename, - bool ParameterPack) { - QualType Type = C.getTemplateTypeParmType(D, P, ParameterPack, Id); - return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack); + SourceLocation KeyLoc, SourceLocation NameLoc, + unsigned D, unsigned P, IdentifierInfo *Id, + bool Typename, bool ParameterPack) { + TemplateTypeParmDecl *TTPDecl = + new (C) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename); + QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl); + TTPDecl->TypeForDecl = TTPType.getTypePtr(); + return TTPDecl; } TemplateTypeParmDecl * TemplateTypeParmDecl::Create(const ASTContext &C, EmptyShell Empty) { - return new (C) TemplateTypeParmDecl(0, SourceLocation(), 0, false, - QualType(), false); + return new (C) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(), + 0, false); } SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { - return DefaultArgument->getTypeLoc().getSourceRange().getBegin(); + return hasDefaultArgument() + ? DefaultArgument->getTypeLoc().getBeginLoc() + : SourceLocation(); +} + +SourceRange TemplateTypeParmDecl::getSourceRange() const { + if (hasDefaultArgument() && !defaultArgumentWasInherited()) + return SourceRange(getLocStart(), + DefaultArgument->getTypeLoc().getEndLoc()); + else + return TypeDecl::getSourceRange(); } unsigned TemplateTypeParmDecl::getDepth() const { @@ -396,19 +460,25 @@ unsigned TemplateTypeParmDecl::getIndex() const { return TypeForDecl->getAs()->getIndex(); } +bool TemplateTypeParmDecl::isParameterPack() const { + return TypeForDecl->getAs()->isParameterPack(); +} + //===----------------------------------------------------------------------===// // NonTypeTemplateParmDecl Method Implementations //===----------------------------------------------------------------------===// NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC, - SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, + SourceLocation StartLoc, + SourceLocation IdLoc, + unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, const QualType *ExpandedTypes, unsigned NumExpandedTypes, TypeSourceInfo **ExpandedTInfos) - : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo), + : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false), ParameterPack(true), ExpandedParameterPack(true), NumExpandedTypes(NumExpandedTypes) @@ -424,16 +494,18 @@ NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC, NonTypeTemplateParmDecl * NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, unsigned P, - IdentifierInfo *Id, QualType T, - bool ParameterPack, TypeSourceInfo *TInfo) { - return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, ParameterPack, - TInfo); + SourceLocation StartLoc, SourceLocation IdLoc, + unsigned D, unsigned P, IdentifierInfo *Id, + QualType T, bool ParameterPack, + TypeSourceInfo *TInfo) { + return new (C) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, + T, ParameterPack, TInfo); } NonTypeTemplateParmDecl * NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, unsigned P, + SourceLocation StartLoc, SourceLocation IdLoc, + unsigned D, unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, const QualType *ExpandedTypes, @@ -442,20 +514,17 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, unsigned Size = sizeof(NonTypeTemplateParmDecl) + NumExpandedTypes * 2 * sizeof(void*); void *Mem = C.Allocate(Size); - return new (Mem) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, TInfo, + return new (Mem) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, + D, P, Id, T, TInfo, ExpandedTypes, NumExpandedTypes, ExpandedTInfos); } -SourceLocation NonTypeTemplateParmDecl::getInnerLocStart() const { - SourceLocation Start = getTypeSpecStartLoc(); - if (Start.isInvalid()) - Start = getLocation(); - return Start; -} - SourceRange NonTypeTemplateParmDecl::getSourceRange() const { - return SourceRange(getOuterLocStart(), getLocation()); + if (hasDefaultArgument() && !defaultArgumentWasInherited()) + return SourceRange(getOuterLocStart(), + getDefaultArgument()->getSourceRange().getEnd()); + return DeclaratorDecl::getSourceRange(); } SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { @@ -499,12 +568,13 @@ TemplateArgumentList::CreateCopy(ASTContext &Context, //===----------------------------------------------------------------------===// ClassTemplateSpecializationDecl:: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, - DeclContext *DC, SourceLocation L, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, ClassTemplateSpecializationDecl *PrevDecl) - : CXXRecordDecl(DK, TK, DC, L, + : CXXRecordDecl(DK, TK, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), @@ -514,14 +584,16 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, } ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(Kind DK) - : CXXRecordDecl(DK, TTK_Struct, 0, SourceLocation(), 0, 0), + : CXXRecordDecl(DK, TTK_Struct, 0, SourceLocation(), SourceLocation(), 0, 0), ExplicitInfo(0), SpecializationKind(TSK_Undeclared) { } ClassTemplateSpecializationDecl * ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, - DeclContext *DC, SourceLocation L, + DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, @@ -529,7 +601,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, ClassTemplateSpecializationDecl *Result = new (Context)ClassTemplateSpecializationDecl(Context, ClassTemplateSpecialization, - TK, DC, L, + TK, DC, StartLoc, IdLoc, SpecializedTemplate, Args, NumArgs, PrevDecl); @@ -564,12 +636,51 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const { return SpecializedTemplate.get(); } +SourceRange +ClassTemplateSpecializationDecl::getSourceRange() const { + if (!ExplicitInfo) + return SourceRange(); + SourceLocation Begin = getExternLoc(); + if (Begin.isInvalid()) + Begin = getTemplateKeywordLoc(); + SourceLocation End = getRBraceLoc(); + if (End.isInvalid()) + End = getTypeAsWritten()->getTypeLoc().getEndLoc(); + return SourceRange(Begin, End); +} + //===----------------------------------------------------------------------===// // ClassTemplatePartialSpecializationDecl Implementation //===----------------------------------------------------------------------===// +ClassTemplatePartialSpecializationDecl:: +ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, + DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + const TemplateArgument *Args, + unsigned NumArgs, + TemplateArgumentLoc *ArgInfos, + unsigned NumArgInfos, + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber) + : ClassTemplateSpecializationDecl(Context, + ClassTemplatePartialSpecialization, + TK, DC, StartLoc, IdLoc, + SpecializedTemplate, + Args, NumArgs, PrevDecl), + TemplateParams(Params), ArgsAsWritten(ArgInfos), + NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), + InstantiatedFromMember(0, false) +{ + AdoptTemplateParameterList(Params, this); +} + ClassTemplatePartialSpecializationDecl * ClassTemplatePartialSpecializationDecl:: -Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, +Create(ASTContext &Context, TagKind TK,DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, @@ -584,8 +695,9 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, ClonedArgs[I] = ArgInfos[I]; ClassTemplatePartialSpecializationDecl *Result - = new (Context)ClassTemplatePartialSpecializationDecl(Context, TK, - DC, L, Params, + = new (Context)ClassTemplatePartialSpecializationDecl(Context, TK, DC, + StartLoc, IdLoc, + Params, SpecializedTemplate, Args, NumArgs, ClonedArgs, N, diff --git a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp index 9d828fcfb85a..7d593bc46f6c 100644 --- a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp @@ -543,12 +543,20 @@ struct XMLDumper : public XMLDeclVisitor, // TypedefDecl void visitTypedefDeclAttrs(TypedefDecl *D) { - visitRedeclarableAttrs(D); + visitRedeclarableAttrs(D); } void visitTypedefDeclChildren(TypedefDecl *D) { dispatch(D->getTypeSourceInfo()->getTypeLoc()); } + // TypeAliasDecl + void visitTypeAliasDeclAttrs(TypeAliasDecl *D) { + visitRedeclarableAttrs(D); + } + void visitTypeAliasDeclChildren(TypeAliasDecl *D) { + dispatch(D->getTypeSourceInfo()->getTypeLoc()); + } + // TagDecl void visitTagDeclAttrs(TagDecl *D) { visitRedeclarableAttrs(D); @@ -911,6 +919,8 @@ struct XMLDumper : public XMLDeclVisitor, case CC_X86StdCall: return set("cc", "x86_stdcall"); case CC_X86ThisCall: return set("cc", "x86_thiscall"); case CC_X86Pascal: return set("cc", "x86_pascal"); + case CC_AAPCS: return set("cc", "aapcs"); + case CC_AAPCS_VFP: return set("cc", "aapcs_vfp"); } } @@ -955,7 +965,7 @@ struct XMLDumper : public XMLDeclVisitor, void visitFunctionTypeAttrs(FunctionType *T) { setFlag("noreturn", T->getNoReturnAttr()); setCallingConv(T->getCallConv()); - if (T->getRegParmType()) setInteger("regparm", T->getRegParmType()); + if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType()); } void visitFunctionTypeChildren(FunctionType *T) { dispatch(T->getResultType()); @@ -975,15 +985,16 @@ struct XMLDumper : public XMLDeclVisitor, dispatch(*I); pop(); - if (T->hasExceptionSpec()) { + if (T->hasDynamicExceptionSpec()) { push("exception_specifiers"); - setFlag("any", T->hasAnyExceptionSpec()); + setFlag("any", T->getExceptionSpecType() == EST_MSAny); completeAttrs(); for (FunctionProtoType::exception_iterator I = T->exception_begin(), E = T->exception_end(); I != E; ++I) dispatch(*I); pop(); } + // FIXME: noexcept specifier } void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) { diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 1c1061b5a229..6499f327b07e 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -35,18 +35,16 @@ using namespace clang; /// but also int expressions which are produced by things like comparisons in /// C. bool Expr::isKnownToHaveBooleanValue() const { + const Expr *E = IgnoreParens(); + // If this value has _Bool type, it is obvious 0/1. - if (getType()->isBooleanType()) return true; + if (E->getType()->isBooleanType()) return true; // If this is a non-scalar-integer type, we don't care enough to try. - if (!getType()->isIntegralOrEnumerationType()) return false; + if (!E->getType()->isIntegralOrEnumerationType()) return false; - if (const ParenExpr *PE = dyn_cast(this)) - return PE->getSubExpr()->isKnownToHaveBooleanValue(); - - if (const UnaryOperator *UO = dyn_cast(this)) { + if (const UnaryOperator *UO = dyn_cast(E)) { switch (UO->getOpcode()) { case UO_Plus: - case UO_Extension: return UO->getSubExpr()->isKnownToHaveBooleanValue(); default: return false; @@ -55,10 +53,10 @@ bool Expr::isKnownToHaveBooleanValue() const { // Only look through implicit casts. If the user writes // '(int) (a && b)' treat it as an arbitrary int. - if (const ImplicitCastExpr *CE = dyn_cast(this)) + if (const ImplicitCastExpr *CE = dyn_cast(E)) return CE->getSubExpr()->isKnownToHaveBooleanValue(); - if (const BinaryOperator *BO = dyn_cast(this)) { + if (const BinaryOperator *BO = dyn_cast(E)) { switch (BO->getOpcode()) { default: return false; case BO_LT: // Relational operators. @@ -84,7 +82,7 @@ bool Expr::isKnownToHaveBooleanValue() const { } } - if (const ConditionalOperator *CO = dyn_cast(this)) + if (const ConditionalOperator *CO = dyn_cast(E)) return CO->getTrueExpr()->isKnownToHaveBooleanValue() && CO->getFalseExpr()->isKnownToHaveBooleanValue(); @@ -276,44 +274,20 @@ void DeclRefExpr::computeDependence() { ExprBits.ContainsUnexpandedParameterPack = true; } -DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - ValueDecl *D, SourceLocation NameLoc, - const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK) - : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), - DecoratedD(D, - (Qualifier? HasQualifierFlag : 0) | - (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)), - Loc(NameLoc) { - if (Qualifier) { - NameQualifier *NQ = getNameQualifier(); - NQ->NNS = Qualifier; - NQ->Range = QualifierRange; - } - - if (TemplateArgs) - getExplicitTemplateArgs().initializeFrom(*TemplateArgs); - - computeDependence(); -} - -DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, +DeclRefExpr::DeclRefExpr(NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, const DeclarationNameInfo &NameInfo, + NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK) : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), - DecoratedD(D, - (Qualifier? HasQualifierFlag : 0) | - (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)), - Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) { - if (Qualifier) { - NameQualifier *NQ = getNameQualifier(); - NQ->NNS = Qualifier; - NQ->Range = QualifierRange; - } - + D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) { + DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0; + if (QualifierLoc) + getInternalQualifierLoc() = QualifierLoc; + DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0; + if (FoundD) + getInternalFoundDecl() = FoundD; + DeclRefExprBits.HasExplicitTemplateArgs = TemplateArgs ? 1 : 0; if (TemplateArgs) getExplicitTemplateArgs().initializeFrom(*TemplateArgs); @@ -321,49 +295,56 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, } DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, SourceLocation NameLoc, QualType T, ExprValueKind VK, + NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) { - return Create(Context, Qualifier, QualifierRange, D, + return Create(Context, QualifierLoc, D, DeclarationNameInfo(D->getDeclName(), NameLoc), - T, VK, TemplateArgs); + T, VK, FoundD, TemplateArgs); } DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, + NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) { + // Filter out cases where the found Decl is the same as the value refenenced. + if (D == FoundD) + FoundD = 0; + std::size_t Size = sizeof(DeclRefExpr); - if (Qualifier != 0) - Size += sizeof(NameQualifier); - + if (QualifierLoc != 0) + Size += sizeof(NestedNameSpecifierLoc); + if (FoundD) + Size += sizeof(NamedDecl *); if (TemplateArgs) Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); - + void *Mem = Context.Allocate(Size, llvm::alignOf()); - return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameInfo, - TemplateArgs, T, VK); + return new (Mem) DeclRefExpr(QualifierLoc, D, NameInfo, FoundD, TemplateArgs, + T, VK); } -DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, +DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier, + bool HasFoundDecl, bool HasExplicitTemplateArgs, unsigned NumTemplateArgs) { std::size_t Size = sizeof(DeclRefExpr); if (HasQualifier) - Size += sizeof(NameQualifier); - + Size += sizeof(NestedNameSpecifierLoc); + if (HasFoundDecl) + Size += sizeof(NamedDecl *); if (HasExplicitTemplateArgs) Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); - + void *Mem = Context.Allocate(Size, llvm::alignOf()); return new (Mem) DeclRefExpr(EmptyShell()); } @@ -371,7 +352,7 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, SourceRange DeclRefExpr::getSourceRange() const { SourceRange R = getNameInfo().getSourceRange(); if (hasQualifier()) - R.setBegin(getQualifierRange().getBegin()); + R.setBegin(getQualifierLoc().getBeginLoc()); if (hasExplicitTemplateArgs()) R.setEnd(getRAngleLoc()); return R; @@ -518,7 +499,7 @@ double FloatingLiteral::getValueAsApproximateDouble() const { StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData, unsigned ByteLength, bool Wide, - QualType Ty, + bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumStrs) { // Allocate enough space for the StringLiteral plus an array of locations for @@ -534,6 +515,7 @@ StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData, SL->StrData = AStrData; SL->ByteLength = ByteLength; SL->IsWide = Wide; + SL->IsPascal = Pascal; SL->TokLocs[0] = Loc[0]; SL->NumConcatenated = NumStrs; @@ -828,11 +810,11 @@ QualType CallExpr::getCallReturnType() const { CalleeType = FnTypePtr->getPointeeType(); else if (const BlockPointerType *BPT = CalleeType->getAs()) CalleeType = BPT->getPointeeType(); - else if (const MemberPointerType *MPT - = CalleeType->getAs()) - CalleeType = MPT->getPointeeType(); + else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) + // This should never be overloaded and so should never return null. + CalleeType = Expr::findBoundMemberType(getCallee()); - const FunctionType *FnType = CalleeType->getAs(); + const FunctionType *FnType = CalleeType->castAs(); return FnType->getResultType(); } @@ -906,8 +888,7 @@ IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const { } MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, - NestedNameSpecifier *qual, - SourceRange qualrange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo nameinfo, @@ -917,7 +898,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, ExprObjectKind ok) { std::size_t Size = sizeof(MemberExpr); - bool hasQualOrFound = (qual != 0 || + bool hasQualOrFound = (QualifierLoc || founddecl.getDecl() != memberdecl || founddecl.getAccess() != memberdecl->getAccess()); if (hasQualOrFound) @@ -931,15 +912,15 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, ty, vk, ok); if (hasQualOrFound) { - if (qual && qual->isDependent()) { + // FIXME: Wrong. We should be looking at the member declaration we found. + if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) { E->setValueDependent(true); E->setTypeDependent(true); } E->HasQualifierOrFoundDecl = true; MemberNameQualifier *NQ = E->getMemberQualifier(); - NQ->NNS = qual; - NQ->Range = qualrange; + NQ->QualifierLoc = QualifierLoc; NQ->FoundDecl = founddecl; } @@ -951,6 +932,28 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, return E; } +SourceRange MemberExpr::getSourceRange() const { + SourceLocation StartLoc; + if (isImplicitAccess()) { + if (hasQualifier()) + StartLoc = getQualifierLoc().getBeginLoc(); + else + StartLoc = MemberLoc; + } else { + // FIXME: We don't want this to happen. Rather, we should be able to + // detect all kinds of implicit accesses more cleanly. + StartLoc = getBase()->getLocStart(); + if (StartLoc.isInvalid()) + StartLoc = MemberLoc; + } + + SourceLocation EndLoc = + HasExplicitTemplateArgumentList? getRAngleLoc() + : getMemberNameInfo().getEndLoc(); + + return SourceRange(StartLoc, EndLoc); +} + const char *CastExpr::getCastKindName() const { switch (getCastKind()) { case CK_Dependent: @@ -1241,7 +1244,7 @@ InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc, false), InitExprs(C, numInits), LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0), - UnionFieldInit(0), HadArrayRangeDesignator(false) + HadArrayRangeDesignator(false) { for (unsigned I = 0; I != numInits; ++I) { if (initExprs[I]->isTypeDependent()) @@ -1276,6 +1279,15 @@ Expr *InitListExpr::updateInit(ASTContext &C, unsigned Init, Expr *expr) { return Result; } +void InitListExpr::setArrayFiller(Expr *filler) { + ArrayFillerOrUnionFieldInit = filler; + // Fill out any "holes" in the array due to designated initializers. + Expr **inits = getInits(); + for (unsigned i = 0, e = getNumInits(); i != e; ++i) + if (inits[i] == 0) + inits[i] = filler; +} + SourceRange InitListExpr::getSourceRange() const { if (SyntacticForm) return SyntacticForm->getSourceRange(); @@ -1348,6 +1360,9 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, case ParenExprClass: return cast(this)->getSubExpr()-> isUnusedResultAWarning(Loc, R1, R2, Ctx); + case GenericSelectionExprClass: + return cast(this)->getResultExpr()-> + isUnusedResultAWarning(Loc, R1, R2, Ctx); case UnaryOperatorClass: { const UnaryOperator *UO = cast(this); @@ -1412,13 +1427,15 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, return false; case ConditionalOperatorClass: { - // The condition must be evaluated, but if either the LHS or RHS is a - // warning, warn about them. + // If only one of the LHS or RHS is a warning, the operator might + // be being used for control flow. Only warn if both the LHS and + // RHS are warnings. const ConditionalOperator *Exp = cast(this); - if (Exp->getLHS() && - Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx)) + if (!Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx)) + return false; + if (!Exp->getLHS()) return true; - return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx); + return Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx); } case MemberExprClass: @@ -1556,21 +1573,20 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, /// isOBJCGCCandidate - Check if an expression is objc gc'able. /// returns true, if it is; false otherwise. bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { - switch (getStmtClass()) { + const Expr *E = IgnoreParens(); + switch (E->getStmtClass()) { default: return false; case ObjCIvarRefExprClass: return true; case Expr::UnaryOperatorClass: - return cast(this)->getSubExpr()->isOBJCGCCandidate(Ctx); - case ParenExprClass: - return cast(this)->getSubExpr()->isOBJCGCCandidate(Ctx); + return cast(E)->getSubExpr()->isOBJCGCCandidate(Ctx); case ImplicitCastExprClass: - return cast(this)->getSubExpr()->isOBJCGCCandidate(Ctx); + return cast(E)->getSubExpr()->isOBJCGCCandidate(Ctx); case CStyleCastExprClass: - return cast(this)->getSubExpr()->isOBJCGCCandidate(Ctx); + return cast(E)->getSubExpr()->isOBJCGCCandidate(Ctx); case DeclRefExprClass: { - const Decl *D = cast(this)->getDecl(); + const Decl *D = cast(E)->getDecl(); if (const VarDecl *VD = dyn_cast(D)) { if (VD->hasGlobalStorage()) return true; @@ -1583,11 +1599,11 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { return false; } case MemberExprClass: { - const MemberExpr *M = cast(this); + const MemberExpr *M = cast(E); return M->getBase()->isOBJCGCCandidate(Ctx); } case ArraySubscriptExprClass: - return cast(this)->getBase()->isOBJCGCCandidate(Ctx); + return cast(E)->getBase()->isOBJCGCCandidate(Ctx); } } @@ -1597,6 +1613,30 @@ bool Expr::isBoundMemberFunction(ASTContext &Ctx) const { return ClassifyLValue(Ctx) == Expr::LV_MemberFunction; } +QualType Expr::findBoundMemberType(const Expr *expr) { + assert(expr->getType()->isSpecificPlaceholderType(BuiltinType::BoundMember)); + + // Bound member expressions are always one of these possibilities: + // x->m x.m x->*y x.*y + // (possibly parenthesized) + + expr = expr->IgnoreParens(); + if (const MemberExpr *mem = dyn_cast(expr)) { + assert(isa(mem->getMemberDecl())); + return mem->getMemberDecl()->getType(); + } + + if (const BinaryOperator *op = dyn_cast(expr)) { + QualType type = op->getRHS()->getType()->castAs() + ->getPointeeType(); + assert(type->isFunctionType()); + return type; + } + + assert(isa(expr)); + return QualType(); +} + static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1, Expr::CanThrowResult CT2) { // CanThrowResult constants are ordered so that the maximum is the correct @@ -1613,7 +1653,7 @@ static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) { return R; } -static Expr::CanThrowResult CanCalleeThrow(const Decl *D, +static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Decl *D, bool NullThrows = true) { if (!D) return NullThrows ? Expr::CT_Can : Expr::CT_Cannot; @@ -1643,7 +1683,7 @@ static Expr::CanThrowResult CanCalleeThrow(const Decl *D, if (!FT) return Expr::CT_Can; - return FT->hasEmptyExceptionSpec() ? Expr::CT_Cannot : Expr::CT_Can; + return FT->isNothrow(Ctx) ? Expr::CT_Cannot : Expr::CT_Can; } static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) { @@ -1707,7 +1747,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CallExprClass: case CXXOperatorCallExprClass: case CXXMemberCallExprClass: { - CanThrowResult CT = CanCalleeThrow(cast(this)->getCalleeDecl()); + CanThrowResult CT = CanCalleeThrow(C,cast(this)->getCalleeDecl()); if (CT == CT_Can) return CT; return MergeCanThrow(CT, CanSubExprsThrow(C, this)); @@ -1715,7 +1755,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CXXConstructExprClass: case CXXTemporaryObjectExprClass: { - CanThrowResult CT = CanCalleeThrow( + CanThrowResult CT = CanCalleeThrow(C, cast(this)->getConstructor()); if (CT == CT_Can) return CT; @@ -1724,8 +1764,8 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CXXNewExprClass: { CanThrowResult CT = MergeCanThrow( - CanCalleeThrow(cast(this)->getOperatorNew()), - CanCalleeThrow(cast(this)->getConstructor(), + CanCalleeThrow(C, cast(this)->getOperatorNew()), + CanCalleeThrow(C, cast(this)->getConstructor(), /*NullThrows*/false)); if (CT == CT_Can) return CT; @@ -1733,7 +1773,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { } case CXXDeleteExprClass: { - CanThrowResult CT = CanCalleeThrow( + CanThrowResult CT = CanCalleeThrow(C, cast(this)->getOperatorDelete()); if (CT == CT_Can) return CT; @@ -1743,7 +1783,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { Arg = Cast->getSubExpr(); if (const PointerType *PT = Arg->getType()->getAs()) { if (const RecordType *RT = PT->getPointeeType()->getAs()) { - CanThrowResult CT2 = CanCalleeThrow( + CanThrowResult CT2 = CanCalleeThrow(C, cast(RT->getDecl())->getDestructor()); if (CT2 == CT_Can) return CT2; @@ -1755,7 +1795,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CXXBindTemporaryExprClass: { // The bound temporary has to be destroyed again, which might throw. - CanThrowResult CT = CanCalleeThrow( + CanThrowResult CT = CanCalleeThrow(C, cast(this)->getTemporary()->getDestructor()); if (CT == CT_Can) return CT; @@ -1810,6 +1850,11 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { return CT_Dependent; return cast(this)->getChosenSubExpr(C)->CanThrow(C); + case GenericSelectionExprClass: + if (cast(this)->isResultDependent()) + return CT_Dependent; + return cast(this)->getResultExpr()->CanThrow(C); + // Some expressions are always dependent. case DependentScopeDeclRefExprClass: case CXXUnresolvedConstructExprClass: @@ -1836,6 +1881,12 @@ Expr* Expr::IgnoreParens() { continue; } } + if (GenericSelectionExpr* P = dyn_cast(E)) { + if (!P->isResultDependent()) { + E = P->getResultExpr(); + continue; + } + } return E; } } @@ -1859,6 +1910,12 @@ Expr *Expr::IgnoreParenCasts() { continue; } } + if (GenericSelectionExpr* P = dyn_cast(E)) { + if (!P->isResultDependent()) { + E = P->getResultExpr(); + continue; + } + } return E; } } @@ -1883,6 +1940,11 @@ Expr *Expr::IgnoreParenLValueCasts() { E = P->getSubExpr(); continue; } + } else if (GenericSelectionExpr* P = dyn_cast(E)) { + if (!P->isResultDependent()) { + E = P->getResultExpr(); + continue; + } } break; } @@ -1906,6 +1968,12 @@ Expr *Expr::IgnoreParenImpCasts() { continue; } } + if (GenericSelectionExpr* P = dyn_cast(E)) { + if (!P->isResultDependent()) { + E = P->getResultExpr(); + continue; + } + } return E; } } @@ -1948,6 +2016,13 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { } } + if (GenericSelectionExpr* P = dyn_cast(E)) { + if (!P->isResultDependent()) { + E = P->getResultExpr(); + continue; + } + } + return E; } } @@ -2023,6 +2098,42 @@ bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const { return true; } +bool Expr::isImplicitCXXThis() const { + const Expr *E = this; + + // Strip away parentheses and casts we don't care about. + while (true) { + if (const ParenExpr *Paren = dyn_cast(E)) { + E = Paren->getSubExpr(); + continue; + } + + if (const ImplicitCastExpr *ICE = dyn_cast(E)) { + if (ICE->getCastKind() == CK_NoOp || + ICE->getCastKind() == CK_LValueToRValue || + ICE->getCastKind() == CK_DerivedToBase || + ICE->getCastKind() == CK_UncheckedDerivedToBase) { + E = ICE->getSubExpr(); + continue; + } + } + + if (const UnaryOperator* UnOp = dyn_cast(E)) { + if (UnOp->getOpcode() == UO_Extension) { + E = UnOp->getSubExpr(); + continue; + } + } + + break; + } + + if (const CXXThisExpr *This = dyn_cast(E)) + return This->isImplicit(); + + return false; +} + /// hasAnyTypeDependentArguments - Determines if any of the expressions /// in Exprs is type-dependent. bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) { @@ -2103,6 +2214,11 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { case ParenExprClass: return cast(this)->getSubExpr() ->isConstantInitializer(Ctx, IsForRef); + case GenericSelectionExprClass: + if (cast(this)->isResultDependent()) + return false; + return cast(this)->getResultExpr() + ->isConstantInitializer(Ctx, IsForRef); case ChooseExprClass: return cast(this)->getChosenSubExpr(Ctx) ->isConstantInitializer(Ctx, IsForRef); @@ -2189,6 +2305,9 @@ Expr::isNullPointerConstant(ASTContext &Ctx, // Accept ((void*)0) as a null pointer constant, as many other // implementations do. return PE->getSubExpr()->isNullPointerConstant(Ctx, NPC); + } else if (const GenericSelectionExpr *GE = + dyn_cast(this)) { + return GE->getResultExpr()->isNullPointerConstant(Ctx, NPC); } else if (const CXXDefaultArgExpr *DefaultArg = dyn_cast(this)) { // See through default argument expressions @@ -2587,6 +2706,51 @@ void ShuffleVectorExpr::setExprs(ASTContext &C, Expr ** Exprs, memcpy(SubExprs, Exprs, sizeof(Expr *) * NumExprs); } +GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context, + SourceLocation GenericLoc, Expr *ControllingExpr, + TypeSourceInfo **AssocTypes, Expr **AssocExprs, + unsigned NumAssocs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, + unsigned ResultIndex) + : Expr(GenericSelectionExprClass, + AssocExprs[ResultIndex]->getType(), + AssocExprs[ResultIndex]->getValueKind(), + AssocExprs[ResultIndex]->getObjectKind(), + AssocExprs[ResultIndex]->isTypeDependent(), + AssocExprs[ResultIndex]->isValueDependent(), + ContainsUnexpandedParameterPack), + AssocTypes(new (Context) TypeSourceInfo*[NumAssocs]), + SubExprs(new (Context) Stmt*[END_EXPR+NumAssocs]), NumAssocs(NumAssocs), + ResultIndex(ResultIndex), GenericLoc(GenericLoc), DefaultLoc(DefaultLoc), + RParenLoc(RParenLoc) { + SubExprs[CONTROLLING] = ControllingExpr; + std::copy(AssocTypes, AssocTypes+NumAssocs, this->AssocTypes); + std::copy(AssocExprs, AssocExprs+NumAssocs, SubExprs+END_EXPR); +} + +GenericSelectionExpr::GenericSelectionExpr(ASTContext &Context, + SourceLocation GenericLoc, Expr *ControllingExpr, + TypeSourceInfo **AssocTypes, Expr **AssocExprs, + unsigned NumAssocs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack) + : Expr(GenericSelectionExprClass, + Context.DependentTy, + VK_RValue, + OK_Ordinary, + /*isTypeDependent=*/ true, + /*isValueDependent=*/ true, + ContainsUnexpandedParameterPack), + AssocTypes(new (Context) TypeSourceInfo*[NumAssocs]), + SubExprs(new (Context) Stmt*[END_EXPR+NumAssocs]), NumAssocs(NumAssocs), + ResultIndex(-1U), GenericLoc(GenericLoc), DefaultLoc(DefaultLoc), + RParenLoc(RParenLoc) { + SubExprs[CONTROLLING] = ControllingExpr; + std::copy(AssocTypes, AssocTypes+NumAssocs, this->AssocTypes); + std::copy(AssocExprs, AssocExprs+NumAssocs, SubExprs+END_EXPR); +} + //===----------------------------------------------------------------------===// // DesignatedInitExpr //===----------------------------------------------------------------------===// @@ -2688,6 +2852,14 @@ void DesignatedInitExpr::setDesignators(ASTContext &C, Designators[I] = Desigs[I]; } +SourceRange DesignatedInitExpr::getDesignatorsSourceRange() const { + DesignatedInitExpr *DIE = const_cast(this); + if (size() == 1) + return DIE->getDesignator(0)->getSourceRange(); + return SourceRange(DIE->getDesignator(0)->getStartLocation(), + DIE->getDesignator(size()-1)->getEndLocation()); +} + SourceRange DesignatedInitExpr::getSourceRange() const { SourceLocation StartLoc; Designator &First = @@ -2802,8 +2974,8 @@ const Expr* ConstExprIterator::operator->() const { return cast(*I); } // Child Iterators for iterating over subexpressions/substatements //===----------------------------------------------------------------------===// -// SizeOfAlignOfExpr -Stmt::child_range SizeOfAlignOfExpr::children() { +// UnaryExprOrTypeTraitExpr +Stmt::child_range UnaryExprOrTypeTraitExpr::children() { // If this is of a type and the type is a VLA type (and not a typedef), the // size expression of the VLA needs to be treated as an executable expression. // Why isn't this weirdness documented better in StmtIterator? diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index 4f4a6b4944d9..1a1a0a36a65b 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -100,6 +100,10 @@ void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, SubExprs = new (C) Stmt*[TotalSize]; } +bool CXXNewExpr::shouldNullCheckAllocation(ASTContext &Ctx) const { + return getOperatorNew()->getType()-> + castAs()->isNothrow(Ctx); +} // CXXDeleteExpr QualType CXXDeleteExpr::getDestroyedType() const { @@ -174,8 +178,7 @@ SourceRange CXXPseudoDestructorExpr::getSourceRange() const { UnresolvedLookupExpr * UnresolvedLookupExpr::Create(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool ADL, const TemplateArgumentListInfo &Args, @@ -184,10 +187,9 @@ UnresolvedLookupExpr::Create(ASTContext &C, { void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + ExplicitTemplateArgumentList::sizeFor(Args)); - return new (Mem) UnresolvedLookupExpr(C, NamingClass, - Qualifier, QualifierRange, NameInfo, + return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, NameInfo, ADL, /*Overload*/ true, &Args, - Begin, End); + Begin, End, /*StdIsAssociated=*/false); } UnresolvedLookupExpr * @@ -204,7 +206,7 @@ UnresolvedLookupExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, } OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, - NestedNameSpecifier *Qualifier, SourceRange QRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, @@ -215,10 +217,11 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, KnownDependent, (KnownContainsUnexpandedParameterPack || NameInfo.containsUnexpandedParameterPack() || - (Qualifier && Qualifier->containsUnexpandedParameterPack()))), + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()))), Results(0), NumResults(End - Begin), NameInfo(NameInfo), - Qualifier(Qualifier), QualifierRange(QRange), - HasExplicitTemplateArgs(TemplateArgs != 0) + QualifierLoc(QualifierLoc), HasExplicitTemplateArgs(TemplateArgs != 0) { NumResults = End - Begin; if (NumResults) { @@ -365,8 +368,10 @@ SourceRange CXXOperatorCallExpr::getSourceRange() const { getArg(0)->getSourceRange().getEnd()); else // Postfix operator - return SourceRange(getArg(0)->getSourceRange().getEnd(), + return SourceRange(getArg(0)->getSourceRange().getBegin(), getOperatorLoc()); + } else if (Kind == OO_Arrow) { + return getArg(0)->getSourceRange(); } else if (Kind == OO_Call) { return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc()); } else if (Kind == OO_Subscript) { @@ -381,14 +386,25 @@ SourceRange CXXOperatorCallExpr::getSourceRange() const { } } -Expr *CXXMemberCallExpr::getImplicitObjectArgument() { - if (MemberExpr *MemExpr = dyn_cast(getCallee()->IgnoreParens())) +Expr *CXXMemberCallExpr::getImplicitObjectArgument() const { + if (const MemberExpr *MemExpr = + dyn_cast(getCallee()->IgnoreParens())) return MemExpr->getBase(); // FIXME: Will eventually need to cope with member pointers. return 0; } +CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const { + if (const MemberExpr *MemExpr = + dyn_cast(getCallee()->IgnoreParens())) + return cast(MemExpr->getMemberDecl()); + + // FIXME: Will eventually need to cope with member pointers. + return 0; +} + + CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() { Expr* ThisArg = getImplicitObjectArgument(); if (!ThisArg) @@ -466,6 +482,36 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(ASTContext &C, return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize); } +/// isAlwaysNull - Return whether the result of the dynamic_cast is proven +/// to always be null. For example: +/// +/// struct A { }; +/// struct B final : A { }; +/// struct C { }; +/// +/// C *f(B* b) { return dynamic_cast(b); } +bool CXXDynamicCastExpr::isAlwaysNull() const +{ + QualType SrcType = getSubExpr()->getType(); + QualType DestType = getType(); + + if (const PointerType *SrcPTy = SrcType->getAs()) { + SrcType = SrcPTy->getPointeeType(); + DestType = DestType->castAs()->getPointeeType(); + } + + const CXXRecordDecl *SrcRD = + cast(SrcType->castAs()->getDecl()); + + if (!SrcRD->hasAttr()) + return false; + + const CXXRecordDecl *DestRD = + cast(DestType->castAs()->getDecl()); + + return !DestRD->isDerivedFrom(SrcRD); +} + CXXReinterpretCastExpr * CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, CastKind K, Expr *Op, @@ -689,20 +735,20 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue, OK_Ordinary, true, true, ((Base && Base->containsUnexpandedParameterPack()) || - (Qualifier && Qualifier->containsUnexpandedParameterPack()) || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()) || MemberNameInfo.containsUnexpandedParameterPack())), Base(Base), BaseType(BaseType), IsArrow(IsArrow), HasExplicitTemplateArgs(TemplateArgs != 0), - OperatorLoc(OperatorLoc), - Qualifier(Qualifier), QualifierRange(QualifierRange), + OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), FirstQualifierFoundInScope(FirstQualifierFoundInScope), MemberNameInfo(MemberNameInfo) { if (TemplateArgs) { @@ -719,18 +765,19 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo) : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue, OK_Ordinary, true, true, ((Base && Base->containsUnexpandedParameterPack()) || - (Qualifier && Qualifier->containsUnexpandedParameterPack()) || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier()-> + containsUnexpandedParameterPack()) || MemberNameInfo.containsUnexpandedParameterPack())), Base(Base), BaseType(BaseType), IsArrow(IsArrow), HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), - Qualifier(Qualifier), QualifierRange(QualifierRange), + QualifierLoc(QualifierLoc), FirstQualifierFoundInScope(FirstQualifierFoundInScope), MemberNameInfo(MemberNameInfo) { } @@ -738,15 +785,14 @@ CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr::Create(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) { if (!TemplateArgs) return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, - Qualifier, QualifierRange, + QualifierLoc, FirstQualifierFoundInScope, MemberNameInfo); @@ -757,7 +803,7 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, void *Mem = C.Allocate(size, llvm::alignOf()); return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, - Qualifier, QualifierRange, + QualifierLoc, FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs); } @@ -768,8 +814,8 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) { if (!HasExplicitTemplateArgs) return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(), - 0, SourceLocation(), 0, - SourceRange(), 0, + 0, SourceLocation(), + NestedNameSpecifierLoc(), 0, DeclarationNameInfo()); std::size_t size = sizeof(CXXDependentScopeMemberExpr) + @@ -777,26 +823,53 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, void *Mem = C.Allocate(size, llvm::alignOf()); CXXDependentScopeMemberExpr *E = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(), - 0, SourceLocation(), 0, - SourceRange(), 0, + 0, SourceLocation(), + NestedNameSpecifierLoc(), 0, DeclarationNameInfo(), 0); E->HasExplicitTemplateArgs = true; return E; } +bool CXXDependentScopeMemberExpr::isImplicitAccess() const { + if (Base == 0) + return true; + + return cast(Base)->isImplicitCXXThis(); +} + +static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin, + UnresolvedSetIterator end) { + do { + NamedDecl *decl = *begin; + if (isa(decl)) + return false; + if (isa(decl)) + decl = cast(decl)->getUnderlyingDecl(); + + // Unresolved member expressions should only contain methods and + // method templates. + assert(isa(decl) || isa(decl)); + + if (isa(decl)) + decl = cast(decl)->getTemplatedDecl(); + if (cast(decl)->isStatic()) + return false; + } while (++begin != end); + + return true; +} + UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedMemberExprClass, C, - Qualifier, QualifierRange, MemberNameInfo, + : OverloadExpr(UnresolvedMemberExprClass, C, QualifierLoc, MemberNameInfo, TemplateArgs, Begin, End, // Dependent ((Base && Base->isTypeDependent()) || @@ -806,6 +879,18 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, BaseType->containsUnexpandedParameterPack())), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) { + + // Check whether all of the members are non-static member functions, + // and if so, mark give this bound-member type instead of overload type. + if (hasOnlyNonStaticMemberFunctions(Begin, End)) + setType(C.BoundMemberTy); +} + +bool UnresolvedMemberExpr::isImplicitAccess() const { + if (Base == 0) + return true; + + return cast(Base)->isImplicitCXXThis(); } UnresolvedMemberExpr * @@ -813,8 +898,7 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, @@ -826,7 +910,7 @@ UnresolvedMemberExpr::Create(ASTContext &C, void *Mem = C.Allocate(size, llvm::alignOf()); return new (Mem) UnresolvedMemberExpr(C, HasUnresolvedUsing, Base, BaseType, - IsArrow, OperatorLoc, Qualifier, QualifierRange, + IsArrow, OperatorLoc, QualifierLoc, MemberNameInfo, TemplateArgs, Begin, End); } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index 890898a985e8..888a93c8aac0 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -61,8 +61,10 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { if (TR->isFunctionType() || TR == Ctx.OverloadTy) kind = Cl::CL_Function; // No void either, but qualified void is OK because it is "other than void". - else if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers()) - kind = Cl::CL_Void; + // Void "lvalues" are classified as addressable void values, which are void + // expressions whose address can be taken. + else if (TR->isVoidType() && !TR.hasQualifiers()) + kind = (kind == Cl::CL_LValue ? Cl::CL_AddressableVoid : Cl::CL_Void); } // Enable this assertion for testing. @@ -71,10 +73,12 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { case Cl::CL_XValue: assert(getValueKind() == VK_XValue); break; case Cl::CL_Function: case Cl::CL_Void: + case Cl::CL_AddressableVoid: case Cl::CL_DuplicateVectorComponents: case Cl::CL_MemberFunction: case Cl::CL_SubObjCPropertySetting: case Cl::CL_ClassTemporary: + case Cl::CL_ObjCMessageRValue: case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break; } @@ -128,7 +132,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // Expressions that are prvalues. case Expr::CXXBoolLiteralExprClass: case Expr::CXXPseudoDestructorExprClass: - case Expr::SizeOfAlignOfExprClass: + case Expr::UnaryExprOrTypeTraitExprClass: case Expr::CXXNewExprClass: case Expr::CXXThisExprClass: case Expr::CXXNullPtrLiteralExprClass: @@ -148,6 +152,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CXXScalarValueInitExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::ArrayTypeTraitExprClass: + case Expr::ExpressionTraitExprClass: case Expr::ObjCSelectorExprClass: case Expr::ObjCProtocolExprClass: case Expr::ObjCStringLiteralClass: @@ -169,6 +175,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // C++ [expr.prim.general]p3: The result is an lvalue if the entity is a // function or variable and a prvalue otherwise. case Expr::DeclRefExprClass: + if (E->getType() == Ctx.UnknownAnyTy) + return isa(cast(E)->getDecl()) + ? Cl::CL_PRValue : Cl::CL_LValue; return ClassifyDecl(Ctx, cast(E)->getDecl()); // We deal with names referenced from blocks the same way. case Expr::BlockDeclRefExprClass: @@ -229,6 +238,14 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ParenExprClass: return ClassifyInternal(Ctx, cast(E)->getSubExpr()); + // C1X 6.5.1.1p4: [A generic selection] is an lvalue, a function designator, + // or a void expression if its result expression is, respectively, an + // lvalue, a function designator, or a void expression. + case Expr::GenericSelectionExprClass: + if (cast(E)->isResultDependent()) + return Cl::CL_PRValue; + return ClassifyInternal(Ctx,cast(E)->getResultExpr()); + case Expr::BinaryOperatorClass: case Expr::CompoundAssignOperatorClass: // C doesn't have any binary expressions that are lvalues. @@ -293,7 +310,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ObjCMessageExprClass: if (const ObjCMethodDecl *Method = cast(E)->getMethodDecl()) { - return ClassifyUnnamed(Ctx, Method->getResultType()); + Cl::Kinds kind = ClassifyUnnamed(Ctx, Method->getResultType()); + return (kind == Cl::CL_PRValue) ? Cl::CL_ObjCMessageRValue : kind; } return Cl::CL_PRValue; @@ -373,6 +391,10 @@ static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) { } static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { + if (E->getType() == Ctx.UnknownAnyTy) + return (isa(E->getMemberDecl()) + ? Cl::CL_PRValue : Cl::CL_LValue); + // Handle C first, it's easier. if (!Ctx.getLangOptions().CPlusPlus) { // C99 6.5.2.3p3 @@ -546,11 +568,13 @@ Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const { case Cl::CL_LValue: return LV_Valid; case Cl::CL_XValue: return LV_InvalidExpression; case Cl::CL_Function: return LV_NotObjectType; - case Cl::CL_Void: return LV_IncompleteVoidType; + case Cl::CL_Void: return LV_InvalidExpression; + case Cl::CL_AddressableVoid: return LV_IncompleteVoidType; case Cl::CL_DuplicateVectorComponents: return LV_DuplicateVectorComponents; case Cl::CL_MemberFunction: return LV_MemberFunction; case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting; case Cl::CL_ClassTemporary: return LV_ClassTemporary; + case Cl::CL_ObjCMessageRValue: return LV_InvalidMessageExpression; case Cl::CL_PRValue: return LV_InvalidExpression; } llvm_unreachable("Unhandled kind"); @@ -564,11 +588,13 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { case Cl::CL_LValue: break; case Cl::CL_XValue: return MLV_InvalidExpression; case Cl::CL_Function: return MLV_NotObjectType; - case Cl::CL_Void: return MLV_IncompleteVoidType; + case Cl::CL_Void: return MLV_InvalidExpression; + case Cl::CL_AddressableVoid: return MLV_IncompleteVoidType; case Cl::CL_DuplicateVectorComponents: return MLV_DuplicateVectorComponents; case Cl::CL_MemberFunction: return MLV_MemberFunction; case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting; case Cl::CL_ClassTemporary: return MLV_ClassTemporary; + case Cl::CL_ObjCMessageRValue: return MLV_InvalidMessageExpression; case Cl::CL_PRValue: return VC.getModifiable() == Cl::CM_LValueCast ? MLV_LValueCast : MLV_InvalidExpression; diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 3a5eb66ea18f..c2caf8d40b16 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -42,25 +42,25 @@ using llvm::APFloat; /// rules. For example, the RHS of (0 && foo()) is not evaluated. We can /// evaluate the expression regardless of what the RHS is, but C only allows /// certain things in certain situations. -struct EvalInfo { - const ASTContext &Ctx; - - /// EvalResult - Contains information about the evaluation. - Expr::EvalResult &EvalResult; - - llvm::DenseMap OpaqueValues; - const APValue *getOpaqueValue(const OpaqueValueExpr *e) { - llvm::DenseMap::iterator - i = OpaqueValues.find(e); - if (i == OpaqueValues.end()) return 0; - return &i->second; - } - - EvalInfo(const ASTContext &ctx, Expr::EvalResult& evalresult) - : Ctx(ctx), EvalResult(evalresult) {} -}; - namespace { + struct EvalInfo { + const ASTContext &Ctx; + + /// EvalResult - Contains information about the evaluation. + Expr::EvalResult &EvalResult; + + typedef llvm::DenseMap MapTy; + MapTy OpaqueValues; + const APValue *getOpaqueValue(const OpaqueValueExpr *e) const { + MapTy::const_iterator i = OpaqueValues.find(e); + if (i == OpaqueValues.end()) return 0; + return &i->second; + } + + EvalInfo(const ASTContext &ctx, Expr::EvalResult &evalresult) + : Ctx(ctx), EvalResult(evalresult) {} + }; + struct ComplexValue { private: bool IsInt; @@ -175,7 +175,7 @@ static bool EvalPointerValueAsBool(LValue& Value, bool& Result) { const ValueDecl* Decl = DeclRef->getDecl(); if (Decl->hasAttr() || Decl->hasAttr() || - Decl->hasAttr()) + Decl->isWeakImported()) return false; return true; @@ -274,6 +274,9 @@ class HasSideEffect } bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { + return Visit(E->getResultExpr()); + } bool VisitDeclRefExpr(DeclRefExpr *E) { if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified()) return true; @@ -290,7 +293,8 @@ class HasSideEffect bool VisitFloatingLiteral(FloatingLiteral *E) { return false; } bool VisitStringLiteral(StringLiteral *E) { return false; } bool VisitCharacterLiteral(CharacterLiteral *E) { return false; } - bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return false; } + bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) + { return false; } bool VisitArraySubscriptExpr(ArraySubscriptExpr *E) { return Visit(E->getLHS()) || Visit(E->getRHS()); } bool VisitChooseExpr(ChooseExpr *E) @@ -315,6 +319,8 @@ class HasSideEffect bool VisitInitListExpr(InitListExpr *E) { for (unsigned i = 0, e = E->getNumInits(); i != e; ++i) if (Visit(E->getInit(i))) return true; + if (Expr *filler = E->getArrayFiller()) + return Visit(filler); return false; } @@ -371,6 +377,9 @@ class LValueExprEvaluator } bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { + return Visit(E->getResultExpr()); + } bool VisitDeclRefExpr(DeclRefExpr *E); bool VisitPredefinedExpr(PredefinedExpr *E) { return Success(E); } bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E); @@ -500,6 +509,9 @@ class PointerExprEvaluator } bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { + return Visit(E->getResultExpr()); + } bool VisitBinaryOperator(const BinaryOperator *E); bool VisitCastExpr(CastExpr* E); @@ -589,7 +601,6 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { case CK_NoOp: case CK_BitCast: - case CK_LValueBitCast: case CK_AnyPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: return Visit(SubExpr); @@ -717,6 +728,8 @@ namespace { APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + APValue VisitGenericSelectionExpr(GenericSelectionExpr *E) + { return Visit(E->getResultExpr()); } APValue VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); } APValue VisitUnaryPlus(const UnaryOperator *E) @@ -755,68 +768,61 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { const Expr* SE = E->getSubExpr(); QualType SETy = SE->getType(); - APValue Result = APValue(); - // Check for vector->vector bitcast and scalar->vector splat. - if (SETy->isVectorType()) { - return this->Visit(const_cast(SE)); - } else if (SETy->isIntegerType()) { - APSInt IntResult; - if (!EvaluateInteger(SE, IntResult, Info)) - return APValue(); - Result = APValue(IntResult); - } else if (SETy->isRealFloatingType()) { - APFloat F(0.0); - if (!EvaluateFloat(SE, F, Info)) - return APValue(); - Result = APValue(F); - } else - return APValue(); - - // For casts of a scalar to ExtVector, convert the scalar to the element type - // and splat it to all elements. - if (E->getType()->isExtVectorType()) { - if (EltTy->isIntegerType() && Result.isInt()) - Result = APValue(HandleIntToIntCast(EltTy, SETy, Result.getInt(), - Info.Ctx)); - else if (EltTy->isIntegerType()) - Result = APValue(HandleFloatToIntCast(EltTy, SETy, Result.getFloat(), - Info.Ctx)); - else if (EltTy->isRealFloatingType() && Result.isInt()) - Result = APValue(HandleIntToFloatCast(EltTy, SETy, Result.getInt(), - Info.Ctx)); - else if (EltTy->isRealFloatingType()) - Result = APValue(HandleFloatToFloatCast(EltTy, SETy, Result.getFloat(), - Info.Ctx)); - else + switch (E->getCastKind()) { + case CK_VectorSplat: { + APValue Result = APValue(); + if (SETy->isIntegerType()) { + APSInt IntResult; + if (!EvaluateInteger(SE, IntResult, Info)) + return APValue(); + Result = APValue(IntResult); + } else if (SETy->isRealFloatingType()) { + APFloat F(0.0); + if (!EvaluateFloat(SE, F, Info)) + return APValue(); + Result = APValue(F); + } else { return APValue(); + } // Splat and create vector APValue. llvm::SmallVector Elts(NElts, Result); return APValue(&Elts[0], Elts.size()); } + case CK_BitCast: { + if (SETy->isVectorType()) + return Visit(const_cast(SE)); - // For casts of a scalar to regular gcc-style vector type, bitcast the scalar - // to the vector. To construct the APValue vector initializer, bitcast the - // initializing value to an APInt, and shift out the bits pertaining to each - // element. - APSInt Init; - Init = Result.isInt() ? Result.getInt() : Result.getFloat().bitcastToAPInt(); - - llvm::SmallVector Elts; - for (unsigned i = 0; i != NElts; ++i) { - APSInt Tmp = Init.extOrTrunc(EltWidth); - - if (EltTy->isIntegerType()) - Elts.push_back(APValue(Tmp)); - else if (EltTy->isRealFloatingType()) - Elts.push_back(APValue(APFloat(Tmp))); - else + if (!SETy->isIntegerType()) return APValue(); - Init >>= EltWidth; + APSInt Init; + if (!EvaluateInteger(SE, Init, Info)) + return APValue(); + + assert((EltTy->isIntegerType() || EltTy->isRealFloatingType()) && + "Vectors must be composed of ints or floats"); + + llvm::SmallVector Elts; + for (unsigned i = 0; i != NElts; ++i) { + APSInt Tmp = Init.extOrTrunc(EltWidth); + + if (EltTy->isIntegerType()) + Elts.push_back(APValue(Tmp)); + else + Elts.push_back(APValue(APFloat(Tmp))); + + Init >>= EltWidth; + } + return APValue(&Elts[0], Elts.size()); + } + case CK_LValueToRValue: + case CK_NoOp: + return Visit(const_cast(SE)); + default: + return APValue(); } - return APValue(&Elts[0], Elts.size()); } APValue @@ -837,6 +843,12 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { // becomes every element of the vector, not just the first. // This is the behavior described in the IBM AltiVec documentation. if (NumInits == 1) { + + // Handle the case where the vector is initialized by a another + // vector (OpenCL 6.1.6). + if (E->getInit(0)->getType()->isVectorType()) + return this->Visit(const_cast(E->getInit(0))); + APValue InitValue; if (EltTy->isIntegerType()) { llvm::APSInt sInt(32); @@ -953,6 +965,11 @@ class IntExprEvaluator return true; } + bool Success(CharUnits Size, const Expr *E) { + return Success(Size.getQuantity(), E); + } + + bool Error(SourceLocation L, diag::kind D, const Expr *E) { // Take the first error. if (Info.EvalResult.Diag == 0) { @@ -977,6 +994,9 @@ class IntExprEvaluator } bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { + return Visit(E->getResultExpr()); + } bool VisitIntegerLiteral(const IntegerLiteral *E) { return Success(E->getValue(), E); @@ -1015,7 +1035,7 @@ class IntExprEvaluator bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E); bool VisitCastExpr(CastExpr* E); - bool VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E); + bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { return Success(E->getValue(), E); @@ -1041,6 +1061,14 @@ class IntExprEvaluator return Success(E->getValue(), E); } + bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { + return Success(E->getValue(), E); + } + + bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { + return Success(E->getValue(), E); + } + bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } @@ -1213,7 +1241,7 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(CallExpr *E) { Size -= Offset; else Size = CharUnits::Zero(); - return Success(Size.getQuantity(), E); + return Success(Size, E); } bool IntExprEvaluator::VisitCallExpr(CallExpr *E) { @@ -1596,36 +1624,59 @@ CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) { } -/// VisitSizeAlignOfExpr - Evaluate a sizeof or alignof with a result as the -/// expression's type. -bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { - // Handle alignof separately. - if (!E->isSizeOf()) { +/// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof or vec_step with +/// a result as the expression's type. +bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( + const UnaryExprOrTypeTraitExpr *E) { + switch(E->getKind()) { + case UETT_AlignOf: { if (E->isArgumentType()) - return Success(GetAlignOfType(E->getArgumentType()).getQuantity(), E); + return Success(GetAlignOfType(E->getArgumentType()), E); else - return Success(GetAlignOfExpr(E->getArgumentExpr()).getQuantity(), E); + return Success(GetAlignOfExpr(E->getArgumentExpr()), E); } - QualType SrcTy = E->getTypeOfArgument(); - // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, - // the result is the size of the referenced type." - // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the - // result shall be the alignment of the referenced type." - if (const ReferenceType *Ref = SrcTy->getAs()) - SrcTy = Ref->getPointeeType(); + case UETT_VecStep: { + QualType Ty = E->getTypeOfArgument(); - // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc - // extension. - if (SrcTy->isVoidType() || SrcTy->isFunctionType()) - return Success(1, E); + if (Ty->isVectorType()) { + unsigned n = Ty->getAs()->getNumElements(); - // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. - if (!SrcTy->isConstantSizeType()) - return false; + // The vec_step built-in functions that take a 3-component + // vector return 4. (OpenCL 1.1 spec 6.11.12) + if (n == 3) + n = 4; - // Get information about the size. - return Success(Info.Ctx.getTypeSizeInChars(SrcTy).getQuantity(), E); + return Success(n, E); + } else + return Success(1, E); + } + + case UETT_SizeOf: { + QualType SrcTy = E->getTypeOfArgument(); + // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, + // the result is the size of the referenced type." + // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the + // result shall be the alignment of the referenced type." + if (const ReferenceType *Ref = SrcTy->getAs()) + SrcTy = Ref->getPointeeType(); + + // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc + // extension. + if (SrcTy->isVoidType() || SrcTy->isFunctionType()) + return Success(1, E); + + // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. + if (!SrcTy->isConstantSizeType()) + return false; + + // Get information about the size. + return Success(Info.Ctx.getTypeSizeInChars(SrcTy), E); + } + } + + llvm_unreachable("unknown expr/type trait"); + return false; } bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) { @@ -1694,7 +1745,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) { } } } - return Success(Result.getQuantity(), E); + return Success(Result, E); } bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { @@ -1742,15 +1793,60 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { QualType DestType = E->getType(); QualType SrcType = SubExpr->getType(); - if (DestType->isBooleanType()) { + switch (E->getCastKind()) { + case CK_BaseToDerived: + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_Dynamic: + case CK_ToUnion: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_NullToPointer: + case CK_NullToMemberPointer: + case CK_BaseToDerivedMemberPointer: + case CK_DerivedToBaseMemberPointer: + case CK_ConstructorConversion: + case CK_IntegralToPointer: + case CK_ToVoid: + case CK_VectorSplat: + case CK_IntegralToFloating: + case CK_FloatingCast: + case CK_AnyPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + case CK_ObjCObjectLValueCast: + case CK_FloatingRealToComplex: + case CK_FloatingComplexToReal: + case CK_FloatingComplexCast: + case CK_FloatingComplexToIntegralComplex: + case CK_IntegralRealToComplex: + case CK_IntegralComplexCast: + case CK_IntegralComplexToFloatingComplex: + llvm_unreachable("invalid cast kind for integral value"); + + case CK_BitCast: + case CK_Dependent: + case CK_GetObjCProperty: + case CK_LValueBitCast: + case CK_UserDefinedConversion: + return false; + + case CK_LValueToRValue: + case CK_NoOp: + return Visit(E->getSubExpr()); + + case CK_MemberPointerToBoolean: + case CK_PointerToBoolean: + case CK_IntegralToBoolean: + case CK_FloatingToBoolean: + case CK_FloatingComplexToBoolean: + case CK_IntegralComplexToBoolean: { bool BoolResult; if (!HandleConversionToBool(SubExpr, BoolResult, Info)) return false; return Success(BoolResult, E); } - // Handle simple integer->integer casts. - if (SrcType->isIntegralOrEnumerationType()) { + case CK_IntegralCast: { if (!Visit(SubExpr)) return false; @@ -1763,8 +1859,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { Result.getInt(), Info.Ctx), E); } - // FIXME: Clean this up! - if (SrcType->isPointerType()) { + case CK_PointerToIntegral: { LValue LV; if (!EvaluatePointer(SubExpr, LV, Info)) return false; @@ -1783,42 +1878,24 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E); } - if (SrcType->isArrayType() || SrcType->isFunctionType()) { - // This handles double-conversion cases, where there's both - // an l-value promotion and an implicit conversion to int. - LValue LV; - if (!EvaluateLValue(SubExpr, LV, Info)) - return false; - - if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(Info.Ctx.VoidPtrTy)) - return false; - - LV.moveInto(Result); - return true; - } - - if (SrcType->isAnyComplexType()) { + case CK_IntegralComplexToReal: { ComplexValue C; if (!EvaluateComplex(SubExpr, C, Info)) return false; - if (C.isComplexFloat()) - return Success(HandleFloatToIntCast(DestType, SrcType, - C.getComplexFloatReal(), Info.Ctx), - E); - else - return Success(HandleIntToIntCast(DestType, SrcType, - C.getComplexIntReal(), Info.Ctx), E); + return Success(C.getComplexIntReal(), E); } - // FIXME: Handle vectors - if (!SrcType->isRealFloatingType()) - return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E); + case CK_FloatingToIntegral: { + APFloat F(0.0); + if (!EvaluateFloat(SubExpr, F, Info)) + return false; - APFloat F(0.0); - if (!EvaluateFloat(SubExpr, F, Info)) - return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E); + return Success(HandleFloatToIntCast(DestType, SrcType, F, Info.Ctx), E); + } + } - return Success(HandleFloatToIntCast(DestType, SrcType, F, Info.Ctx), E); + llvm_unreachable("unknown cast resulting in integral value"); + return false; } bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { @@ -1871,6 +1948,9 @@ class FloatExprEvaluator } bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { + return Visit(E->getResultExpr()); + } bool VisitCallExpr(const CallExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); @@ -2119,7 +2199,15 @@ bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) { bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) { Expr* SubExpr = E->getSubExpr(); - if (SubExpr->getType()->isIntegralOrEnumerationType()) { + switch (E->getCastKind()) { + default: + return false; + + case CK_LValueToRValue: + case CK_NoOp: + return Visit(SubExpr); + + case CK_IntegralToFloating: { APSInt IntResult; if (!EvaluateInteger(SubExpr, IntResult, Info)) return false; @@ -2127,7 +2215,8 @@ bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) { IntResult, Info.Ctx); return true; } - if (SubExpr->getType()->isRealFloatingType()) { + + case CK_FloatingCast: { if (!Visit(SubExpr)) return false; Result = HandleFloatToFloatCast(E->getType(), SubExpr->getType(), @@ -2135,13 +2224,14 @@ bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) { return true; } - if (E->getCastKind() == CK_FloatingComplexToReal) { + case CK_FloatingComplexToReal: { ComplexValue V; if (!EvaluateComplex(SubExpr, V, Info)) return false; Result = V.getComplexFloatReal(); return true; } + } return false; } @@ -2194,6 +2284,9 @@ class ComplexExprEvaluator } bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitGenericSelectionExpr(GenericSelectionExpr *E) { + return Visit(E->getResultExpr()); + } bool VisitImaginaryLiteral(ImaginaryLiteral *E); @@ -2253,7 +2346,6 @@ bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) { switch (E->getCastKind()) { case CK_BitCast: - case CK_LValueBitCast: case CK_BaseToDerived: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: @@ -2293,6 +2385,7 @@ bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) { case CK_Dependent: case CK_GetObjCProperty: + case CK_LValueBitCast: case CK_UserDefinedConversion: return false; @@ -2782,12 +2875,16 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::ParenExprClass: return CheckICE(cast(E)->getSubExpr(), Ctx); + case Expr::GenericSelectionExprClass: + return CheckICE(cast(E)->getResultExpr(), Ctx); case Expr::IntegerLiteralClass: case Expr::CharacterLiteralClass: case Expr::CXXBoolLiteralExprClass: case Expr::CXXScalarValueInitExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::ArrayTypeTraitExprClass: + case Expr::ExpressionTraitExprClass: case Expr::CXXNoexceptExprClass: return NoDiag(); case Expr::CallExprClass: @@ -2879,9 +2976,10 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // are ICEs, the value of the offsetof must be an integer constant. return CheckEvalInICE(E, Ctx); } - case Expr::SizeOfAlignOfExprClass: { - const SizeOfAlignOfExpr *Exp = cast(E); - if (Exp->isSizeOf() && Exp->getTypeOfArgument()->isVariableArrayType()) + case Expr::UnaryExprOrTypeTraitExprClass: { + const UnaryExprOrTypeTraitExpr *Exp = cast(E); + if ((Exp->getKind() == UETT_SizeOf) && + Exp->getTypeOfArgument()->isVariableArrayType()) return ICEDiag(2, E->getLocStart()); return NoDiag(); } diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp new file mode 100644 index 000000000000..89bf56db1af7 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp @@ -0,0 +1,59 @@ +//===- ExternalASTSource.cpp - Abstract External AST 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 provides the default implementation of the ExternalASTSource +// interface, which enables construction of AST nodes from some external +// source. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ExternalASTSource.h" +#include "clang/AST/DeclarationName.h" + +using namespace clang; + +ExternalASTSource::~ExternalASTSource() { } + +void ExternalASTSource::PrintStats() { } + +Decl *ExternalASTSource::GetExternalDecl(uint32_t ID) { + return 0; +} + +Selector ExternalASTSource::GetExternalSelector(uint32_t ID) { + return Selector(); +} + +uint32_t ExternalASTSource::GetNumExternalSelectors() { + return 0; +} + +Stmt *ExternalASTSource::GetExternalDeclStmt(uint64_t Offset) { + return 0; +} + +CXXBaseSpecifier * +ExternalASTSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { + return 0; +} + +DeclContextLookupResult +ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) { + return DeclContext::lookup_result(); +} + +void ExternalASTSource::MaterializeVisibleDecls(const DeclContext *DC) { } + +bool +ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC, + bool (*isKindWeWant)(Decl::Kind), + llvm::SmallVectorImpl &Result) { + return true; +} diff --git a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp index 533a2329c583..c47a9dadbadd 100644 --- a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp +++ b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp @@ -17,7 +17,6 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/TypeOrdering.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/raw_ostream.h" #include @@ -136,28 +135,34 @@ InheritanceHierarchyWriter::WriteNodeReference(QualType Type, /// class using GraphViz. void CXXRecordDecl::viewInheritance(ASTContext& Context) const { QualType Self = Context.getTypeDeclType(const_cast(this)); - // Create temp directory - SmallString<128> Filename; - int FileFD = 0; - if (error_code ec = sys::fs::unique_file( - "clang-class-inheritance-hierarchy-%%-%%-%%-%%-" + - Self.getAsString() + ".dot", - FileFD, Filename)) { - errs() << "Error creating temporary output file: " << ec.message() << '\n'; + std::string ErrMsg; + sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); + if (Filename.isEmpty()) { + llvm::errs() << "Error: " << ErrMsg << "\n"; + return; + } + Filename.appendComponent(Self.getAsString() + ".dot"); + if (Filename.makeUnique(true,&ErrMsg)) { + llvm::errs() << "Error: " << ErrMsg << "\n"; return; } - llvm::errs() << "Writing '" << Filename << "'... "; + llvm::errs() << "Writing '" << Filename.c_str() << "'... "; - llvm::raw_fd_ostream O(FileFD, true); - InheritanceHierarchyWriter Writer(Context, O); - Writer.WriteGraph(Self); + llvm::raw_fd_ostream O(Filename.c_str(), ErrMsg); - llvm::errs() << " done. \n"; - O.close(); + if (ErrMsg.empty()) { + InheritanceHierarchyWriter Writer(Context, O); + Writer.WriteGraph(Self); + llvm::errs() << " done. \n"; - // Display the graph - DisplayGraph(sys::Path(Filename)); + O.close(); + + // Display the graph + DisplayGraph(Filename); + } else { + llvm::errs() << "error opening file for writing!\n"; + } } } diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index bed02b4c0010..30aece3ee73b 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This provides C++ AST support targetting the Itanium C++ ABI, which is +// This provides C++ AST support targeting the Itanium C++ ABI, which is // documented at: // http://www.codesourcery.com/public/cxx-abi/abi.html // http://www.codesourcery.com/public/cxx-abi/abi-eh.html diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index 939ca7a924aa..c460929c461d 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -21,6 +21,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/ABI.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -50,18 +51,16 @@ static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) { return 0; } -static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) { - assert((isa(MD) || isa(MD)) && - "Passed in decl is not a ctor or dtor!"); +static const FunctionDecl *getStructor(const FunctionDecl *fn) { + if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate()) + return ftd->getTemplatedDecl(); - if (const TemplateDecl *TD = MD->getPrimaryTemplate()) { - MD = cast(TD->getTemplatedDecl()); + return fn; +} - assert((isa(MD) || isa(MD)) && - "Templated decl is not a ctor or dtor!"); - } - - return MD; +static const NamedDecl *getStructor(const NamedDecl *decl) { + const FunctionDecl *fn = dyn_cast_or_null(decl); + return (fn ? getStructor(fn) : decl); } static const unsigned UnknownArity = ~0U; @@ -138,27 +137,75 @@ class CXXNameMangler { ItaniumMangleContext &Context; llvm::raw_ostream &Out; - const CXXMethodDecl *Structor; + /// The "structor" is the top-level declaration being mangled, if + /// that's not a template specialization; otherwise it's the pattern + /// for that specialization. + const NamedDecl *Structor; unsigned StructorType; /// SeqID - The next subsitution sequence number. unsigned SeqID; + class FunctionTypeDepthState { + unsigned Bits; + + enum { InResultTypeMask = 1 }; + + public: + FunctionTypeDepthState() : Bits(0) {} + + /// The number of function types we're inside. + unsigned getDepth() const { + return Bits >> 1; + } + + /// True if we're in the return type of the innermost function type. + bool isInResultType() const { + return Bits & InResultTypeMask; + } + + FunctionTypeDepthState push() { + FunctionTypeDepthState tmp = *this; + Bits = (Bits & ~InResultTypeMask) + 2; + return tmp; + } + + void enterResultType() { + Bits |= InResultTypeMask; + } + + void leaveResultType() { + Bits &= ~InResultTypeMask; + } + + void pop(FunctionTypeDepthState saved) { + assert(getDepth() == saved.getDepth() + 1); + Bits = saved.Bits; + } + + } FunctionTypeDepth; + llvm::DenseMap Substitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } public: - CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_) - : Context(C), Out(Out_), Structor(0), StructorType(0), SeqID(0) { } + CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_, + const NamedDecl *D = 0) + : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0), + SeqID(0) { + // These can't be mangled without a ctor type or dtor type. + assert(!D || (!isa(D) && + !isa(D))); + } CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_, const CXXConstructorDecl *D, CXXCtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), - SeqID(0) { } + SeqID(0) { } CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), - SeqID(0) { } + SeqID(0) { } #if MANGLE_CHECKER ~CXXNameMangler() { @@ -200,11 +247,16 @@ class CXXNameMangler { void addSubstitution(TemplateName Template); void addSubstitution(uintptr_t Ptr); - void mangleUnresolvedScope(NestedNameSpecifier *Qualifier); - void mangleUnresolvedName(NestedNameSpecifier *Qualifier, - DeclarationName Name, + void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, + NamedDecl *firstQualifierLookup, + bool recursive = false); + void mangleUnresolvedName(NestedNameSpecifier *qualifier, + NamedDecl *firstQualifierLookup, + DeclarationName name, unsigned KnownArity = UnknownArity); + void mangleUnresolvedType(QualType type); + void mangleName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); @@ -223,6 +275,7 @@ class CXXNameMangler { void mangleNestedName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); + void manglePrefix(NestedNameSpecifier *qualifier); void manglePrefix(const DeclContext *DC, bool NoFunction=false); void mangleTemplatePrefix(const TemplateDecl *ND); void mangleTemplatePrefix(TemplateName Template); @@ -245,10 +298,11 @@ class CXXNameMangler { void mangleNeonVectorType(const VectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); - void mangleMemberExpr(const Expr *Base, bool IsArrow, - NestedNameSpecifier *Qualifier, - DeclarationName Name, - unsigned KnownArity); + void mangleMemberExpr(const Expr *base, bool isArrow, + NestedNameSpecifier *qualifier, + NamedDecl *firstQualifierLookup, + DeclarationName name, + unsigned knownArity); void mangleExpression(const Expr *E, unsigned Arity = UnknownArity); void mangleCXXCtorType(CXXCtorType T); void mangleCXXDtorType(CXXDtorType T); @@ -265,6 +319,8 @@ class CXXNameMangler { void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A); void mangleTemplateParameter(unsigned Index); + + void mangleFunctionParam(const ParmVarDecl *parm); }; } @@ -334,10 +390,11 @@ void CXXNameMangler::mangle(const NamedDecl *D, llvm::StringRef Prefix) { // another has a "\01foo". That is known to happen on ELF with the // tricks normally used for producing aliases (PR9177). Fortunately the // llvm mangler on ELF is a nop, so we can just avoid adding the \01 - // marker. + // marker. We also avoid adding the marker if this is an alias for an + // LLVM intrinsic. llvm::StringRef UserLabelPrefix = getASTContext().Target.getUserLabelPrefix(); - if (!UserLabelPrefix.empty()) + if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm.")) Out << '\01'; // LLVM IR Marker for __asm("foo") Out << ALA->getLabel(); @@ -552,11 +609,24 @@ void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) { addSubstitution(Template); } -void CXXNameMangler::mangleFloat(const llvm::APFloat &F) { - // TODO: avoid this copy with careful stream management. - llvm::SmallString<20> Buffer; - F.bitcastToAPInt().toString(Buffer, 16, false); - Out.write(Buffer.data(), Buffer.size()); +void CXXNameMangler::mangleFloat(const llvm::APFloat &f) { + // ABI: + // Floating-point literals are encoded using a fixed-length + // lowercase hexadecimal string corresponding to the internal + // representation (IEEE on Itanium), high-order bytes first, + // without leading zeroes. For example: "Lf bf800000 E" is -1.0f + // on Itanium. + // APInt::toString uses uppercase hexadecimal, and it's not really + // worth embellishing that interface for this use case, so we just + // do a second pass to lowercase things. + typedef llvm::SmallString<20> buffer_t; + buffer_t buffer; + f.bitcastToAPInt().toString(buffer, 16, false); + + for (buffer_t::iterator i = buffer.begin(), e = buffer.end(); i != e; ++i) + if (isupper(*i)) *i = tolower(*i); + + Out.write(buffer.data(), buffer.size()); } void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) { @@ -597,59 +667,162 @@ void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) { Out << '_'; } -void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) { - Qualifier = getASTContext().getCanonicalNestedNameSpecifier(Qualifier); - switch (Qualifier->getKind()) { - case NestedNameSpecifier::Global: - // nothing - break; - case NestedNameSpecifier::Namespace: - mangleName(Qualifier->getAsNamespace()); - break; - case NestedNameSpecifier::NamespaceAlias: - mangleName(Qualifier->getAsNamespaceAlias()->getNamespace()); - break; - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - const Type *QTy = Qualifier->getAsType(); - - if (const TemplateSpecializationType *TST = - dyn_cast(QTy)) { - if (!mangleSubstitution(QualType(TST, 0))) { - mangleTemplatePrefix(TST->getTemplateName()); +void CXXNameMangler::mangleUnresolvedType(QualType type) { + if (const TemplateSpecializationType *TST = + type->getAs()) { + if (!mangleSubstitution(QualType(TST, 0))) { + mangleTemplatePrefix(TST->getTemplateName()); - // FIXME: GCC does not appear to mangle the template arguments when - // the template in question is a dependent template name. Should we - // emulate that badness? - mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(), - TST->getNumArgs()); - addSubstitution(QualType(TST, 0)); - } - } else { - // We use the QualType mangle type variant here because it handles - // substitutions. - mangleType(QualType(QTy, 0)); + // FIXME: GCC does not appear to mangle the template arguments when + // the template in question is a dependent template name. Should we + // emulate that badness? + mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(), + TST->getNumArgs()); + addSubstitution(QualType(TST, 0)); } - } - break; - case NestedNameSpecifier::Identifier: - // Member expressions can have these without prefixes. - if (Qualifier->getPrefix()) - mangleUnresolvedScope(Qualifier->getPrefix()); - mangleSourceName(Qualifier->getAsIdentifier()); - break; + } else if (const DependentTemplateSpecializationType *DTST + = type->getAs()) { + TemplateName Template + = getASTContext().getDependentTemplateName(DTST->getQualifier(), + DTST->getIdentifier()); + mangleTemplatePrefix(Template); + + // FIXME: GCC does not appear to mangle the template arguments when + // the template in question is a dependent template name. Should we + // emulate that badness? + mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs()); + } else { + // We use the QualType mangle type variant here because it handles + // substitutions. + mangleType(type); } } -/// Mangles a name which was not resolved to a specific entity. -void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *Qualifier, - DeclarationName Name, - unsigned KnownArity) { - if (Qualifier) - mangleUnresolvedScope(Qualifier); - // FIXME: ambiguity of unqualified lookup with :: +/// Mangle everything prior to the base-unresolved-name in an unresolved-name. +/// +/// \param firstQualifierLookup - the entity found by unqualified lookup +/// for the first name in the qualifier, if this is for a member expression +/// \param recursive - true if this is being called recursively, +/// i.e. if there is more prefix "to the right". +void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, + NamedDecl *firstQualifierLookup, + bool recursive) { - mangleUnqualifiedName(0, Name, KnownArity); + // x, ::x + // ::= [gs] + + // T::x / decltype(p)::x + // ::= sr + + // T::N::x /decltype(p)::N::x + // ::= srN + E + // + + // A::x, N::y, A::z; "gs" means leading "::" + // ::= [gs] sr + E + // + + switch (qualifier->getKind()) { + case NestedNameSpecifier::Global: + Out << "gs"; + + // We want an 'sr' unless this is the entire NNS. + if (recursive) + Out << "sr"; + + // We never want an 'E' here. + return; + + case NestedNameSpecifier::Namespace: + if (qualifier->getPrefix()) + mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, + /*recursive*/ true); + else + Out << "sr"; + mangleSourceName(qualifier->getAsNamespace()->getIdentifier()); + break; + case NestedNameSpecifier::NamespaceAlias: + if (qualifier->getPrefix()) + mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, + /*recursive*/ true); + else + Out << "sr"; + mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier()); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + // Both cases want this. + Out << "sr"; + + // We only get here recursively if we're followed by identifiers. + if (recursive) Out << 'N'; + + mangleUnresolvedType(QualType(qualifier->getAsType(), 0)); + + // We never want to print 'E' directly after an unresolved-type, + // so we return directly. + return; + } + + case NestedNameSpecifier::Identifier: + // Member expressions can have these without prefixes. + if (qualifier->getPrefix()) { + mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup, + /*recursive*/ true); + } else if (firstQualifierLookup) { + + // Try to make a proper qualifier out of the lookup result, and + // then just recurse on that. + NestedNameSpecifier *newQualifier; + if (TypeDecl *typeDecl = dyn_cast(firstQualifierLookup)) { + QualType type = getASTContext().getTypeDeclType(typeDecl); + + // Pretend we had a different nested name specifier. + newQualifier = NestedNameSpecifier::Create(getASTContext(), + /*prefix*/ 0, + /*template*/ false, + type.getTypePtr()); + } else if (NamespaceDecl *nspace = + dyn_cast(firstQualifierLookup)) { + newQualifier = NestedNameSpecifier::Create(getASTContext(), + /*prefix*/ 0, + nspace); + } else if (NamespaceAliasDecl *alias = + dyn_cast(firstQualifierLookup)) { + newQualifier = NestedNameSpecifier::Create(getASTContext(), + /*prefix*/ 0, + alias); + } else { + // No sensible mangling to do here. + newQualifier = 0; + } + + if (newQualifier) + return mangleUnresolvedPrefix(newQualifier, /*lookup*/ 0, recursive); + + } else { + Out << "sr"; + } + + mangleSourceName(qualifier->getAsIdentifier()); + break; + } + + // If this was the innermost part of the NNS, and we fell out to + // here, append an 'E'. + if (!recursive) + Out << 'E'; +} + +/// Mangle an unresolved-name, which is generally used for names which +/// weren't resolved to specific entities. +void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, + NamedDecl *firstQualifierLookup, + DeclarationName name, + unsigned knownArity) { + if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup); + mangleUnqualifiedName(0, name, knownArity); } static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) { @@ -684,10 +857,12 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, case DeclarationName::Identifier: { if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { // We must avoid conflicts between internally- and externally- - // linked variable declaration names in the same TU. - // This naming convention is the same as that followed by GCC, though it - // shouldn't actually matter. - if (ND && isa(ND) && ND->getLinkage() == InternalLinkage && + // linked variable and function declaration names in the same TU: + // void test() { extern void foo(); } + // static void foo(); + // This naming convention is the same as that followed by GCC, + // though it shouldn't actually matter. + if (ND && ND->getLinkage() == InternalLinkage && ND->getDeclContext()->isFileContext()) Out << 'L'; @@ -734,7 +909,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // We must have an anonymous struct. const TagDecl *TD = cast(ND); - if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) { + if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) { assert(TD->getDeclContext() == D->getDeclContext() && "Typedef should not be in another decl context!"); assert(D->getDeclName().getAsIdentifierInfo() && @@ -906,6 +1081,38 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { mangleUnqualifiedName(ND); } +void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { + switch (qualifier->getKind()) { + case NestedNameSpecifier::Global: + // nothing + return; + + case NestedNameSpecifier::Namespace: + mangleName(qualifier->getAsNamespace()); + return; + + case NestedNameSpecifier::NamespaceAlias: + mangleName(qualifier->getAsNamespaceAlias()->getNamespace()); + return; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + mangleUnresolvedType(QualType(qualifier->getAsType(), 0)); + return; + + case NestedNameSpecifier::Identifier: + // Member expressions can have these without prefixes, but that + // should end up in mangleUnresolvedPrefix instead. + assert(qualifier->getPrefix()); + manglePrefix(qualifier->getPrefix()); + + mangleSourceName(qualifier->getAsIdentifier()); + return; + } + + llvm_unreachable("unexpected nested name specifier"); +} + void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // ::= // ::= @@ -959,7 +1166,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { return mangleTemplatePrefix(TD); if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName()) - mangleUnresolvedScope(Qualified->getQualifier()); + manglePrefix(Qualified->getQualifier()); if (OverloadedTemplateStorage *Overloaded = Template.getAsOverloadedTemplate()) { @@ -970,7 +1177,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); assert(Dependent && "Unknown template name kind?"); - mangleUnresolvedScope(Dependent->getQualifier()); + manglePrefix(Dependent->getQualifier()); mangleUnscopedTemplateName(Template); } @@ -1033,7 +1240,7 @@ void CXXNameMangler::mangleType(TemplateName TN) { // ::= // ::= - mangleUnresolvedScope(Dependent->getQualifier()); + mangleUnresolvedPrefix(Dependent->getQualifier(), 0); mangleSourceName(Dependent->getIdentifier()); break; } @@ -1313,8 +1520,9 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Overload: case BuiltinType::Dependent: - assert(false && - "Overloaded and dependent types shouldn't get to name mangling"); + case BuiltinType::BoundMember: + case BuiltinType::UnknownAny: + llvm_unreachable("mangling a placeholder type"); break; case BuiltinType::ObjCId: Out << "11objc_object"; break; case BuiltinType::ObjCClass: Out << "10objc_class"; break; @@ -1339,13 +1547,22 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, // We should never be mangling something without a prototype. const FunctionProtoType *Proto = cast(T); + // Record that we're in a function type. See mangleFunctionParam + // for details on what we're trying to achieve here. + FunctionTypeDepthState saved = FunctionTypeDepth.push(); + // ::= + - if (MangleReturnType) + if (MangleReturnType) { + FunctionTypeDepth.enterResultType(); mangleType(Proto->getResultType()); + FunctionTypeDepth.leaveResultType(); + } if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) { // ::= v # void Out << 'v'; + + FunctionTypeDepth.pop(saved); return; } @@ -1354,6 +1571,8 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, Arg != ArgEnd; ++Arg) mangleType(*Arg); + FunctionTypeDepth.pop(saved); + // ::= z # ellipsis if (Proto->isVariadic()) Out << 'z'; @@ -1590,13 +1809,13 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { void CXXNameMangler::mangleType(const DependentNameType *T) { // Typename types are always nested Out << 'N'; - mangleUnresolvedScope(T->getQualifier()); + manglePrefix(T->getQualifier()); mangleSourceName(T->getIdentifier()); Out << 'E'; } void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) { - // Dependently-scoped template types are always nested + // Dependently-scoped template types are nested if they have a prefix. Out << 'N'; // TODO: avoid making this TemplateName. @@ -1676,23 +1895,54 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T, /// Mangles a member expression. Implicit accesses are not handled, /// but that should be okay, because you shouldn't be able to /// make an implicit access in a function template declaration. -void CXXNameMangler::mangleMemberExpr(const Expr *Base, - bool IsArrow, - NestedNameSpecifier *Qualifier, - DeclarationName Member, - unsigned Arity) { - // gcc-4.4 uses 'dt' for dot expressions, which is reasonable. - // OTOH, gcc also mangles the name as an expression. - Out << (IsArrow ? "pt" : "dt"); - mangleExpression(Base); - mangleUnresolvedName(Qualifier, Member, Arity); +void CXXNameMangler::mangleMemberExpr(const Expr *base, + bool isArrow, + NestedNameSpecifier *qualifier, + NamedDecl *firstQualifierLookup, + DeclarationName member, + unsigned arity) { + // ::= dt + // ::= pt + Out << (isArrow ? "pt" : "dt"); + mangleExpression(base); + mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity); +} + +/// Look at the callee of the given call expression and determine if +/// it's a parenthesized id-expression which would have triggered ADL +/// otherwise. +static bool isParenthesizedADLCallee(const CallExpr *call) { + const Expr *callee = call->getCallee(); + const Expr *fn = callee->IgnoreParens(); + + // Must be parenthesized. IgnoreParens() skips __extension__ nodes, + // too, but for those to appear in the callee, it would have to be + // parenthesized. + if (callee == fn) return false; + + // Must be an unresolved lookup. + const UnresolvedLookupExpr *lookup = dyn_cast(fn); + if (!lookup) return false; + + assert(!lookup->requiresADL()); + + // Must be an unqualified lookup. + if (lookup->getQualifier()) return false; + + // Must not have found a class member. Note that if one is a class + // member, they're all class members. + if (lookup->getNumDecls() > 0 && + (*lookup->decls_begin())->isCXXClassMember()) + return false; + + // Otherwise, ADL would have been triggered. + return true; } void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { // ::= // ::= // ::= - // ::= cl * E # call // ::= cv expression # conversion with one argument // ::= cv _ * E # conversion with a different number of arguments // ::= st # sizeof (a type) @@ -1735,6 +1985,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::ChooseExprClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: + case Expr::GenericSelectionExprClass: case Expr::ObjCEncodeExprClass: case Expr::ObjCIsaExprClass: case Expr::ObjCIvarRefExprClass: @@ -1749,6 +2000,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::StmtExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::ArrayTypeTraitExprClass: + case Expr::ExpressionTraitExprClass: case Expr::VAArgExprClass: case Expr::CXXUuidofExprClass: case Expr::CXXNoexceptExprClass: @@ -1784,7 +2037,22 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::CXXMemberCallExprClass: // fallthrough case Expr::CallExprClass: { const CallExpr *CE = cast(E); - Out << "cl"; + + // ::= cp * E + // We use this mangling only when the call would use ADL except + // for being parenthesized. Per discussion with David + // Vandervoorde, 2011.04.25. + if (isParenthesizedADLCallee(CE)) { + Out << "cp"; + // The callee here is a parenthesized UnresolvedLookupExpr with + // no qualifier and should always get mangled as a + // anyway. + + // ::= cl * E + } else { + Out << "cl"; + } + mangleExpression(CE->getCallee(), CE->getNumArgs()); for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I) mangleExpression(CE->getArg(I)); @@ -1815,7 +2083,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::MemberExprClass: { const MemberExpr *ME = cast(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), - ME->getQualifier(), ME->getMemberDecl()->getDeclName(), + ME->getQualifier(), 0, ME->getMemberDecl()->getDeclName(), Arity); break; } @@ -1823,7 +2091,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::UnresolvedMemberExprClass: { const UnresolvedMemberExpr *ME = cast(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), - ME->getQualifier(), ME->getMemberName(), + ME->getQualifier(), 0, ME->getMemberName(), Arity); if (ME->hasExplicitTemplateArgs()) mangleTemplateArgs(ME->getExplicitTemplateArgs()); @@ -1834,19 +2102,16 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { const CXXDependentScopeMemberExpr *ME = cast(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), - ME->getQualifier(), ME->getMember(), - Arity); + ME->getQualifier(), ME->getFirstQualifierFoundInScope(), + ME->getMember(), Arity); if (ME->hasExplicitTemplateArgs()) mangleTemplateArgs(ME->getExplicitTemplateArgs()); break; } case Expr::UnresolvedLookupExprClass: { - // The ABI doesn't cover how to mangle overload sets, so we mangle - // using something as close as possible to the original lookup - // expression. const UnresolvedLookupExpr *ULE = cast(E); - mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity); + mangleUnresolvedName(ULE->getQualifier(), 0, ULE->getName(), Arity); if (ULE->hasExplicitTemplateArgs()) mangleTemplateArgs(ULE->getExplicitTemplateArgs()); break; @@ -1877,10 +2142,22 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { break; } - case Expr::SizeOfAlignOfExprClass: { - const SizeOfAlignOfExpr *SAE = cast(E); - if (SAE->isSizeOf()) Out << 's'; - else Out << 'a'; + case Expr::UnaryExprOrTypeTraitExprClass: { + const UnaryExprOrTypeTraitExpr *SAE = cast(E); + switch(SAE->getKind()) { + case UETT_SizeOf: + Out << 's'; + break; + case UETT_AlignOf: + Out << 'a'; + break; + case UETT_VecStep: + Diagnostic &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error, + "cannot yet mangle vec_step expression"); + Diags.Report(DiagID); + return; + } if (SAE->isArgumentType()) { Out << 't'; mangleType(SAE->getArgumentType()); @@ -1939,7 +2216,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::ArraySubscriptExprClass: { const ArraySubscriptExpr *AE = cast(E); - // Array subscript is treated as a syntactically wierd form of + // Array subscript is treated as a syntactically weird form of // binary operator. Out << "ix"; mangleExpression(AE->getLHS()); @@ -2009,6 +2286,10 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { Out << 'E'; break; + case Decl::ParmVar: + mangleFunctionParam(cast(D)); + break; + case Decl::EnumConstant: { const EnumConstantDecl *ED = cast(D); mangleIntegerLiteral(ED->getType(), ED->getInitVal()); @@ -2165,10 +2446,72 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { Diags.Report(DiagID); return; } + break; } } } +/// Mangle an expression which refers to a parameter variable. +/// +/// ::= +/// ::= fp _ # L == 0, I == 0 +/// ::= fp +/// _ # L == 0, I > 0 +/// ::= fL +/// p _ # L > 0, I == 0 +/// ::= fL +/// p +/// _ # L > 0, I > 0 +/// +/// L is the nesting depth of the parameter, defined as 1 if the +/// parameter comes from the innermost function prototype scope +/// enclosing the current context, 2 if from the next enclosing +/// function prototype scope, and so on, with one special case: if +/// we've processed the full parameter clause for the innermost +/// function type, then L is one less. This definition conveniently +/// makes it irrelevant whether a function's result type was written +/// trailing or leading, but is otherwise overly complicated; the +/// numbering was first designed without considering references to +/// parameter in locations other than return types, and then the +/// mangling had to be generalized without changing the existing +/// manglings. +/// +/// I is the zero-based index of the parameter within its parameter +/// declaration clause. Note that the original ABI document describes +/// this using 1-based ordinals. +void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) { + unsigned parmDepth = parm->getFunctionScopeDepth(); + unsigned parmIndex = parm->getFunctionScopeIndex(); + + // Compute 'L'. + // parmDepth does not include the declaring function prototype. + // FunctionTypeDepth does account for that. + assert(parmDepth < FunctionTypeDepth.getDepth()); + unsigned nestingDepth = FunctionTypeDepth.getDepth() - parmDepth; + if (FunctionTypeDepth.isInResultType()) + nestingDepth--; + + if (nestingDepth == 0) { + Out << "fp"; + } else { + Out << "fL" << (nestingDepth - 1) << 'p'; + } + + // Top-level qualifiers. We don't have to worry about arrays here, + // because parameters declared as arrays should already have been + // tranformed to have pointer type. FIXME: apparently these don't + // get mangled if used as an rvalue of a known non-class type? + assert(!parm->getType()->isArrayType() + && "parameter's type is still an array type?"); + mangleQualifiers(parm->getType().getQualifiers()); + + // Parameter index. + if (parmIndex != 0) { + Out << (parmIndex - 1); + } + Out << '_'; +} + void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) { // ::= C1 # complete object constructor // ::= C2 # base object constructor @@ -2287,8 +2630,7 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P, // an expression. We compensate for it here to produce the correct mangling. NamedDecl *D = cast(A.getAsDecl()); const NonTypeTemplateParmDecl *Parameter = cast(P); - bool compensateMangling = D->isCXXClassMember() && - !Parameter->getType()->isReferenceType(); + bool compensateMangling = !Parameter->getType()->isReferenceType(); if (compensateMangling) { Out << 'X'; mangleOperatorName(OO_Amp, 1); @@ -2576,7 +2918,7 @@ void ItaniumMangleContext::mangleName(const NamedDecl *D, getASTContext().getSourceManager(), "Mangling declaration"); - CXXNameMangler Mangler(*this, Out); + CXXNameMangler Mangler(*this, Out, D); return Mangler.mangle(D); } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp index 4de93bb4beab..206f6dd0c9eb 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This provides C++ AST support targetting the Microsoft Visual C++ +// This provides C++ AST support targeting the Microsoft Visual C++ // ABI. // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 4bf7f23a0a9d..5424bebc81b0 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This provides C++ name mangling targetting the Microsoft Visual C++ ABI. +// This provides C++ name mangling targeting the Microsoft Visual C++ ABI. // //===----------------------------------------------------------------------===// @@ -314,7 +314,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // We must have an anonymous struct. const TagDecl *TD = cast(ND); - if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) { + if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) { assert(TD->getDeclContext() == D->getDeclContext() && "Typedef should not be in another decl context!"); assert(D->getDeclName().getAsIdentifierInfo() && @@ -676,12 +676,6 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { // ::= M # float // ::= N # double // ::= O # long double (__float80 is mangled differently) - // ::= _D # __int8 (yup, it's a distinct type in MSVC) - // ::= _E # unsigned __int8 - // ::= _F # __int16 - // ::= _G # unsigned __int16 - // ::= _H # __int32 - // ::= _I # unsigned __int32 // ::= _J # long long, __int64 // ::= _K # unsigned long long, __int64 // ::= _L # __int128 @@ -706,7 +700,6 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Double: Out << 'N'; break; // TODO: Determine size and mangle accordingly case BuiltinType::LongDouble: Out << 'O'; break; - // TODO: __int8 and friends case BuiltinType::LongLong: Out << "_J"; break; case BuiltinType::ULongLong: Out << "_K"; break; case BuiltinType::Int128: Out << "_L"; break; @@ -717,6 +710,8 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Overload: case BuiltinType::Dependent: + case BuiltinType::UnknownAny: + case BuiltinType::BoundMember: assert(false && "Overloaded and dependent types shouldn't get to name mangling"); break; @@ -873,6 +868,8 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T, if (CC == CC_Default) CC = IsInstMethod ? getASTContext().getDefaultMethodCallConv() : CC_C; switch (CC) { + default: + assert(0 && "Unsupported CC for mangling"); case CC_Default: case CC_C: Out << 'A'; break; case CC_X86Pascal: Out << 'C'; break; diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index 6f1ec058d74e..2878dff3edc4 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -371,3 +371,249 @@ TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { void *TypeData = LoadPointer(Data, Offset); return TypeLoc(Qualifier->getAsType(), TypeData); } + +namespace { + void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, + unsigned &BufferCapacity) { + if (BufferSize + (End - Start) > BufferCapacity) { + // Reallocate the buffer. + unsigned NewCapacity + = std::max((unsigned)(BufferCapacity? BufferCapacity * 2 + : sizeof(void*) * 2), + (unsigned)(BufferSize + (End - Start))); + char *NewBuffer = static_cast(malloc(NewCapacity)); + memcpy(NewBuffer, Buffer, BufferSize); + + if (BufferCapacity) + free(Buffer); + Buffer = NewBuffer; + BufferCapacity = NewCapacity; + } + + memcpy(Buffer + BufferSize, Start, End - Start); + BufferSize += End-Start; + } + + /// \brief Save a source location to the given buffer. + void SaveSourceLocation(SourceLocation Loc, char *&Buffer, + unsigned &BufferSize, unsigned &BufferCapacity) { + unsigned Raw = Loc.getRawEncoding(); + Append(reinterpret_cast(&Raw), + reinterpret_cast(&Raw) + sizeof(unsigned), + Buffer, BufferSize, BufferCapacity); + } + + /// \brief Save a pointer to the given buffer. + void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, + unsigned &BufferCapacity) { + Append(reinterpret_cast(&Ptr), + reinterpret_cast(&Ptr) + sizeof(void *), + Buffer, BufferSize, BufferCapacity); + } +} + +NestedNameSpecifierLocBuilder::NestedNameSpecifierLocBuilder() + : Representation(0), Buffer(0), BufferSize(0), BufferCapacity(0) { } + +NestedNameSpecifierLocBuilder:: +NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) + : Representation(Other.Representation), Buffer(0), + BufferSize(0), BufferCapacity(0) +{ + if (!Other.Buffer) + return; + + if (Other.BufferCapacity == 0) { + // Shallow copy is okay. + Buffer = Other.Buffer; + BufferSize = Other.BufferSize; + return; + } + + // Deep copy + BufferSize = Other.BufferSize; + BufferCapacity = Other.BufferSize; + Buffer = static_cast(malloc(BufferCapacity)); + memcpy(Buffer, Other.Buffer, BufferSize); +} + +NestedNameSpecifierLocBuilder & +NestedNameSpecifierLocBuilder:: +operator=(const NestedNameSpecifierLocBuilder &Other) { + Representation = Other.Representation; + + if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { + // Re-use our storage. + BufferSize = Other.BufferSize; + memcpy(Buffer, Other.Buffer, BufferSize); + return *this; + } + + // Free our storage, if we have any. + if (BufferCapacity) { + free(Buffer); + BufferCapacity = 0; + } + + if (!Other.Buffer) { + // Empty. + Buffer = 0; + BufferSize = 0; + return *this; + } + + if (Other.BufferCapacity == 0) { + // Shallow copy is okay. + Buffer = Other.Buffer; + BufferSize = Other.BufferSize; + return *this; + } + + // Deep copy. + BufferSize = Other.BufferSize; + BufferCapacity = BufferSize; + Buffer = static_cast(malloc(BufferSize)); + memcpy(Buffer, Other.Buffer, BufferSize); + return *this; +} + +NestedNameSpecifierLocBuilder::~NestedNameSpecifierLocBuilder() { + if (BufferCapacity) + free(Buffer); +} + +void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, + SourceLocation TemplateKWLoc, + TypeLoc TL, + SourceLocation ColonColonLoc) { + Representation = NestedNameSpecifier::Create(Context, Representation, + TemplateKWLoc.isValid(), + TL.getTypePtr()); + + // Push source-location info into the buffer. + SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); +} + +void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, + IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonColonLoc) { + Representation = NestedNameSpecifier::Create(Context, Representation, + Identifier); + + // Push source-location info into the buffer. + SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); +} + +void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, + NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, + SourceLocation ColonColonLoc) { + Representation = NestedNameSpecifier::Create(Context, Representation, + Namespace); + + // Push source-location info into the buffer. + SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); +} + +void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, + NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, + SourceLocation ColonColonLoc) { + Representation = NestedNameSpecifier::Create(Context, Representation, Alias); + + // Push source-location info into the buffer. + SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); +} + +void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, + SourceLocation ColonColonLoc) { + assert(!Representation && "Already have a nested-name-specifier!?"); + Representation = NestedNameSpecifier::GlobalSpecifier(Context); + + // Push source-location info into the buffer. + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); +} + +void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, + NestedNameSpecifier *Qualifier, + SourceRange R) { + Representation = Qualifier; + + // Construct bogus (but well-formed) source information for the + // nested-name-specifier. + BufferSize = 0; + llvm::SmallVector Stack; + for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) + Stack.push_back(NNS); + while (!Stack.empty()) { + NestedNameSpecifier *NNS = Stack.back(); + Stack.pop_back(); + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + TypeSourceInfo *TSInfo + = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), + R.getBegin()); + SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, + BufferCapacity); + break; + } + + case NestedNameSpecifier::Global: + break; + } + + // Save the location of the '::'. + SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), + Buffer, BufferSize, BufferCapacity); + } +} + +void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { + if (BufferCapacity) + free(Buffer); + + if (!Other) { + Representation = 0; + BufferSize = 0; + return; + } + + // Rather than copying the data (which is wasteful), "adopt" the + // pointer (which points into the ASTContext) but set the capacity to zero to + // indicate that we don't own it. + Representation = Other.getNestedNameSpecifier(); + Buffer = static_cast(Other.getOpaqueData()); + BufferSize = Other.getDataLength(); + BufferCapacity = 0; +} + +NestedNameSpecifierLoc +NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { + if (!Representation) + return NestedNameSpecifierLoc(); + + // If we adopted our data pointer from elsewhere in the AST context, there's + // no need to copy the memory. + if (BufferCapacity == 0) + return NestedNameSpecifierLoc(Representation, Buffer); + + // FIXME: After copying the source-location information, should we free + // our (temporary) buffer and adopt the ASTContext-allocated memory? + // Doing so would optimize repeated calls to getWithLocInContext(). + void *Mem = Context.Allocate(BufferSize, llvm::alignOf()); + memcpy(Mem, Buffer, BufferSize); + return NestedNameSpecifierLoc(Representation, Mem); +} + diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index 4ed031f97499..0770e1f15143 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -19,7 +19,7 @@ #include "llvm/Support/Format.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/MathExtras.h" -#include +#include "llvm/Support/CrashRecoveryContext.h" using namespace clang; @@ -564,6 +564,8 @@ class RecordLayoutBuilder { unsigned IsUnion : 1; unsigned IsMac68kAlign : 1; + + unsigned IsMsStruct : 1; /// UnfilledBitsInLastByte - If the last field laid out was a bitfield, /// this contains the number of bits in the last byte that can be used for @@ -580,6 +582,8 @@ class RecordLayoutBuilder { CharUnits NonVirtualSize; CharUnits NonVirtualAlignment; + CharUnits ZeroLengthBitfieldAlignment; + /// PrimaryBase - the primary base class (if one exists) of the class /// we're laying out. const CXXRecordDecl *PrimaryBase; @@ -612,10 +616,12 @@ class RecordLayoutBuilder { *EmptySubobjects) : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), Alignment(CharUnits::One()), UnpackedAlignment(Alignment), - Packed(false), IsUnion(false), IsMac68kAlign(false), + Packed(false), IsUnion(false), + IsMac68kAlign(false), IsMsStruct(false), UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()), DataSize(0), NonVirtualSize(CharUnits::Zero()), - NonVirtualAlignment(CharUnits::One()), PrimaryBase(0), + NonVirtualAlignment(CharUnits::One()), + ZeroLengthBitfieldAlignment(CharUnits::Zero()), PrimaryBase(0), PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { } void Layout(const RecordDecl *D); @@ -657,7 +663,7 @@ class RecordLayoutBuilder { void SelectPrimaryVBase(const CXXRecordDecl *RD); - virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const; + virtual CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const; /// LayoutNonVirtualBases - Determines the primary base class (if any) and /// lays it out. Will then proceed to lay out all non-virtual base clasess. @@ -757,9 +763,9 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { } } -uint64_t +CharUnits RecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const { - return Context.Target.getPointerWidth(0); + return Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); } /// DeterminePrimaryBase - Determine the primary base of the given class. @@ -815,8 +821,8 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { assert(DataSize == 0 && "Vtable pointer must be at offset zero!"); // Update the size. - setSize(getSizeInBits() + GetVirtualPointersSize(RD)); - setDataSize(getSizeInBits()); + setSize(getSize() + GetVirtualPointersSize(RD)); + setDataSize(getSize()); CharUnits UnpackedBaseAlign = Context.toCharUnitsFromBits(Context.Target.getPointerAlign(0)); @@ -1108,8 +1114,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { // If we have an empty base class, try to place it at offset 0. if (Base->Class->isEmpty() && EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) { - uint64_t RecordSizeInBits = Context.toBits(Layout.getSize()); - setSize(std::max(getSizeInBits(), RecordSizeInBits)); + setSize(std::max(getSize(), Layout.getSize())); return CharUnits::Zero(); } @@ -1124,27 +1129,24 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { } // Round up the current record size to the base's alignment boundary. - uint64_t Offset = - llvm::RoundUpToAlignment(getDataSizeInBits(), Context.toBits(BaseAlign)); + CharUnits Offset = getDataSize().RoundUpToAlignment(BaseAlign); // Try to place the base. - while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, - Context.toCharUnitsFromBits(Offset))) - Offset += Context.toBits(BaseAlign); + while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset)) + Offset += BaseAlign; if (!Base->Class->isEmpty()) { // Update the data size. - setDataSize(Offset + Context.toBits(Layout.getNonVirtualSize())); + setDataSize(Offset + Layout.getNonVirtualSize()); - setSize(std::max(getSizeInBits(), getDataSizeInBits())); + setSize(std::max(getSize(), getDataSize())); } else - setSize(std::max(getSizeInBits(), - Offset + Context.toBits(Layout.getSize()))); + setSize(std::max(getSize(), Offset + Layout.getSize())); // Remember max struct/class alignment. UpdateAlignment(BaseAlign, UnpackedBaseAlign); - return Context.toCharUnitsFromBits(Offset); + return Offset; } void RecordLayoutBuilder::InitializeLayout(const Decl *D) { @@ -1152,6 +1154,8 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) { IsUnion = RD->isUnion(); Packed = D->hasAttr(); + + IsMsStruct = D->hasAttr(); // mac68k alignment supersedes maximum field alignment and attribute aligned, // and forces all structures to have 2-byte alignment. The IBM docs on it @@ -1187,8 +1191,9 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { LayoutFields(RD); - // FIXME: Size isn't always an exact multiple of the char width. Round up? - NonVirtualSize = Context.toCharUnitsFromBits(getSizeInBits()); + NonVirtualSize = Context.toCharUnitsFromBits( + llvm::RoundUpToAlignment(getSizeInBits(), + Context.Target.getCharAlign())); NonVirtualAlignment = Alignment; // Lay out the virtual bases and add the primary virtual base offsets. @@ -1233,7 +1238,7 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { // We start laying out ivars not at the end of the superclass // structure, but at the next byte following the last field. setSize(SL.getDataSize()); - setDataSize(getSizeInBits()); + setDataSize(getSize()); } InitializeLayout(D); @@ -1252,9 +1257,28 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Layout each field, for now, just sequentially, respecting alignment. In // the future, this will need to be tweakable by targets. + const FieldDecl *LastFD = 0; for (RecordDecl::field_iterator Field = D->field_begin(), - FieldEnd = D->field_end(); Field != FieldEnd; ++Field) + FieldEnd = D->field_end(); Field != FieldEnd; ++Field) { + if (IsMsStruct) { + const FieldDecl *FD = (*Field); + if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD)) { + // FIXME. Multiple zero bitfields may follow a bitfield. + // set ZeroLengthBitfieldAlignment to max. of its + // currrent and alignment of 'FD'. + std::pair FieldInfo = + Context.getTypeInfoInChars(FD->getType()); + ZeroLengthBitfieldAlignment = FieldInfo.second; + continue; + } + // Zero-length bitfields following non-bitfield members are + // ignored: + if (Context.ZeroBitfieldFollowsNonBitfield(FD, LastFD)) + continue; + LastFD = FD; + } LayoutField(*Field); + } } void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, @@ -1285,7 +1309,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, } assert(!Type.isNull() && "Did not find a type!"); - unsigned TypeAlign = Context.getTypeAlign(Type); + CharUnits TypeAlign = Context.getTypeAlignInChars(Type); // We're not going to use any of the unfilled bits in the last byte. UnfilledBitsInLastByte = 0; @@ -1299,11 +1323,13 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, } else { // The bitfield is allocated starting at the next offset aligned appropriately // for T', with length n bits. - FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(), TypeAlign); + FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(), + Context.toBits(TypeAlign)); uint64_t NewSizeInBits = FieldOffset + FieldSize; - setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 8)); + setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, + Context.Target.getCharAlign())); UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; } @@ -1311,13 +1337,13 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, FieldOffsets.push_back(FieldOffset); CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset, - TypeAlign, FieldPacked, D); + Context.toBits(TypeAlign), FieldPacked, D); // Update the size. setSize(std::max(getSizeInBits(), getDataSizeInBits())); // Remember max struct/class alignment. - UpdateAlignment(Context.toCharUnitsFromBits(TypeAlign)); + UpdateAlignment(TypeAlign); } void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { @@ -1380,7 +1406,8 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { } else { uint64_t NewSizeInBits = FieldOffset + FieldSize; - setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 8)); + setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, + Context.Target.getCharAlign())); UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; } @@ -1428,6 +1455,9 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { Context.getTypeInfoInChars(D->getType()); FieldSize = FieldInfo.first; FieldAlign = FieldInfo.second; + if (ZeroLengthBitfieldAlignment > FieldAlign) + FieldAlign = ZeroLengthBitfieldAlignment; + ZeroLengthBitfieldAlignment = CharUnits::Zero(); if (Context.getLangOptions().MSBitfields) { // If MS bitfield layout is required, figure out what type is being @@ -1487,7 +1517,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { if (IsUnion) setSize(std::max(getSizeInBits(), FieldSizeInBits)); else - setSize(Context.toBits(FieldOffset) + FieldSizeInBits); + setSize(FieldOffset + FieldSize); // Update the data size. setDataSize(getSizeInBits()); @@ -1504,17 +1534,18 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { // which is not empty but of size 0; such as having fields of // array of zero-length, remains of Size 0 if (RD->isEmpty()) - setSize(8); + setSize(CharUnits::One()); } else - setSize(8); + setSize(CharUnits::One()); } // Finally, round the size of the record up to the alignment of the // record itself. uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte; - uint64_t UnpackedSize = + uint64_t UnpackedSizeInBits = llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(UnpackedAlignment)); + CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits); setSize(llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment))); unsigned CharBitNum = Context.Target.getCharWidth(); @@ -1536,7 +1567,7 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { // Warn if we packed it unnecessarily. If the alignment is 1 byte don't // bother since there won't be alignment issues. if (Packed && UnpackedAlignment > CharUnits::One() && - getSizeInBits() == UnpackedSize) + getSize() == UnpackedSize) Diag(D->getLocation(), diag::warn_unnecessary_packed) << Context.getTypeDeclType(RD); } @@ -1664,17 +1695,19 @@ namespace { EmptySubobjectMap *EmptySubobjects) : RecordLayoutBuilder(Ctx, EmptySubobjects) {} - virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const; + virtual CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const; }; } -uint64_t +CharUnits MSRecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const { // We should reserve space for two pointers if the class has both // virtual functions and virtual bases. + CharUnits PointerWidth = + Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); if (RD->isPolymorphic() && RD->getNumVBases() > 0) - return 2 * Context.Target.getPointerWidth(0); - return Context.Target.getPointerWidth(0); + return 2 * PointerWidth; + return PointerWidth; } /// getASTRecordLayout - Get or compute information about the layout of the @@ -1705,6 +1738,10 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { case CXXABI_Microsoft: Builder.reset(new MSRecordLayoutBuilder(*this, &EmptySubobjects)); } + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + RecordBuilderCleanup(Builder.get()); + Builder->Layout(RD); // FIXME: This is not always correct. See the part about bitfields at @@ -1713,17 +1750,15 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { bool IsPODForThePurposeOfLayout = cast(D)->isPOD(); // FIXME: This should be done in FinalizeLayout. - uint64_t DataSize = - IsPODForThePurposeOfLayout ? Builder->Size : Builder->DataSize; - CharUnits NonVirtualSize = - IsPODForThePurposeOfLayout ? - toCharUnitsFromBits(DataSize) : Builder->NonVirtualSize; + CharUnits DataSize = + IsPODForThePurposeOfLayout ? Builder->getSize() : Builder->getDataSize(); + CharUnits NonVirtualSize = + IsPODForThePurposeOfLayout ? DataSize : Builder->NonVirtualSize; - CharUnits RecordSize = toCharUnitsFromBits(Builder->Size); NewEntry = - new (*this) ASTRecordLayout(*this, RecordSize, + new (*this) ASTRecordLayout(*this, Builder->getSize(), Builder->Alignment, - toCharUnitsFromBits(DataSize), + DataSize, Builder->FieldOffsets.data(), Builder->FieldOffsets.size(), NonVirtualSize, @@ -1736,12 +1771,10 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0); Builder.Layout(D); - CharUnits RecordSize = toCharUnitsFromBits(Builder.Size); - NewEntry = - new (*this) ASTRecordLayout(*this, RecordSize, + new (*this) ASTRecordLayout(*this, Builder.getSize(), Builder.Alignment, - toCharUnitsFromBits(Builder.Size), + Builder.getSize(), Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); } @@ -1797,12 +1830,10 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0); Builder.Layout(D); - CharUnits RecordSize = toCharUnitsFromBits(Builder.Size); - const ASTRecordLayout *NewEntry = - new (*this) ASTRecordLayout(*this, RecordSize, + new (*this) ASTRecordLayout(*this, Builder.getSize(), Builder.Alignment, - toCharUnitsFromBits(Builder.DataSize), + Builder.getDataSize(), Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index 8a80275aa165..380ad94ca224 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -540,6 +540,40 @@ CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, std::copy(handlers, handlers + NumHandlers, Stmts + 1); } +CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt, + Expr *Cond, Expr *Inc, DeclStmt *LoopVar, + Stmt *Body, SourceLocation FL, + SourceLocation CL, SourceLocation RPL) + : Stmt(CXXForRangeStmtClass), ForLoc(FL), ColonLoc(CL), RParenLoc(RPL) { + SubExprs[RANGE] = Range; + SubExprs[BEGINEND] = BeginEndStmt; + SubExprs[COND] = reinterpret_cast(Cond); + SubExprs[INC] = reinterpret_cast(Inc); + SubExprs[LOOPVAR] = LoopVar; + SubExprs[BODY] = Body; +} + +Expr *CXXForRangeStmt::getRangeInit() { + DeclStmt *RangeStmt = getRangeStmt(); + VarDecl *RangeDecl = dyn_cast_or_null(RangeStmt->getSingleDecl()); + assert(RangeDecl &&& "for-range should have a single var decl"); + return RangeDecl->getInit(); +} + +const Expr *CXXForRangeStmt::getRangeInit() const { + return const_cast(this)->getRangeInit(); +} + +VarDecl *CXXForRangeStmt::getLoopVariable() { + Decl *LV = cast(getLoopVarStmt())->getSingleDecl(); + assert(LV && "No loop variable in CXXForRangeStmt"); + return cast(LV); +} + +const VarDecl *CXXForRangeStmt::getLoopVariable() const { + return const_cast(this)->getLoopVariable(); +} + IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, Stmt *then, SourceLocation EL, Stmt *elsev) : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) @@ -628,14 +662,14 @@ void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) { } Stmt *SwitchCase::getSubStmt() { - if (isa(this)) return cast(this)->getSubStmt(); + if (isa(this)) + return cast(this)->getSubStmt(); return cast(this)->getSubStmt(); } WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL) -: Stmt(WhileStmtClass) -{ + : Stmt(WhileStmtClass) { setConditionVariable(C, Var); SubExprs[COND] = reinterpret_cast(cond); SubExprs[BODY] = body; @@ -676,3 +710,61 @@ const Expr* ReturnStmt::getRetValue() const { Expr* ReturnStmt::getRetValue() { return cast_or_null(RetExpr); } + +SEHTryStmt::SEHTryStmt(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) + : Stmt(SEHTryStmtClass), + IsCXXTry(IsCXXTry), + TryLoc(TryLoc) +{ + Children[TRY] = TryBlock; + Children[HANDLER] = Handler; +} + +SEHTryStmt* SEHTryStmt::Create(ASTContext &C, + bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); +} + +SEHExceptStmt* SEHTryStmt::getExceptHandler() const { + return dyn_cast(getHandler()); +} + +SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { + return dyn_cast(getHandler()); +} + +SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) + : Stmt(SEHExceptStmtClass), + Loc(Loc) +{ + Children[FILTER_EXPR] = reinterpret_cast(FilterExpr); + Children[BLOCK] = Block; +} + +SEHExceptStmt* SEHExceptStmt::Create(ASTContext &C, + SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + return new(C) SEHExceptStmt(Loc,FilterExpr,Block); +} + +SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, + Stmt *Block) + : Stmt(SEHFinallyStmtClass), + Loc(Loc), + Block(Block) +{} + +SEHFinallyStmt* SEHFinallyStmt::Create(ASTContext &C, + SourceLocation Loc, + Stmt *Block) { + return new(C)SEHFinallyStmt(Loc,Block); +} diff --git a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp index 5c7dbb3ed990..fb024f33ab30 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp @@ -141,7 +141,7 @@ namespace { void VisitFloatingLiteral(FloatingLiteral *Node); void VisitStringLiteral(StringLiteral *Str); void VisitUnaryOperator(UnaryOperator *Node); - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node); + void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node); void VisitMemberExpr(MemberExpr *Node); void VisitExtVectorElementExpr(ExtVectorElementExpr *Node); void VisitBinaryOperator(BinaryOperator *Node); @@ -236,6 +236,9 @@ void StmtDumper::DumpDeclarator(Decl *D) { if (TypedefDecl *localType = dyn_cast(D)) { OS << "\"typedef " << localType->getUnderlyingType().getAsString() << ' ' << localType << '"'; + } else if (TypeAliasDecl *localType = dyn_cast(D)) { + OS << "\"using " << localType << " = " + << localType->getUnderlyingType().getAsString() << '"'; } else if (ValueDecl *VD = dyn_cast(D)) { OS << "\""; // Emit storage class for vardecls. @@ -284,6 +287,12 @@ void StmtDumper::DumpDeclarator(Decl *D) { OS << ";\""; } else if (LabelDecl *LD = dyn_cast(D)) { OS << "label " << LD->getNameAsString(); + } else if (StaticAssertDecl *SAD = dyn_cast(D)) { + OS << "\"static_assert(\n"; + DumpSubTree(SAD->getAssertExpr()); + OS << ",\n"; + DumpSubTree(SAD->getMessage()); + OS << ");\""; } else { assert(0 && "Unexpected decl"); } @@ -360,6 +369,11 @@ void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) { OS << " "; DumpDeclRef(Node->getDecl()); + if (Node->getDecl() != Node->getFoundDecl()) { + OS << " ("; + DumpDeclRef(Node->getFoundDecl()); + OS << ")"; + } } void StmtDumper::DumpDeclRef(Decl *d) { @@ -441,9 +455,19 @@ void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) { OS << " " << (Node->isPostfix() ? "postfix" : "prefix") << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; } -void StmtDumper::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) { +void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) { DumpExpr(Node); - OS << " " << (Node->isSizeOf() ? "sizeof" : "alignof") << " "; + switch(Node->getKind()) { + case UETT_SizeOf: + OS << " sizeof "; + break; + case UETT_AlignOf: + OS << " __alignof "; + break; + case UETT_VecStep: + OS << " vec_step "; + break; + } if (Node->isArgumentType()) DumpType(Node->getArgumentType()); } diff --git a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp index 9a7265a043f2..9bf4aeaae83e 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp @@ -98,7 +98,7 @@ bool StmtIteratorBase::HandleDecl(Decl* D) { if (VD->getInit()) return true; } - else if (TypedefDecl* TD = dyn_cast(D)) { + else if (TypedefNameDecl* TD = dyn_cast(D)) { if (const VariableArrayType* VAPtr = FindVA(TD->getUnderlyingType().getTypePtr())) { setVAPtr(VAPtr); diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index 1cdd22088141..0d13502e8d58 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -66,6 +66,8 @@ namespace { void PrintRawIfStmt(IfStmt *If); void PrintRawCXXCatchStmt(CXXCatchStmt *Catch); void PrintCallArgs(CallExpr *E); + void PrintRawSEHExceptHandler(SEHExceptStmt *S); + void PrintRawSEHFinallyStmt(SEHFinallyStmt *S); void PrintExpr(Expr *E) { if (E) @@ -291,6 +293,18 @@ void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) { } } +void StmtPrinter::VisitCXXForRangeStmt(CXXForRangeStmt *Node) { + Indent() << "for ("; + PrintingPolicy SubPolicy(Policy); + SubPolicy.SuppressInitializers = true; + Node->getLoopVariable()->print(OS, SubPolicy, IndentLevel); + OS << " : "; + PrintExpr(Node->getRangeInit()); + OS << ") {\n"; + PrintStmt(Node->getBody()); + Indent() << "}\n"; +} + void StmtPrinter::VisitGotoStmt(GotoStmt *Node) { Indent() << "goto " << Node->getLabel()->getName() << ";\n"; } @@ -461,6 +475,46 @@ void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) { OS << "\n"; } +void StmtPrinter::VisitSEHTryStmt(SEHTryStmt *Node) { + Indent() << (Node->getIsCXXTry() ? "try " : "__try "); + PrintRawCompoundStmt(Node->getTryBlock()); + SEHExceptStmt *E = Node->getExceptHandler(); + SEHFinallyStmt *F = Node->getFinallyHandler(); + if(E) + PrintRawSEHExceptHandler(E); + else { + assert(F && "Must have a finally block..."); + PrintRawSEHFinallyStmt(F); + } + OS << "\n"; +} + +void StmtPrinter::PrintRawSEHFinallyStmt(SEHFinallyStmt *Node) { + OS << "__finally "; + PrintRawCompoundStmt(Node->getBlock()); + OS << "\n"; +} + +void StmtPrinter::PrintRawSEHExceptHandler(SEHExceptStmt *Node) { + OS << "__except ("; + VisitExpr(Node->getFilterExpr()); + OS << ")\n"; + PrintRawCompoundStmt(Node->getBlock()); + OS << "\n"; +} + +void StmtPrinter::VisitSEHExceptStmt(SEHExceptStmt *Node) { + Indent(); + PrintRawSEHExceptHandler(Node); + OS << "\n"; +} + +void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) { + Indent(); + PrintRawSEHFinallyStmt(Node); + OS << "\n"; +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// @@ -706,8 +760,18 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) { OS << ")"; } -void StmtPrinter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) { - OS << (Node->isSizeOf() ? "sizeof" : "__alignof"); +void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){ + switch(Node->getKind()) { + case UETT_SizeOf: + OS << "sizeof"; + break; + case UETT_AlignOf: + OS << "__alignof"; + break; + case UETT_VecStep: + OS << "vec_step"; + break; + } if (Node->isArgumentType()) OS << "(" << Node->getArgumentType().getAsString(Policy) << ")"; else { @@ -715,6 +779,23 @@ void StmtPrinter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) { PrintExpr(Node->getArgumentExpr()); } } + +void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) { + OS << "_Generic("; + PrintExpr(Node->getControllingExpr()); + for (unsigned i = 0; i != Node->getNumAssocs(); ++i) { + OS << ", "; + QualType T = Node->getAssocType(i); + if (T.isNull()) + OS << "default"; + else + OS << T.getAsString(Policy); + OS << ": "; + PrintExpr(Node->getAssocExpr(i)); + } + OS << ")"; +} + void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) { PrintExpr(Node->getLHS()); OS << "["; @@ -1212,33 +1293,75 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { static const char *getTypeTraitName(UnaryTypeTrait UTT) { switch (UTT) { - default: llvm_unreachable("Unknown unary type trait"); case UTT_HasNothrowAssign: return "__has_nothrow_assign"; - case UTT_HasNothrowCopy: return "__has_nothrow_copy"; case UTT_HasNothrowConstructor: return "__has_nothrow_constructor"; + case UTT_HasNothrowCopy: return "__has_nothrow_copy"; case UTT_HasTrivialAssign: return "__has_trivial_assign"; - case UTT_HasTrivialCopy: return "__has_trivial_copy"; case UTT_HasTrivialConstructor: return "__has_trivial_constructor"; + case UTT_HasTrivialCopy: return "__has_trivial_copy"; case UTT_HasTrivialDestructor: return "__has_trivial_destructor"; case UTT_HasVirtualDestructor: return "__has_virtual_destructor"; case UTT_IsAbstract: return "__is_abstract"; + case UTT_IsArithmetic: return "__is_arithmetic"; + case UTT_IsArray: return "__is_array"; case UTT_IsClass: return "__is_class"; + case UTT_IsCompleteType: return "__is_complete_type"; + case UTT_IsCompound: return "__is_compound"; + case UTT_IsConst: return "__is_const"; case UTT_IsEmpty: return "__is_empty"; case UTT_IsEnum: return "__is_enum"; + case UTT_IsFloatingPoint: return "__is_floating_point"; + case UTT_IsFunction: return "__is_function"; + case UTT_IsFundamental: return "__is_fundamental"; + case UTT_IsIntegral: return "__is_integral"; + case UTT_IsLiteral: return "__is_literal"; + case UTT_IsLvalueReference: return "__is_lvalue_reference"; + case UTT_IsMemberFunctionPointer: return "__is_member_function_pointer"; + case UTT_IsMemberObjectPointer: return "__is_member_object_pointer"; + case UTT_IsMemberPointer: return "__is_member_pointer"; + case UTT_IsObject: return "__is_object"; case UTT_IsPOD: return "__is_pod"; + case UTT_IsPointer: return "__is_pointer"; case UTT_IsPolymorphic: return "__is_polymorphic"; + case UTT_IsReference: return "__is_reference"; + case UTT_IsRvalueReference: return "__is_rvalue_reference"; + case UTT_IsScalar: return "__is_scalar"; + case UTT_IsSigned: return "__is_signed"; + case UTT_IsStandardLayout: return "__is_standard_layout"; + case UTT_IsTrivial: return "__is_trivial"; case UTT_IsUnion: return "__is_union"; + case UTT_IsUnsigned: return "__is_unsigned"; + case UTT_IsVoid: return "__is_void"; + case UTT_IsVolatile: return "__is_volatile"; } - return ""; + llvm_unreachable("Type trait not covered by switch statement"); } static const char *getTypeTraitName(BinaryTypeTrait BTT) { switch (BTT) { case BTT_IsBaseOf: return "__is_base_of"; + case BTT_IsConvertible: return "__is_convertible"; + case BTT_IsSame: return "__is_same"; case BTT_TypeCompatible: return "__builtin_types_compatible_p"; case BTT_IsConvertibleTo: return "__is_convertible_to"; } - return ""; + llvm_unreachable("Binary type trait not covered by switch"); +} + +static const char *getTypeTraitName(ArrayTypeTrait ATT) { + switch (ATT) { + case ATT_ArrayRank: return "__array_rank"; + case ATT_ArrayExtent: return "__array_extent"; + } + llvm_unreachable("Array type trait not covered by switch"); +} + +static const char *getExpressionTraitName(ExpressionTrait ET) { + switch (ET) { + case ET_IsLValueExpr: return "__is_lvalue_expr"; + case ET_IsRValueExpr: return "__is_rvalue_expr"; + } + llvm_unreachable("Expression type trait not covered by switch"); } void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { @@ -1252,6 +1375,17 @@ void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { << E->getRhsType().getAsString(Policy) << ")"; } +void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + OS << getTypeTraitName(E->getTrait()) << "(" + << E->getQueriedType().getAsString(Policy) << ")"; +} + +void StmtPrinter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { + OS << getExpressionTraitName(E->getTrait()) << "("; + PrintExpr(E->getQueriedExpression()); + OS << ")"; +} + void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { OS << "noexcept("; PrintExpr(E->getOperand()); diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index b54001167b42..44818e8c0847 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -177,6 +177,22 @@ void StmtProfiler::VisitCXXTryStmt(CXXTryStmt *S) { VisitStmt(S); } +void StmtProfiler::VisitCXXForRangeStmt(CXXForRangeStmt *S) { + VisitStmt(S); +} + +void StmtProfiler::VisitSEHTryStmt(SEHTryStmt *S) { + VisitStmt(S); +} + +void StmtProfiler::VisitSEHFinallyStmt(SEHFinallyStmt *S) { + VisitStmt(S); +} + +void StmtProfiler::VisitSEHExceptStmt(SEHExceptStmt *S) { + VisitStmt(S); +} + void StmtProfiler::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { VisitStmt(S); } @@ -290,9 +306,9 @@ void StmtProfiler::VisitOffsetOfExpr(OffsetOfExpr *S) { VisitExpr(S); } -void StmtProfiler::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *S) { +void StmtProfiler::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *S) { VisitExpr(S); - ID.AddBoolean(S->isSizeOf()); + ID.AddInteger(S->getKind()); if (S->isArgumentType()) VisitType(S->getArgumentType()); } @@ -430,6 +446,18 @@ void StmtProfiler::VisitBlockDeclRefExpr(BlockDeclRefExpr *S) { ID.AddBoolean(S->isConstQualAdded()); } +void StmtProfiler::VisitGenericSelectionExpr(GenericSelectionExpr *S) { + VisitExpr(S); + for (unsigned i = 0; i != S->getNumAssocs(); ++i) { + QualType T = S->getAssocType(i); + if (T.isNull()) + ID.AddPointer(0); + else + VisitType(T); + VisitExpr(S->getAssocExpr(i)); + } +} + static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S, UnaryOperatorKind &UnaryOp, BinaryOperatorKind &BinaryOp) { @@ -786,6 +814,18 @@ void StmtProfiler::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *S) { VisitType(S->getRhsType()); } +void StmtProfiler::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *S) { + VisitExpr(S); + ID.AddInteger(S->getTrait()); + VisitType(S->getQueriedType()); +} + +void StmtProfiler::VisitExpressionTraitExpr(ExpressionTraitExpr *S) { + VisitExpr(S); + ID.AddInteger(S->getTrait()); + VisitExpr(S->getQueriedExpression()); +} + void StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) { VisitExpr(S); @@ -921,12 +961,16 @@ void StmtProfiler::VisitDecl(Decl *D) { } if (ParmVarDecl *Parm = dyn_cast(D)) { - // The Itanium C++ ABI uses the type of a parameter when mangling - // expressions that involve function parameters, so we will use the - // parameter's type for establishing function parameter identity. That - // way, our definition of "equivalent" (per C++ [temp.over.link]) - // matches the definition of "equivalent" used for name mangling. + // The Itanium C++ ABI uses the type, scope depth, and scope + // index of a parameter when mangling expressions that involve + // function parameters, so we will use the parameter's type for + // establishing function parameter identity. That way, our + // definition of "equivalent" (per C++ [temp.over.link]) is at + // least as strong as the definition of "equivalent" used for + // name mangling. VisitType(Parm->getType()); + ID.AddInteger(Parm->getFunctionScopeDepth()); + ID.AddInteger(Parm->getFunctionScopeIndex()); return; } diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index 1764f4ab1f03..6114a5a051be 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -338,7 +338,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, //===----------------------------------------------------------------------===// TemplateArgumentLocInfo::TemplateArgumentLocInfo() { - memset(this, 0, sizeof(TemplateArgumentLocInfo)); + memset((void*)this, 0, sizeof(TemplateArgumentLocInfo)); } SourceRange TemplateArgumentLoc::getSourceRange() const { @@ -356,14 +356,14 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { return SourceRange(); case TemplateArgument::Template: - if (getTemplateQualifierRange().isValid()) - return SourceRange(getTemplateQualifierRange().getBegin(), + if (getTemplateQualifierLoc()) + return SourceRange(getTemplateQualifierLoc().getBeginLoc(), getTemplateNameLoc()); return SourceRange(getTemplateNameLoc()); case TemplateArgument::TemplateExpansion: - if (getTemplateQualifierRange().isValid()) - return SourceRange(getTemplateQualifierRange().getBegin(), + if (getTemplateQualifierLoc()) + return SourceRange(getTemplateQualifierLoc().getBeginLoc(), getTemplateEllipsisLoc()); return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); @@ -425,7 +425,7 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, Ellipsis = getTemplateEllipsisLoc(); NumExpansions = Argument.getNumTemplateExpansions(); return TemplateArgumentLoc(Argument.getPackExpansionPattern(), - getTemplateQualifierRange(), + getTemplateQualifierLoc(), getTemplateNameLoc()); case TemplateArgument::Declaration: diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp index 6b378a001101..ebd07f486783 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp @@ -118,6 +118,10 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy, } else if (SubstTemplateTemplateParmPackStorage *SubstPack = getAsSubstTemplateTemplateParmPack()) OS << SubstPack->getParameterPack()->getNameAsString(); + else { + OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); + (*OTS->begin())->printName(OS); + } } const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index b03314e11d13..9eb497bea629 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -21,11 +21,24 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Specifiers.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" #include using namespace clang; +bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { + return (*this != Other) && + // CVR qualifiers superset + (((Mask & CVRMask) | (Other.Mask & CVRMask)) == (Mask & CVRMask)) && + // ObjC GC qualifiers superset + ((getObjCGCAttr() == Other.getObjCGCAttr()) || + (hasObjCGCAttr() && !Other.hasObjCGCAttr())) && + // Address space superset. + ((getAddressSpace() == Other.getAddressSpace()) || + (hasAddressSpace()&& !Other.hasAddressSpace())); +} + bool QualType::isConstant(QualType T, ASTContext &Ctx) { if (T.isConstQualified()) return true; @@ -407,6 +420,16 @@ const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const { return 0; } +const ObjCObjectPointerType *Type::getAsObjCQualifiedClassType() const { + // There is no sugar for ObjCQualifiedClassType's, just return the canonical + // type pointer if it is the right class. + if (const ObjCObjectPointerType *OPT = getAs()) { + if (OPT->isObjCQualifiedClassType()) + return OPT; + } + return 0; +} + const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const { if (const ObjCObjectPointerType *OPT = getAs()) { if (OPT->getInterfaceType()) @@ -858,37 +881,178 @@ bool Type::isPODType() const { } bool Type::isLiteralType() const { - if (isIncompleteType()) + if (isDependentType()) return false; // C++0x [basic.types]p10: // A type is a literal type if it is: - switch (CanonicalType->getTypeClass()) { - // We're whitelisting - default: return false; + // [...] + // -- an array of literal type + // Extension: variable arrays cannot be literal types, since they're + // runtime-sized. + if (isVariableArrayType()) + return false; + const Type *BaseTy = getBaseElementTypeUnsafe(); + assert(BaseTy && "NULL element type"); - // -- a scalar type - case Builtin: - case Complex: - case Pointer: - case MemberPointer: - case Vector: - case ExtVector: - case ObjCObjectPointer: - case Enum: - return true; - - // -- a class type with ... - case Record: - // FIXME: Do the tests + // Return false for incomplete types after skipping any incomplete array + // types; those are expressly allowed by the standard and thus our API. + if (BaseTy->isIncompleteType()) return false; - // -- an array of literal type - // Extension: variable arrays cannot be literal types, since they're - // runtime-sized. - case ConstantArray: - return cast(CanonicalType)->getElementType()->isLiteralType(); + // C++0x [basic.types]p10: + // A type is a literal type if it is: + // -- a scalar type; or + // As an extension, Clang treats vector types as Scalar types. + if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; + // -- a reference type; or + if (BaseTy->isReferenceType()) return true; + // -- a class type that has all of the following properties: + if (const RecordType *RT = BaseTy->getAs()) { + if (const CXXRecordDecl *ClassDecl = + dyn_cast(RT->getDecl())) { + // -- a trivial destructor, + if (!ClassDecl->hasTrivialDestructor()) return false; + // -- every constructor call and full-expression in the + // brace-or-equal-initializers for non-static data members (if any) + // is a constant expression, + // FIXME: C++0x: Clang doesn't yet support non-static data member + // declarations with initializers, or constexprs. + // -- it is an aggregate type or has at least one constexpr + // constructor or constructor template that is not a copy or move + // constructor, and + if (!ClassDecl->isAggregate() && + !ClassDecl->hasConstExprNonCopyMoveConstructor()) + return false; + // -- all non-static data members and base classes of literal types + if (ClassDecl->hasNonLiteralTypeFieldsOrBases()) return false; + } + + return true; } + return false; +} + +bool Type::isTrivialType() const { + if (isDependentType()) + return false; + + // C++0x [basic.types]p9: + // Scalar types, trivial class types, arrays of such types, and + // cv-qualified versions of these types are collectively called trivial + // types. + const Type *BaseTy = getBaseElementTypeUnsafe(); + assert(BaseTy && "NULL element type"); + + // Return false for incomplete types after skipping any incomplete array + // types which are expressly allowed by the standard and thus our API. + if (BaseTy->isIncompleteType()) + return false; + + // As an extension, Clang treats vector types as Scalar types. + if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; + if (const RecordType *RT = BaseTy->getAs()) { + if (const CXXRecordDecl *ClassDecl = + dyn_cast(RT->getDecl())) { + // C++0x [class]p5: + // A trivial class is a class that has a trivial default constructor + if (!ClassDecl->hasTrivialConstructor()) return false; + // and is trivially copyable. + if (!ClassDecl->isTriviallyCopyable()) return false; + } + + return true; + } + + // No other types can match. + return false; +} + +bool Type::isStandardLayoutType() const { + if (isDependentType()) + return false; + + // C++0x [basic.types]p9: + // Scalar types, standard-layout class types, arrays of such types, and + // cv-qualified versions of these types are collectively called + // standard-layout types. + const Type *BaseTy = getBaseElementTypeUnsafe(); + assert(BaseTy && "NULL element type"); + + // Return false for incomplete types after skipping any incomplete array + // types which are expressly allowed by the standard and thus our API. + if (BaseTy->isIncompleteType()) + return false; + + // As an extension, Clang treats vector types as Scalar types. + if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; + if (const RecordType *RT = BaseTy->getAs()) { + if (const CXXRecordDecl *ClassDecl = + dyn_cast(RT->getDecl())) + if (!ClassDecl->isStandardLayout()) + return false; + + // Default to 'true' for non-C++ class types. + // FIXME: This is a bit dubious, but plain C structs should trivially meet + // all the requirements of standard layout classes. + return true; + } + + // No other types can match. + return false; +} + +// This is effectively the intersection of isTrivialType and +// isStandardLayoutType. We implement it dircetly to avoid redundant +// conversions from a type to a CXXRecordDecl. +bool Type::isCXX11PODType() const { + if (isDependentType()) + return false; + + // C++11 [basic.types]p9: + // Scalar types, POD classes, arrays of such types, and cv-qualified + // versions of these types are collectively called trivial types. + const Type *BaseTy = getBaseElementTypeUnsafe(); + assert(BaseTy && "NULL element type"); + + // Return false for incomplete types after skipping any incomplete array + // types which are expressly allowed by the standard and thus our API. + if (BaseTy->isIncompleteType()) + return false; + + // As an extension, Clang treats vector types as Scalar types. + if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; + if (const RecordType *RT = BaseTy->getAs()) { + if (const CXXRecordDecl *ClassDecl = + dyn_cast(RT->getDecl())) { + // C++11 [class]p10: + // A POD struct is a non-union class that is both a trivial class [...] + // C++11 [class]p5: + // A trivial class is a class that has a trivial default constructor + if (!ClassDecl->hasTrivialConstructor()) return false; + // and is trivially copyable. + if (!ClassDecl->isTriviallyCopyable()) return false; + + // C++11 [class]p10: + // A POD struct is a non-union class that is both a trivial class and + // a standard-layout class [...] + if (!ClassDecl->isStandardLayout()) return false; + + // C++11 [class]p10: + // A POD struct is a non-union class that is both a trivial class and + // a standard-layout class, and has no non-static data members of type + // non-POD struct, non-POD union (or array of such types). [...] + // + // We don't directly query the recursive aspect as the requiremets for + // both standard-layout classes and trivial classes apply recursively + // already. + } + + return true; + } + + // No other types can match. + return false; } bool Type::isPromotableIntegerType() const { @@ -1040,9 +1204,9 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType( QualType Canon) : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, /*VariablyModified=*/false, - NNS->containsUnexpandedParameterPack()), + NNS && NNS->containsUnexpandedParameterPack()), NNS(NNS), Name(Name), NumArgs(NumArgs) { - assert(NNS && NNS->isDependent() && + assert((!NNS || NNS->isDependent()) && "DependentTemplateSpecializatonType requires dependent qualifier"); for (unsigned I = 0; I != NumArgs; ++I) { if (Args[I].containsUnexpandedParameterPack()) @@ -1120,7 +1284,9 @@ const char *BuiltinType::getName(const LangOptions &LO) const { case Char32: return "char32_t"; case NullPtr: return "nullptr_t"; case Overload: return ""; + case BoundMember: return ""; case Dependent: return ""; + case UnknownAny: return ""; case ObjCId: return "id"; case ObjCClass: return "Class"; case ObjCSel: return "SEL"; @@ -1157,6 +1323,8 @@ llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86FastCall: return "fastcall"; case CC_X86ThisCall: return "thiscall"; case CC_X86Pascal: return "pascal"; + case CC_AAPCS: return "aapcs"; + case CC_AAPCS_VFP: return "aapcs-vfp"; } llvm_unreachable("Invalid calling convention."); @@ -1173,8 +1341,7 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, result->containsUnexpandedParameterPack(), epi.ExtInfo), NumArgs(numArgs), NumExceptions(epi.NumExceptions), - HasExceptionSpec(epi.HasExceptionSpec), - HasAnyExceptionSpec(epi.HasAnyExceptionSpec) + ExceptionSpecType(epi.ExceptionSpecType) { // Fill in the trailing argument array. QualType *argSlot = reinterpret_cast(this+1); @@ -1187,20 +1354,50 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, argSlot[i] = args[i]; } - - // Fill in the exception array. - QualType *exnSlot = argSlot + numArgs; - for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) { - if (epi.Exceptions[i]->isDependentType()) - setDependent(); - if (epi.Exceptions[i]->containsUnexpandedParameterPack()) - setContainsUnexpandedParameterPack(); + if (getExceptionSpecType() == EST_Dynamic) { + // Fill in the exception array. + QualType *exnSlot = argSlot + numArgs; + for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) { + if (epi.Exceptions[i]->isDependentType()) + setDependent(); - exnSlot[i] = epi.Exceptions[i]; + if (epi.Exceptions[i]->containsUnexpandedParameterPack()) + setContainsUnexpandedParameterPack(); + + exnSlot[i] = epi.Exceptions[i]; + } + } else if (getExceptionSpecType() == EST_ComputedNoexcept) { + // Store the noexcept expression and context. + Expr **noexSlot = reinterpret_cast(argSlot + numArgs); + *noexSlot = epi.NoexceptExpr; } } +FunctionProtoType::NoexceptResult +FunctionProtoType::getNoexceptSpec(ASTContext &ctx) const { + ExceptionSpecificationType est = getExceptionSpecType(); + if (est == EST_BasicNoexcept) + return NR_Nothrow; + + if (est != EST_ComputedNoexcept) + return NR_NoNoexcept; + + Expr *noexceptExpr = getNoexceptExpr(); + if (!noexceptExpr) + return NR_BadNoexcept; + if (noexceptExpr->isValueDependent()) + return NR_Dependent; + + llvm::APSInt value; + bool isICE = noexceptExpr->isIntegerConstantExpr(value, ctx, 0, + /*evaluated*/false); + (void)isICE; + assert(isICE && "AST should not contain bad noexcept expressions."); + + return value.getBoolValue() ? NR_Nothrow : NR_Throw; +} + bool FunctionProtoType::isTemplateVariadic() const { for (unsigned ArgIdx = getNumArgs(); ArgIdx; --ArgIdx) if (isa(getArgType(ArgIdx - 1))) @@ -1211,23 +1408,28 @@ bool FunctionProtoType::isTemplateVariadic() const { void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, const QualType *ArgTys, unsigned NumArgs, - const ExtProtoInfo &epi) { + const ExtProtoInfo &epi, + const ASTContext &Context) { ID.AddPointer(Result.getAsOpaquePtr()); for (unsigned i = 0; i != NumArgs; ++i) ID.AddPointer(ArgTys[i].getAsOpaquePtr()); ID.AddBoolean(epi.Variadic); ID.AddInteger(epi.TypeQuals); ID.AddInteger(epi.RefQualifier); - if (epi.HasExceptionSpec) { - ID.AddBoolean(epi.HasAnyExceptionSpec); + ID.AddInteger(epi.ExceptionSpecType); + if (epi.ExceptionSpecType == EST_Dynamic) { for (unsigned i = 0; i != epi.NumExceptions; ++i) ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr()); + } else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){ + epi.NoexceptExpr->Profile(ID, Context, true); } epi.ExtInfo.Profile(ID); } -void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getResultType(), arg_type_begin(), NumArgs, getExtProtoInfo()); +void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &Ctx) { + Profile(ID, getResultType(), arg_type_begin(), NumArgs, getExtProtoInfo(), + Ctx); } QualType TypedefType::desugar() const { @@ -1302,6 +1504,10 @@ bool EnumType::classof(const TagType *TT) { return isa(TT->getDecl()); } +IdentifierInfo *TemplateTypeParmType::getIdentifier() const { + return isCanonicalUnqualified() ? 0 : getDecl()->getIdentifier(); +} + SubstTemplateTypeParmPackType:: SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, QualType Canon, @@ -1357,10 +1563,11 @@ TemplateSpecializationType(TemplateName T, unsigned NumArgs, QualType Canon) : Type(TemplateSpecialization, Canon.isNull()? QualType(this, 0) : Canon, - T.isDependent(), false, - T.containsUnexpandedParameterPack()), + T.isDependent(), false, T.containsUnexpandedParameterPack()), Template(T), NumArgs(NumArgs) { + assert(!T.getAsDependentTemplateName() && + "Use DependentTemplateSpecializationType for dependent template-name"); assert((!Canon.isNull() || T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) && "No canonical type for non-dependent class template specialization"); @@ -1529,7 +1736,7 @@ static CachedProperties computeCachedProperties(const Type *T) { NamedDecl::LinkageInfo LV = Tag->getLinkageAndVisibility(); bool IsLocalOrUnnamed = Tag->getDeclContext()->isFunctionOrMethod() || - (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()); + (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()); return CachedProperties(LV.linkage(), LV.visibility(), IsLocalOrUnnamed); } diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp index 14db7f83c2d0..34e7693e3075 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp @@ -102,6 +102,8 @@ SourceLocation TypeLoc::getBeginLoc() const { // FIXME: Currently QualifiedTypeLoc does not have a source range // case Qualified: case Elaborated: + case DependentName: + case DependentTemplateSpecialization: break; default: TypeLoc Next = Cur.getNextTypeLoc(); @@ -116,18 +118,37 @@ SourceLocation TypeLoc::getBeginLoc() const { SourceLocation TypeLoc::getEndLoc() const { TypeLoc Cur = *this; + TypeLoc Last; while (true) { switch (Cur.getTypeLocClass()) { default: + if (!Last) + Last = Cur; + return Last.getLocalSourceRange().getEnd(); + case Paren: + case ConstantArray: + case DependentSizedArray: + case IncompleteArray: + case VariableArray: + case FunctionProto: + case FunctionNoProto: + Last = Cur; + break; + case Pointer: + case BlockPointer: + case MemberPointer: + case LValueReference: + case RValueReference: + case PackExpansion: + if (!Last) + Last = Cur; break; case Qualified: case Elaborated: - Cur = Cur.getNextTypeLoc(); - continue; + break; } - break; + Cur = Cur.getNextTypeLoc(); } - return Cur.getLocalSourceRange().getEnd(); } @@ -213,6 +234,8 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::NullPtr: case BuiltinType::Overload: case BuiltinType::Dependent: + case BuiltinType::BoundMember: + case BuiltinType::UnknownAny: case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: @@ -229,6 +252,43 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { return TL; } +void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + setKeywordLoc(Loc); + NestedNameSpecifierLocBuilder Builder; + Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); + setQualifierLoc(Builder.getWithLocInContext(Context)); +} + +void DependentNameTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + setKeywordLoc(Loc); + NestedNameSpecifierLocBuilder Builder; + Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); + setQualifierLoc(Builder.getWithLocInContext(Context)); + setNameLoc(Loc); +} + +void +DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, + SourceLocation Loc) { + setKeywordLoc(Loc); + if (getTypePtr()->getQualifier()) { + NestedNameSpecifierLocBuilder Builder; + Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); + setQualifierLoc(Builder.getWithLocInContext(Context)); + } else { + setQualifierLoc(NestedNameSpecifierLoc()); + } + + setNameLoc(Loc); + setLAngleLoc(Loc); + setRAngleLoc(Loc); + TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), + getTypePtr()->getArgs(), + getArgInfos(), Loc); +} + void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, unsigned NumArgs, const TemplateArgument *Args, @@ -252,13 +312,22 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, break; case TemplateArgument::Template: - ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, - SourceLocation()); - break; + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Args[i].getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); - case TemplateArgument::TemplateExpansion: - ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, Loc); + ArgInfos[i] = TemplateArgumentLocInfo( + Builder.getWithLocInContext(Context), + Loc, + Args[i].getKind() == TemplateArgument::Template + ? SourceLocation() + : Loc); break; + } } } } diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index 139073987a0e..0c5df7fae671 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -400,6 +400,12 @@ void TypePrinter::printFunctionProto(const FunctionProtoType *T, case CC_X86Pascal: S += " __attribute__((pascal))"; break; + case CC_AAPCS: + S += " __attribute__((pcs(\"aapcs\")))"; + break; + case CC_AAPCS_VFP: + S += " __attribute__((pcs(\"aapcs-vfp\")))"; + break; } if (Info.getNoReturn()) S += " __attribute__((noreturn))"; @@ -421,12 +427,12 @@ void TypePrinter::printFunctionProto(const FunctionProtoType *T, S += " &&"; break; } - - if (T->hasExceptionSpec()) { + + if (T->hasDynamicExceptionSpec()) { S += " throw("; - if (T->hasAnyExceptionSpec()) + if (T->getExceptionSpecType() == EST_MSAny) S += "..."; - else + else for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) { if (I) S += ", "; @@ -436,6 +442,16 @@ void TypePrinter::printFunctionProto(const FunctionProtoType *T, S += ExceptionType; } S += ")"; + } else if (isNoexceptExceptionSpec(T->getExceptionSpecType())) { + S += " noexcept"; + if (T->getExceptionSpecType() == EST_ComputedNoexcept) { + S += "("; + llvm::raw_string_ostream EOut(S); + T->getNoexceptExpr()->printPretty(EOut, 0, Policy); + EOut.flush(); + S += EOut.str(); + S += ")"; + } } print(T->getResultType(), S); @@ -530,7 +546,7 @@ void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { Buffer += Spec->getIdentifier()->getName(); Buffer += TemplateArgsStr; } else if (TagDecl *Tag = dyn_cast(DC)) { - if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) + if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl()) Buffer += Typedef->getIdentifier()->getName(); else if (Tag->getIdentifier()) Buffer += Tag->getIdentifier()->getName(); @@ -547,9 +563,13 @@ void TypePrinter::printTag(TagDecl *D, std::string &InnerString) { std::string Buffer; bool HasKindDecoration = false; + // bool SuppressTagKeyword + // = Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword; + // We don't print tags unless this is an elaborated type. // In C, we just assume every RecordType is an elaborated type. - if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) { + if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword || + D->getTypedefNameForAnonDecl())) { HasKindDecoration = true; Buffer += D->getKindName(); Buffer += ' '; @@ -563,7 +583,7 @@ void TypePrinter::printTag(TagDecl *D, std::string &InnerString) { if (const IdentifierInfo *II = D->getIdentifier()) Buffer += II->getNameStart(); - else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) { + else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) { assert(Typedef->getIdentifier() && "Typedef without identifier?"); Buffer += Typedef->getIdentifier()->getNameStart(); } else { @@ -632,12 +652,12 @@ void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'. S = ' ' + S; - - if (!T->getName()) + + if (IdentifierInfo *Id = T->getIdentifier()) + S = Id->getName().str() + S; + else S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' + llvm::utostr_32(T->getIndex()) + S; - else - S = T->getName()->getName().str() + S; } void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, @@ -691,6 +711,7 @@ void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) { std::string TypeStr; PrintingPolicy InnerPolicy(Policy); + InnerPolicy.SuppressTagKeyword = true; InnerPolicy.SuppressScope = true; TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr); @@ -737,7 +758,8 @@ void TypePrinter::printDependentTemplateSpecialization( if (T->getKeyword() != ETK_None) OS << " "; - T->getQualifier()->print(OS, Policy); + if (T->getQualifier()) + T->getQualifier()->print(OS, Policy); OS << T->getIdentifier()->getName(); OS << TemplateSpecializationType::PrintTemplateArgumentList( T->getArgs(), @@ -759,10 +781,14 @@ void TypePrinter::printPackExpansion(const PackExpansionType *T, void TypePrinter::printAttributed(const AttributedType *T, std::string &S) { + // Prefer the macro forms of the GC qualifiers. + if (T->getAttrKind() == AttributedType::attr_objc_gc) + return print(T->getEquivalentType(), S); + print(T->getModifiedType(), S); // TODO: not all attributes are GCC-style attributes. - S += "__attribute__(("; + S += " __attribute__(("; switch (T->getAttrKind()) { case AttributedType::attr_address_space: S += "address_space("; @@ -831,6 +857,16 @@ void TypePrinter::printAttributed(const AttributedType *T, case AttributedType::attr_stdcall: S += "stdcall"; break; case AttributedType::attr_thiscall: S += "thiscall"; break; case AttributedType::attr_pascal: S += "pascal"; break; + case AttributedType::attr_pcs: { + S += "pcs("; + QualType t = T->getEquivalentType(); + while (!t->isFunctionType()) + t = t->getPointeeType(); + S += (t->getAs()->getCallConv() == CC_AAPCS ? + "\"aapcs\"" : "\"aapcs-vfp\""); + S += ")"; + break; + } } S += "))"; } @@ -1031,20 +1067,18 @@ std::string Qualifiers::getAsString() const { void Qualifiers::getAsStringInternal(std::string &S, const PrintingPolicy&) const { AppendTypeQualList(S, getCVRQualifiers()); - if (unsigned AddressSpace = getAddressSpace()) { + if (unsigned addrspace = getAddressSpace()) { if (!S.empty()) S += ' '; S += "__attribute__((address_space("; - S += llvm::utostr_32(AddressSpace); + S += llvm::utostr_32(addrspace); S += ")))"; } - if (Qualifiers::GC GCAttrType = getObjCGCAttr()) { + if (Qualifiers::GC gc = getObjCGCAttr()) { if (!S.empty()) S += ' '; - S += "__attribute__((objc_gc("; - if (GCAttrType == Qualifiers::Weak) - S += "weak"; + if (gc == Qualifiers::Weak) + S += "__weak"; else - S += "strong"; - S += ")))"; + S += "__strong"; } } diff --git a/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp index 62097ef20dd9..ddc5e887031b 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp @@ -29,6 +29,24 @@ using namespace clang; +AnalysisContext::AnalysisContext(const Decl *d, + idx::TranslationUnit *tu, + bool useUnoptimizedCFG, + bool addehedges, + bool addImplicitDtors, + bool addInitializers) + : D(d), TU(tu), + forcedBlkExprs(0), + builtCFG(false), builtCompleteCFG(false), + useUnoptimizedCFG(useUnoptimizedCFG), + ReferencedBlockVars(0) +{ + cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; + cfgBuildOptions.AddEHEdges = addehedges; + cfgBuildOptions.AddImplicitDtors = addImplicitDtors; + cfgBuildOptions.AddInitializers = addInitializers; +} + void AnalysisContextManager::clear() { for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I) delete I->second; @@ -56,57 +74,71 @@ const ImplicitParamDecl *AnalysisContext::getSelfDecl() const { return NULL; } +void AnalysisContext::registerForcedBlockExpression(const Stmt *stmt) { + if (!forcedBlkExprs) + forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs(); + // Default construct an entry for 'stmt'. + if (const ParenExpr *pe = dyn_cast(stmt)) + stmt = pe->IgnoreParens(); + (void) (*forcedBlkExprs)[stmt]; +} + +const CFGBlock * +AnalysisContext::getBlockForRegisteredExpression(const Stmt *stmt) { + assert(forcedBlkExprs); + if (const ParenExpr *pe = dyn_cast(stmt)) + stmt = pe->IgnoreParens(); + CFG::BuildOptions::ForcedBlkExprs::const_iterator itr = + forcedBlkExprs->find(stmt); + assert(itr != forcedBlkExprs->end()); + return itr->second; +} + CFG *AnalysisContext::getCFG() { - if (UseUnoptimizedCFG) + if (useUnoptimizedCFG) return getUnoptimizedCFG(); if (!builtCFG) { - CFG::BuildOptions B; - B.AddEHEdges = AddEHEdges; - B.AddImplicitDtors = AddImplicitDtors; - B.AddInitializers = AddInitializers; - cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), B); + cfg.reset(CFG::buildCFG(D, getBody(), + &D->getASTContext(), cfgBuildOptions)); // Even when the cfg is not successfully built, we don't // want to try building it again. builtCFG = true; } - return cfg; + return cfg.get(); } CFG *AnalysisContext::getUnoptimizedCFG() { if (!builtCompleteCFG) { - CFG::BuildOptions B; + CFG::BuildOptions B = cfgBuildOptions; B.PruneTriviallyFalseEdges = false; - B.AddEHEdges = AddEHEdges; - B.AddImplicitDtors = AddImplicitDtors; - B.AddInitializers = AddInitializers; - completeCFG = CFG::buildCFG(D, getBody(), &D->getASTContext(), B); + completeCFG.reset(CFG::buildCFG(D, getBody(), &D->getASTContext(), B)); // Even when the cfg is not successfully built, we don't // want to try building it again. builtCompleteCFG = true; } - return completeCFG; + return completeCFG.get(); } CFGStmtMap *AnalysisContext::getCFGStmtMap() { if (cfgStmtMap) - return cfgStmtMap; + return cfgStmtMap.get(); if (CFG *c = getCFG()) { - cfgStmtMap = CFGStmtMap::Build(c, &getParentMap()); - return cfgStmtMap; + cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap())); + return cfgStmtMap.get(); } return 0; } -CFGReachabilityAnalysis *AnalysisContext::getCFGReachablityAnalysis() { +CFGReverseBlockReachabilityAnalysis *AnalysisContext::getCFGReachablityAnalysis() { if (CFA) - return CFA; + return CFA.get(); if (CFG *c = getCFG()) { - CFA = new CFGReachabilityAnalysis(*c); - return CFA; + CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c)); + return CFA.get(); } return 0; @@ -118,42 +150,37 @@ void AnalysisContext::dumpCFG() { ParentMap &AnalysisContext::getParentMap() { if (!PM) - PM = new ParentMap(getBody()); + PM.reset(new ParentMap(getBody())); return *PM; } PseudoConstantAnalysis *AnalysisContext::getPseudoConstantAnalysis() { if (!PCA) - PCA = new PseudoConstantAnalysis(getBody()); - return PCA; + PCA.reset(new PseudoConstantAnalysis(getBody())); + return PCA.get(); } LiveVariables *AnalysisContext::getLiveVariables() { if (!liveness) { - CFG *c = getCFG(); - if (!c) - return 0; - - liveness = new LiveVariables(*this); - liveness->runOnCFG(*c); - liveness->runOnAllBlocks(*c, 0, true); + if (CFG *c = getCFG()) { + liveness.reset(new LiveVariables(*this)); + liveness->runOnCFG(*c); + liveness->runOnAllBlocks(*c, 0, true); + } } - return liveness; + return liveness.get(); } LiveVariables *AnalysisContext::getRelaxedLiveVariables() { - if (!relaxedLiveness) { - CFG *c = getCFG(); - if (!c) - return 0; + if (!relaxedLiveness) + if (CFG *c = getCFG()) { + relaxedLiveness.reset(new LiveVariables(*this, false)); + relaxedLiveness->runOnCFG(*c); + relaxedLiveness->runOnAllBlocks(*c, 0, true); + } - relaxedLiveness = new LiveVariables(*this, false); - relaxedLiveness->runOnCFG(*c); - relaxedLiveness->runOnAllBlocks(*c, 0, true); - } - - return relaxedLiveness; + return relaxedLiveness.get(); } AnalysisContext *AnalysisContextManager::getContext(const Decl *D, @@ -370,14 +397,7 @@ AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) { //===----------------------------------------------------------------------===// AnalysisContext::~AnalysisContext() { - delete cfg; - delete completeCFG; - delete cfgStmtMap; - delete liveness; - delete relaxedLiveness; - delete PM; - delete PCA; - delete CFA; + delete forcedBlkExprs; delete ReferencedBlockVars; } diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp index cc6e9c592a1e..de16334ce137 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp @@ -36,6 +36,8 @@ static SourceLocation GetEndLoc(Decl* D) { return D->getLocation(); } +class CFGBuilder; + /// The CFG builder uses a recursive algorithm to build the CFG. When /// we process an expression, sometimes we know that we must add the /// subexpressions as block-level expressions. For example: @@ -55,13 +57,13 @@ class AddStmtChoice { AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {} - bool alwaysAdd() const { return kind & AlwaysAdd; } + bool alwaysAdd(CFGBuilder &builder, + const Stmt *stmt) const; /// Return a copy of this object, except with the 'always-add' bit /// set as specified. AddStmtChoice withAlwaysAdd(bool alwaysAdd) const { - return AddStmtChoice(alwaysAdd ? Kind(kind | AlwaysAdd) : - Kind(kind & ~AlwaysAdd)); + return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd); } private: @@ -210,6 +212,25 @@ struct BlockScopePosPair { LocalScope::const_iterator scopePosition; }; +/// TryResult - a class representing a variant over the values +/// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool, +/// and is used by the CFGBuilder to decide if a branch condition +/// can be decided up front during CFG construction. +class TryResult { + int X; +public: + TryResult(bool b) : X(b ? 1 : 0) {} + TryResult() : X(-1) {} + + bool isTrue() const { return X == 1; } + bool isFalse() const { return X == 0; } + bool isKnown() const { return X >= 0; } + void negate() { + assert(isKnown()); + X ^= 0x1; + } +}; + /// CFGBuilder - This class implements CFG construction from an AST. /// The builder is stateful: an instance of the builder should be used to only /// construct a single CFG. @@ -238,7 +259,7 @@ class CFGBuilder { CFGBlock* SwitchTerminatedBlock; CFGBlock* DefaultCaseBlock; CFGBlock* TryTerminatedBlock; - + // Current position in local scope. LocalScope::const_iterator ScopePos; @@ -256,18 +277,30 @@ class CFGBuilder { LabelSetTy AddressTakenLabels; bool badCFG; - CFG::BuildOptions BuildOpts; + const CFG::BuildOptions &BuildOpts; + + // State to track for building switch statements. + bool switchExclusivelyCovered; + Expr::EvalResult *switchCond; + + CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry; + const Stmt *lastLookup; public: - explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG - Block(NULL), Succ(NULL), - SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), - TryTerminatedBlock(NULL), badCFG(false) {} + explicit CFGBuilder(ASTContext *astContext, + const CFG::BuildOptions &buildOpts) + : Context(astContext), cfg(new CFG()), // crew a new CFG + Block(NULL), Succ(NULL), + SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), + TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), + switchExclusivelyCovered(false), switchCond(0), + cachedEntry(0), lastLookup(0) {} // buildCFG - Used by external clients to construct the CFG. - CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, - CFG::BuildOptions BO); + CFG* buildCFG(const Decl *D, Stmt *Statement); + bool alwaysAdd(const Stmt *stmt); + private: // Visitors to walk an AST and construct the CFG. CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); @@ -279,6 +312,7 @@ class CFGBuilder { AddStmtChoice asc); CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); + CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S); CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, AddStmtChoice asc); CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc); @@ -311,7 +345,8 @@ class CFGBuilder { CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); CFGBlock *VisitReturnStmt(ReturnStmt* R); - CFGBlock *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, AddStmtChoice asc); + CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, + AddStmtChoice asc); CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); CFGBlock *VisitSwitchStmt(SwitchStmt *S); CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc); @@ -359,9 +394,11 @@ class CFGBuilder { void addLocalScopeAndDtors(Stmt* S); // Interface to CFGBlock - adding CFGElements. - void appendStmt(CFGBlock *B, Stmt *S, - AddStmtChoice asc = AddStmtChoice::AlwaysAdd) { - B->appendStmt(S, cfg->getBumpVectorContext()); + void appendStmt(CFGBlock *B, const Stmt *S) { + if (alwaysAdd(S)) + cachedEntry->second = B; + + B->appendStmt(const_cast(S), cfg->getBumpVectorContext()); } void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { B->appendInitializer(I, cfg->getBumpVectorContext()); @@ -387,47 +424,74 @@ class CFGBuilder { B->addSuccessor(S, cfg->getBumpVectorContext()); } - /// TryResult - a class representing a variant over the values - /// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool, - /// and is used by the CFGBuilder to decide if a branch condition - /// can be decided up front during CFG construction. - class TryResult { - int X; - public: - TryResult(bool b) : X(b ? 1 : 0) {} - TryResult() : X(-1) {} - - bool isTrue() const { return X == 1; } - bool isFalse() const { return X == 0; } - bool isKnown() const { return X >= 0; } - void negate() { - assert(isKnown()); - X ^= 0x1; - } - }; + /// Try and evaluate an expression to an integer constant. + bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) { + if (!BuildOpts.PruneTriviallyFalseEdges) + return false; + return !S->isTypeDependent() && + !S->isValueDependent() && + S->Evaluate(outResult, *Context); + } /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 /// if we can evaluate to a known value, otherwise return -1. TryResult tryEvaluateBool(Expr *S) { - if (!BuildOpts.PruneTriviallyFalseEdges) - return TryResult(); - Expr::EvalResult Result; - if (!S->isTypeDependent() && !S->isValueDependent() && - S->Evaluate(Result, *Context)) { - if (Result.Val.isInt()) - return Result.Val.getInt().getBoolValue(); - if (Result.Val.isLValue()) { - Expr *e = Result.Val.getLValueBase(); - const CharUnits &c = Result.Val.getLValueOffset(); - if (!e && c.isZero()) - return false; - } + if (!tryEvaluate(S, Result)) + return TryResult(); + + if (Result.Val.isInt()) + return Result.Val.getInt().getBoolValue(); + + if (Result.Val.isLValue()) { + Expr *e = Result.Val.getLValueBase(); + const CharUnits &c = Result.Val.getLValueOffset(); + if (!e && c.isZero()) + return false; } return TryResult(); } + }; +inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, + const Stmt *stmt) const { + return builder.alwaysAdd(stmt) || kind == AlwaysAdd; +} + +bool CFGBuilder::alwaysAdd(const Stmt *stmt) { + if (!BuildOpts.forcedBlkExprs) + return false; + + if (lastLookup == stmt) { + if (cachedEntry) { + assert(cachedEntry->first == stmt); + return true; + } + return false; + } + + lastLookup = stmt; + + // Perform the lookup! + CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs; + + if (!fb) { + // No need to update 'cachedEntry', since it will always be null. + assert(cachedEntry == 0); + return false; + } + + CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt); + if (itr == fb->end()) { + cachedEntry = 0; + return false; + } + + cachedEntry = &*itr; + return true; +} + // FIXME: Add support for dependent-sized array types in C++? // Does it even make sense to build a CFG for an uninstantiated template? static const VariableArrayType *FindVA(const Type *t) { @@ -447,16 +511,11 @@ static const VariableArrayType *FindVA(const Type *t) { /// body (compound statement). The ownership of the returned CFG is /// transferred to the caller. If CFG construction fails, this method returns /// NULL. -CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C, - CFG::BuildOptions BO) { - - Context = C; +CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement) { assert(cfg.get()); if (!Statement) return NULL; - BuildOpts = BO; - // Create an empty block that will serve as the exit block for the CFG. Since // this is the first block added to the CFG, it will be implicitly registered // as the exit block. @@ -853,6 +912,9 @@ CFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { case Stmt::CXXTryStmtClass: return VisitCXXTryStmt(cast(S)); + case Stmt::CXXForRangeStmtClass: + return VisitCXXForRangeStmt(cast(S)); + case Stmt::DeclStmtClass: return VisitDeclStmt(cast(S)); @@ -908,8 +970,9 @@ CFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { case Stmt::ReturnStmtClass: return VisitReturnStmt(cast(S)); - case Stmt::SizeOfAlignOfExprClass: - return VisitSizeOfAlignOfExpr(cast(S), asc); + case Stmt::UnaryExprOrTypeTraitExprClass: + return VisitUnaryExprOrTypeTraitExpr(cast(S), + asc); case Stmt::StmtExprClass: return VisitStmtExpr(cast(S), asc); @@ -926,9 +989,9 @@ CFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { } CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, S)) { autoCreateBlock(); - appendStmt(Block, S, asc); + appendStmt(Block, S); } return VisitChildren(S); @@ -949,9 +1012,9 @@ CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc) { AddressTakenLabels.insert(A->getLabel()); - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, A)) { autoCreateBlock(); - appendStmt(Block, A, asc); + appendStmt(Block, A); } return Block; @@ -959,9 +1022,9 @@ CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, U)) { autoCreateBlock(); - appendStmt(Block, U, asc); + appendStmt(Block, U); } return Visit(U->getSubExpr(), AddStmtChoice()); @@ -971,7 +1034,7 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc) { if (B->isLogicalOp()) { // && or || CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); - appendStmt(ConfluenceBlock, B, asc); + appendStmt(ConfluenceBlock, B); if (badCFG) return 0; @@ -1016,23 +1079,23 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, if (B->getOpcode() == BO_Comma) { // , autoCreateBlock(); - appendStmt(Block, B, asc); + appendStmt(Block, B); addStmt(B->getRHS()); return addStmt(B->getLHS()); } if (B->isAssignmentOp()) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, B)) { autoCreateBlock(); - appendStmt(Block, B, asc); + appendStmt(Block, B); } Visit(B->getLHS()); return Visit(B->getRHS()); } - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, B)) { autoCreateBlock(); - appendStmt(Block, B, asc); + appendStmt(Block, B); } CFGBlock *RBlock = Visit(B->getRHS()); @@ -1044,9 +1107,9 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, } CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, E)) { autoCreateBlock(); - appendStmt(Block, E, asc); + appendStmt(Block, E); } return Block; } @@ -1073,7 +1136,7 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { return Block; } -static bool CanThrow(Expr *E) { +static bool CanThrow(Expr *E, ASTContext &Ctx) { QualType Ty = E->getType(); if (Ty->isFunctionPointerType()) Ty = Ty->getAs()->getPointeeType(); @@ -1083,7 +1146,7 @@ static bool CanThrow(Expr *E) { const FunctionType *FT = Ty->getAs(); if (FT) { if (const FunctionProtoType *Proto = dyn_cast(FT)) - if (Proto->hasEmptyExceptionSpec()) + if (Proto->isNothrow(Ctx)) return false; } return true; @@ -1099,7 +1162,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { bool AddEHEdge = false; // Languages without exceptions are assumed to not throw. - if (Context->getLangOptions().areExceptionsEnabled()) { + if (Context->getLangOptions().Exceptions) { if (BuildOpts.AddEHEdges) AddEHEdge = true; } @@ -1111,7 +1174,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { AddEHEdge = false; } - if (!CanThrow(C->getCallee())) + if (!CanThrow(C->getCallee(), *Context)) AddEHEdge = false; if (!NoReturn && !AddEHEdge) @@ -1124,7 +1187,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { } Block = createBlock(!NoReturn); - appendStmt(Block, C, asc); + appendStmt(Block, C); if (NoReturn) { // Wire this to the exit block directly. @@ -1144,7 +1207,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc) { CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); - appendStmt(ConfluenceBlock, C, asc); + appendStmt(ConfluenceBlock, C); if (badCFG) return 0; @@ -1197,7 +1260,7 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, // Create the confluence block that will "merge" the results of the ternary // expression. CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); - appendStmt(ConfluenceBlock, C, asc); + appendStmt(ConfluenceBlock, C); if (badCFG) return 0; @@ -1353,7 +1416,7 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) { addAutomaticObjDtors(ScopePos, BeginScopePos, I); } - // The block we were proccessing is now finished. Make it the successor + // The block we were processing is now finished. Make it the successor // block. if (Block) { Succ = Block; @@ -1436,7 +1499,7 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) { if (VarDecl *VD = I->getConditionVariable()) { if (Expr *Init = VD->getInit()) { autoCreateBlock(); - appendStmt(Block, I, AddStmtChoice::AlwaysAdd); + appendStmt(Block, I->getConditionVariableDeclStmt()); addStmt(Init); } } @@ -1574,7 +1637,7 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { if (VarDecl *VD = F->getConditionVariable()) { if (Expr *Init = VD->getInit()) { autoCreateBlock(); - appendStmt(Block, F, AddStmtChoice::AlwaysAdd); + appendStmt(Block, F->getConditionVariableDeclStmt()); EntryConditionBlock = addStmt(Init); assert(Block == EntryConditionBlock); } @@ -1672,9 +1735,9 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { } CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, M)) { autoCreateBlock(); - appendStmt(Block, M, asc); + appendStmt(Block, M); } return Visit(M->getBase()); } @@ -1736,7 +1799,7 @@ CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { Block = ExitConditionBlock; // Walk the 'element' expression to see if there are any side-effects. We - // generate new blocks as necesary. We DON'T add the statement by default to + // generate new blocks as necessary. We DON'T add the statement by default to // the CFG unless it contains control-flow. EntryConditionBlock = Visit(S->getElement(), AddStmtChoice::NotAlwaysAdd); if (Block) { @@ -1799,7 +1862,7 @@ CFGBlock* CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S) { // Add the @synchronized to the CFG. autoCreateBlock(); - appendStmt(Block, S, AddStmtChoice::AlwaysAdd); + appendStmt(Block, S); // Inline the sync expression. return addStmt(S->getSynchExpr()); @@ -1858,7 +1921,7 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { if (VarDecl *VD = W->getConditionVariable()) { if (Expr *Init = VD->getInit()) { autoCreateBlock(); - appendStmt(Block, W, AddStmtChoice::AlwaysAdd); + appendStmt(Block, W->getConditionVariableDeclStmt()); EntryConditionBlock = addStmt(Init); assert(Block == EntryConditionBlock); } @@ -2105,28 +2168,30 @@ CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) { return Block; } -CFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, - AddStmtChoice asc) { +CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, + AddStmtChoice asc) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, E)) { autoCreateBlock(); appendStmt(Block, E); } // VLA types have expressions that must be evaluated. + CFGBlock *lastBlock = Block; + if (E->isArgumentType()) { for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr()); VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) - addStmt(VA->getSizeExpr()); + lastBlock = addStmt(VA->getSizeExpr()); } - return Block; + return lastBlock; } /// VisitStmtExpr - Utility method to handle (nested) statement /// expressions (a GCC extension). CFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, SE)) { autoCreateBlock(); appendStmt(Block, SE); } @@ -2180,6 +2245,18 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { assert(Terminator->getBody() && "switch must contain a non-NULL body"); Block = NULL; + // For pruning unreachable case statements, save the current state + // for tracking the condition value. + SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered, + false); + + // Determine if the switch condition can be explicitly evaluated. + assert(Terminator->getCond() && "switch condition must be non-NULL"); + Expr::EvalResult result; + bool b = tryEvaluate(Terminator->getCond(), result); + SaveAndRestore save_switchCond(switchCond, + b ? &result : 0); + // If body is not a compound statement create implicit scope // and add destructors. if (!isa(Terminator->getBody())) @@ -2192,12 +2269,14 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { } // If we have no "default:" case, the default transition is to the code - // following the switch body. - addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock); + // following the switch body. Moreover, take into account if all the + // cases of a switch are covered (e.g., switching on an enum value). + addSuccessor(SwitchTerminatedBlock, + switchExclusivelyCovered || Terminator->isAllEnumCasesCovered() + ? 0 : DefaultCaseBlock); // Add the terminator and condition in the switch block. SwitchTerminatedBlock->setTerminator(Terminator); - assert(Terminator->getCond() && "switch condition must be non-NULL"); Block = SwitchTerminatedBlock; Block = addStmt(Terminator->getCond()); @@ -2206,19 +2285,60 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { if (VarDecl *VD = Terminator->getConditionVariable()) { if (Expr *Init = VD->getInit()) { autoCreateBlock(); - appendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd); + appendStmt(Block, Terminator->getConditionVariableDeclStmt()); addStmt(Init); } } return Block; } + +static bool shouldAddCase(bool &switchExclusivelyCovered, + const Expr::EvalResult *switchCond, + const CaseStmt *CS, + ASTContext &Ctx) { + if (!switchCond) + return true; + + bool addCase = false; + + if (!switchExclusivelyCovered) { + if (switchCond->Val.isInt()) { + // Evaluate the LHS of the case value. + Expr::EvalResult V1; + CS->getLHS()->Evaluate(V1, Ctx); + assert(V1.Val.isInt()); + const llvm::APSInt &condInt = switchCond->Val.getInt(); + const llvm::APSInt &lhsInt = V1.Val.getInt(); + + if (condInt == lhsInt) { + addCase = true; + switchExclusivelyCovered = true; + } + else if (condInt < lhsInt) { + if (const Expr *RHS = CS->getRHS()) { + // Evaluate the RHS of the case value. + Expr::EvalResult V2; + RHS->Evaluate(V2, Ctx); + assert(V2.Val.isInt()); + if (V2.Val.getInt() <= condInt) { + addCase = true; + switchExclusivelyCovered = true; + } + } + } + } + else + addCase = true; + } + return addCase; +} CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) { // CaseStmts are essentially labels, so they are the first statement in a // block. CFGBlock *TopBlock = 0, *LastBlock = 0; - + if (Stmt *Sub = CS->getSubStmt()) { // For deeply nested chains of CaseStmts, instead of doing a recursion // (which can blow out the stack), manually unroll and create blocks @@ -2232,9 +2352,12 @@ CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) { else TopBlock = currentBlock; - addSuccessor(SwitchTerminatedBlock, currentBlock); - LastBlock = currentBlock; + addSuccessor(SwitchTerminatedBlock, + shouldAddCase(switchExclusivelyCovered, switchCond, + CS, *Context) + ? currentBlock : 0); + LastBlock = currentBlock; CS = cast(Sub); Sub = CS->getSubStmt(); } @@ -2256,7 +2379,10 @@ CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) { // Add this block to the list of successors for the block with the switch // statement. assert(SwitchTerminatedBlock); - addSuccessor(SwitchTerminatedBlock, CaseBlock); + addSuccessor(SwitchTerminatedBlock, + shouldAddCase(switchExclusivelyCovered, switchCond, + CS, *Context) + ? CaseBlock : 0); // We set Block to NULL to allow lazy creation of a new block (if necessary) Block = NULL; @@ -2391,6 +2517,122 @@ CFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) { return CatchBlock; } +CFGBlock* CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt* S) { + // C++0x for-range statements are specified as [stmt.ranged]: + // + // { + // auto && __range = range-init; + // for ( auto __begin = begin-expr, + // __end = end-expr; + // __begin != __end; + // ++__begin ) { + // for-range-declaration = *__begin; + // statement + // } + // } + + // Save local scope position before the addition of the implicit variables. + SaveAndRestore save_scope_pos(ScopePos); + + // Create local scopes and destructors for range, begin and end variables. + if (Stmt *Range = S->getRangeStmt()) + addLocalScopeForStmt(Range); + if (Stmt *BeginEnd = S->getBeginEndStmt()) + addLocalScopeForStmt(BeginEnd); + addAutomaticObjDtors(ScopePos, save_scope_pos.get(), S); + + LocalScope::const_iterator ContinueScopePos = ScopePos; + + // "for" is a control-flow statement. Thus we stop processing the current + // block. + CFGBlock* LoopSuccessor = NULL; + if (Block) { + if (badCFG) + return 0; + LoopSuccessor = Block; + } else + LoopSuccessor = Succ; + + // Save the current value for the break targets. + // All breaks should go to the code following the loop. + SaveAndRestore save_break(BreakJumpTarget); + BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); + + // The block for the __begin != __end expression. + CFGBlock* ConditionBlock = createBlock(false); + ConditionBlock->setTerminator(S); + + // Now add the actual condition to the condition block. + if (Expr *C = S->getCond()) { + Block = ConditionBlock; + CFGBlock *BeginConditionBlock = addStmt(C); + if (badCFG) + return 0; + assert(BeginConditionBlock == ConditionBlock && + "condition block in for-range was unexpectedly complex"); + (void)BeginConditionBlock; + } + + // The condition block is the implicit successor for the loop body as well as + // any code above the loop. + Succ = ConditionBlock; + + // See if this is a known constant. + TryResult KnownVal(true); + + if (S->getCond()) + KnownVal = tryEvaluateBool(S->getCond()); + + // Now create the loop body. + { + assert(S->getBody()); + + // Save the current values for Block, Succ, and continue targets. + SaveAndRestore save_Block(Block), save_Succ(Succ); + SaveAndRestore save_continue(ContinueJumpTarget); + + // Generate increment code in its own basic block. This is the target of + // continue statements. + Block = 0; + Succ = addStmt(S->getInc()); + ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); + + // The starting block for the loop increment is the block that should + // represent the 'loop target' for looping back to the start of the loop. + ContinueJumpTarget.block->setLoopTarget(S); + + // Finish up the increment block and prepare to start the loop body. + assert(Block); + if (badCFG) + return 0; + Block = 0; + + + // Add implicit scope and dtors for loop variable. + addLocalScopeAndDtors(S->getLoopVarStmt()); + + // Populate a new block to contain the loop body and loop variable. + Block = addStmt(S->getBody()); + if (badCFG) + return 0; + Block = addStmt(S->getLoopVarStmt()); + if (badCFG) + return 0; + + // This new body block is a successor to our condition block. + addSuccessor(ConditionBlock, KnownVal.isFalse() ? 0 : Block); + } + + // Link up the condition block with the code that follows the loop (the + // false branch). + addSuccessor(ConditionBlock, KnownVal.isTrue() ? 0 : LoopSuccessor); + + // Add the initialization statements. + Block = createBlock(); + addStmt(S->getBeginEndStmt()); + return addStmt(S->getRangeStmt()); +} + CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc) { if (BuildOpts.AddImplicitDtors) { @@ -2407,9 +2649,9 @@ CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E, CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, AddStmtChoice asc) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, E)) { autoCreateBlock(); - appendStmt(Block, E, asc); + appendStmt(Block, E); // We do not want to propagate the AlwaysAdd property. asc = asc.withAlwaysAdd(false); @@ -2421,16 +2663,16 @@ CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc) { autoCreateBlock(); if (!C->isElidable()) - appendStmt(Block, C, asc.withAlwaysAdd(true)); + appendStmt(Block, C); return VisitChildren(C); } CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, AddStmtChoice asc) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, E)) { autoCreateBlock(); - appendStmt(Block, E, asc); + appendStmt(Block, E); // We do not want to propagate the AlwaysAdd property. asc = asc.withAlwaysAdd(false); } @@ -2440,22 +2682,22 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, AddStmtChoice asc) { autoCreateBlock(); - appendStmt(Block, C, asc.withAlwaysAdd(true)); + appendStmt(Block, C); return VisitChildren(C); } CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc) { autoCreateBlock(); - appendStmt(Block, C, asc.withAlwaysAdd(true)); + appendStmt(Block, C); return VisitChildren(C); } CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc) { - if (asc.alwaysAdd()) { + if (asc.alwaysAdd(*this, E)) { autoCreateBlock(); - appendStmt(Block, E, asc); + appendStmt(Block, E); } return Visit(E->getSubExpr(), AddStmtChoice()); } @@ -2699,9 +2941,53 @@ CFGBlock* CFG::createBlock() { /// buildCFG - Constructs a CFG from an AST. Ownership of the returned /// CFG is returned to the caller. CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C, - BuildOptions BO) { - CFGBuilder Builder; - return Builder.buildCFG(D, Statement, C, BO); + const BuildOptions &BO) { + CFGBuilder Builder(C, BO); + return Builder.buildCFG(D, Statement); +} + +const CXXDestructorDecl * +CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { + switch (getKind()) { + case CFGElement::Invalid: + case CFGElement::Statement: + case CFGElement::Initializer: + llvm_unreachable("getDestructorDecl should only be used with " + "ImplicitDtors"); + case CFGElement::AutomaticObjectDtor: { + const VarDecl *var = cast(this)->getVarDecl(); + QualType ty = var->getType(); + ty = ty.getNonReferenceType(); + if (const ArrayType *arrayType = astContext.getAsArrayType(ty)) { + ty = arrayType->getElementType(); + } + const RecordType *recordType = ty->getAs(); + const CXXRecordDecl *classDecl = + cast(recordType->getDecl()); + return classDecl->getDestructor(); + } + case CFGElement::TemporaryDtor: { + const CXXBindTemporaryExpr *bindExpr = + cast(this)->getBindTemporaryExpr(); + const CXXTemporary *temp = bindExpr->getTemporary(); + return temp->getDestructor(); + } + case CFGElement::BaseDtor: + case CFGElement::MemberDtor: + + // Not yet supported. + return 0; + } + llvm_unreachable("getKind() returned bogus value"); + return 0; +} + +bool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { + if (const CXXDestructorDecl *cdecl = getDestructorDecl(astContext)) { + QualType ty = cdecl->getType(); + return cast(ty)->getNoReturnAttr(); + } + return false; } //===----------------------------------------------------------------------===// @@ -2740,8 +3026,8 @@ static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) - if (CFGStmt S = BI->getAs()) - FindSubExprAssignments(S, SubExprAssignments); + if (const CFGStmt *S = BI->getAs()) + FindSubExprAssignments(S->getStmt(), SubExprAssignments); for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { @@ -2749,10 +3035,10 @@ static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { // block-level that are block-level expressions. for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) { - CFGStmt CS = BI->getAs(); - if (!CS.isValid()) + const CFGStmt *CS = BI->getAs(); + if (!CS) continue; - if (Expr* Exp = dyn_cast(CS.getStmt())) { + if (Expr* Exp = dyn_cast(CS->getStmt())) { if (BinaryOperator* B = dyn_cast(Exp)) { // Assignment expressions that are not nested within another @@ -2814,15 +3100,15 @@ unsigned CFG::getNumBlkExprs() { bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, const CFGBlock *From, const CFGBlock *To) { - if (F.IgnoreDefaultsWithCoveredEnums) { + if (To && F.IgnoreDefaultsWithCoveredEnums) { // If the 'To' has no label or is labeled but the label isn't a // CaseStmt then filter this edge. if (const SwitchStmt *S = - dyn_cast_or_null(From->getTerminator().getStmt())) { + dyn_cast_or_null(From->getTerminator().getStmt())) { if (S->isAllEnumCasesCovered()) { - const Stmt *L = To->getLabel(); - if (!L || !isa(L)) - return true; + const Stmt *L = To->getLabel(); + if (!L || !isa(L)) + return true; } } } @@ -2845,8 +3131,8 @@ CFG::~CFG() { namespace { class StmtPrinterHelper : public PrinterHelper { - typedef llvm::DenseMap > StmtMapTy; - typedef llvm::DenseMap > DeclMapTy; + typedef llvm::DenseMap > StmtMapTy; + typedef llvm::DenseMap > DeclMapTy; StmtMapTy StmtMap; DeclMapTy DeclMap; signed currentBlock; @@ -2855,42 +3141,62 @@ class StmtPrinterHelper : public PrinterHelper { public: StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) - : currentBlock(0), currentStmt(0), LangOpts(LO) { + : currentBlock(0), currentStmt(0), LangOpts(LO) + { for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { unsigned j = 1; for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; BI != BEnd; ++BI, ++j ) { - if (CFGStmt SE = BI->getAs()) { + if (const CFGStmt *SE = BI->getAs()) { + const Stmt *stmt= SE->getStmt(); std::pair P((*I)->getBlockID(), j); - StmtMap[SE] = P; + StmtMap[stmt] = P; - if (DeclStmt* DS = dyn_cast(SE.getStmt())) { - DeclMap[DS->getSingleDecl()] = P; - - } else if (IfStmt* IS = dyn_cast(SE.getStmt())) { - if (VarDecl* VD = IS->getConditionVariable()) - DeclMap[VD] = P; - - } else if (ForStmt* FS = dyn_cast(SE.getStmt())) { - if (VarDecl* VD = FS->getConditionVariable()) - DeclMap[VD] = P; - - } else if (WhileStmt* WS = dyn_cast(SE.getStmt())) { - if (VarDecl* VD = WS->getConditionVariable()) - DeclMap[VD] = P; - - } else if (SwitchStmt* SS = dyn_cast(SE.getStmt())) { - if (VarDecl* VD = SS->getConditionVariable()) - DeclMap[VD] = P; - - } else if (CXXCatchStmt* CS = dyn_cast(SE.getStmt())) { - if (VarDecl* VD = CS->getExceptionDecl()) - DeclMap[VD] = P; + switch (stmt->getStmtClass()) { + case Stmt::DeclStmtClass: + DeclMap[cast(stmt)->getSingleDecl()] = P; + break; + case Stmt::IfStmtClass: { + const VarDecl *var = cast(stmt)->getConditionVariable(); + if (var) + DeclMap[var] = P; + break; + } + case Stmt::ForStmtClass: { + const VarDecl *var = cast(stmt)->getConditionVariable(); + if (var) + DeclMap[var] = P; + break; + } + case Stmt::WhileStmtClass: { + const VarDecl *var = + cast(stmt)->getConditionVariable(); + if (var) + DeclMap[var] = P; + break; + } + case Stmt::SwitchStmtClass: { + const VarDecl *var = + cast(stmt)->getConditionVariable(); + if (var) + DeclMap[var] = P; + break; + } + case Stmt::CXXCatchStmtClass: { + const VarDecl *var = + cast(stmt)->getExceptionDecl(); + if (var) + DeclMap[var] = P; + break; + } + default: + break; } } } } } + virtual ~StmtPrinterHelper() {} @@ -2913,7 +3219,7 @@ class StmtPrinterHelper : public PrinterHelper { return true; } - bool handleDecl(Decl* D, llvm::raw_ostream& OS) { + bool handleDecl(const Decl* D, llvm::raw_ostream& OS) { DeclMapTy::iterator I = DeclMap.find(D); if (I == DeclMap.end()) @@ -3031,8 +3337,8 @@ class CFGBlockTerminatorPrint static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, const CFGElement &E) { - if (CFGStmt CS = E.getAs()) { - Stmt *S = CS; + if (const CFGStmt *CS = E.getAs()) { + Stmt *S = CS->getStmt(); if (Helper) { @@ -3069,8 +3375,8 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, if (isa(S)) OS << '\n'; - } else if (CFGInitializer IE = E.getAs()) { - CXXCtorInitializer* I = IE; + } else if (const CFGInitializer *IE = E.getAs()) { + const CXXCtorInitializer *I = IE->getInitializer(); if (I->isBaseInitializer()) OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); else OS << I->getAnyMember()->getName(); @@ -3084,8 +3390,8 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, OS << " (Base initializer)\n"; else OS << " (Member initializer)\n"; - } else if (CFGAutomaticObjDtor DE = E.getAs()){ - VarDecl* VD = DE.getVarDecl(); + } else if (const CFGAutomaticObjDtor *DE = E.getAs()){ + const VarDecl* VD = DE->getVarDecl(); Helper->handleDecl(VD, OS); const Type* T = VD->getType().getTypePtr(); @@ -3097,13 +3403,13 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; OS << " (Implicit destructor)\n"; - } else if (CFGBaseDtor BE = E.getAs()) { - const CXXBaseSpecifier *BS = BE.getBaseSpecifier(); + } else if (const CFGBaseDtor *BE = E.getAs()) { + const CXXBaseSpecifier *BS = BE->getBaseSpecifier(); OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; OS << " (Base object destructor)\n"; - } else if (CFGMemberDtor ME = E.getAs()) { - FieldDecl *FD = ME.getFieldDecl(); + } else if (const CFGMemberDtor *ME = E.getAs()) { + const FieldDecl *FD = ME->getFieldDecl(); const Type *T = FD->getType().getTypePtr(); if (const Type *ET = T->getArrayElementTypeNoTypeQual()) @@ -3113,8 +3419,8 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; OS << " (Member object destructor)\n"; - } else if (CFGTemporaryDtor TE = E.getAs()) { - CXXBindTemporaryExpr *BT = TE.getBindTemporaryExpr(); + } else if (const CFGTemporaryDtor *TE = E.getAs()) { + const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr(); OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()"; OS << " (Temporary object destructor)\n"; } @@ -3344,32 +3650,6 @@ Stmt* CFGBlock::getTerminatorCondition() { return E ? E->IgnoreParens() : NULL; } -bool CFGBlock::hasBinaryBranchTerminator() const { - const Stmt *Terminator = this->Terminator; - if (!Terminator) - return false; - - Expr* E = NULL; - - switch (Terminator->getStmtClass()) { - default: - return false; - - case Stmt::ForStmtClass: - case Stmt::WhileStmtClass: - case Stmt::DoStmtClass: - case Stmt::IfStmtClass: - case Stmt::ChooseExprClass: - case Stmt::BinaryConditionalOperatorClass: - case Stmt::ConditionalOperatorClass: - case Stmt::BinaryOperatorClass: - return true; - } - - return E ? E->IgnoreParens() : NULL; -} - - //===----------------------------------------------------------------------===// // CFG Graphviz Visualization //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp index 77865849014a..65cd0898573c 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp @@ -19,10 +19,10 @@ using namespace clang; -CFGReachabilityAnalysis::CFGReachabilityAnalysis(const CFG &cfg) +CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(const CFG &cfg) : analyzed(cfg.getNumBlockIDs(), false) {} -bool CFGReachabilityAnalysis::isReachable(const CFGBlock *Src, +bool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src, const CFGBlock *Dst) { const unsigned DstBlockID = Dst->getBlockID(); @@ -39,7 +39,7 @@ bool CFGReachabilityAnalysis::isReachable(const CFGBlock *Src, // Maps reachability to a common node by walking the predecessors of the // destination node. -void CFGReachabilityAnalysis::mapReachability(const CFGBlock *Dst) { +void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) { llvm::SmallVector worklist; llvm::BitVector visited(analyzed.size()); diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp index 3a030f9bdd1e..1fd5eedfeb86 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp @@ -50,11 +50,11 @@ static void Accumulate(SMap &SM, CFGBlock *B) { // First walk the block-level expressions. for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) { const CFGElement &CE = *I; - CFGStmt CS = CE.getAs(); - if (!CS.isValid()) + const CFGStmt *CS = CE.getAs(); + if (!CS) continue; - CFGBlock *&Entry = SM[CS]; + CFGBlock *&Entry = SM[CS->getStmt()]; // If 'Entry' is already initialized (e.g., a terminator was already), // skip. if (Entry) diff --git a/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp index 22b6c1aaf021..4c62f36e6c92 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp @@ -16,6 +16,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; using namespace ento; @@ -35,84 +36,27 @@ using llvm::StringRef; // not release it." // -static bool isWordEnd(char ch, char prev, char next) { - return ch == '\0' - || (islower(prev) && isupper(ch)) // xxxC - || (isupper(prev) && isupper(ch) && islower(next)) // XXCreate - || !isalpha(ch); -} - -static const char* parseWord(const char* s) { - char ch = *s, prev = '\0'; - assert(ch != '\0'); - char next = *(s+1); - while (!isWordEnd(ch, prev, next)) { - prev = ch; - ch = next; - next = *((++s)+1); - } - return s; -} - -cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S, - bool ignorePrefix) { - IdentifierInfo *II = S.getIdentifierInfoForSlot(0); - - if (!II) +cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S) { + switch (S.getMethodFamily()) { + case OMF_None: + case OMF_autorelease: + case OMF_dealloc: + case OMF_release: + case OMF_retain: + case OMF_retainCount: return NoConvention; - const char *s = II->getNameStart(); + case OMF_init: + return InitRule; - const char *orig = s; - // A method/function name may contain a prefix. We don't know it is there, - // however, until we encounter the first '_'. - while (*s != '\0') { - // Skip '_', numbers, ':', etc. - if (*s == '_' || !isalpha(*s)) { - ++s; - continue; - } - break; - } - - if (!ignorePrefix && s != orig) - return NoConvention; - - // Parse the first word, and look for specific keywords. - const char *wordEnd = parseWord(s); - assert(wordEnd > s); - unsigned len = wordEnd - s; - - switch (len) { - default: - return NoConvention; - case 3: - // Methods starting with 'new' follow the create rule. - return (memcmp(s, "new", 3) == 0) ? CreateRule : NoConvention; - case 4: - // Methods starting with 'copy' follow the create rule. - if (memcmp(s, "copy", 4) == 0) - return CreateRule; - // Methods starting with 'init' follow the init rule. - if (memcmp(s, "init", 4) == 0) - return InitRule; - return NoConvention; - case 5: - return (memcmp(s, "alloc", 5) == 0) ? CreateRule : NoConvention; - case 7: - // Methods starting with 'mutableCopy' follow the create rule. - if (memcmp(s, "mutable", 7) == 0) { - // Look at the next word to see if it is "Copy". - s = wordEnd; - if (*s != '\0') { - wordEnd = parseWord(s); - len = wordEnd - s; - if (len == 4 && memcmp(s, "Copy", 4) == 0) - return CreateRule; - } - } - return NoConvention; + case OMF_alloc: + case OMF_copy: + case OMF_mutableCopy: + case OMF_new: + return CreateRule; } + llvm_unreachable("unexpected naming convention"); + return NoConvention; } bool cocoa::isRefType(QualType RetTy, llvm::StringRef Prefix, diff --git a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp index ef5c0fbfbdcf..ce2690f45cae 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp @@ -397,8 +397,32 @@ bool PrintfSpecifier::fixType(QualType QT) { // Set length modifier switch (BT->getKind()) { - default: - // The rest of the conversions are either optional or for non-builtin types + case BuiltinType::Bool: + case BuiltinType::WChar_U: + case BuiltinType::WChar_S: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::UInt128: + case BuiltinType::Int128: + // Integral types which are non-trivial to correct. + return false; + + case BuiltinType::Void: + case BuiltinType::NullPtr: + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + case BuiltinType::Dependent: + case BuiltinType::Overload: + case BuiltinType::BoundMember: + case BuiltinType::UnknownAny: + // Misc other stuff which doesn't make sense here. + return false; + + case BuiltinType::UInt: + case BuiltinType::Int: + case BuiltinType::Float: + case BuiltinType::Double: LM.setKind(LengthModifier::None); break; @@ -414,8 +438,6 @@ bool PrintfSpecifier::fixType(QualType QT) { LM.setKind(LengthModifier::AsShort); break; - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: case BuiltinType::Long: case BuiltinType::ULong: LM.setKind(LengthModifier::AsLong); @@ -445,24 +467,19 @@ bool PrintfSpecifier::fixType(QualType QT) { else if (QT->isRealFloatingType()) { CS.setKind(ConversionSpecifier::fArg); } - else if (QT->isPointerType()) { - CS.setKind(ConversionSpecifier::pArg); - Precision.setHowSpecified(OptionalAmount::NotSpecified); - HasAlternativeForm = 0; - HasLeadingZeroes = 0; - HasPlusPrefix = 0; - } else if (QT->isSignedIntegerType()) { CS.setKind(ConversionSpecifier::dArg); HasAlternativeForm = 0; } else if (QT->isUnsignedIntegerType()) { - CS.setKind(ConversionSpecifier::uArg); + // Preserve the original formatting, e.g. 'X', 'o'. + if (!cast(CS).isUIntArg()) + CS.setKind(ConversionSpecifier::uArg); HasAlternativeForm = 0; HasPlusPrefix = 0; } else { - return false; + assert(0 && "Unexpected type"); } return true; diff --git a/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp b/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp index 7afa586479b3..9ac456f53a67 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp @@ -31,11 +31,11 @@ static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R1, R1 = R2 = SourceRange(); if (sn < b.size()) { - CFGStmt CS = b[sn].getAs(); + const CFGStmt *CS = b[sn].getAs(); if (!CS) return SourceLocation(); - S = CS.getStmt(); + S = CS->getStmt(); } else if (b.getTerminator()) S = b.getTerminator(); else @@ -49,7 +49,7 @@ static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R1, const BinaryOperator *BO = cast(S); if (BO->getOpcode() == BO_Comma) { if (sn+1 < b.size()) - return b[sn+1].getAs().getStmt()->getLocStart(); + return b[sn+1].getAs()->getStmt()->getLocStart(); const CFGBlock *n = &b; while (1) { if (n->getTerminator()) @@ -60,7 +60,7 @@ static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R1, if (n->pred_size() != 1) return SourceLocation(); if (!n->empty()) - return n[0][0].getAs().getStmt()->getLocStart(); + return n[0][0].getAs()->getStmt()->getLocStart(); } } R1 = BO->getLHS()->getSourceRange(); @@ -193,7 +193,7 @@ unsigned ScanReachableFromBlock(const CFGBlock &Start, unsigned count = 0; llvm::SmallVector WL; - // Prep work queue + // Prep work queue Reachable.set(Start.getBlockID()); ++count; WL.push_back(&Start); diff --git a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp index c08cbedf4b94..88a2db751a43 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp @@ -7,311 +7,723 @@ // //===----------------------------------------------------------------------===// // -// This file implements Uninitialized Values analysis for source-level CFGs. +// This file implements uninitialized values analysis for source-level CFGs. // //===----------------------------------------------------------------------===// -#include "clang/Analysis/Analyses/UninitializedValues.h" +#include +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/Decl.h" +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" -#include "clang/Analysis/AnalysisDiagnostic.h" -#include "clang/AST/ASTContext.h" -#include "clang/Analysis/FlowSensitive/DataflowSolver.h" - -#include "llvm/ADT/SmallPtrSet.h" +#include "clang/Analysis/Analyses/UninitializedValues.h" +#include "clang/Analysis/Support/SaveAndRestore.h" using namespace clang; -//===----------------------------------------------------------------------===// -// Dataflow initialization logic. -//===----------------------------------------------------------------------===// +static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) { + if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() && + !vd->isExceptionVariable() && + vd->getDeclContext() == dc) { + QualType ty = vd->getType(); + return ty->isScalarType() || ty->isVectorType(); + } + return false; +} + +//------------------------------------------------------------------------====// +// DeclToIndex: a mapping from Decls we track to value indices. +//====------------------------------------------------------------------------// namespace { - -class RegisterDecls - : public CFGRecStmtDeclVisitor { - - UninitializedValues::AnalysisDataTy& AD; +class DeclToIndex { + llvm::DenseMap map; public: - RegisterDecls(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {} + DeclToIndex() {} + + /// Compute the actual mapping from declarations to bits. + void computeMap(const DeclContext &dc); + + /// Return the number of declarations in the map. + unsigned size() const { return map.size(); } + + /// Returns the bit vector index for a given declaration. + llvm::Optional getValueIndex(const VarDecl *d) const; +}; +} - void VisitVarDecl(VarDecl* VD) { AD.Register(VD); } - CFG& getCFG() { return AD.getCFG(); } +void DeclToIndex::computeMap(const DeclContext &dc) { + unsigned count = 0; + DeclContext::specific_decl_iterator I(dc.decls_begin()), + E(dc.decls_end()); + for ( ; I != E; ++I) { + const VarDecl *vd = *I; + if (isTrackedVar(vd, &dc)) + map[vd] = count++; + } +} + +llvm::Optional DeclToIndex::getValueIndex(const VarDecl *d) const { + llvm::DenseMap::const_iterator I = map.find(d); + if (I == map.end()) + return llvm::Optional(); + return I->second; +} + +//------------------------------------------------------------------------====// +// CFGBlockValues: dataflow values for CFG blocks. +//====------------------------------------------------------------------------// + +// These values are defined in such a way that a merge can be done using +// a bitwise OR. +enum Value { Unknown = 0x0, /* 00 */ + Initialized = 0x1, /* 01 */ + Uninitialized = 0x2, /* 10 */ + MayUninitialized = 0x3 /* 11 */ }; + +static bool isUninitialized(const Value v) { + return v >= Uninitialized; +} +static bool isAlwaysUninit(const Value v) { + return v == Uninitialized; +} + +namespace { +class ValueVector { + llvm::BitVector vec; +public: + ValueVector() {} + ValueVector(unsigned size) : vec(size << 1) {} + void resize(unsigned n) { vec.resize(n << 1); } + void merge(const ValueVector &rhs) { vec |= rhs.vec; } + bool operator!=(const ValueVector &rhs) const { return vec != rhs.vec; } + void reset() { vec.reset(); } + + class reference { + ValueVector &vv; + const unsigned idx; + + reference(); // Undefined + public: + reference(ValueVector &vv, unsigned idx) : vv(vv), idx(idx) {} + ~reference() {} + + reference &operator=(Value v) { + vv.vec[idx << 1] = (((unsigned) v) & 0x1) ? true : false; + vv.vec[(idx << 1) | 1] = (((unsigned) v) & 0x2) ? true : false; + return *this; + } + operator Value() { + unsigned x = (vv.vec[idx << 1] ? 1 : 0) | (vv.vec[(idx << 1) | 1] ? 2 :0); + return (Value) x; + } + }; + + reference operator[](unsigned idx) { return reference(*this, idx); } }; +typedef std::pair BVPair; + +class CFGBlockValues { + const CFG &cfg; + BVPair *vals; + ValueVector scratch; + DeclToIndex declToIndex; + + ValueVector &lazyCreate(ValueVector *&bv); +public: + CFGBlockValues(const CFG &cfg); + ~CFGBlockValues(); + + unsigned getNumEntries() const { return declToIndex.size(); } + + void computeSetOfDeclarations(const DeclContext &dc); + ValueVector &getValueVector(const CFGBlock *block, + const CFGBlock *dstBlock); + + BVPair &getValueVectors(const CFGBlock *block, bool shouldLazyCreate); + + void mergeIntoScratch(ValueVector const &source, bool isFirst); + bool updateValueVectorWithScratch(const CFGBlock *block); + bool updateValueVectors(const CFGBlock *block, const BVPair &newVals); + + bool hasNoDeclarations() const { + return declToIndex.size() == 0; + } + + bool hasEntry(const VarDecl *vd) const { + return declToIndex.getValueIndex(vd).hasValue(); + } + + bool hasValues(const CFGBlock *block); + + void resetScratch(); + ValueVector &getScratch() { return scratch; } + + ValueVector::reference operator[](const VarDecl *vd); +}; } // end anonymous namespace -void UninitializedValues::InitializeValues(const CFG& cfg) { - RegisterDecls R(getAnalysisData()); - cfg.VisitBlockStmts(R); +CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) { + unsigned n = cfg.getNumBlockIDs(); + if (!n) + return; + vals = new std::pair[n]; + memset((void*)vals, 0, sizeof(*vals) * n); } -//===----------------------------------------------------------------------===// -// Transfer functions. -//===----------------------------------------------------------------------===// +CFGBlockValues::~CFGBlockValues() { + unsigned n = cfg.getNumBlockIDs(); + if (n == 0) + return; + for (unsigned i = 0; i < n; ++i) { + delete vals[i].first; + delete vals[i].second; + } + delete [] vals; +} + +void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) { + declToIndex.computeMap(dc); + scratch.resize(declToIndex.size()); +} + +ValueVector &CFGBlockValues::lazyCreate(ValueVector *&bv) { + if (!bv) + bv = new ValueVector(declToIndex.size()); + return *bv; +} + +/// This function pattern matches for a '&&' or '||' that appears at +/// the beginning of a CFGBlock that also (1) has a terminator and +/// (2) has no other elements. If such an expression is found, it is returned. +static BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) { + if (block->empty()) + return 0; + + const CFGStmt *cstmt = block->front().getAs(); + if (!cstmt) + return 0; + + BinaryOperator *b = llvm::dyn_cast_or_null(cstmt->getStmt()); + + if (!b || !b->isLogicalOp()) + return 0; + + if (block->pred_size() == 2 && + ((block->succ_size() == 2 && block->getTerminatorCondition() == b) || + block->size() == 1)) + return b; + + return 0; +} + +ValueVector &CFGBlockValues::getValueVector(const CFGBlock *block, + const CFGBlock *dstBlock) { + unsigned idx = block->getBlockID(); + if (dstBlock && getLogicalOperatorInChain(block)) { + if (*block->succ_begin() == dstBlock) + return lazyCreate(vals[idx].first); + assert(*(block->succ_begin()+1) == dstBlock); + return lazyCreate(vals[idx].second); + } + + assert(vals[idx].second == 0); + return lazyCreate(vals[idx].first); +} + +bool CFGBlockValues::hasValues(const CFGBlock *block) { + unsigned idx = block->getBlockID(); + return vals[idx].second != 0; +} + +BVPair &CFGBlockValues::getValueVectors(const clang::CFGBlock *block, + bool shouldLazyCreate) { + unsigned idx = block->getBlockID(); + lazyCreate(vals[idx].first); + if (shouldLazyCreate) + lazyCreate(vals[idx].second); + return vals[idx]; +} + +void CFGBlockValues::mergeIntoScratch(ValueVector const &source, + bool isFirst) { + if (isFirst) + scratch = source; + else + scratch.merge(source); +} +#if 0 +static void printVector(const CFGBlock *block, ValueVector &bv, + unsigned num) { + + llvm::errs() << block->getBlockID() << " :"; + for (unsigned i = 0; i < bv.size(); ++i) { + llvm::errs() << ' ' << bv[i]; + } + llvm::errs() << " : " << num << '\n'; +} +#endif + +bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) { + ValueVector &dst = getValueVector(block, 0); + bool changed = (dst != scratch); + if (changed) + dst = scratch; +#if 0 + printVector(block, scratch, 0); +#endif + return changed; +} + +bool CFGBlockValues::updateValueVectors(const CFGBlock *block, + const BVPair &newVals) { + BVPair &vals = getValueVectors(block, true); + bool changed = *newVals.first != *vals.first || + *newVals.second != *vals.second; + *vals.first = *newVals.first; + *vals.second = *newVals.second; +#if 0 + printVector(block, *vals.first, 1); + printVector(block, *vals.second, 2); +#endif + return changed; +} + +void CFGBlockValues::resetScratch() { + scratch.reset(); +} + +ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) { + const llvm::Optional &idx = declToIndex.getValueIndex(vd); + assert(idx.hasValue()); + return scratch[idx.getValue()]; +} + +//------------------------------------------------------------------------====// +// Worklist: worklist for dataflow analysis. +//====------------------------------------------------------------------------// namespace { -class TransferFuncs - : public CFGStmtVisitor { - - UninitializedValues::ValTy V; - UninitializedValues::AnalysisDataTy& AD; +class DataflowWorklist { + llvm::SmallVector worklist; + llvm::BitVector enqueuedBlocks; public: - TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {} - - UninitializedValues::ValTy& getVal() { return V; } - CFG& getCFG() { return AD.getCFG(); } - - void SetTopValue(UninitializedValues::ValTy& X) { - X.setDeclValues(AD); - X.resetBlkExprValues(AD); - } - - bool VisitDeclRefExpr(DeclRefExpr* DR); - bool VisitBinaryOperator(BinaryOperator* B); - bool VisitUnaryOperator(UnaryOperator* U); - bool VisitStmt(Stmt* S); - bool VisitCallExpr(CallExpr* C); - bool VisitDeclStmt(DeclStmt* D); - bool VisitAbstractConditionalOperator(AbstractConditionalOperator* C); - bool BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S); - - bool Visit(Stmt *S); - bool BlockStmt_VisitExpr(Expr* E); - - void VisitTerminator(CFGBlock* B) { } - - void setCurrentBlock(const CFGBlock *block) {} + DataflowWorklist(const CFG &cfg) : enqueuedBlocks(cfg.getNumBlockIDs()) {} + + void enqueue(const CFGBlock *block); + void enqueueSuccessors(const CFGBlock *block); + const CFGBlock *dequeue(); + }; +} -static const bool Initialized = false; -static const bool Uninitialized = true; +void DataflowWorklist::enqueue(const CFGBlock *block) { + if (!block) + return; + unsigned idx = block->getBlockID(); + if (enqueuedBlocks[idx]) + return; + worklist.push_back(block); + enqueuedBlocks[idx] = true; +} -bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) { +void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) { + for (CFGBlock::const_succ_iterator I = block->succ_begin(), + E = block->succ_end(); I != E; ++I) { + enqueue(*I); + } +} - if (VarDecl* VD = dyn_cast(DR->getDecl())) - if (VD->isLocalVarDecl()) { +const CFGBlock *DataflowWorklist::dequeue() { + if (worklist.empty()) + return 0; + const CFGBlock *b = worklist.back(); + worklist.pop_back(); + enqueuedBlocks[b->getBlockID()] = false; + return b; +} - if (AD.Observer) - AD.Observer->ObserveDeclRefExpr(V, AD, DR, VD); +//------------------------------------------------------------------------====// +// Transfer function for uninitialized values analysis. +//====------------------------------------------------------------------------// - // Pseudo-hack to prevent cascade of warnings. If an accessed variable - // is uninitialized, then we are already going to flag a warning for - // this variable, which a "source" of uninitialized values. - // We can otherwise do a full "taint" of uninitialized values. The - // client has both options by toggling AD.FullUninitTaint. +namespace { +class FindVarResult { + const VarDecl *vd; + const DeclRefExpr *dr; +public: + FindVarResult(VarDecl *vd, DeclRefExpr *dr) : vd(vd), dr(dr) {} + + const DeclRefExpr *getDeclRefExpr() const { return dr; } + const VarDecl *getDecl() const { return vd; } +}; + +class TransferFunctions : public CFGRecStmtVisitor { + CFGBlockValues &vals; + const CFG &cfg; + AnalysisContext ∾ + UninitVariablesHandler *handler; + const DeclRefExpr *currentDR; + const Expr *currentVoidCast; + const bool flagBlockUses; +public: + TransferFunctions(CFGBlockValues &vals, const CFG &cfg, + AnalysisContext &ac, + UninitVariablesHandler *handler, + bool flagBlockUses) + : vals(vals), cfg(cfg), ac(ac), handler(handler), currentDR(0), + currentVoidCast(0), flagBlockUses(flagBlockUses) {} + + const CFG &getCFG() { return cfg; } + void reportUninit(const DeclRefExpr *ex, const VarDecl *vd, + bool isAlwaysUninit); - if (AD.FullUninitTaint) - return V(VD,AD); + void VisitBlockExpr(BlockExpr *be); + void VisitDeclStmt(DeclStmt *ds); + void VisitDeclRefExpr(DeclRefExpr *dr); + void VisitUnaryOperator(UnaryOperator *uo); + void VisitBinaryOperator(BinaryOperator *bo); + void VisitCastExpr(CastExpr *ce); + void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *se); + void VisitCXXTypeidExpr(CXXTypeidExpr *E); + void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt *fs); + + bool isTrackedVar(const VarDecl *vd) { + return ::isTrackedVar(vd, cast(ac.getDecl())); + } + + FindVarResult findBlockVarDecl(Expr *ex); +}; +} + +void TransferFunctions::reportUninit(const DeclRefExpr *ex, + const VarDecl *vd, bool isAlwaysUnit) { + if (handler) handler->handleUseOfUninitVariable(ex, vd, isAlwaysUnit); +} + +FindVarResult TransferFunctions::findBlockVarDecl(Expr* ex) { + if (DeclRefExpr* dr = dyn_cast(ex->IgnoreParenCasts())) + if (VarDecl *vd = dyn_cast(dr->getDecl())) + if (isTrackedVar(vd)) + return FindVarResult(vd, dr); + return FindVarResult(0, 0); +} + +void TransferFunctions::BlockStmt_VisitObjCForCollectionStmt( + ObjCForCollectionStmt *fs) { + + Visit(fs->getCollection()); + + // This represents an initialization of the 'element' value. + Stmt *element = fs->getElement(); + const VarDecl* vd = 0; + + if (DeclStmt* ds = dyn_cast(element)) { + vd = cast(ds->getSingleDecl()); + if (!isTrackedVar(vd)) + vd = 0; + } + else { + // Initialize the value of the reference variable. + const FindVarResult &res = findBlockVarDecl(cast(element)); + vd = res.getDecl(); + if (!vd) { + Visit(element); + return; } - - return Initialized; + } + + if (vd) + vals[vd] = Initialized; } -static VarDecl* FindBlockVarDecl(Expr* E) { - - // Blast through casts and parentheses to find any DeclRefExprs that - // refer to a block VarDecl. - - if (DeclRefExpr* DR = dyn_cast(E->IgnoreParenCasts())) - if (VarDecl* VD = dyn_cast(DR->getDecl())) - if (VD->isLocalVarDecl()) return VD; - - return NULL; -} - -bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) { - - if (VarDecl* VD = FindBlockVarDecl(B->getLHS())) - if (B->isAssignmentOp()) { - if (B->getOpcode() == BO_Assign) - return V(VD,AD) = Visit(B->getRHS()); - else // Handle +=, -=, *=, etc. We do want '&', not '&&'. - return V(VD,AD) = Visit(B->getLHS()) & Visit(B->getRHS()); +void TransferFunctions::VisitBlockExpr(BlockExpr *be) { + if (!flagBlockUses || !handler) + return; + const BlockDecl *bd = be->getBlockDecl(); + for (BlockDecl::capture_const_iterator i = bd->capture_begin(), + e = bd->capture_end() ; i != e; ++i) { + const VarDecl *vd = i->getVariable(); + if (!vd->hasLocalStorage()) + continue; + if (!isTrackedVar(vd)) + continue; + if (i->isByRef()) { + vals[vd] = Initialized; + continue; } - - return VisitStmt(B); + Value v = vals[vd]; + if (isUninitialized(v)) + handler->handleUseOfUninitVariable(be, vd, isAlwaysUninit(v)); + } } -bool TransferFuncs::VisitDeclStmt(DeclStmt* S) { - for (DeclStmt::decl_iterator I=S->decl_begin(), E=S->decl_end(); I!=E; ++I) { - VarDecl *VD = dyn_cast(*I); - if (VD && VD->isLocalVarDecl()) { - if (Stmt* I = VD->getInit()) { - // Visit the subexpression to check for uses of uninitialized values, - // even if we don't propagate that value. - bool isSubExprUninit = Visit(I); - V(VD,AD) = AD.FullUninitTaint ? isSubExprUninit : Initialized; - } - else { - // Special case for declarations of array types. For things like: - // - // char x[10]; - // - // we should treat "x" as being initialized, because the variable - // "x" really refers to the memory block. Clearly x[1] is - // uninitialized, but expressions like "(char *) x" really do refer to - // an initialized value. This simple dataflow analysis does not reason - // about the contents of arrays, although it could be potentially - // extended to do so if the array were of constant size. - if (VD->getType()->isArrayType()) - V(VD,AD) = Initialized; - else - V(VD,AD) = Uninitialized; +void TransferFunctions::VisitDeclStmt(DeclStmt *ds) { + for (DeclStmt::decl_iterator DI = ds->decl_begin(), DE = ds->decl_end(); + DI != DE; ++DI) { + if (VarDecl *vd = dyn_cast(*DI)) { + if (isTrackedVar(vd)) { + if (Expr *init = vd->getInit()) { + Visit(init); + + // If the initializer consists solely of a reference to itself, we + // explicitly mark the variable as uninitialized. This allows code + // like the following: + // + // int x = x; + // + // to deliberately leave a variable uninitialized. Different analysis + // clients can detect this pattern and adjust their reporting + // appropriately, but we need to continue to analyze subsequent uses + // of the variable. + DeclRefExpr *DRE = dyn_cast(init->IgnoreParenImpCasts()); + vals[vd] = (DRE && DRE->getDecl() == vd) ? Uninitialized + : Initialized; + } + } else if (Stmt *init = vd->getInit()) { + Visit(init); } } } - return Uninitialized; // Value is never consumed. } -bool TransferFuncs::VisitCallExpr(CallExpr* C) { - VisitChildren(C); - return Initialized; +void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) { + // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast + // cannot be block-level expressions. Therefore, we determine if + // a DeclRefExpr is involved in a "load" by comparing it to the current + // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr. + // If a DeclRefExpr is not involved in a load, we are essentially computing + // its address, either for assignment to a reference or via the '&' operator. + // In such cases, treat the variable as being initialized, since this + // analysis isn't powerful enough to do alias tracking. + if (dr != currentDR) + if (const VarDecl *vd = dyn_cast(dr->getDecl())) + if (isTrackedVar(vd)) + vals[vd] = Initialized; } -bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) { - switch (U->getOpcode()) { - case UO_AddrOf: { - VarDecl* VD = FindBlockVarDecl(U->getSubExpr()); - if (VD && VD->isLocalVarDecl()) - return V(VD,AD) = Initialized; +void TransferFunctions::VisitBinaryOperator(clang::BinaryOperator *bo) { + if (bo->isAssignmentOp()) { + const FindVarResult &res = findBlockVarDecl(bo->getLHS()); + if (const VarDecl* vd = res.getDecl()) { + // We assume that DeclRefExprs wrapped in a BinaryOperator "assignment" + // cannot be block-level expressions. Therefore, we determine if + // a DeclRefExpr is involved in a "load" by comparing it to the current + // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr. + SaveAndRestore lastDR(currentDR, + res.getDeclRefExpr()); + Visit(bo->getRHS()); + Visit(bo->getLHS()); + + ValueVector::reference val = vals[vd]; + if (isUninitialized(val)) { + if (bo->getOpcode() != BO_Assign) + reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val)); + val = Initialized; + } + return; + } + } + Visit(bo->getRHS()); + Visit(bo->getLHS()); +} + +void TransferFunctions::VisitUnaryOperator(clang::UnaryOperator *uo) { + switch (uo->getOpcode()) { + case clang::UO_PostDec: + case clang::UO_PostInc: + case clang::UO_PreDec: + case clang::UO_PreInc: { + const FindVarResult &res = findBlockVarDecl(uo->getSubExpr()); + if (const VarDecl *vd = res.getDecl()) { + // We assume that DeclRefExprs wrapped in a unary operator ++/-- + // cannot be block-level expressions. Therefore, we determine if + // a DeclRefExpr is involved in a "load" by comparing it to the current + // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr. + SaveAndRestore lastDR(currentDR, + res.getDeclRefExpr()); + Visit(uo->getSubExpr()); + + ValueVector::reference val = vals[vd]; + if (isUninitialized(val)) { + reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val)); + // Don't cascade warnings. + val = Initialized; + } + return; + } break; } - default: break; } - - return Visit(U->getSubExpr()); + Visit(uo->getSubExpr()); } -bool -TransferFuncs::BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { - // This represents a use of the 'collection' - bool x = Visit(S->getCollection()); +void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) { + if (ce->getCastKind() == CK_LValueToRValue) { + const FindVarResult &res = findBlockVarDecl(ce->getSubExpr()); + if (const VarDecl *vd = res.getDecl()) { + // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast + // cannot be block-level expressions. Therefore, we determine if + // a DeclRefExpr is involved in a "load" by comparing it to the current + // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr. + // Here we update 'currentDR' to be the one associated with this + // lvalue-to-rvalue cast. Then, when we analyze the DeclRefExpr, we + // will know that we are not computing its lvalue for other purposes + // than to perform a load. + SaveAndRestore lastDR(currentDR, + res.getDeclRefExpr()); + Visit(ce->getSubExpr()); + if (currentVoidCast != ce) { + Value val = vals[vd]; + if (isUninitialized(val)) { + reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val)); + // Don't cascade warnings. + vals[vd] = Initialized; + } + } + return; + } + } + else if (CStyleCastExpr *cse = dyn_cast(ce)) { + if (cse->getType()->isVoidType()) { + // e.g. (void) x; + SaveAndRestore + lastVoidCast(currentVoidCast, cse->getSubExpr()->IgnoreParens()); + Visit(cse->getSubExpr()); + return; + } + } + Visit(ce->getSubExpr()); +} - if (x == Uninitialized) - return Uninitialized; +void TransferFunctions::VisitUnaryExprOrTypeTraitExpr( + UnaryExprOrTypeTraitExpr *se) { + if (se->getKind() == UETT_SizeOf) { + if (se->getType()->isConstantSizeType()) + return; + // Handle VLAs. + Visit(se->getArgumentExpr()); + } +} - // This represents an initialization of the 'element' value. - Stmt* Element = S->getElement(); - VarDecl* VD = 0; +void TransferFunctions::VisitCXXTypeidExpr(CXXTypeidExpr *E) { + // typeid(expression) is potentially evaluated when the argument is + // a glvalue of polymorphic type. (C++ 5.2.8p2-3) + if (!E->isTypeOperand() && E->Classify(ac.getASTContext()).isGLValue()) { + QualType SubExprTy = E->getExprOperand()->getType(); + if (const RecordType *Record = SubExprTy->getAs()) + if (cast(Record->getDecl())->isPolymorphic()) + Visit(E->getExprOperand()); + } +} - if (DeclStmt* DS = dyn_cast(Element)) - VD = cast(DS->getSingleDecl()); - else { - Expr* ElemExpr = cast(Element)->IgnoreParens(); +//------------------------------------------------------------------------====// +// High-level "driver" logic for uninitialized values analysis. +//====------------------------------------------------------------------------// - // Initialize the value of the reference variable. - if (DeclRefExpr* DR = dyn_cast(ElemExpr)) - VD = cast(DR->getDecl()); - else - return Visit(ElemExpr); +static bool runOnBlock(const CFGBlock *block, const CFG &cfg, + AnalysisContext &ac, CFGBlockValues &vals, + llvm::BitVector &wasAnalyzed, + UninitVariablesHandler *handler = 0, + bool flagBlockUses = false) { + + wasAnalyzed[block->getBlockID()] = true; + + if (const BinaryOperator *b = getLogicalOperatorInChain(block)) { + CFGBlock::const_pred_iterator itr = block->pred_begin(); + BVPair vA = vals.getValueVectors(*itr, false); + ++itr; + BVPair vB = vals.getValueVectors(*itr, false); + + BVPair valsAB; + + if (b->getOpcode() == BO_LAnd) { + // Merge the 'F' bits from the first and second. + vals.mergeIntoScratch(*(vA.second ? vA.second : vA.first), true); + vals.mergeIntoScratch(*(vB.second ? vB.second : vB.first), false); + valsAB.first = vA.first; + valsAB.second = &vals.getScratch(); + } + else { + // Merge the 'T' bits from the first and second. + assert(b->getOpcode() == BO_LOr); + vals.mergeIntoScratch(*vA.first, true); + vals.mergeIntoScratch(*vB.first, false); + valsAB.first = &vals.getScratch(); + valsAB.second = vA.second ? vA.second : vA.first; + } + return vals.updateValueVectors(block, valsAB); } - V(VD,AD) = Initialized; - return Initialized; -} - - -bool TransferFuncs:: -VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { - Visit(C->getCond()); - - bool rhsResult = Visit(C->getFalseExpr()); - // Handle the GNU extension for missing LHS. - if (isa(C)) - return Visit(C->getTrueExpr()) & rhsResult; // Yes: we want &, not &&. - else - return rhsResult; -} - -bool TransferFuncs::VisitStmt(Stmt* S) { - bool x = Initialized; - - // We don't stop at the first subexpression that is Uninitialized because - // evaluating some subexpressions may result in propogating "Uninitialized" - // or "Initialized" to variables referenced in the other subexpressions. - for (Stmt::child_range I = S->children(); I; ++I) - if (*I && Visit(*I) == Uninitialized) x = Uninitialized; - - return x; -} - -bool TransferFuncs::Visit(Stmt *S) { - if (AD.isTracked(static_cast(S))) return V(static_cast(S),AD); - else return static_cast*>(this)->Visit(S); -} - -bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) { - bool x = static_cast*>(this)->Visit(E); - if (AD.isTracked(E)) V(E,AD) = x; - return x; -} - -} // end anonymous namespace - -//===----------------------------------------------------------------------===// -// Merge operator. -// -// In our transfer functions we take the approach that any -// combination of uninitialized values, e.g. -// Uninitialized + ___ = Uninitialized. -// -// Merges take the same approach, preferring soundness. At a confluence point, -// if any predecessor has a variable marked uninitialized, the value is -// uninitialized at the confluence point. -//===----------------------------------------------------------------------===// - -namespace { - typedef StmtDeclBitVector_Types::Union Merge; - typedef DataflowSolver Solver; -} - -//===----------------------------------------------------------------------===// -// Uninitialized values checker. Scan an AST and flag variable uses -//===----------------------------------------------------------------------===// - -UninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {} - -namespace { -class UninitializedValuesChecker - : public UninitializedValues::ObserverTy { - - ASTContext &Ctx; - Diagnostic &Diags; - llvm::SmallPtrSet AlreadyWarned; - -public: - UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags) - : Ctx(ctx), Diags(diags) {} - - virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V, - UninitializedValues::AnalysisDataTy& AD, - DeclRefExpr* DR, VarDecl* VD) { - - assert ( AD.isTracked(VD) && "Unknown VarDecl."); - - if (V(VD,AD) == Uninitialized) - if (AlreadyWarned.insert(VD)) - Diags.Report(Ctx.getFullLoc(DR->getSourceRange().getBegin()), - diag::warn_uninit_val); + // Default behavior: merge in values of predecessor blocks. + vals.resetScratch(); + bool isFirst = true; + for (CFGBlock::const_pred_iterator I = block->pred_begin(), + E = block->pred_end(); I != E; ++I) { + vals.mergeIntoScratch(vals.getValueVector(*I, block), isFirst); + isFirst = false; } -}; -} // end anonymous namespace - -namespace clang { -void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags, - bool FullUninitTaint) { - - // Compute the uninitialized values information. - UninitializedValues U(cfg); - U.getAnalysisData().FullUninitTaint = FullUninitTaint; - Solver S(U); - S.runOnCFG(cfg); - - // Scan for DeclRefExprs that use uninitialized values. - UninitializedValuesChecker Observer(Ctx,Diags); - U.getAnalysisData().Observer = &Observer; - S.runOnAllBlocks(cfg); + // Apply the transfer function. + TransferFunctions tf(vals, cfg, ac, handler, flagBlockUses); + for (CFGBlock::const_iterator I = block->begin(), E = block->end(); + I != E; ++I) { + if (const CFGStmt *cs = dyn_cast(&*I)) { + tf.BlockStmt_Visit(cs->getStmt()); + } + } + return vals.updateValueVectorWithScratch(block); } -} // end namespace clang + +void clang::runUninitializedVariablesAnalysis(const DeclContext &dc, + const CFG &cfg, + AnalysisContext &ac, + UninitVariablesHandler &handler) { + CFGBlockValues vals(cfg); + vals.computeSetOfDeclarations(dc); + if (vals.hasNoDeclarations()) + return; + + // Mark all variables uninitialized at the entry. + const CFGBlock &entry = cfg.getEntry(); + for (CFGBlock::const_succ_iterator i = entry.succ_begin(), + e = entry.succ_end(); i != e; ++i) { + if (const CFGBlock *succ = *i) { + ValueVector &vec = vals.getValueVector(&entry, succ); + const unsigned n = vals.getNumEntries(); + for (unsigned j = 0; j < n ; ++j) { + vec[j] = Uninitialized; + } + } + } + + // Proceed with the workist. + DataflowWorklist worklist(cfg); + llvm::BitVector previouslyVisited(cfg.getNumBlockIDs()); + worklist.enqueueSuccessors(&cfg.getEntry()); + llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false); + + while (const CFGBlock *block = worklist.dequeue()) { + // Did the block change? + bool changed = runOnBlock(block, cfg, ac, vals, wasAnalyzed); + if (changed || !previouslyVisited[block->getBlockID()]) + worklist.enqueueSuccessors(block); + previouslyVisited[block->getBlockID()] = true; + } + + // Run through the blocks one more time, and report uninitialized variabes. + for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { + if (wasAnalyzed[(*BI)->getBlockID()]) + runOnBlock(*BI, cfg, ac, vals, wasAnalyzed, &handler, + /* flagBlockUses */ true); + } +} + +UninitVariablesHandler::~UninitVariablesHandler() {} + diff --git a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValuesV2.cpp b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValuesV2.cpp deleted file mode 100644 index 75eccbf7a3c8..000000000000 --- a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValuesV2.cpp +++ /dev/null @@ -1,610 +0,0 @@ -//==- UninitializedValuesV2.cpp - Find Uninitialized Values -----*- 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 uninitialized values analysis for source-level CFGs. -// -//===----------------------------------------------------------------------===// - -#include -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "clang/AST/Decl.h" -#include "clang/Analysis/CFG.h" -#include "clang/Analysis/AnalysisContext.h" -#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" -#include "clang/Analysis/Analyses/UninitializedValuesV2.h" -#include "clang/Analysis/Support/SaveAndRestore.h" - -using namespace clang; - -static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) { - return vd->isLocalVarDecl() && !vd->hasGlobalStorage() && - vd->getType()->isScalarType() && - vd->getDeclContext() == dc; -} - -//------------------------------------------------------------------------====// -// DeclToBit: a mapping from Decls we track to bitvector indices. -//====------------------------------------------------------------------------// - -namespace { -class DeclToBit { - llvm::DenseMap map; -public: - DeclToBit() {} - - /// Compute the actual mapping from declarations to bits. - void computeMap(const DeclContext &dc); - - /// Return the number of declarations in the map. - unsigned size() const { return map.size(); } - - /// Returns the bit vector index for a given declaration. - llvm::Optional getBitVectorIndex(const VarDecl *d); -}; -} - -void DeclToBit::computeMap(const DeclContext &dc) { - unsigned count = 0; - DeclContext::specific_decl_iterator I(dc.decls_begin()), - E(dc.decls_end()); - for ( ; I != E; ++I) { - const VarDecl *vd = *I; - if (isTrackedVar(vd, &dc)) - map[vd] = count++; - } -} - -llvm::Optional DeclToBit::getBitVectorIndex(const VarDecl *d) { - llvm::DenseMap::iterator I = map.find(d); - if (I == map.end()) - return llvm::Optional(); - return I->second; -} - -//------------------------------------------------------------------------====// -// CFGBlockValues: dataflow values for CFG blocks. -//====------------------------------------------------------------------------// - -typedef std::pair BVPair; - -namespace { -class CFGBlockValues { - const CFG &cfg; - BVPair *vals; - llvm::BitVector scratch; - DeclToBit declToBit; - - llvm::BitVector &lazyCreate(llvm::BitVector *&bv); -public: - CFGBlockValues(const CFG &cfg); - ~CFGBlockValues(); - - void computeSetOfDeclarations(const DeclContext &dc); - llvm::BitVector &getBitVector(const CFGBlock *block, - const CFGBlock *dstBlock); - - BVPair &getBitVectors(const CFGBlock *block, bool shouldLazyCreate); - - void mergeIntoScratch(llvm::BitVector const &source, bool isFirst); - bool updateBitVectorWithScratch(const CFGBlock *block); - bool updateBitVectors(const CFGBlock *block, const BVPair &newVals); - - bool hasNoDeclarations() const { - return declToBit.size() == 0; - } - - void resetScratch(); - llvm::BitVector &getScratch() { return scratch; } - - llvm::BitVector::reference operator[](const VarDecl *vd); -}; -} - -CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) { - unsigned n = cfg.getNumBlockIDs(); - if (!n) - return; - vals = new std::pair[n]; - memset(vals, 0, sizeof(*vals) * n); -} - -CFGBlockValues::~CFGBlockValues() { - unsigned n = cfg.getNumBlockIDs(); - if (n == 0) - return; - for (unsigned i = 0; i < n; ++i) { - delete vals[i].first; - delete vals[i].second; - } - delete [] vals; -} - -void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) { - declToBit.computeMap(dc); - scratch.resize(declToBit.size()); -} - -llvm::BitVector &CFGBlockValues::lazyCreate(llvm::BitVector *&bv) { - if (!bv) - bv = new llvm::BitVector(declToBit.size()); - return *bv; -} - -/// This function pattern matches for a '&&' or '||' that appears at -/// the beginning of a CFGBlock that also (1) has a terminator and -/// (2) has no other elements. If such an expression is found, it is returned. -static BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) { - if (block->empty()) - return 0; - - CFGStmt cstmt = block->front().getAs(); - BinaryOperator *b = llvm::dyn_cast_or_null(cstmt.getStmt()); - - if (!b || !b->isLogicalOp()) - return 0; - - if (block->pred_size() == 2 && - ((block->succ_size() == 2 && block->getTerminatorCondition() == b) || - block->size() == 1)) - return b; - - return 0; -} - -llvm::BitVector &CFGBlockValues::getBitVector(const CFGBlock *block, - const CFGBlock *dstBlock) { - unsigned idx = block->getBlockID(); - if (dstBlock && getLogicalOperatorInChain(block)) { - if (*block->succ_begin() == dstBlock) - return lazyCreate(vals[idx].first); - assert(*(block->succ_begin()+1) == dstBlock); - return lazyCreate(vals[idx].second); - } - - assert(vals[idx].second == 0); - return lazyCreate(vals[idx].first); -} - -BVPair &CFGBlockValues::getBitVectors(const clang::CFGBlock *block, - bool shouldLazyCreate) { - unsigned idx = block->getBlockID(); - lazyCreate(vals[idx].first); - if (shouldLazyCreate) - lazyCreate(vals[idx].second); - return vals[idx]; -} - -void CFGBlockValues::mergeIntoScratch(llvm::BitVector const &source, - bool isFirst) { - if (isFirst) - scratch = source; - else - scratch |= source; -} -#if 0 -static void printVector(const CFGBlock *block, llvm::BitVector &bv, - unsigned num) { - - llvm::errs() << block->getBlockID() << " :"; - for (unsigned i = 0; i < bv.size(); ++i) { - llvm::errs() << ' ' << bv[i]; - } - llvm::errs() << " : " << num << '\n'; -} -#endif - -bool CFGBlockValues::updateBitVectorWithScratch(const CFGBlock *block) { - llvm::BitVector &dst = getBitVector(block, 0); - bool changed = (dst != scratch); - if (changed) - dst = scratch; -#if 0 - printVector(block, scratch, 0); -#endif - return changed; -} - -bool CFGBlockValues::updateBitVectors(const CFGBlock *block, - const BVPair &newVals) { - BVPair &vals = getBitVectors(block, true); - bool changed = *newVals.first != *vals.first || - *newVals.second != *vals.second; - *vals.first = *newVals.first; - *vals.second = *newVals.second; -#if 0 - printVector(block, *vals.first, 1); - printVector(block, *vals.second, 2); -#endif - return changed; -} - -void CFGBlockValues::resetScratch() { - scratch.reset(); -} - -llvm::BitVector::reference CFGBlockValues::operator[](const VarDecl *vd) { - const llvm::Optional &idx = declToBit.getBitVectorIndex(vd); - assert(idx.hasValue()); - return scratch[idx.getValue()]; -} - -//------------------------------------------------------------------------====// -// Worklist: worklist for dataflow analysis. -//====------------------------------------------------------------------------// - -namespace { -class DataflowWorklist { - llvm::SmallVector worklist; - llvm::BitVector enqueuedBlocks; -public: - DataflowWorklist(const CFG &cfg) : enqueuedBlocks(cfg.getNumBlockIDs()) {} - - void enqueue(const CFGBlock *block); - void enqueueSuccessors(const CFGBlock *block); - const CFGBlock *dequeue(); - -}; -} - -void DataflowWorklist::enqueue(const CFGBlock *block) { - if (!block) - return; - unsigned idx = block->getBlockID(); - if (enqueuedBlocks[idx]) - return; - worklist.push_back(block); - enqueuedBlocks[idx] = true; -} - -void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) { - for (CFGBlock::const_succ_iterator I = block->succ_begin(), - E = block->succ_end(); I != E; ++I) { - enqueue(*I); - } -} - -const CFGBlock *DataflowWorklist::dequeue() { - if (worklist.empty()) - return 0; - const CFGBlock *b = worklist.back(); - worklist.pop_back(); - enqueuedBlocks[b->getBlockID()] = false; - return b; -} - -//------------------------------------------------------------------------====// -// Transfer function for uninitialized values analysis. -//====------------------------------------------------------------------------// - -static const bool Initialized = false; -static const bool Uninitialized = true; - -namespace { -class FindVarResult { - const VarDecl *vd; - const DeclRefExpr *dr; -public: - FindVarResult(VarDecl *vd, DeclRefExpr *dr) : vd(vd), dr(dr) {} - - const DeclRefExpr *getDeclRefExpr() const { return dr; } - const VarDecl *getDecl() const { return vd; } -}; - -class TransferFunctions : public CFGRecStmtVisitor { - CFGBlockValues &vals; - const CFG &cfg; - AnalysisContext ∾ - UninitVariablesHandler *handler; - const DeclRefExpr *currentDR; - const Expr *currentVoidCast; - const bool flagBlockUses; -public: - TransferFunctions(CFGBlockValues &vals, const CFG &cfg, - AnalysisContext &ac, - UninitVariablesHandler *handler, - bool flagBlockUses) - : vals(vals), cfg(cfg), ac(ac), handler(handler), currentDR(0), - currentVoidCast(0), flagBlockUses(flagBlockUses) {} - - const CFG &getCFG() { return cfg; } - void reportUninit(const DeclRefExpr *ex, const VarDecl *vd); - - void VisitBlockExpr(BlockExpr *be); - void VisitDeclStmt(DeclStmt *ds); - void VisitDeclRefExpr(DeclRefExpr *dr); - void VisitUnaryOperator(UnaryOperator *uo); - void VisitBinaryOperator(BinaryOperator *bo); - void VisitCastExpr(CastExpr *ce); - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *se); - void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt *fs); - - bool isTrackedVar(const VarDecl *vd) { - return ::isTrackedVar(vd, cast(ac.getDecl())); - } - - FindVarResult findBlockVarDecl(Expr *ex); -}; -} - -void TransferFunctions::reportUninit(const DeclRefExpr *ex, - const VarDecl *vd) { - if (handler) handler->handleUseOfUninitVariable(ex, vd); -} - -FindVarResult TransferFunctions::findBlockVarDecl(Expr* ex) { - if (DeclRefExpr* dr = dyn_cast(ex->IgnoreParenCasts())) - if (VarDecl *vd = dyn_cast(dr->getDecl())) - if (isTrackedVar(vd)) - return FindVarResult(vd, dr); - return FindVarResult(0, 0); -} - -void TransferFunctions::BlockStmt_VisitObjCForCollectionStmt( - ObjCForCollectionStmt *fs) { - - Visit(fs->getCollection()); - - // This represents an initialization of the 'element' value. - Stmt *element = fs->getElement(); - const VarDecl* vd = 0; - - if (DeclStmt* ds = dyn_cast(element)) { - vd = cast(ds->getSingleDecl()); - if (!isTrackedVar(vd)) - vd = 0; - } - else { - // Initialize the value of the reference variable. - const FindVarResult &res = findBlockVarDecl(cast(element)); - vd = res.getDecl(); - if (!vd) { - Visit(element); - return; - } - } - - if (vd) - vals[vd] = Initialized; -} - -void TransferFunctions::VisitBlockExpr(BlockExpr *be) { - if (!flagBlockUses || !handler) - return; - AnalysisContext::referenced_decls_iterator i, e; - llvm::tie(i, e) = ac.getReferencedBlockVars(be->getBlockDecl()); - for ( ; i != e; ++i) { - const VarDecl *vd = *i; - if (vd->getAttr() || !vd->hasLocalStorage() || - !isTrackedVar(vd)) - continue; - if (vals[vd] == Uninitialized) - handler->handleUseOfUninitVariable(be, vd); - } -} - -void TransferFunctions::VisitDeclStmt(DeclStmt *ds) { - for (DeclStmt::decl_iterator DI = ds->decl_begin(), DE = ds->decl_end(); - DI != DE; ++DI) { - if (VarDecl *vd = dyn_cast(*DI)) { - if (isTrackedVar(vd)) { - vals[vd] = Uninitialized; - if (Stmt *init = vd->getInit()) { - Visit(init); - vals[vd] = Initialized; - } - } - else if (Stmt *init = vd->getInit()) { - Visit(init); - } - } - } -} - -void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) { - // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast - // cannot be block-level expressions. Therefore, we determine if - // a DeclRefExpr is involved in a "load" by comparing it to the current - // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr. - // If a DeclRefExpr is not involved in a load, we are essentially computing - // its address, either for assignment to a reference or via the '&' operator. - // In such cases, treat the variable as being initialized, since this - // analysis isn't powerful enough to do alias tracking. - if (dr != currentDR) - if (const VarDecl *vd = dyn_cast(dr->getDecl())) - if (isTrackedVar(vd)) - vals[vd] = Initialized; -} - -void TransferFunctions::VisitBinaryOperator(clang::BinaryOperator *bo) { - if (bo->isAssignmentOp()) { - const FindVarResult &res = findBlockVarDecl(bo->getLHS()); - if (const VarDecl* vd = res.getDecl()) { - // We assume that DeclRefExprs wrapped in a BinaryOperator "assignment" - // cannot be block-level expressions. Therefore, we determine if - // a DeclRefExpr is involved in a "load" by comparing it to the current - // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr. - SaveAndRestore lastDR(currentDR, - res.getDeclRefExpr()); - Visit(bo->getRHS()); - Visit(bo->getLHS()); - - llvm::BitVector::reference bit = vals[vd]; - if (bit == Uninitialized) { - if (bo->getOpcode() != BO_Assign) - reportUninit(res.getDeclRefExpr(), vd); - bit = Initialized; - } - return; - } - } - Visit(bo->getRHS()); - Visit(bo->getLHS()); -} - -void TransferFunctions::VisitUnaryOperator(clang::UnaryOperator *uo) { - switch (uo->getOpcode()) { - case clang::UO_PostDec: - case clang::UO_PostInc: - case clang::UO_PreDec: - case clang::UO_PreInc: { - const FindVarResult &res = findBlockVarDecl(uo->getSubExpr()); - if (const VarDecl *vd = res.getDecl()) { - // We assume that DeclRefExprs wrapped in a unary operator ++/-- - // cannot be block-level expressions. Therefore, we determine if - // a DeclRefExpr is involved in a "load" by comparing it to the current - // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr. - SaveAndRestore lastDR(currentDR, - res.getDeclRefExpr()); - Visit(uo->getSubExpr()); - - llvm::BitVector::reference bit = vals[vd]; - if (bit == Uninitialized) { - reportUninit(res.getDeclRefExpr(), vd); - bit = Initialized; - } - return; - } - break; - } - default: - break; - } - Visit(uo->getSubExpr()); -} - -void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) { - if (ce->getCastKind() == CK_LValueToRValue) { - const FindVarResult &res = findBlockVarDecl(ce->getSubExpr()); - if (const VarDecl *vd = res.getDecl()) { - // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast - // cannot be block-level expressions. Therefore, we determine if - // a DeclRefExpr is involved in a "load" by comparing it to the current - // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr. - // Here we update 'currentDR' to be the one associated with this - // lvalue-to-rvalue cast. Then, when we analyze the DeclRefExpr, we - // will know that we are not computing its lvalue for other purposes - // than to perform a load. - SaveAndRestore lastDR(currentDR, - res.getDeclRefExpr()); - Visit(ce->getSubExpr()); - if (currentVoidCast != ce && vals[vd] == Uninitialized) { - reportUninit(res.getDeclRefExpr(), vd); - // Don't cascade warnings. - vals[vd] = Initialized; - } - return; - } - } - else if (CStyleCastExpr *cse = dyn_cast(ce)) { - if (cse->getType()->isVoidType()) { - // e.g. (void) x; - SaveAndRestore - lastVoidCast(currentVoidCast, cse->getSubExpr()->IgnoreParens()); - Visit(cse->getSubExpr()); - return; - } - } - Visit(ce->getSubExpr()); -} - -void TransferFunctions::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *se) { - if (se->isSizeOf()) { - if (se->getType()->isConstantSizeType()) - return; - // Handle VLAs. - Visit(se->getArgumentExpr()); - } -} - -//------------------------------------------------------------------------====// -// High-level "driver" logic for uninitialized values analysis. -//====------------------------------------------------------------------------// - -static bool runOnBlock(const CFGBlock *block, const CFG &cfg, - AnalysisContext &ac, CFGBlockValues &vals, - UninitVariablesHandler *handler = 0, - bool flagBlockUses = false) { - - if (const BinaryOperator *b = getLogicalOperatorInChain(block)) { - CFGBlock::const_pred_iterator itr = block->pred_begin(); - BVPair vA = vals.getBitVectors(*itr, false); - ++itr; - BVPair vB = vals.getBitVectors(*itr, false); - - BVPair valsAB; - - if (b->getOpcode() == BO_LAnd) { - // Merge the 'F' bits from the first and second. - vals.mergeIntoScratch(*(vA.second ? vA.second : vA.first), true); - vals.mergeIntoScratch(*(vB.second ? vB.second : vB.first), false); - valsAB.first = vA.first; - valsAB.second = &vals.getScratch(); - } - else { - // Merge the 'T' bits from the first and second. - assert(b->getOpcode() == BO_LOr); - vals.mergeIntoScratch(*vA.first, true); - vals.mergeIntoScratch(*vB.first, false); - valsAB.first = &vals.getScratch(); - valsAB.second = vA.second ? vA.second : vA.first; - } - return vals.updateBitVectors(block, valsAB); - } - - // Default behavior: merge in values of predecessor blocks. - vals.resetScratch(); - bool isFirst = true; - for (CFGBlock::const_pred_iterator I = block->pred_begin(), - E = block->pred_end(); I != E; ++I) { - vals.mergeIntoScratch(vals.getBitVector(*I, block), isFirst); - isFirst = false; - } - // Apply the transfer function. - TransferFunctions tf(vals, cfg, ac, handler, flagBlockUses); - for (CFGBlock::const_iterator I = block->begin(), E = block->end(); - I != E; ++I) { - if (const CFGStmt *cs = dyn_cast(&*I)) { - tf.BlockStmt_Visit(cs->getStmt()); - } - } - return vals.updateBitVectorWithScratch(block); -} - -void clang::runUninitializedVariablesAnalysis(const DeclContext &dc, - const CFG &cfg, - AnalysisContext &ac, - UninitVariablesHandler &handler) { - CFGBlockValues vals(cfg); - vals.computeSetOfDeclarations(dc); - if (vals.hasNoDeclarations()) - return; - DataflowWorklist worklist(cfg); - llvm::BitVector previouslyVisited(cfg.getNumBlockIDs()); - - worklist.enqueueSuccessors(&cfg.getEntry()); - - while (const CFGBlock *block = worklist.dequeue()) { - // Did the block change? - bool changed = runOnBlock(block, cfg, ac, vals); - if (changed || !previouslyVisited[block->getBlockID()]) - worklist.enqueueSuccessors(block); - previouslyVisited[block->getBlockID()] = true; - } - - // Run through the blocks one more time, and report uninitialized variabes. - for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { - runOnBlock(*BI, cfg, ac, vals, &handler, /* flagBlockUses */ true); - } -} - -UninitVariablesHandler::~UninitVariablesHandler() {} - diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp index 31e33315cce2..e8cd21885d22 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp @@ -16,6 +16,8 @@ #include "clang/Basic/PartialDiagnostic.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/CrashRecoveryContext.h" + using namespace clang; static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT, @@ -49,11 +51,6 @@ Diagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr &diags, ErrorLimit = 0; TemplateBacktraceLimit = 0; - // Create a DiagState and DiagStatePoint representing diagnostic changes - // through command-line. - DiagStates.push_back(DiagState()); - PushDiagStatePoint(&DiagStates.back(), SourceLocation()); - Reset(); } @@ -100,6 +97,16 @@ void Diagnostic::Reset() { // displayed. LastDiagLevel = (DiagnosticIDs::Level)-1; DelayedDiagID = 0; + + // Clear state related to #pragma diagnostic. + DiagStates.clear(); + DiagStatePoints.clear(); + DiagStateOnPushStack.clear(); + + // Create a DiagState and DiagStatePoint representing diagnostic changes + // through command-line. + DiagStates.push_back(DiagState()); + PushDiagStatePoint(&DiagStates.back(), SourceLocation()); } void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1, @@ -168,7 +175,7 @@ void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, // after the previous one. if ((Loc.isValid() && LastStateChangePos.isInvalid()) || LastStateChangePos.isBeforeInTranslationUnitThan(Loc)) { - // A diagnostic pragma occured, create a new DiagState initialized with + // A diagnostic pragma occurred, create a new DiagState initialized with // the current one and a new DiagStatePoint to record at which location // the new state became active. DiagStates.push_back(*GetCurDiagState()); @@ -683,5 +690,7 @@ PartialDiagnostic::StorageAllocator::StorageAllocator() { } PartialDiagnostic::StorageAllocator::~StorageAllocator() { - assert(NumFreeListEntries == NumCached && "A partial is on the lamb"); + // Don't assert if we are in a CrashRecovery context, as this + // invariant may be invalidated during a crash. + assert((NumFreeListEntries == NumCached || llvm::CrashRecoveryContext::isRecoveringFromCrash()) && "A partial is on the lamb"); } diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp index 553e4c929454..b4dd575a9684 100644 --- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp @@ -46,19 +46,41 @@ struct StaticDiagInfoRec { unsigned AccessControl : 1; unsigned Category : 5; + const char *Name; + const char *Description; const char *OptionGroup; + const char *BriefExplanation; + const char *FullExplanation; + bool operator<(const StaticDiagInfoRec &RHS) const { return DiagID < RHS.DiagID; } }; +struct StaticDiagNameIndexRec { + const char *Name; + unsigned short DiagID; + + bool operator<(const StaticDiagNameIndexRec &RHS) const { + assert(Name && RHS.Name && "Null Diagnostic Name"); + return strcmp(Name, RHS.Name) == -1; + } + + bool operator==(const StaticDiagNameIndexRec &RHS) const { + assert(Name && RHS.Name && "Null Diagnostic Name"); + return strcmp(Name, RHS.Name) == 0; + } +}; + } static const StaticDiagInfoRec StaticDiagInfo[] = { -#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) \ - { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, CATEGORY, DESC, GROUP }, +#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) \ + { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, \ + ACCESS, CATEGORY, #ENUM, DESC, GROUP, BRIEF, FULL }, #include "clang/Basic/DiagnosticCommonKinds.inc" #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" @@ -67,20 +89,32 @@ static const StaticDiagInfoRec StaticDiagInfo[] = { #include "clang/Basic/DiagnosticASTKinds.inc" #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" - { 0, 0, 0, 0, 0, 0, 0, 0} -}; #undef DIAG + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +static const unsigned StaticDiagInfoSize = + sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1; + +/// To be sorted before first use (since it's splitted among multiple files) +static StaticDiagNameIndexRec StaticDiagNameIndex[] = { +#define DIAG_NAME_INDEX(ENUM) { #ENUM, diag::ENUM }, +#include "clang/Basic/DiagnosticIndexName.inc" +#undef DIAG_NAME_INDEX + { 0, 0 } +}; + +static const unsigned StaticDiagNameIndexSize = + sizeof(StaticDiagNameIndex)/sizeof(StaticDiagNameIndex[0])-1; /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, /// or null if the ID is invalid. static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { - unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1; - // If assertions are enabled, verify that the StaticDiagInfo array is sorted. #ifndef NDEBUG static bool IsFirst = true; if (IsFirst) { - for (unsigned i = 1; i != NumDiagEntries; ++i) { + for (unsigned i = 1; i != StaticDiagInfoSize; ++i) { assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID && "Diag ID conflict, the enums at the start of clang::diag (in " "DiagnosticIDs.h) probably need to be increased"); @@ -93,11 +127,11 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { #endif // Search the diagnostic table with a binary search. - StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0, 0 }; + StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const StaticDiagInfoRec *Found = - std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find); - if (Found == StaticDiagInfo + NumDiagEntries || + std::lower_bound(StaticDiagInfo, StaticDiagInfo + StaticDiagInfoSize, Find); + if (Found == StaticDiagInfo + StaticDiagInfoSize || Found->DiagID != DiagID) return 0; @@ -119,7 +153,7 @@ const char *DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { return 0; } -/// getWarningOptionForDiag - Return the category number that a specified +/// getCategoryNumberForDiag - Return the category number that a specified /// DiagID belongs to, or 0 if no category. unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) { if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) @@ -167,7 +201,48 @@ DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { return SFINAE_Report; } -/// getDiagClass - Return the class field of the diagnostic. +/// getName - Given a diagnostic ID, return its name +const char *DiagnosticIDs::getName(unsigned DiagID) { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return Info->Name; + return 0; +} + +/// getIdFromName - Given a diagnostic name, return its ID, or 0 +unsigned DiagnosticIDs::getIdFromName(char const *Name) { + StaticDiagNameIndexRec *StaticDiagNameIndexEnd = + StaticDiagNameIndex + StaticDiagNameIndexSize; + + if (Name == 0) { return diag::DIAG_UPPER_LIMIT; } + + StaticDiagNameIndexRec Find = { Name, 0 }; + + const StaticDiagNameIndexRec *Found = + std::lower_bound( StaticDiagNameIndex, StaticDiagNameIndexEnd, Find); + if (Found == StaticDiagNameIndexEnd || + strcmp(Found->Name, Name) != 0) + return diag::DIAG_UPPER_LIMIT; + + return Found->DiagID; +} + +/// getBriefExplanation - Given a diagnostic ID, return a brief explanation +/// of the issue +const char *DiagnosticIDs::getBriefExplanation(unsigned DiagID) { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return Info->BriefExplanation; + return 0; +} + +/// getFullExplanation - Given a diagnostic ID, return a full explanation +/// of the issue +const char *DiagnosticIDs::getFullExplanation(unsigned DiagID) { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return Info->FullExplanation; + return 0; +} + +/// getBuiltinDiagClass - Return the class field of the diagnostic. /// static unsigned getBuiltinDiagClass(unsigned DiagID) { if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) @@ -329,6 +404,8 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, if (mapping) *mapping = (diag::Mapping) (MappingInfo & 7); + bool ShouldEmitInSystemHeader = false; + switch (MappingInfo & 7) { default: assert(0 && "Unknown mapping!"); case diag::MAP_IGNORE: @@ -351,6 +428,9 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, case diag::MAP_FATAL: Result = DiagnosticIDs::Fatal; break; + case diag::MAP_WARNING_SHOW_IN_SYSTEM_HEADER: + ShouldEmitInSystemHeader = true; + // continue as MAP_WARNING. case diag::MAP_WARNING: // If warnings are globally mapped to ignore or error, do it. if (Diag.IgnoreAllWarnings) @@ -395,6 +475,20 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID)) return DiagnosticIDs::Ignored; + // If we are in a system header, we ignore it. + // We also want to ignore extensions and warnings in -Werror and + // -pedantic-errors modes, which *map* warnings/extensions to errors. + if (Result >= DiagnosticIDs::Warning && + DiagClass != CLASS_ERROR && + // Custom diagnostics always are emitted in system headers. + DiagID < diag::DIAG_UPPER_LIMIT && + !ShouldEmitInSystemHeader && + Diag.SuppressSystemWarnings && + Loc.isValid() && + Diag.getSourceManager().isInSystemHeader( + Diag.getSourceManager().getInstantiationLoc(Loc))) + return DiagnosticIDs::Ignored; + return Result; } @@ -480,16 +574,9 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { DiagnosticIDs::Level DiagLevel; unsigned DiagID = Info.getID(); - // ShouldEmitInSystemHeader - True if this diagnostic should be produced even - // in a system header. - bool ShouldEmitInSystemHeader; - if (DiagID >= diag::DIAG_UPPER_LIMIT) { // Handle custom diagnostics, which cannot be mapped. DiagLevel = CustomDiagInfo->getLevel(DiagID); - - // Custom diagnostics always are emitted in system headers. - ShouldEmitInSystemHeader = true; } else { // Get the class of the diagnostic. If this is a NOTE, map it onto whatever // the diagnostic level was for the previous diagnostic so that it is @@ -497,14 +584,7 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { unsigned DiagClass = getBuiltinDiagClass(DiagID); if (DiagClass == CLASS_NOTE) { DiagLevel = DiagnosticIDs::Note; - ShouldEmitInSystemHeader = false; // extra consideration is needed } else { - // If this is not an error and we are in a system header, we ignore it. - // Check the original Diag ID here, because we also want to ignore - // extensions and warnings in -Werror and -pedantic-errors modes, which - // *map* warnings/extensions to errors. - ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR; - DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(), Diag); } @@ -540,18 +620,6 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { Diag.LastDiagLevel == DiagnosticIDs::Ignored)) return false; - // If this diagnostic is in a system header and is not a clang error, suppress - // it. - if (Diag.SuppressSystemWarnings && !ShouldEmitInSystemHeader && - Info.getLocation().isValid() && - Diag.getSourceManager().isInSystemHeader( - Diag.getSourceManager().getInstantiationLoc(Info.getLocation())) && - (DiagLevel != DiagnosticIDs::Note || - Diag.LastDiagLevel == DiagnosticIDs::Ignored)) { - Diag.LastDiagLevel = DiagnosticIDs::Ignored; - return false; - } - if (DiagLevel >= DiagnosticIDs::Error) { if (Diag.Client->IncludeInDiagnosticCounts()) { Diag.ErrorOccurred = true; diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp index 342413d7da52..4e5a129082f4 100644 --- a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp @@ -313,7 +313,7 @@ const DirectoryEntry *FileManager::getDirectory(llvm::StringRef DirName) { /// getFile - Lookup, cache, and verify the specified file (real or /// virtual). This returns NULL if the file doesn't exist. /// -const FileEntry *FileManager::getFile(llvm::StringRef Filename) { +const FileEntry *FileManager::getFile(llvm::StringRef Filename, bool openFile) { ++NumFileLookups; // See if there is already an entry in the map. @@ -354,6 +354,11 @@ const FileEntry *FileManager::getFile(llvm::StringRef Filename) { return 0; } + if (FileDescriptor != -1 && !openFile) { + close(FileDescriptor); + FileDescriptor = -1; + } + // It exists. See if we have already opened a file with the same inode. // This occurs when one dir is symlinked to another, for example. FileEntry &UFE = UniqueRealFiles.getFile(InterndFileName, StatBuf); @@ -450,13 +455,15 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, return UFE; } -void FileManager::FixupRelativePath(llvm::sys::Path &path, - const FileSystemOptions &FSOpts) { - if (FSOpts.WorkingDir.empty() || llvm::sys::path::is_absolute(path.str())) +void FileManager::FixupRelativePath(llvm::SmallVectorImpl &path) const { + llvm::StringRef pathRef(path.data(), path.size()); + + if (FileSystemOpts.WorkingDir.empty() + || llvm::sys::path::is_absolute(pathRef)) return; - llvm::SmallString<128> NewPath(FSOpts.WorkingDir); - llvm::sys::path::append(NewPath, path.str()); + llvm::SmallString<128> NewPath(FileSystemOpts.WorkingDir); + llvm::sys::path::append(NewPath, pathRef); path = NewPath; } @@ -464,30 +471,32 @@ llvm::MemoryBuffer *FileManager:: getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) { llvm::OwningPtr Result; llvm::error_code ec; + + const char *Filename = Entry->getName(); + // If the file is already open, use the open file descriptor. + if (Entry->FD != -1) { + ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, + Entry->getSize()); + if (ErrorStr) + *ErrorStr = ec.message(); + + close(Entry->FD); + Entry->FD = -1; + return Result.take(); + } + + // Otherwise, open the file. + if (FileSystemOpts.WorkingDir.empty()) { - const char *Filename = Entry->getName(); - // If the file is already open, use the open file descriptor. - if (Entry->FD != -1) { - ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, - Entry->getSize()); - if (ErrorStr) - *ErrorStr = ec.message(); - - close(Entry->FD); - Entry->FD = -1; - return Result.take(); - } - - // Otherwise, open the file. ec = llvm::MemoryBuffer::getFile(Filename, Result, Entry->getSize()); if (ec && ErrorStr) *ErrorStr = ec.message(); return Result.take(); } - - llvm::sys::Path FilePath(Entry->getName()); - FixupRelativePath(FilePath, FileSystemOpts); - ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result, Entry->getSize()); + + llvm::SmallString<128> FilePath(Entry->getName()); + FixupRelativePath(FilePath); + ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, Entry->getSize()); if (ec && ErrorStr) *ErrorStr = ec.message(); return Result.take(); @@ -504,8 +513,8 @@ getBufferForFile(llvm::StringRef Filename, std::string *ErrorStr) { return Result.take(); } - llvm::sys::Path FilePath(Filename); - FixupRelativePath(FilePath, FileSystemOpts); + llvm::SmallString<128> FilePath(Filename); + FixupRelativePath(FilePath); ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result); if (ec && ErrorStr) *ErrorStr = ec.message(); @@ -525,13 +534,21 @@ bool FileManager::getStatValue(const char *Path, struct stat &StatBuf, return FileSystemStatCache::get(Path, StatBuf, FileDescriptor, StatCache.get()); - llvm::sys::Path FilePath(Path); - FixupRelativePath(FilePath, FileSystemOpts); + llvm::SmallString<128> FilePath(Path); + FixupRelativePath(FilePath); return FileSystemStatCache::get(FilePath.c_str(), StatBuf, FileDescriptor, StatCache.get()); } +bool FileManager::getNoncachedStatValue(llvm::StringRef Path, + struct stat &StatBuf) { + llvm::SmallString<128> FilePath(Path); + FixupRelativePath(FilePath); + + return ::stat(FilePath.c_str(), &StatBuf) != 0; +} + void FileManager::GetUniqueIDMapping( llvm::SmallVectorImpl &UIDToFiles) const { UIDToFiles.clear(); diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp index ef11d658ed9e..cb1f55b75773 100644 --- a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp @@ -81,17 +81,18 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts, // Constants for TokenKinds.def namespace { enum { - KEYALL = 1, - KEYC99 = 2, - KEYCXX = 4, - KEYCXX0X = 8, - KEYGNU = 16, - KEYMS = 32, - BOOLSUPPORT = 64, - KEYALTIVEC = 128, - KEYNOCXX = 256, - KEYBORLAND = 512, - KEYOPENCL = 1024 + KEYC99 = 0x1, + KEYCXX = 0x2, + KEYCXX0X = 0x4, + KEYGNU = 0x8, + KEYMS = 0x10, + BOOLSUPPORT = 0x20, + KEYALTIVEC = 0x40, + KEYNOCXX = 0x80, + KEYBORLAND = 0x100, + KEYOPENCL = 0x200, + KEYC1X = 0x400, + KEYALL = 0x7ff }; } @@ -107,7 +108,7 @@ static void AddKeyword(llvm::StringRef Keyword, tok::TokenKind TokenCode, unsigned Flags, const LangOptions &LangOpts, IdentifierTable &Table) { unsigned AddResult = 0; - if (Flags & KEYALL) AddResult = 2; + if (Flags == KEYALL) AddResult = 2; else if (LangOpts.CPlusPlus && (Flags & KEYCXX)) AddResult = 2; else if (LangOpts.CPlusPlus0x && (Flags & KEYCXX0X)) AddResult = 2; else if (LangOpts.C99 && (Flags & KEYC99)) AddResult = 2; @@ -118,6 +119,7 @@ static void AddKeyword(llvm::StringRef Keyword, else if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) AddResult = 2; else if (LangOpts.OpenCL && (Flags & KEYOPENCL)) AddResult = 2; else if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) AddResult = 2; + else if (LangOpts.C1X && (Flags & KEYC1X)) AddResult = 2; // Don't add this keyword if disabled in this language. if (AddResult == 0) return; @@ -162,7 +164,12 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) { #define OBJC2_AT_KEYWORD(NAME) \ if (LangOpts.ObjC2) \ AddObjCKeyword(llvm::StringRef(#NAME), tok::objc_##NAME, *this); +#define TESTING_KEYWORD(NAME, FLAGS) #include "clang/Basic/TokenKinds.def" + + if (LangOpts.ParseUnknownAnytype) + AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL, + LangOpts, *this); } tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { @@ -364,6 +371,56 @@ std::string Selector::getAsString() const { return reinterpret_cast(InfoPtr)->getName(); } +/// Interpreting the given string using the normal CamelCase +/// conventions, determine whether the given string starts with the +/// given "word", which is assumed to end in a lowercase letter. +static bool startsWithWord(llvm::StringRef name, llvm::StringRef word) { + if (name.size() < word.size()) return false; + return ((name.size() == word.size() || + !islower(name[word.size()])) + && name.startswith(word)); +} + +ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) { + IdentifierInfo *first = sel.getIdentifierInfoForSlot(0); + if (!first) return OMF_None; + + llvm::StringRef name = first->getName(); + if (sel.isUnarySelector()) { + if (name == "autorelease") return OMF_autorelease; + if (name == "dealloc") return OMF_dealloc; + if (name == "release") return OMF_release; + if (name == "retain") return OMF_retain; + if (name == "retainCount") return OMF_retainCount; + } + + // The other method families may begin with a prefix of underscores. + while (!name.empty() && name.front() == '_') + name = name.substr(1); + + if (name.empty()) return OMF_None; + switch (name.front()) { + case 'a': + if (startsWithWord(name, "alloc")) return OMF_alloc; + break; + case 'c': + if (startsWithWord(name, "copy")) return OMF_copy; + break; + case 'i': + if (startsWithWord(name, "init")) return OMF_init; + break; + case 'm': + if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy; + break; + case 'n': + if (startsWithWord(name, "new")) return OMF_new; + break; + default: + break; + } + + return OMF_None; +} namespace { struct SelectorTableImpl { @@ -376,6 +433,10 @@ static SelectorTableImpl &getSelectorTableImpl(void *P) { return *static_cast(P); } +size_t SelectorTable::getTotalMemory() const { + SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl); + return SelTabImpl.Allocator.getTotalMemory(); +} Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) { if (nKeys < 2) diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp index e2783ba6fda2..c3e03933e5e5 100644 --- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp @@ -46,13 +46,26 @@ unsigned ContentCache::getSizeBytesMapped() const { return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0; } +/// Returns the kind of memory used to back the memory buffer for +/// this content cache. This is used for performance analysis. +llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const { + assert(Buffer.getPointer()); + + // Should be unreachable, but keep for sanity. + if (!Buffer.getPointer()) + return llvm::MemoryBuffer::MemoryBuffer_Malloc; + + const llvm::MemoryBuffer *buf = Buffer.getPointer(); + return buf->getBufferKind(); +} + /// getSize - Returns the size of the content encapsulated by this ContentCache. /// This can be the size of the source file or the size of an arbitrary /// scratch buffer. If the ContentCache encapsulates a source file, that /// file is not lazily brought in from disk to satisfy this query. unsigned ContentCache::getSize() const { return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize() - : (unsigned) Entry->getSize(); + : (unsigned) ContentsEntry->getSize(); } void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, @@ -70,8 +83,8 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, SourceLocation Loc, bool *Invalid) const { // Lazily create the Buffer for ContentCaches that wrap files. If we already - // computed it, jsut return what we have. - if (Buffer.getPointer() || Entry == 0) { + // computed it, just return what we have. + if (Buffer.getPointer() || ContentsEntry == 0) { if (Invalid) *Invalid = isBufferInvalid(); @@ -79,7 +92,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, } std::string ErrorStr; - Buffer.setPointer(SM.getFileManager().getBufferForFile(Entry, &ErrorStr)); + Buffer.setPointer(SM.getFileManager().getBufferForFile(ContentsEntry, &ErrorStr)); // If we were unable to open the file, then we are in an inconsistent // situation where the content cache referenced a file which no longer @@ -93,18 +106,18 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, // possible. if (!Buffer.getPointer()) { const llvm::StringRef FillStr("<<>>\n"); - Buffer.setPointer(MemoryBuffer::getNewMemBuffer(Entry->getSize(), + Buffer.setPointer(MemoryBuffer::getNewMemBuffer(ContentsEntry->getSize(), "")); char *Ptr = const_cast(Buffer.getPointer()->getBufferStart()); - for (unsigned i = 0, e = Entry->getSize(); i != e; ++i) + for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i) Ptr[i] = FillStr[i % FillStr.size()]; if (Diag.isDiagnosticInFlight()) Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, - Entry->getName(), ErrorStr); + ContentsEntry->getName(), ErrorStr); else Diag.Report(Loc, diag::err_cannot_open_file) - << Entry->getName() << ErrorStr; + << ContentsEntry->getName() << ErrorStr; Buffer.setInt(Buffer.getInt() | InvalidFlag); @@ -114,25 +127,24 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, // Check that the file's size is the same as in the file entry (which may // have come from a stat cache). - if (getRawBuffer()->getBufferSize() != (size_t)Entry->getSize()) { + if (getRawBuffer()->getBufferSize() != (size_t)ContentsEntry->getSize()) { if (Diag.isDiagnosticInFlight()) Diag.SetDelayedDiagnostic(diag::err_file_modified, - Entry->getName()); + ContentsEntry->getName()); else Diag.Report(Loc, diag::err_file_modified) - << Entry->getName(); + << ContentsEntry->getName(); Buffer.setInt(Buffer.getInt() | InvalidFlag); if (Invalid) *Invalid = true; return Buffer.getPointer(); } - + // If the buffer is valid, check to see if it has a UTF Byte Order Mark - // (BOM). We only support UTF-8 without a BOM right now. See + // (BOM). We only support UTF-8 with and without a BOM right now. See // http://en.wikipedia.org/wiki/Byte_order_mark for more information. llvm::StringRef BufStr = Buffer.getPointer()->getBuffer(); - const char *BOM = llvm::StringSwitch(BufStr) - .StartsWith("\xEF\xBB\xBF", "UTF-8") + const char *InvalidBOM = llvm::StringSwitch(BufStr) .StartsWith("\xFE\xFF", "UTF-16 (BE)") .StartsWith("\xFF\xFE", "UTF-16 (LE)") .StartsWith("\x00\x00\xFE\xFF", "UTF-32 (BE)") @@ -145,9 +157,9 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, .StartsWith("\x84\x31\x95\x33", "GB-18030") .Default(0); - if (BOM) { + if (InvalidBOM) { Diag.Report(Loc, diag::err_unsupported_bom) - << BOM << Entry->getName(); + << InvalidBOM << ContentsEntry->getName(); Buffer.setInt(Buffer.getInt() | InvalidFlag); } @@ -279,7 +291,12 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID) { std::pair LocInfo = getDecomposedInstantiationLoc(Loc); - const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile(); + bool Invalid = false; + const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); + if (!Entry.isFile() || Invalid) + return; + + const SrcMgr::FileInfo &FileInfo = Entry.getFile(); // Remember that this file has #line directives now if it doesn't already. const_cast(FileInfo).setHasLineDirectives(); @@ -303,7 +320,13 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, } std::pair LocInfo = getDecomposedInstantiationLoc(Loc); - const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile(); + + bool Invalid = false; + const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); + if (!Entry.isFile() || Invalid) + return; + + const SrcMgr::FileInfo &FileInfo = Entry.getFile(); // Remember that this file has #line directives now if it doesn't already. const_cast(FileInfo).setHasLineDirectives(); @@ -340,9 +363,9 @@ LineTableInfo &SourceManager::getLineTable() { //===----------------------------------------------------------------------===// SourceManager::SourceManager(Diagnostic &Diag, FileManager &FileMgr) - : Diag(Diag), FileMgr(FileMgr), + : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), - NumBinaryProbes(0) { + NumBinaryProbes(0), FakeBufferForRecovery(0) { clearIDTables(); Diag.setSourceManager(this); } @@ -362,6 +385,8 @@ SourceManager::~SourceManager() { I->second->~ContentCache(); ContentCacheAlloc.Deallocate(I->second); } + + delete FakeBufferForRecovery; } void SourceManager::clearIDTables() { @@ -395,7 +420,18 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) { unsigned EntryAlign = llvm::AlignOf::Alignment; EntryAlign = std::max(8U, EntryAlign); Entry = ContentCacheAlloc.Allocate(1, EntryAlign); - new (Entry) ContentCache(FileEnt); + + // If the file contents are overridden with contents from another file, + // pass that file to ContentCache. + llvm::DenseMap::iterator + overI = OverriddenFiles.find(FileEnt); + if (overI == OverriddenFiles.end()) + new (Entry) ContentCache(FileEnt); + else + new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt + : overI->second, + overI->second); + return Entry; } @@ -445,6 +481,15 @@ void SourceManager::ClearPreallocatedSLocEntries() { ExternalSLocEntries = 0; } +/// \brief As part of recovering from missing or changed content, produce a +/// fake, non-empty buffer. +const llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { + if (!FakeBufferForRecovery) + FakeBufferForRecovery + = llvm::MemoryBuffer::getMemBuffer("<<>"); + + return FakeBufferForRecovery; +} //===----------------------------------------------------------------------===// // Methods to create new FileID's and instantiations. @@ -531,10 +576,21 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile, const_cast(IR)->replaceBuffer(Buffer, DoNotFree); } +void SourceManager::overrideFileContents(const FileEntry *SourceFile, + const FileEntry *NewFile) { + assert(SourceFile->getSize() == NewFile->getSize() && + "Different sizes, use the FileManager to create a virtual file with " + "the correct size"); + assert(FileInfos.count(SourceFile) == 0 && + "This function should be called at the initialization stage, before " + "any parsing occurs."); + OverriddenFiles[SourceFile] = NewFile; +} + llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { bool MyInvalid = false; - const SLocEntry &SLoc = getSLocEntry(FID.ID); - if (!SLoc.isFile()) { + const SLocEntry &SLoc = getSLocEntry(FID.ID, &MyInvalid); + if (!SLoc.isFile() || MyInvalid) { if (Invalid) *Invalid = true; return "<<<<>>>>"; @@ -562,7 +618,8 @@ llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { /// SLocEntryTable which contains the specified location. /// FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { - assert(SLocOffset && "Invalid FileID"); + if (!SLocOffset) + return FileID::get(0); // After the first and second level caches, I see two common sorts of // behavior: 1) a lot of searched FileID's are "near" the cached file location @@ -590,8 +647,13 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { unsigned NumProbes = 0; while (1) { --I; - if (ExternalSLocEntries) - getSLocEntry(FileID::get(I - SLocEntryTable.begin())); + if (ExternalSLocEntries) { + bool Invalid = false; + getSLocEntry(FileID::get(I - SLocEntryTable.begin()), &Invalid); + if (Invalid) + return FileID::get(0); + } + if (I->getOffset() <= SLocOffset) { #if 0 printf("lin %d -> %d [%s] %d %d\n", SLocOffset, @@ -621,9 +683,13 @@ FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { unsigned LessIndex = 0; NumProbes = 0; while (1) { + bool Invalid = false; unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex; - unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex)).getOffset(); - + unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex), &Invalid) + .getOffset(); + if (Invalid) + return FileID::get(0); + ++NumProbes; // If the offset of the midpoint is too large, chop the high side of the @@ -773,9 +839,16 @@ const char *SourceManager::getCharacterData(SourceLocation SL, // Note that calling 'getBuffer()' may lazily page in a source file. bool CharDataInvalid = false; + const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid); + if (CharDataInvalid || !Entry.isFile()) { + if (Invalid) + *Invalid = true; + + return "<<<>>>"; + } const llvm::MemoryBuffer *Buffer - = getSLocEntry(LocInfo.first).getFile().getContentCache() - ->getBuffer(Diag, *this, SourceLocation(), &CharDataInvalid); + = Entry.getFile().getContentCache() + ->getBuffer(Diag, *this, SourceLocation(), &CharDataInvalid); if (Invalid) *Invalid = CharDataInvalid; return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second); @@ -891,10 +964,18 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, ContentCache *Content; if (LastLineNoFileIDQuery == FID) Content = LastLineNoContentCache; - else - Content = const_cast(getSLocEntry(FID) - .getFile().getContentCache()); - + else { + bool MyInvalid = false; + const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); + if (MyInvalid || !Entry.isFile()) { + if (Invalid) + *Invalid = true; + return 1; + } + + Content = const_cast(Entry.getFile().getContentCache()); + } + // If this is the first use of line information for this buffer, compute the /// SourceLineCache for it on demand. if (Content->SourceLineCache == 0) { @@ -1021,7 +1102,12 @@ SrcMgr::CharacteristicKind SourceManager::getFileCharacteristic(SourceLocation Loc) const { assert(!Loc.isInvalid() && "Can't get file characteristic of invalid loc!"); std::pair LocInfo = getDecomposedInstantiationLoc(Loc); - const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile(); + bool Invalid = false; + const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid); + if (Invalid || !SEntry.isFile()) + return C_User; + + const SrcMgr::FileInfo &FI = SEntry.getFile(); // If there are no #line directives in this file, just return the whole-file // state. @@ -1064,18 +1150,23 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { // Presumed locations are always for instantiation points. std::pair LocInfo = getDecomposedInstantiationLoc(Loc); - const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile(); + bool Invalid = false; + const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); + if (Invalid || !Entry.isFile()) + return PresumedLoc(); + + const SrcMgr::FileInfo &FI = Entry.getFile(); const SrcMgr::ContentCache *C = FI.getContentCache(); // To get the source name, first consult the FileEntry (if one exists) // before the MemBuffer as this will avoid unnecessarily paging in the // MemBuffer. const char *Filename; - if (C->Entry) - Filename = C->Entry->getName(); + if (C->OrigEntry) + Filename = C->OrigEntry->getName(); else Filename = C->getBuffer(Diag, *this)->getBufferIdentifier(); - bool Invalid = false; + unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid); if (Invalid) return PresumedLoc(); @@ -1152,18 +1243,22 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, llvm::Optional SourceFileInode; llvm::Optional SourceFileName; if (!MainFileID.isInvalid()) { - const SLocEntry &MainSLoc = getSLocEntry(MainFileID); + bool Invalid = false; + const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid); + if (Invalid) + return SourceLocation(); + if (MainSLoc.isFile()) { const ContentCache *MainContentCache = MainSLoc.getFile().getContentCache(); if (!MainContentCache) { // Can't do anything - } else if (MainContentCache->Entry == SourceFile) { + } else if (MainContentCache->OrigEntry == SourceFile) { FirstFID = MainFileID; } else { // Fall back: check whether we have the same base name and inode // as the main file. - const FileEntry *MainFile = MainContentCache->Entry; + const FileEntry *MainFile = MainContentCache->OrigEntry; SourceFileName = llvm::sys::path::filename(SourceFile->getName()); if (*SourceFileName == llvm::sys::path::filename(MainFile->getName())) { SourceFileInode = getActualFileInode(SourceFile); @@ -1185,10 +1280,14 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, // The location we're looking for isn't in the main file; look // through all of the source locations. for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) { - const SLocEntry &SLoc = getSLocEntry(I); + bool Invalid = false; + const SLocEntry &SLoc = getSLocEntry(I, &Invalid); + if (Invalid) + return SourceLocation(); + if (SLoc.isFile() && SLoc.getFile().getContentCache() && - SLoc.getFile().getContentCache()->Entry == SourceFile) { + SLoc.getFile().getContentCache()->OrigEntry == SourceFile) { FirstFID = FileID::get(I); break; } @@ -1203,12 +1302,16 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile, (SourceFileName = llvm::sys::path::filename(SourceFile->getName()))) && (SourceFileInode || (SourceFileInode = getActualFileInode(SourceFile)))) { + bool Invalid = false; for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) { - const SLocEntry &SLoc = getSLocEntry(I); + const SLocEntry &SLoc = getSLocEntry(I, &Invalid); + if (Invalid) + return SourceLocation(); + if (SLoc.isFile()) { const ContentCache *FileContentCache = SLoc.getFile().getContentCache(); - const FileEntry *Entry =FileContentCache? FileContentCache->Entry : 0; + const FileEntry *Entry =FileContentCache? FileContentCache->OrigEntry : 0; if (Entry && *SourceFileName == llvm::sys::path::filename(Entry->getName())) { if (llvm::Optional EntryInode = getActualFileInode(Entry)) { @@ -1367,7 +1470,7 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, while (!MoveUpIncludeHierarchy(LOffs, *this)) /*empty*/; while (!MoveUpIncludeHierarchy(ROffs, *this)) /*empty*/; - // If exactly one location is a memory buffer, assume it preceeds the other. + // If exactly one location is a memory buffer, assume it precedes the other. // Strip off macro instantation locations, going up to the top-level File // SLocEntry. @@ -1403,3 +1506,24 @@ void SourceManager::PrintStats() const { } ExternalSLocEntrySource::~ExternalSLocEntrySource() { } + +/// Return the amount of memory used by memory buffers, breaking down +/// by heap-backed versus mmap'ed memory. +SourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const { + size_t malloc_bytes = 0; + size_t mmap_bytes = 0; + + for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) + if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped()) + switch (MemBufferInfos[i]->getMemoryBufferKind()) { + case llvm::MemoryBuffer::MemoryBuffer_MMap: + mmap_bytes += sized_mapped; + break; + case llvm::MemoryBuffer::MemoryBuffer_Malloc: + malloc_bytes += sized_mapped; + break; + } + + return MemoryBufferSizes(malloc_bytes, mmap_bytes); +} + diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp index a9eeb8b4cc4e..dcf0cb4237a9 100644 --- a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/APFloat.h" @@ -19,6 +20,8 @@ #include using namespace clang; +static const LangAS::Map DefaultAddrSpaceMap = { 0 }; + // TargetInfo Constructor. TargetInfo::TargetInfo(const std::string &T) : Triple(T) { // Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or @@ -64,6 +67,13 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { // Default to using the Itanium ABI. CXXABI = CXXABI_Itanium; + + // Default to an empty address space map. + AddrSpaceMap = &DefaultAddrSpaceMap; + + // Default to an unknown platform name. + PlatformName = "unknown"; + PlatformMinVersion = VersionTuple(); } // Out of line virtual dtor for TargetInfo. @@ -422,7 +432,7 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints, case ',': // multiple alternative constraint. Ignore comma. break; case '?': // Disparage slightly code. - case '!': // Disparage severly. + case '!': // Disparage severely. break; // Pass them. } diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp index 08a92084bb5a..97109caf1237 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp @@ -76,7 +76,9 @@ class OSTargetInfo : public TgtInfo { static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, - const llvm::Triple &Triple) { + const llvm::Triple &Triple, + llvm::StringRef &PlatformName, + VersionTuple &PlatformMinVersion) { Builder.defineMacro("__APPLE_CC__", "5621"); Builder.defineMacro("__APPLE__"); Builder.defineMacro("__MACH__"); @@ -99,19 +101,40 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, if (Opts.POSIXThreads) Builder.defineMacro("_REENTRANT"); - // Get the OS version number from the triple. + // Get the platform type and version number from the triple. unsigned Maj, Min, Rev; // If no version was given, default to to 10.4.0, for simplifying tests. - if (Triple.getOSName() == "darwin") { + if (Triple.getOSName() == "darwin" || Triple.getOSName() == "osx") { + PlatformName = "macosx"; Min = Rev = 0; Maj = 8; - } else - Triple.getDarwinNumber(Maj, Min, Rev); + } else { + // Otherwise, honor all three triple forms ("-darwinNNN[-iphoneos]", + // "-osxNNN", and "-iosNNN"). + + if (Triple.getOS() == llvm::Triple::Darwin) { + // For historical reasons that make little sense, the version passed here + // is the "darwin" version, which drops the 10 and offsets by 4. + Triple.getOSVersion(Maj, Min, Rev); + + if (Triple.getEnvironmentName() == "iphoneos") { + PlatformName = "ios"; + } else { + PlatformName = "macosx"; + Rev = Min; + Min = Maj - 4; + Maj = 10; + } + } else { + Triple.getOSVersion(Maj, Min, Rev); + PlatformName = llvm::Triple::getOSTypeName(Triple.getOS()); + } + } // Set the appropriate OS version define. - if (Triple.getEnvironmentName() == "iphoneos") { - assert(Maj < 10 && Min < 99 && Rev < 99 && "Invalid version!"); + if (PlatformName == "ios") { + assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!"); char Str[6]; Str[0] = '0' + Maj; Str[1] = '0' + (Min / 10); @@ -121,22 +144,22 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, Str[5] = '\0'; Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", Str); } else { - // For historical reasons that make little sense, the version passed here is - // the "darwin" version, which drops the 10 and offsets by 4. - Rev = Min; - Min = Maj - 4; - Maj = 10; - + // Note that the Driver allows versions which aren't representable in the + // define (because we only get a single digit for the minor and micro + // revision numbers). So, we limit them to the maximum representable + // version. assert(Triple.getEnvironmentName().empty() && "Invalid environment!"); - assert(Maj < 99 && Min < 10 && Rev < 10 && "Invalid version!"); + assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!"); char Str[5]; Str[0] = '0' + (Maj / 10); Str[1] = '0' + (Maj % 10); - Str[2] = '0' + Min; - Str[3] = '0' + Rev; + Str[2] = '0' + std::min(Min, 9U); + Str[3] = '0' + std::min(Rev, 9U); Str[4] = '\0'; Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); } + + PlatformMinVersion = VersionTuple(Maj, Min, Rev); } namespace { @@ -145,7 +168,8 @@ class DarwinTargetInfo : public OSTargetInfo { protected: virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, MacroBuilder &Builder) const { - getDarwinDefines(Builder, Opts, Triple); + getDarwinDefines(Builder, Opts, Triple, this->PlatformName, + this->PlatformMinVersion); } public: @@ -159,8 +183,9 @@ class DarwinTargetInfo : public OSTargetInfo { // Let MCSectionMachO validate this. llvm::StringRef Segment, Section; unsigned TAA, StubSize; + bool HasTAA; return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section, - TAA, StubSize); + TAA, HasTAA, StubSize); } virtual const char *getStaticInitSectionSpecifier() const { @@ -822,6 +847,87 @@ class DarwinPPC64TargetInfo : }; } // end anonymous namespace. +namespace { + class PTXTargetInfo : public TargetInfo { + static const char * const GCCRegNames[]; + static const Builtin::Info BuiltinInfo[]; + public: + PTXTargetInfo(const std::string& triple) : TargetInfo(triple) { + TLSSupported = false; + LongWidth = LongAlign = 64; + } + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("__PTX__"); + } + virtual void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const { + Records = BuiltinInfo; + NumRecords = clang::PTX::LastTSBuiltin-Builtin::FirstTSBuiltin; + } + + virtual void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const; + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + // No aliases. + Aliases = 0; + NumAliases = 0; + } + virtual bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const { + // FIXME: implement + return true; + } + virtual const char *getClobbers() const { + // FIXME: Is this really right? + return ""; + } + virtual const char *getVAListDeclaration() const { + // FIXME: implement + return "typedef char* __builtin_va_list;"; + } + }; + + const Builtin::Info PTXTargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES, false }, +#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\ + ALL_LANGUAGES, false }, +#include "clang/Basic/BuiltinsPTX.def" + }; + + const char * const PTXTargetInfo::GCCRegNames[] = { + "r0" + }; + + void PTXTargetInfo::getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const { + Names = GCCRegNames; + NumNames = llvm::array_lengthof(GCCRegNames); + } + + + class PTX32TargetInfo : public PTXTargetInfo { + public: + PTX32TargetInfo(const std::string& triple) : PTXTargetInfo(triple) { + PointerWidth = PointerAlign = 32; + SizeType = PtrDiffType = IntPtrType = TargetInfo::UnsignedInt; + DescriptionString + = "e-p:32:32-i64:64:64-f64:64:64-n1:8:16:32:64"; + } + }; + + class PTX64TargetInfo : public PTXTargetInfo { + public: + PTX64TargetInfo(const std::string& triple) : PTXTargetInfo(triple) { + PointerWidth = PointerAlign = 64; + SizeType = PtrDiffType = IntPtrType = TargetInfo::UnsignedLongLong; + DescriptionString + = "e-p:64:64-i64:64:64-f64:64:64-n1:8:16:32:64"; + } + }; +} + namespace { // MBlaze abstract base class class MBlazeTargetInfo : public TargetInfo { @@ -1074,8 +1180,11 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, else if (CPU == "corei7") { setFeatureEnabled(Features, "sse4", true); setFeatureEnabled(Features, "aes", true); - } - else if (CPU == "k6" || CPU == "winchip-c6") + } else if (CPU == "sandybridge") { + setFeatureEnabled(Features, "sse4", true); + setFeatureEnabled(Features, "aes", true); +// setFeatureEnabled(Features, "avx", true); + } else if (CPU == "k6" || CPU == "winchip-c6") setFeatureEnabled(Features, "mmx", true); else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" || CPU == "athlon-tbird" || CPU == "winchip2" || CPU == "c3") { @@ -1450,7 +1559,7 @@ class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo { public: VisualStudioWindowsX86_32TargetInfo(const std::string& triple) : WindowsX86_32TargetInfo(triple) { - LongDoubleWidth = 64; + LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble; } virtual void getTargetDefines(const LangOptions &Opts, @@ -1480,7 +1589,15 @@ class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo { Builder.defineMacro("_X86_"); Builder.defineMacro("__MSVCRT__"); Builder.defineMacro("__MINGW32__"); - Builder.defineMacro("__declspec", "__declspec"); + + // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)). + // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions. + if (Opts.Microsoft) + // Provide "as-is" __declspec. + Builder.defineMacro("__declspec", "__declspec"); + else + // Provide alias of __attribute__ like mingw32-gcc. + Builder.defineMacro("__declspec(a)", "__attribute__((a))"); } }; } // end anonymous namespace @@ -1605,6 +1722,8 @@ class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo { public: VisualStudioWindowsX86_64TargetInfo(const std::string& triple) : WindowsX86_64TargetInfo(triple) { + LongDoubleWidth = LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble; } virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { @@ -1628,8 +1747,17 @@ class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo { WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder); DefineStd(Builder, "WIN64", Opts); Builder.defineMacro("__MSVCRT__"); + Builder.defineMacro("__MINGW32__"); Builder.defineMacro("__MINGW64__"); - Builder.defineMacro("__declspec", "__declspec"); + + // mingw32-gcc provides __declspec(a) as alias of __attribute__((a)). + // In contrast, clang-cc1 provides __declspec(a) with -fms-extensions. + if (Opts.Microsoft) + // Provide "as-is" __declspec. + Builder.defineMacro("__declspec", "__declspec"); + else + // Provide alias of __attribute__ like mingw32-gcc. + Builder.defineMacro("__declspec(a)", "__attribute__((a))"); } }; } // end anonymous namespace @@ -1699,13 +1827,15 @@ class ARMTargetInfo : public TargetInfo { // FIXME: Should we just treat this as a feature? IsThumb = getTriple().getArchName().startswith("thumb"); if (IsThumb) { + // Thumb1 add sp, #imm requires the immediate value be multiple of 4, + // so set preferred for small types to 32. DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-" - "v64:64:64-v128:128:128-a0:0:32-n32"); + "v64:64:64-v128:64:128-a0:0:32-n32"); } else { DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-" - "v64:64:64-v128:128:128-a0:0:64-n32"); + "v64:64:64-v128:64:128-a0:0:64-n32"); } // ARM targets default to using the ARM C++ ABI. @@ -1728,13 +1858,15 @@ class ARMTargetInfo : public TargetInfo { UseBitFieldTypeAlignment = false; if (IsThumb) { + // Thumb1 add sp, #imm requires the immediate value be multiple of 4, + // so set preferred for small types to 32. DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-" "i64:32:32-f32:32:32-f64:32:32-" - "v64:64:64-v128:128:128-a0:0:32-n32"); + "v64:32:64-v128:32:128-a0:0:32-n32"); } else { DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" - "i64:32:32-f32:32:32-f64:32:32-" - "v64:64:64-v128:128:128-a0:0:64-n32"); + "i64:32:64-f32:32:32-f64:32:64-" + "v64:32:64-v128:32:128-a0:0:32-n32"); } // FIXME: Override "preferred align" for double and long long. @@ -1821,6 +1953,7 @@ class ARMTargetInfo : public TargetInfo { .Cases("arm1156t2-s", "arm1156t2f-s", "6T2") .Cases("cortex-a8", "cortex-a9", "7A") .Case("cortex-m3", "7M") + .Case("cortex-m0", "6M") .Default(0); } virtual bool setCPU(const std::string &Name) { @@ -1983,7 +2116,7 @@ class DarwinARMTargetInfo : protected: virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, MacroBuilder &Builder) const { - getDarwinDefines(Builder, Opts, Triple); + getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); } public: @@ -2562,11 +2695,12 @@ static TargetInfo *AllocateTarget(const std::string &T) { case llvm::Triple::arm: case llvm::Triple::thumb: + if (Triple.isOSDarwin()) + return new DarwinARMTargetInfo(T); + switch (os) { case llvm::Triple::Linux: return new LinuxTargetInfo(T); - case llvm::Triple::Darwin: - return new DarwinARMTargetInfo(T); case llvm::Triple::FreeBSD: return new FreeBSDTargetInfo(T); default: @@ -2594,14 +2728,14 @@ static TargetInfo *AllocateTarget(const std::string &T) { return new MipselTargetInfo(T); case llvm::Triple::ppc: - if (os == llvm::Triple::Darwin) + if (Triple.isOSDarwin()) return new DarwinPPC32TargetInfo(T); else if (os == llvm::Triple::FreeBSD) return new FreeBSDTargetInfo(T); return new PPC32TargetInfo(T); case llvm::Triple::ppc64: - if (os == llvm::Triple::Darwin) + if (Triple.isOSDarwin()) return new DarwinPPC64TargetInfo(T); else if (os == llvm::Triple::Lv2) return new PS3PPUTargetInfo(T); @@ -2609,6 +2743,11 @@ static TargetInfo *AllocateTarget(const std::string &T) { return new FreeBSDTargetInfo(T); return new PPC64TargetInfo(T); + case llvm::Triple::ptx32: + return new PTX32TargetInfo(T); + case llvm::Triple::ptx64: + return new PTX64TargetInfo(T); + case llvm::Triple::mblaze: return new MBlazeTargetInfo(T); @@ -2630,11 +2769,12 @@ static TargetInfo *AllocateTarget(const std::string &T) { return new TCETargetInfo(T); case llvm::Triple::x86: + if (Triple.isOSDarwin()) + return new DarwinI386TargetInfo(T); + switch (os) { case llvm::Triple::AuroraUX: return new AuroraUXTargetInfo(T); - case llvm::Triple::Darwin: - return new DarwinI386TargetInfo(T); case llvm::Triple::Linux: return new LinuxTargetInfo(T); case llvm::Triple::DragonFly: @@ -2662,11 +2802,12 @@ static TargetInfo *AllocateTarget(const std::string &T) { } case llvm::Triple::x86_64: + if (Triple.isOSDarwin() || Triple.getEnvironment() == llvm::Triple::MachO) + return new DarwinX86_64TargetInfo(T); + switch (os) { case llvm::Triple::AuroraUX: return new AuroraUXTargetInfo(T); - case llvm::Triple::Darwin: - return new DarwinX86_64TargetInfo(T); case llvm::Triple::Linux: return new LinuxTargetInfo(T); case llvm::Triple::DragonFly: @@ -2682,10 +2823,7 @@ static TargetInfo *AllocateTarget(const std::string &T) { case llvm::Triple::MinGW32: return new MinGWX86_64TargetInfo(T); case llvm::Triple::Win32: // This is what Triple.h supports now. - if (Triple.getEnvironment() == llvm::Triple::MachO) - return new DarwinX86_64TargetInfo(T); - else - return new VisualStudioWindowsX86_64TargetInfo(T); + return new VisualStudioWindowsX86_64TargetInfo(T); default: return new X86_64TargetInfo(T); } diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp index 3a82e5d23a4d..89076cabc97c 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Version.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp @@ -17,11 +17,12 @@ #include #include -using namespace std; - namespace clang { std::string getClangRepositoryPath() { +#if defined(CLANG_REPOSITORY_STRING) + return CLANG_REPOSITORY_STRING; +#else #ifdef SVN_REPOSITORY llvm::StringRef URL(SVN_REPOSITORY); #else @@ -45,6 +46,7 @@ std::string getClangRepositoryPath() { URL = URL.substr(Start + 4); return URL; +#endif } std::string getClangRevision() { @@ -89,4 +91,17 @@ std::string getClangFullVersion() { return OS.str(); } +std::string getClangFullCPPVersion() { + // The version string we report in __VERSION__ is just a compacted version of + // the one we report on the command line. + std::string buf; + llvm::raw_string_ostream OS(buf); +#ifdef CLANG_VENDOR + OS << CLANG_VENDOR; +#endif + OS << "Clang " CLANG_VERSION_STRING " (" + << getClangFullRepositoryVersion() << ')'; + return OS.str(); +} + } // end namespace clang diff --git a/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp b/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp new file mode 100644 index 000000000000..d5cf126ff487 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Basic/VersionTuple.cpp @@ -0,0 +1,36 @@ +//===- VersionTuple.cpp - Version Number Handling ---------------*- 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 the VersionTuple class, which represents a version in +// the form major[.minor[.subminor]]. +// +//===----------------------------------------------------------------------===// +#include "clang/Basic/VersionTuple.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; + +std::string VersionTuple::getAsString() const { + std::string Result; + { + llvm::raw_string_ostream Out(Result); + Out << *this; + } + return Result; +} + +llvm::raw_ostream& clang::operator<<(llvm::raw_ostream &Out, + const VersionTuple &V) { + Out << V.getMajor(); + if (llvm::Optional Minor = V.getMinor()) + Out << '.' << *Minor; + if (llvm::Optional Subminor = V.getSubminor()) + Out << '.' << *Subminor; + return Out; +} diff --git a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp index 9897b1b1a028..1264473dabce 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp @@ -30,6 +30,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" +#include "llvm/Transforms/Instrumentation.h" using namespace clang; using namespace llvm; @@ -108,9 +109,9 @@ void EmitAssemblyHelper::CreatePasses() { OptLevel = 0; Inlining = CodeGenOpts.NoInlining; } - + FunctionPassManager *FPM = getPerFunctionPasses(); - + TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(TheModule->getTargetTriple())); if (!CodeGenOpts.SimplifyLibCalls) @@ -133,8 +134,10 @@ void EmitAssemblyHelper::CreatePasses() { // // FIXME: Derive these constants in a principled fashion. unsigned Threshold = 225; - if (CodeGenOpts.OptimizeSize) + if (CodeGenOpts.OptimizeSize == 1) //-Os Threshold = 75; + else if (CodeGenOpts.OptimizeSize == 2) //-Oz + Threshold = 25; else if (OptLevel > 2) Threshold = 275; InliningPass = createFunctionInliningPass(Threshold); @@ -146,12 +149,19 @@ void EmitAssemblyHelper::CreatePasses() { } PassManager *MPM = getPerModulePasses(); - + TLI = new TargetLibraryInfo(Triple(TheModule->getTargetTriple())); if (!CodeGenOpts.SimplifyLibCalls) TLI->disableAllFunctions(); MPM->add(TLI); + if (CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes) { + MPM->add(createGCOVProfilerPass(CodeGenOpts.EmitGcovNotes, + CodeGenOpts.EmitGcovArcs)); + if (!CodeGenOpts.DebugInfo) + MPM->add(createStripSymbolsPass(true)); + } + // For now we always create per module passes. llvm::createStandardModulePasses(MPM, OptLevel, CodeGenOpts.OptimizeSize, @@ -190,7 +200,7 @@ bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, } // Set float ABI type. - if (CodeGenOpts.FloatABI == "soft") + if (CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp") llvm::FloatABIType = llvm::FloatABI::Soft; else if (CodeGenOpts.FloatABI == "hard") llvm::FloatABIType = llvm::FloatABI::Hard; @@ -248,6 +258,8 @@ bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, } if (llvm::TimePassesIsEnabled) BackendArgs.push_back("-time-passes"); + for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i) + BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str()); BackendArgs.push_back(0); llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, const_cast(&BackendArgs[0])); @@ -266,6 +278,10 @@ bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, if (CodeGenOpts.RelaxAll) TM->setMCRelaxAll(true); + if (CodeGenOpts.SaveTempLabels) + TM->setMCSaveTempLabels(true); + if (CodeGenOpts.NoDwarf2CFIAsm) + TM->setMCUseCFI(false); // Create the code generator passes. PassManager *PM = getCodeGenPasses(); @@ -319,6 +335,9 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) { return; } + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + // Run passes. For now we do all passes at once, but eventually we // would like to have the option of streaming code generation. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp index 9587de223aa7..99a69a4f4a93 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp @@ -27,13 +27,16 @@ using namespace CodeGen; CGBlockInfo::CGBlockInfo(const BlockExpr *blockExpr, const char *N) : Name(N), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), - HasCXXObject(false), StructureType(0), Block(blockExpr) { + HasCXXObject(false), UsesStret(false), StructureType(0), Block(blockExpr) { // Skip asm prefix, if any. if (Name && Name[0] == '\01') ++Name; } +// Anchor the vtable to this translation unit. +CodeGenModule::ByrefHelpers::~ByrefHelpers() {} + /// Build the given block as a global block. static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, const CGBlockInfo &blockInfo, @@ -104,23 +107,6 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType()); } -static BlockFlags computeBlockFlag(CodeGenModule &CGM, - const BlockExpr *BE, - BlockFlags flags) { - const FunctionType *ftype = BE->getFunctionType(); - - // This is a bit overboard. - CallArgList args; - const CGFunctionInfo &fnInfo = - CGM.getTypes().getFunctionInfo(ftype->getResultType(), args, - ftype->getExtInfo()); - - if (CGM.ReturnTypeUsesSRet(fnInfo)) - flags |= BLOCK_USE_STRET; - - return flags; -} - /* Purely notional variadic template describing the layout of a block. @@ -536,7 +522,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { BlockFlags flags = BLOCK_HAS_SIGNATURE; if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ; - flags = computeBlockFlag(CGM, blockInfo.getBlockExpr(), flags); + if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; // Initialize the block literal. Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa")); @@ -630,7 +616,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue, declRef, VK_RValue); - EmitAnyExprToMem(&l2r, blockField, /*volatile*/ false, /*init*/ true); + EmitExprAsInit(&l2r, variable, blockField, + getContext().getDeclAlign(variable), + /*captured by init*/ false); } // Push a destructor if necessary. The semantics for when this @@ -734,7 +722,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, // Add the block literal. QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy); CallArgList Args; - Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy)); + Args.add(RValue::get(BlockLiteral), VoidPtrTy); QualType FnType = BPT->getPointeeType(); @@ -745,7 +733,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, // Load the function. llvm::Value *Func = Builder.CreateLoad(FuncPtr, "tmp"); - const FunctionType *FuncTy = FnType->getAs(); + const FunctionType *FuncTy = FnType->castAs(); QualType ResultType = FuncTy->getResultType(); const CGFunctionInfo &FnInfo = @@ -834,8 +822,9 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, fields[0] = CGM.getNSConcreteGlobalBlock(); // __flags - BlockFlags flags = computeBlockFlag(CGM, blockInfo.getBlockExpr(), - BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE); + BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE; + if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; + fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask()); // Reserved @@ -873,7 +862,10 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const DeclMapTy &ldm) { const BlockDecl *blockDecl = blockInfo.getBlockDecl(); - DebugInfo = CGM.getDebugInfo(); + // Check if we should generate debug info for this block function. + if (CGM.getModuleDebugInfo()) + DebugInfo = CGM.getModuleDebugInfo(); + BlockInfo = &blockInfo; // Arrange for local static and local extern declarations to appear @@ -897,12 +889,12 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, ImplicitParamDecl selfDecl(const_cast(blockDecl), SourceLocation(), II, selfTy); - args.push_back(std::make_pair(&selfDecl, selfTy)); + args.push_back(&selfDecl); // Now add the rest of the parameters. for (BlockDecl::param_const_iterator i = blockDecl->param_begin(), e = blockDecl->param_end(); i != e; ++i) - args.push_back(std::make_pair(*i, (*i)->getType())); + args.push_back(*i); // Create the function declaration. const FunctionProtoType *fnType = @@ -910,6 +902,9 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const CGFunctionInfo &fnInfo = CGM.getTypes().getFunctionInfo(fnType->getResultType(), args, fnType->getExtInfo()); + if (CGM.ReturnTypeUsesSRet(fnInfo)) + blockInfo.UsesStret = true; + const llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo, fnType->isVariadic()); @@ -921,8 +916,8 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); // Begin generating the function. - StartFunction(blockDecl, fnType->getResultType(), fn, args, - blockInfo.getBlockExpr()->getBody()->getLocEnd()); + StartFunction(blockDecl, fnType->getResultType(), fn, fnInfo, args, + blockInfo.getBlockExpr()->getBody()->getLocStart()); CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl // Okay. Undo some of what StartFunction did. @@ -1049,13 +1044,10 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { ASTContext &C = getContext(); FunctionArgList args; - // FIXME: This leaks - ImplicitParamDecl *dstDecl = - ImplicitParamDecl::Create(C, 0, SourceLocation(), 0, C.VoidPtrTy); - args.push_back(std::make_pair(dstDecl, dstDecl->getType())); - ImplicitParamDecl *srcDecl = - ImplicitParamDecl::Create(C, 0, SourceLocation(), 0, C.VoidPtrTy); - args.push_back(std::make_pair(srcDecl, srcDecl->getType())); + ImplicitParamDecl dstDecl(0, SourceLocation(), 0, C.VoidPtrTy); + args.push_back(&dstDecl); + ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); + args.push_back(&srcDecl); const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo()); @@ -1073,20 +1065,21 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), II, C.VoidTy, 0, SC_Static, SC_None, false, true); - StartFunction(FD, C.VoidTy, Fn, args, SourceLocation()); + StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); - llvm::Value *src = GetAddrOfLocalVar(srcDecl); + llvm::Value *src = GetAddrOfLocalVar(&srcDecl); src = Builder.CreateLoad(src); src = Builder.CreateBitCast(src, structPtrTy, "block.source"); - llvm::Value *dst = GetAddrOfLocalVar(dstDecl); + llvm::Value *dst = GetAddrOfLocalVar(&dstDecl); dst = Builder.CreateLoad(dst); dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest"); @@ -1143,10 +1136,8 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { ASTContext &C = getContext(); FunctionArgList args; - // FIXME: This leaks - ImplicitParamDecl *srcDecl = - ImplicitParamDecl::Create(C, 0, SourceLocation(), 0, C.VoidPtrTy); - args.push_back(std::make_pair(srcDecl, srcDecl->getType())); + ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); + args.push_back(&srcDecl); const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo()); @@ -1163,15 +1154,16 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { = &CGM.getContext().Idents.get("__destroy_helper_block_"); FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), II, C.VoidTy, 0, SC_Static, SC_None, false, true); - StartFunction(FD, C.VoidTy, Fn, args, SourceLocation()); + StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); - llvm::Value *src = GetAddrOfLocalVar(srcDecl); + llvm::Value *src = GetAddrOfLocalVar(&srcDecl); src = Builder.CreateLoad(src); src = Builder.CreateBitCast(src, structPtrTy, "block"); @@ -1229,99 +1221,158 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); } -llvm::Constant *CodeGenFunction:: -GeneratebyrefCopyHelperFunction(const llvm::Type *T, BlockFieldFlags flags, - const VarDecl *variable) { - QualType R = getContext().VoidTy; +namespace { - FunctionArgList Args; - // FIXME: This leaks - ImplicitParamDecl *Dst = - ImplicitParamDecl::Create(getContext(), 0, - SourceLocation(), 0, - getContext().getPointerType(getContext().VoidTy)); - Args.push_back(std::make_pair(Dst, Dst->getType())); +/// Emits the copy/dispose helper functions for a __block object of id type. +class ObjectByrefHelpers : public CodeGenModule::ByrefHelpers { + BlockFieldFlags Flags; - // FIXME: This leaks - ImplicitParamDecl *Src = - ImplicitParamDecl::Create(getContext(), 0, - SourceLocation(), 0, - getContext().getPointerType(getContext().VoidTy)); - Args.push_back(std::make_pair(Src, Src->getType())); +public: + ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags) + : ByrefHelpers(alignment), Flags(flags) {} + + void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, + llvm::Value *srcField) { + destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy); + + srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy); + llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField); + + unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask(); + + llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); + llvm::Value *fn = CGF.CGM.getBlockObjectAssign(); + CGF.Builder.CreateCall3(fn, destField, srcValue, flagsVal); + } + + void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { + field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0)); + llvm::Value *value = CGF.Builder.CreateLoad(field); + + CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER); + } + + void profileImpl(llvm::FoldingSetNodeID &id) const { + id.AddInteger(Flags.getBitMask()); + } +}; + +/// Emits the copy/dispose helpers for a __block variable with a +/// nontrivial copy constructor or destructor. +class CXXByrefHelpers : public CodeGenModule::ByrefHelpers { + QualType VarType; + const Expr *CopyExpr; + +public: + CXXByrefHelpers(CharUnits alignment, QualType type, + const Expr *copyExpr) + : ByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {} + + bool needsCopy() const { return CopyExpr != 0; } + void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, + llvm::Value *srcField) { + if (!CopyExpr) return; + CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr); + } + + void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { + EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); + CGF.PushDestructorCleanup(VarType, field); + CGF.PopCleanupBlocks(cleanupDepth); + } + + void profileImpl(llvm::FoldingSetNodeID &id) const { + id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); + } +}; +} // end anonymous namespace + +static llvm::Constant * +generateByrefCopyHelper(CodeGenFunction &CGF, + const llvm::StructType &byrefType, + CodeGenModule::ByrefHelpers &byrefInfo) { + ASTContext &Context = CGF.getContext(); + + QualType R = Context.VoidTy; + + FunctionArgList args; + ImplicitParamDecl dst(0, SourceLocation(), 0, Context.VoidPtrTy); + args.push_back(&dst); + + ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); + args.push_back(&src); const CGFunctionInfo &FI = - CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo()); + CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo()); - CodeGenTypes &Types = CGM.getTypes(); + CodeGenTypes &Types = CGF.CGM.getTypes(); const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); // FIXME: We'd like to put these into a mergable by content, with // internal linkage. llvm::Function *Fn = llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, - "__Block_byref_object_copy_", &CGM.getModule()); + "__Block_byref_object_copy_", &CGF.CGM.getModule()); IdentifierInfo *II - = &CGM.getContext().Idents.get("__Block_byref_object_copy_"); + = &Context.Idents.get("__Block_byref_object_copy_"); - FunctionDecl *FD = FunctionDecl::Create(getContext(), - getContext().getTranslationUnitDecl(), + FunctionDecl *FD = FunctionDecl::Create(Context, + Context.getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), II, R, 0, SC_Static, SC_None, false, true); - StartFunction(FD, R, Fn, Args, SourceLocation()); + CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); - // dst->x - llvm::Value *V = GetAddrOfLocalVar(Dst); - V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0)); - V = Builder.CreateLoad(V); - V = Builder.CreateStructGEP(V, 6, "x"); - llvm::Value *DstObj = V; + if (byrefInfo.needsCopy()) { + const llvm::Type *byrefPtrType = byrefType.getPointerTo(0); - // src->x - V = GetAddrOfLocalVar(Src); - V = Builder.CreateLoad(V); - V = Builder.CreateBitCast(V, T); - V = Builder.CreateStructGEP(V, 6, "x"); - - if (Expr *copyExpr = getContext().getBlockVarCopyInits(variable)) { - llvm::Value *SrcObj = V; - EmitSynthesizedCXXCopyCtor(DstObj, SrcObj, copyExpr); - } else { - DstObj = Builder.CreateBitCast(DstObj, VoidPtrTy); - V = Builder.CreateBitCast(V, VoidPtrPtrTy); - llvm::Value *SrcObj = Builder.CreateLoad(V); - flags |= BLOCK_BYREF_CALLER; - llvm::Value *N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask()); - llvm::Value *F = CGM.getBlockObjectAssign(); - Builder.CreateCall3(F, DstObj, SrcObj, N); - } - - FinishFunction(); + // dst->x + llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst); + destField = CGF.Builder.CreateLoad(destField); + destField = CGF.Builder.CreateBitCast(destField, byrefPtrType); + destField = CGF.Builder.CreateStructGEP(destField, 6, "x"); - return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy); + // src->x + llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src); + srcField = CGF.Builder.CreateLoad(srcField); + srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType); + srcField = CGF.Builder.CreateStructGEP(srcField, 6, "x"); + + byrefInfo.emitCopy(CGF, destField, srcField); + } + + CGF.FinishFunction(); + + return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); } -llvm::Constant * -CodeGenFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, - BlockFieldFlags flags, - const VarDecl *variable) { - QualType R = getContext().VoidTy; +/// Build the copy helper for a __block variable. +static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM, + const llvm::StructType &byrefType, + CodeGenModule::ByrefHelpers &info) { + CodeGenFunction CGF(CGM); + return generateByrefCopyHelper(CGF, byrefType, info); +} - FunctionArgList Args; - // FIXME: This leaks - ImplicitParamDecl *Src = - ImplicitParamDecl::Create(getContext(), 0, - SourceLocation(), 0, - getContext().getPointerType(getContext().VoidTy)); +/// Generate code for a __block variable's dispose helper. +static llvm::Constant * +generateByrefDisposeHelper(CodeGenFunction &CGF, + const llvm::StructType &byrefType, + CodeGenModule::ByrefHelpers &byrefInfo) { + ASTContext &Context = CGF.getContext(); + QualType R = Context.VoidTy; - Args.push_back(std::make_pair(Src, Src->getType())); + FunctionArgList args; + ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); + args.push_back(&src); const CGFunctionInfo &FI = - CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo()); + CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo()); - CodeGenTypes &Types = CGM.getTypes(); + CodeGenTypes &Types = CGF.CGM.getTypes(); const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); // FIXME: We'd like to put these into a mergable by content, with @@ -1329,81 +1380,255 @@ CodeGenFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, llvm::Function *Fn = llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, "__Block_byref_object_dispose_", - &CGM.getModule()); + &CGF.CGM.getModule()); IdentifierInfo *II - = &CGM.getContext().Idents.get("__Block_byref_object_dispose_"); + = &Context.Idents.get("__Block_byref_object_dispose_"); - FunctionDecl *FD = FunctionDecl::Create(getContext(), - getContext().getTranslationUnitDecl(), + FunctionDecl *FD = FunctionDecl::Create(Context, + Context.getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), II, R, 0, SC_Static, SC_None, false, true); - StartFunction(FD, R, Fn, Args, SourceLocation()); + CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); - llvm::Value *V = GetAddrOfLocalVar(Src); - V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0)); - V = Builder.CreateLoad(V); - V = Builder.CreateStructGEP(V, 6, "x"); + if (byrefInfo.needsDispose()) { + llvm::Value *V = CGF.GetAddrOfLocalVar(&src); + V = CGF.Builder.CreateLoad(V); + V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0)); + V = CGF.Builder.CreateStructGEP(V, 6, "x"); - // If it's not any kind of special object, it must have a destructor - // or something. - if (!flags.isSpecialPointer()) { - EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin(); - PushDestructorCleanup(variable->getType(), V); - PopCleanupBlocks(CleanupDepth); - - // Otherwise, call _Block_object_dispose. - } else { - V = Builder.CreateBitCast(V, llvm::PointerType::get(Int8PtrTy, 0)); - V = Builder.CreateLoad(V); - - flags |= BLOCK_BYREF_CALLER; - BuildBlockRelease(V, flags); + byrefInfo.emitDispose(CGF, V); } - FinishFunction(); + CGF.FinishFunction(); - return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy); + return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); } -llvm::Constant *CodeGenModule::BuildbyrefCopyHelper(const llvm::Type *T, - BlockFieldFlags flags, - unsigned align, - const VarDecl *var) { - // All alignments below pointer alignment are bumped up, as we - // always have at least that much alignment to begin with. - if (align < PointerAlignInBytes) align = PointerAlignInBytes; - - // As an optimization, we only generate a single function of each kind we - // might need. We need a different one for each alignment and for each - // setting of flags. We mix Align and flag to get the kind. - uint64_t Kind = (uint64_t)align*BLOCK_BYREF_CURRENT_MAX + flags.getBitMask(); - llvm::Constant *&Entry = AssignCache[Kind]; - if (!Entry) - Entry = CodeGenFunction(*this). - GeneratebyrefCopyHelperFunction(T, flags, var); - return Entry; +/// Build the dispose helper for a __block variable. +static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM, + const llvm::StructType &byrefType, + CodeGenModule::ByrefHelpers &info) { + CodeGenFunction CGF(CGM); + return generateByrefDisposeHelper(CGF, byrefType, info); } -llvm::Constant *CodeGenModule::BuildbyrefDestroyHelper(const llvm::Type *T, - BlockFieldFlags flags, - unsigned align, - const VarDecl *var) { - // All alignments below pointer alignment are bumped up, as we - // always have at least that much alignment to begin with. - if (align < PointerAlignInBytes) align = PointerAlignInBytes; +/// +template static T *buildByrefHelpers(CodeGenModule &CGM, + const llvm::StructType &byrefTy, + T &byrefInfo) { + // Increase the field's alignment to be at least pointer alignment, + // since the layout of the byref struct will guarantee at least that. + byrefInfo.Alignment = std::max(byrefInfo.Alignment, + CharUnits::fromQuantity(CGM.PointerAlignInBytes)); + + llvm::FoldingSetNodeID id; + byrefInfo.Profile(id); + + void *insertPos; + CodeGenModule::ByrefHelpers *node + = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos); + if (node) return static_cast(node); + + byrefInfo.CopyHelper = buildByrefCopyHelper(CGM, byrefTy, byrefInfo); + byrefInfo.DisposeHelper = buildByrefDisposeHelper(CGM, byrefTy, byrefInfo); + + T *copy = new (CGM.getContext()) T(byrefInfo); + CGM.ByrefHelpersCache.InsertNode(copy, insertPos); + return copy; +} + +CodeGenModule::ByrefHelpers * +CodeGenFunction::buildByrefHelpers(const llvm::StructType &byrefType, + const AutoVarEmission &emission) { + const VarDecl &var = *emission.Variable; + QualType type = var.getType(); + + if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { + const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var); + if (!copyExpr && record->hasTrivialDestructor()) return 0; + + CXXByrefHelpers byrefInfo(emission.Alignment, type, copyExpr); + return ::buildByrefHelpers(CGM, byrefType, byrefInfo); + } + + BlockFieldFlags flags; + if (type->isBlockPointerType()) { + flags |= BLOCK_FIELD_IS_BLOCK; + } else if (CGM.getContext().isObjCNSObjectType(type) || + type->isObjCObjectPointerType()) { + flags |= BLOCK_FIELD_IS_OBJECT; + } else { + return 0; + } + + if (type.isObjCGCWeak()) + flags |= BLOCK_FIELD_IS_WEAK; + + ObjectByrefHelpers byrefInfo(emission.Alignment, flags); + return ::buildByrefHelpers(CGM, byrefType, byrefInfo); +} + +unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const { + assert(ByRefValueInfo.count(VD) && "Did not find value!"); - // As an optimization, we only generate a single function of each kind we - // might need. We need a different one for each alignment and for each - // setting of flags. We mix Align and flag to get the kind. - uint64_t Kind = (uint64_t)align*BLOCK_BYREF_CURRENT_MAX + flags.getBitMask(); - llvm::Constant *&Entry = DestroyCache[Kind]; - if (!Entry) - Entry = CodeGenFunction(*this). - GeneratebyrefDestroyHelperFunction(T, flags, var); - return Entry; + return ByRefValueInfo.find(VD)->second.second; +} + +llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr, + const VarDecl *V) { + llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding"); + Loc = Builder.CreateLoad(Loc); + Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V), + V->getNameAsString()); + return Loc; +} + +/// BuildByRefType - This routine changes a __block variable declared as T x +/// into: +/// +/// struct { +/// void *__isa; +/// void *__forwarding; +/// int32_t __flags; +/// int32_t __size; +/// void *__copy_helper; // only if needed +/// void *__destroy_helper; // only if needed +/// char padding[X]; // only if needed +/// T x; +/// } x +/// +const llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) { + std::pair &Info = ByRefValueInfo[D]; + if (Info.first) + return Info.first; + + QualType Ty = D->getType(); + + std::vector Types; + + llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(getLLVMContext()); + + // void *__isa; + Types.push_back(Int8PtrTy); + + // void *__forwarding; + Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder)); + + // int32_t __flags; + Types.push_back(Int32Ty); + + // int32_t __size; + Types.push_back(Int32Ty); + + bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty); + if (HasCopyAndDispose) { + /// void *__copy_helper; + Types.push_back(Int8PtrTy); + + /// void *__destroy_helper; + Types.push_back(Int8PtrTy); + } + + bool Packed = false; + CharUnits Align = getContext().getDeclAlign(D); + if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) { + // We have to insert padding. + + // The struct above has 2 32-bit integers. + unsigned CurrentOffsetInBytes = 4 * 2; + + // And either 2 or 4 pointers. + CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) * + CGM.getTargetData().getTypeAllocSize(Int8PtrTy); + + // Align the offset. + unsigned AlignedOffsetInBytes = + llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity()); + + unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes; + if (NumPaddingBytes > 0) { + const llvm::Type *Ty = llvm::Type::getInt8Ty(getLLVMContext()); + // FIXME: We need a sema error for alignment larger than the minimum of + // the maximal stack alignmint and the alignment of malloc on the system. + if (NumPaddingBytes > 1) + Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); + + Types.push_back(Ty); + + // We want a packed struct. + Packed = true; + } + } + + // T x; + Types.push_back(ConvertTypeForMem(Ty)); + + const llvm::Type *T = llvm::StructType::get(getLLVMContext(), Types, Packed); + + cast(ByRefTypeHolder.get())->refineAbstractTypeTo(T); + CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(), + ByRefTypeHolder.get()); + + Info.first = ByRefTypeHolder.get(); + + Info.second = Types.size() - 1; + + return Info.first; +} + +/// Initialize the structural components of a __block variable, i.e. +/// everything but the actual object. +void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { + // Find the address of the local. + llvm::Value *addr = emission.Address; + + // That's an alloca of the byref structure type. + const llvm::StructType *byrefType = cast( + cast(addr->getType())->getElementType()); + + // Build the byref helpers if necessary. This is null if we don't need any. + CodeGenModule::ByrefHelpers *helpers = + buildByrefHelpers(*byrefType, emission); + + const VarDecl &D = *emission.Variable; + QualType type = D.getType(); + + llvm::Value *V; + + // Initialize the 'isa', which is just 0 or 1. + int isa = 0; + if (type.isObjCGCWeak()) + isa = 1; + V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); + Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa")); + + // Store the address of the variable into its own forwarding pointer. + Builder.CreateStore(addr, + Builder.CreateStructGEP(addr, 1, "byref.forwarding")); + + // Blocks ABI: + // c) the flags field is set to either 0 if no helper functions are + // needed or BLOCK_HAS_COPY_DISPOSE if they are, + BlockFlags flags; + if (helpers) flags |= BLOCK_HAS_COPY_DISPOSE; + Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), + Builder.CreateStructGEP(addr, 2, "byref.flags")); + + CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType); + V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity()); + Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size")); + + if (helpers) { + llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4); + Builder.CreateStore(helpers->CopyHelper, copy_helper); + + llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5); + Builder.CreateStore(helpers->DisposeHelper, destroy_helper); + } } void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) { @@ -1413,3 +1638,26 @@ void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) { N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask()); Builder.CreateCall2(F, V, N); } + +namespace { + struct CallBlockRelease : EHScopeStack::Cleanup { + llvm::Value *Addr; + CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {} + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF); + } + }; +} + +/// Enter a cleanup to destroy a __block variable. Note that this +/// cleanup should be a no-op if the variable hasn't left the stack +/// yet; if a cleanup is required for the variable itself, that needs +/// to be done externally. +void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) { + // We don't enter this cleanup if we're in pure-GC mode. + if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) + return; + + EHStack.pushCleanup(NormalAndEHCleanup, emission.Address); +} diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h index 0bc8bcaa14f9..9bd18e5fde74 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h @@ -173,6 +173,10 @@ class CGBlockInfo { /// need to be run even in GC mode. bool HasCXXObject : 1; + /// UsesStret : True if the block uses an stret return. Mutable + /// because it gets set later in the block-creation process. + mutable bool UsesStret : 1; + const llvm::StructType *StructureType; const BlockExpr *Block; CharUnits BlockSize; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp index 5eeb605f18ee..7a0c8da50248 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp @@ -176,7 +176,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E) { // See if we can constant fold this builtin. If so, don't emit it at all. Expr::EvalResult Result; - if (E->Evaluate(Result, CGM.getContext())) { + if (E->Evaluate(Result, CGM.getContext()) && + !Result.hasSideEffects()) { if (Result.Val.isInt()) return RValue::get(llvm::ConstantInt::get(getLLVMContext(), Result.Val.getInt())); @@ -312,9 +313,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, } case Builtin::BI__builtin_expect: { // FIXME: pass expect through to LLVM + Value *ArgValue = EmitScalarExpr(E->getArg(0)); if (E->getArg(1)->HasSideEffects(getContext())) (void)EmitScalarExpr(E->getArg(1)); - return RValue::get(EmitScalarExpr(E->getArg(0))); + return RValue::get(ArgValue); } case Builtin::BI__builtin_bswap32: case Builtin::BI__builtin_bswap64: { @@ -473,7 +475,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, BasicBlock *End = createBasicBlock("fpclassify_end", this->CurFn); Builder.SetInsertPoint(End); PHINode *Result = - Builder.CreatePHI(ConvertType(E->getArg(0)->getType()), + Builder.CreatePHI(ConvertType(E->getArg(0)->getType()), 4, "fpclassify_result"); // if (V==0) return FP_ZERO @@ -543,6 +545,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Address); } + case Builtin::BI__builtin___memcpy_chk: { + // fold __builtin_memcpy_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. + if (!E->getArg(2)->isEvaluatable(CGM.getContext()) || + !E->getArg(3)->isEvaluatable(CGM.getContext())) + break; + llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext()); + llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext()); + if (Size.ugt(DstSize)) + break; + Value *Dest = EmitScalarExpr(E->getArg(0)); + Value *Src = EmitScalarExpr(E->getArg(1)); + Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); + Builder.CreateMemCpy(Dest, Src, SizeVal, 1, false); + return RValue::get(Dest); + } + case Builtin::BI__builtin_objc_memmove_collectable: { Value *Address = EmitScalarExpr(E->getArg(0)); Value *SrcAddr = EmitScalarExpr(E->getArg(1)); @@ -551,7 +569,23 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Address, SrcAddr, SizeVal); return RValue::get(Address); } - + + case Builtin::BI__builtin___memmove_chk: { + // fold __builtin_memmove_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. + if (!E->getArg(2)->isEvaluatable(CGM.getContext()) || + !E->getArg(3)->isEvaluatable(CGM.getContext())) + break; + llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext()); + llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext()); + if (Size.ugt(DstSize)) + break; + Value *Dest = EmitScalarExpr(E->getArg(0)); + Value *Src = EmitScalarExpr(E->getArg(1)); + Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); + Builder.CreateMemMove(Dest, Src, SizeVal, 1, false); + return RValue::get(Dest); + } + case Builtin::BImemmove: case Builtin::BI__builtin_memmove: { Value *Address = EmitScalarExpr(E->getArg(0)); @@ -569,6 +603,23 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Builder.CreateMemSet(Address, ByteVal, SizeVal, 1, false); return RValue::get(Address); } + case Builtin::BI__builtin___memset_chk: { + // fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. + if (!E->getArg(2)->isEvaluatable(CGM.getContext()) || + !E->getArg(3)->isEvaluatable(CGM.getContext())) + break; + llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext()); + llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext()); + if (Size.ugt(DstSize)) + break; + Value *Address = EmitScalarExpr(E->getArg(0)); + Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), + Builder.getInt8Ty()); + Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); + Builder.CreateMemSet(Address, ByteVal, SizeVal, 1, false); + + return RValue::get(Address); + } case Builtin::BI__builtin_dwarf_cfa: { // The offset in bytes from the first argument to the CFA. // @@ -721,6 +772,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__sync_bool_compare_and_swap: case Builtin::BI__sync_lock_test_and_set: case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_swap: assert(0 && "Shouldn't make it through sema"); case Builtin::BI__sync_fetch_and_add_1: case Builtin::BI__sync_fetch_and_add_2: @@ -860,6 +912,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Result); } + case Builtin::BI__sync_swap_1: + case Builtin::BI__sync_swap_2: + case Builtin::BI__sync_swap_4: + case Builtin::BI__sync_swap_8: + case Builtin::BI__sync_swap_16: + return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E); + case Builtin::BI__sync_lock_test_and_set_1: case Builtin::BI__sync_lock_test_and_set_2: case Builtin::BI__sync_lock_test_and_set_4: @@ -948,8 +1007,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return EmitCall(E->getCallee()->getType(), CGM.getBuiltinLibFunction(FD, BuiltinID), - ReturnValueSlot(), - E->arg_begin(), E->arg_end()); + ReturnValueSlot(), E->arg_begin(), E->arg_end(), FD); // See if we have a target specific intrinsic. const char *Name = getContext().BuiltinInfo.GetName(BuiltinID); @@ -1116,13 +1174,16 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { if (BuiltinID == ARM::BI__clear_cache) { const FunctionDecl *FD = E->getDirectCallee(); - Value *a = EmitScalarExpr(E->getArg(0)); - Value *b = EmitScalarExpr(E->getArg(1)); + // Oddly people write this call without args on occasion and gcc accepts + // it - it's also marked as varargs in the description file. + llvm::SmallVector Ops; + for (unsigned i = 0; i < E->getNumArgs(); i++) + Ops.push_back(EmitScalarExpr(E->getArg(i))); const llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType()); const llvm::FunctionType *FTy = cast(Ty); llvm::StringRef Name = FD->getName(); - return Builder.CreateCall2(CGM.CreateRuntimeFunction(FTy, Name), - a, b); + return Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), + Ops.begin(), Ops.end()); } llvm::SmallVector Ops; @@ -1462,9 +1523,9 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmulp, &Ty, 1), Ops, "vmul"); case ARM::BI__builtin_neon_vmull_v: - assert(poly && "vmull builtin only supported for polynomial types"); - return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmullp, &Ty, 1), - Ops, "vmull"); + Int = usgn ? Intrinsic::arm_neon_vmullu : Intrinsic::arm_neon_vmulls; + Int = poly ? (unsigned)Intrinsic::arm_neon_vmullp : Int; + return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vmull"); case ARM::BI__builtin_neon_vpadal_v: case ARM::BI__builtin_neon_vpadalq_v: { Int = usgn ? Intrinsic::arm_neon_vpadalu : Intrinsic::arm_neon_vpadals; @@ -2082,6 +2143,149 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, // If palignr is shifting the pair of vectors more than 32 bytes, emit zero. return llvm::Constant::getNullValue(ConvertType(E->getType())); } + case X86::BI__builtin_ia32_loaddqu: { + const llvm::Type *VecTy = ConvertType(E->getType()); + const llvm::Type *IntTy = llvm::IntegerType::get(getLLVMContext(), 128); + + Value *BC = Builder.CreateBitCast(Ops[0], + llvm::PointerType::getUnqual(IntTy), + "cast"); + LoadInst *LI = Builder.CreateLoad(BC); + LI->setAlignment(1); // Unaligned load. + return Builder.CreateBitCast(LI, VecTy, "loadu.cast"); + } + // 3DNow! + case X86::BI__builtin_ia32_pavgusb: + case X86::BI__builtin_ia32_pf2id: + case X86::BI__builtin_ia32_pfacc: + case X86::BI__builtin_ia32_pfadd: + case X86::BI__builtin_ia32_pfcmpeq: + case X86::BI__builtin_ia32_pfcmpge: + case X86::BI__builtin_ia32_pfcmpgt: + case X86::BI__builtin_ia32_pfmax: + case X86::BI__builtin_ia32_pfmin: + case X86::BI__builtin_ia32_pfmul: + case X86::BI__builtin_ia32_pfrcp: + case X86::BI__builtin_ia32_pfrcpit1: + case X86::BI__builtin_ia32_pfrcpit2: + case X86::BI__builtin_ia32_pfrsqrt: + case X86::BI__builtin_ia32_pfrsqit1: + case X86::BI__builtin_ia32_pfrsqrtit1: + case X86::BI__builtin_ia32_pfsub: + case X86::BI__builtin_ia32_pfsubr: + case X86::BI__builtin_ia32_pi2fd: + case X86::BI__builtin_ia32_pmulhrw: + case X86::BI__builtin_ia32_pf2iw: + case X86::BI__builtin_ia32_pfnacc: + case X86::BI__builtin_ia32_pfpnacc: + case X86::BI__builtin_ia32_pi2fw: + case X86::BI__builtin_ia32_pswapdsf: + case X86::BI__builtin_ia32_pswapdsi: { + const char *name = 0; + Intrinsic::ID ID = Intrinsic::not_intrinsic; + switch(BuiltinID) { + case X86::BI__builtin_ia32_pavgusb: + name = "pavgusb"; + ID = Intrinsic::x86_3dnow_pavgusb; + break; + case X86::BI__builtin_ia32_pf2id: + name = "pf2id"; + ID = Intrinsic::x86_3dnow_pf2id; + break; + case X86::BI__builtin_ia32_pfacc: + name = "pfacc"; + ID = Intrinsic::x86_3dnow_pfacc; + break; + case X86::BI__builtin_ia32_pfadd: + name = "pfadd"; + ID = Intrinsic::x86_3dnow_pfadd; + break; + case X86::BI__builtin_ia32_pfcmpeq: + name = "pfcmpeq"; + ID = Intrinsic::x86_3dnow_pfcmpeq; + break; + case X86::BI__builtin_ia32_pfcmpge: + name = "pfcmpge"; + ID = Intrinsic::x86_3dnow_pfcmpge; + break; + case X86::BI__builtin_ia32_pfcmpgt: + name = "pfcmpgt"; + ID = Intrinsic::x86_3dnow_pfcmpgt; + break; + case X86::BI__builtin_ia32_pfmax: + name = "pfmax"; + ID = Intrinsic::x86_3dnow_pfmax; + break; + case X86::BI__builtin_ia32_pfmin: + name = "pfmin"; + ID = Intrinsic::x86_3dnow_pfmin; + break; + case X86::BI__builtin_ia32_pfmul: + name = "pfmul"; + ID = Intrinsic::x86_3dnow_pfmul; + break; + case X86::BI__builtin_ia32_pfrcp: + name = "pfrcp"; + ID = Intrinsic::x86_3dnow_pfrcp; + break; + case X86::BI__builtin_ia32_pfrcpit1: + name = "pfrcpit1"; + ID = Intrinsic::x86_3dnow_pfrcpit1; + break; + case X86::BI__builtin_ia32_pfrcpit2: + name = "pfrcpit2"; + ID = Intrinsic::x86_3dnow_pfrcpit2; + break; + case X86::BI__builtin_ia32_pfrsqrt: + name = "pfrsqrt"; + ID = Intrinsic::x86_3dnow_pfrsqrt; + break; + case X86::BI__builtin_ia32_pfrsqit1: + case X86::BI__builtin_ia32_pfrsqrtit1: + name = "pfrsqit1"; + ID = Intrinsic::x86_3dnow_pfrsqit1; + break; + case X86::BI__builtin_ia32_pfsub: + name = "pfsub"; + ID = Intrinsic::x86_3dnow_pfsub; + break; + case X86::BI__builtin_ia32_pfsubr: + name = "pfsubr"; + ID = Intrinsic::x86_3dnow_pfsubr; + break; + case X86::BI__builtin_ia32_pi2fd: + name = "pi2fd"; + ID = Intrinsic::x86_3dnow_pi2fd; + break; + case X86::BI__builtin_ia32_pmulhrw: + name = "pmulhrw"; + ID = Intrinsic::x86_3dnow_pmulhrw; + break; + case X86::BI__builtin_ia32_pf2iw: + name = "pf2iw"; + ID = Intrinsic::x86_3dnowa_pf2iw; + break; + case X86::BI__builtin_ia32_pfnacc: + name = "pfnacc"; + ID = Intrinsic::x86_3dnowa_pfnacc; + break; + case X86::BI__builtin_ia32_pfpnacc: + name = "pfpnacc"; + ID = Intrinsic::x86_3dnowa_pfpnacc; + break; + case X86::BI__builtin_ia32_pi2fw: + name = "pi2fw"; + ID = Intrinsic::x86_3dnowa_pi2fw; + break; + case X86::BI__builtin_ia32_pswapdsf: + case X86::BI__builtin_ia32_pswapdsi: + name = "pswapd"; + ID = Intrinsic::x86_3dnowa_pswapd; + break; + } + llvm::Function *F = CGM.getIntrinsic(ID); + return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); + } } } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp index 7ffc6e732554..184147cb728d 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp @@ -194,39 +194,44 @@ void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { EmitGlobal(GlobalDecl(D, Ctor_Base)); } -void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, - CXXCtorType Type) { +void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor, + CXXCtorType ctorType) { // The complete constructor is equivalent to the base constructor // for classes with no virtual bases. Try to emit it as an alias. - if (Type == Ctor_Complete && - !D->getParent()->getNumVBases() && - !TryEmitDefinitionAsAlias(GlobalDecl(D, Ctor_Complete), - GlobalDecl(D, Ctor_Base))) + if (ctorType == Ctor_Complete && + !ctor->getParent()->getNumVBases() && + !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete), + GlobalDecl(ctor, Ctor_Base))) return; - llvm::Function *Fn = cast(GetAddrOfCXXConstructor(D, Type)); - setFunctionLinkage(D, Fn); + const CGFunctionInfo &fnInfo = getTypes().getFunctionInfo(ctor, ctorType); - CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); + llvm::Function *fn = + cast(GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo)); + setFunctionLinkage(ctor, fn); - SetFunctionDefinitionAttributes(D, Fn); - SetLLVMFunctionAttributesForDefinition(D, Fn); + CodeGenFunction(*this).GenerateCode(GlobalDecl(ctor, ctorType), fn, fnInfo); + + SetFunctionDefinitionAttributes(ctor, fn); + SetLLVMFunctionAttributesForDefinition(ctor, fn); } llvm::GlobalValue * -CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, - CXXCtorType Type) { - GlobalDecl GD(D, Type); +CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor, + CXXCtorType ctorType, + const CGFunctionInfo *fnInfo) { + GlobalDecl GD(ctor, ctorType); - llvm::StringRef Name = getMangledName(GD); - if (llvm::GlobalValue *V = GetGlobalValue(Name)) - return V; + llvm::StringRef name = getMangledName(GD); + if (llvm::GlobalValue *existing = GetGlobalValue(name)) + return existing; - const FunctionProtoType *FPT = D->getType()->getAs(); - const llvm::FunctionType *FTy = - getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), - FPT->isVariadic()); - return cast(GetOrCreateLLVMFunction(Name, FTy, GD, + if (!fnInfo) fnInfo = &getTypes().getFunctionInfo(ctor, ctorType); + + const FunctionProtoType *proto = ctor->getType()->castAs(); + const llvm::FunctionType *fnType = + getTypes().GetFunctionType(*fnInfo, proto->isVariadic()); + return cast(GetOrCreateLLVMFunction(name, fnType, GD, /*ForVTable=*/false)); } @@ -246,45 +251,51 @@ void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) { EmitGlobal(GlobalDecl(D, Dtor_Base)); } -void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, - CXXDtorType Type) { +void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor, + CXXDtorType dtorType) { // The complete destructor is equivalent to the base destructor for // classes with no virtual bases, so try to emit it as an alias. - if (Type == Dtor_Complete && - !D->getParent()->getNumVBases() && - !TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Complete), - GlobalDecl(D, Dtor_Base))) + if (dtorType == Dtor_Complete && + !dtor->getParent()->getNumVBases() && + !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete), + GlobalDecl(dtor, Dtor_Base))) return; // The base destructor is equivalent to the base destructor of its // base class if there is exactly one non-virtual base class with a // non-trivial destructor, there are no fields with a non-trivial // destructor, and the body of the destructor is trivial. - if (Type == Dtor_Base && !TryEmitBaseDestructorAsAlias(D)) + if (dtorType == Dtor_Base && !TryEmitBaseDestructorAsAlias(dtor)) return; - llvm::Function *Fn = cast(GetAddrOfCXXDestructor(D, Type)); - setFunctionLinkage(D, Fn); + const CGFunctionInfo &fnInfo = getTypes().getFunctionInfo(dtor, dtorType); - CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); + llvm::Function *fn = + cast(GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo)); + setFunctionLinkage(dtor, fn); - SetFunctionDefinitionAttributes(D, Fn); - SetLLVMFunctionAttributesForDefinition(D, Fn); + CodeGenFunction(*this).GenerateCode(GlobalDecl(dtor, dtorType), fn, fnInfo); + + SetFunctionDefinitionAttributes(dtor, fn); + SetLLVMFunctionAttributesForDefinition(dtor, fn); } llvm::GlobalValue * -CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D, - CXXDtorType Type) { - GlobalDecl GD(D, Type); +CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor, + CXXDtorType dtorType, + const CGFunctionInfo *fnInfo) { + GlobalDecl GD(dtor, dtorType); - llvm::StringRef Name = getMangledName(GD); - if (llvm::GlobalValue *V = GetGlobalValue(Name)) - return V; + llvm::StringRef name = getMangledName(GD); + if (llvm::GlobalValue *existing = GetGlobalValue(name)) + return existing; - const llvm::FunctionType *FTy = - getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false); + if (!fnInfo) fnInfo = &getTypes().getFunctionInfo(dtor, dtorType); - return cast(GetOrCreateLLVMFunction(Name, FTy, GD, + const llvm::FunctionType *fnType = + getTypes().GetFunctionType(*fnInfo, false); + + return cast(GetOrCreateLLVMFunction(name, fnType, GD, /*ForVTable=*/false)); } @@ -334,7 +345,7 @@ CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD, MD = MD->getCanonicalDecl(); uint64_t VTableIndex = CGM.getVTables().getMethodVTableIndex(MD); uint64_t AddressPoint = - CGM.getVTables().getAddressPoint(BaseSubobject(RD, 0), RD); + CGM.getVTables().getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD); VTableIndex += AddressPoint; llvm::Value *VFuncPtr = Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); @@ -369,7 +380,7 @@ CodeGenFunction::BuildAppleKextVirtualDestructorCall( uint64_t VTableIndex = CGM.getVTables().getMethodVTableIndex(GlobalDecl(DD, Type)); uint64_t AddressPoint = - CGM.getVTables().getAddressPoint(BaseSubobject(RD, 0), RD); + CGM.getVTables().getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD); VTableIndex += AddressPoint; llvm::Value *VFuncPtr = Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp index 8373b660b2f4..92f1c63a3829 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp @@ -115,7 +115,7 @@ bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { return true; } -void CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params) { +void CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { const CXXMethodDecl *MD = cast(CGF.CurGD.getDecl()); // FIXME: I'm not entirely sure I like using a fake decl just for code @@ -124,7 +124,7 @@ void CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params) { = ImplicitParamDecl::Create(CGM.getContext(), 0, MD->getLocation(), &CGM.getContext().Idents.get("this"), MD->getThisType(CGM.getContext())); - Params.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); + params.push_back(ThisDecl); getThisDecl(CGF) = ThisDecl; } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp index ae84b6196dfa..a765f0f3439a 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp @@ -36,6 +36,8 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) { case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; + case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS; + case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP; // TODO: add support for CC_X86Pascal to llvm } } @@ -104,6 +106,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D) { if (D->hasAttr()) return CC_X86Pascal; + if (PcsAttr *PCS = D->getAttr()) + return (PCS->getPCS() == PcsAttr::AAPCS ? CC_AAPCS : CC_AAPCS_VFP); + return CC_C; } @@ -188,6 +193,7 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) { ArgTys, FunctionType::ExtInfo( /*NoReturn*/ false, + /*HasRegParm*/ false, /*RegParm*/ 0, getCallingConventionForDecl(MD))); } @@ -212,7 +218,7 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, llvm::SmallVector ArgTys; for (CallArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; ++i) - ArgTys.push_back(Context.getCanonicalParamType(i->second)); + ArgTys.push_back(Context.getCanonicalParamType(i->Ty)); return getFunctionInfo(GetReturnType(ResTy), ArgTys, Info); } @@ -223,10 +229,15 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, llvm::SmallVector ArgTys; for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; ++i) - ArgTys.push_back(Context.getCanonicalParamType(i->second)); + ArgTys.push_back(Context.getCanonicalParamType((*i)->getType())); return getFunctionInfo(GetReturnType(ResTy), ArgTys, Info); } +const CGFunctionInfo &CodeGenTypes::getNullaryFunctionInfo() { + llvm::SmallVector args; + return getFunctionInfo(getContext().VoidTy, args, FunctionType::ExtInfo()); +} + const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy, const llvm::SmallVectorImpl &ArgTys, const FunctionType::ExtInfo &Info, @@ -250,7 +261,7 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy, return *FI; // Construct the function info. - FI = new CGFunctionInfo(CC, Info.getNoReturn(), Info.getRegParm(), ResTy, + FI = new CGFunctionInfo(CC, Info.getNoReturn(), Info.getHasRegParm(), Info.getRegParm(), ResTy, ArgTys.data(), ArgTys.size()); FunctionInfos.InsertNode(FI, InsertPos); @@ -279,13 +290,13 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy, } CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention, - bool _NoReturn, unsigned _RegParm, + bool _NoReturn, bool _HasRegParm, unsigned _RegParm, CanQualType ResTy, const CanQualType *ArgTys, unsigned NumArgTys) : CallingConvention(_CallingConvention), EffectiveCallingConvention(_CallingConvention), - NoReturn(_NoReturn), RegParm(_RegParm) + NoReturn(_NoReturn), HasRegParm(_HasRegParm), RegParm(_RegParm) { NumArgs = NumArgTys; @@ -622,7 +633,8 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic, assert(!RetAI.getIndirectAlign() && "Align unused on indirect return."); ResultType = llvm::Type::getVoidTy(getLLVMContext()); const llvm::Type *STy = ConvertType(RetTy, IsRecursive); - ArgTys.push_back(llvm::PointerType::get(STy, RetTy.getAddressSpace())); + unsigned AS = Context.getTargetAddressSpace(RetTy); + ArgTys.push_back(llvm::PointerType::get(STy, AS)); break; } @@ -704,7 +716,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, FuncAttrs |= llvm::Attribute::NoUnwind; else if (const FunctionDecl *Fn = dyn_cast(TargetDecl)) { const FunctionProtoType *FPT = Fn->getType()->getAs(); - if (FPT && FPT->hasEmptyExceptionSpec()) + if (FPT && FPT->isNothrow(getContext())) FuncAttrs |= llvm::Attribute::NoUnwind; } @@ -756,8 +768,10 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, PAL.push_back(llvm::AttributeWithIndex::get(0, RetAttrs)); // FIXME: RegParm should be reduced in case of global register variable. - signed RegParm = FI.getRegParm(); - if (!RegParm) + signed RegParm; + if (FI.getHasRegParm()) + RegParm = FI.getRegParm(); + else RegParm = CodeGenOpts.NumRegisterParameters; unsigned PointerWidth = getContext().Target.getPointerWidth(0); @@ -826,6 +840,26 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, PAL.push_back(llvm::AttributeWithIndex::get(~0, FuncAttrs)); } +/// An argument came in as a promoted argument; demote it back to its +/// declared type. +static llvm::Value *emitArgumentDemotion(CodeGenFunction &CGF, + const VarDecl *var, + llvm::Value *value) { + const llvm::Type *varType = CGF.ConvertType(var->getType()); + + // This can happen with promotions that actually don't change the + // underlying type, like the enum promotions. + if (value->getType() == varType) return value; + + assert((varType->isIntegerTy() || varType->isFloatingPointTy()) + && "unexpected promotion type"); + + if (isa(varType)) + return CGF.Builder.CreateTrunc(value, varType, "arg.unpromote"); + + return CGF.Builder.CreateFPCast(value, varType, "arg.unpromote"); +} + void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Function *Fn, const FunctionArgList &Args) { @@ -856,13 +890,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, assert(FI.arg_size() == Args.size() && "Mismatch between function signature & arguments."); + unsigned ArgNo = 1; CGFunctionInfo::const_arg_iterator info_it = FI.arg_begin(); - for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); - i != e; ++i, ++info_it) { - const VarDecl *Arg = i->first; + for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); + i != e; ++i, ++info_it, ++ArgNo) { + const VarDecl *Arg = *i; QualType Ty = info_it->type; const ABIArgInfo &ArgI = info_it->info; + bool isPromoted = + isa(Arg) && cast(Arg)->isKNRPromoted(); + switch (ArgI.getKind()) { case ABIArgInfo::Indirect: { llvm::Value *V = AI; @@ -880,8 +918,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // copy. const llvm::Type *I8PtrTy = Builder.getInt8PtrTy(); CharUnits Size = getContext().getTypeSizeInChars(Ty); - Builder.CreateMemCpy(Builder.CreateBitCast(AlignedTemp, I8PtrTy), - Builder.CreateBitCast(V, I8PtrTy), + llvm::Value *Dst = Builder.CreateBitCast(AlignedTemp, I8PtrTy); + llvm::Value *Src = Builder.CreateBitCast(V, I8PtrTy); + Builder.CreateMemCpy(Dst, + Src, llvm::ConstantInt::get(IntPtrTy, Size.getQuantity()), ArgI.getIndirectAlign(), @@ -892,13 +932,11 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // Load scalar value from indirect argument. CharUnits Alignment = getContext().getTypeAlignInChars(Ty); V = EmitLoadOfScalar(V, false, Alignment.getQuantity(), Ty); - if (!getContext().typesAreCompatible(Ty, Arg->getType())) { - // This must be a promotion, for something like - // "void a(x) short x; {..." - V = EmitScalarConversion(V, Ty, Arg->getType()); - } + + if (isPromoted) + V = emitArgumentDemotion(*this, Arg, V); } - EmitParmDecl(*Arg, V); + EmitParmDecl(*Arg, V, ArgNo); break; } @@ -914,12 +952,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, if (Arg->getType().isRestrictQualified()) AI->addAttr(llvm::Attribute::NoAlias); - if (!getContext().typesAreCompatible(Ty, Arg->getType())) { - // This must be a promotion, for something like - // "void a(x) short x; {..." - V = EmitScalarConversion(V, Ty, Arg->getType()); - } - EmitParmDecl(*Arg, V); + if (isPromoted) + V = emitArgumentDemotion(*this, Arg, V); + + EmitParmDecl(*Arg, V, ArgNo); break; } @@ -968,13 +1004,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // Match to what EmitParmDecl is expecting for this type. if (!CodeGenFunction::hasAggregateLLVMType(Ty)) { V = EmitLoadOfScalar(V, false, AlignmentToUse, Ty); - if (!getContext().typesAreCompatible(Ty, Arg->getType())) { - // This must be a promotion, for something like - // "void a(x) short x; {..." - V = EmitScalarConversion(V, Ty, Arg->getType()); - } + if (isPromoted) + V = emitArgumentDemotion(*this, Arg, V); } - EmitParmDecl(*Arg, V); + EmitParmDecl(*Arg, V, ArgNo); continue; // Skip ++AI increment, already done. } @@ -985,7 +1018,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Value *Temp = CreateMemTemp(Ty, Arg->getName() + ".addr"); llvm::Function::arg_iterator End = ExpandTypeFromArgs(Ty, MakeAddrLValue(Temp, Ty), AI); - EmitParmDecl(*Arg, Temp); + EmitParmDecl(*Arg, Temp, ArgNo); // Name the arguments used in expansion and increment AI. unsigned Index = 0; @@ -997,9 +1030,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, case ABIArgInfo::Ignore: // Initialize the local variable appropriately. if (hasAggregateLLVMType(Ty)) - EmitParmDecl(*Arg, CreateMemTemp(Ty)); + EmitParmDecl(*Arg, CreateMemTemp(Ty), ArgNo); else - EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType()))); + EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())), + ArgNo); // Skip increment, no matching LLVM parameter. continue; @@ -1091,42 +1125,48 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) { Ret->setDebugLoc(RetDbgLoc); } -RValue CodeGenFunction::EmitDelegateCallArg(const VarDecl *Param) { +void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, + const VarDecl *param) { // StartFunction converted the ABI-lowered parameter(s) into a // local alloca. We need to turn that into an r-value suitable // for EmitCall. - llvm::Value *Local = GetAddrOfLocalVar(Param); + llvm::Value *local = GetAddrOfLocalVar(param); - QualType ArgType = Param->getType(); + QualType type = param->getType(); // For the most part, we just need to load the alloca, except: // 1) aggregate r-values are actually pointers to temporaries, and // 2) references to aggregates are pointers directly to the aggregate. // I don't know why references to non-aggregates are different here. - if (const ReferenceType *RefType = ArgType->getAs()) { - if (hasAggregateLLVMType(RefType->getPointeeType())) - return RValue::getAggregate(Local); + if (const ReferenceType *ref = type->getAs()) { + if (hasAggregateLLVMType(ref->getPointeeType())) + return args.add(RValue::getAggregate(local), type); // Locals which are references to scalars are represented // with allocas holding the pointer. - return RValue::get(Builder.CreateLoad(Local)); + return args.add(RValue::get(Builder.CreateLoad(local)), type); } - if (ArgType->isAnyComplexType()) - return RValue::getComplex(LoadComplexFromAddr(Local, /*volatile*/ false)); + if (type->isAnyComplexType()) { + ComplexPairTy complex = LoadComplexFromAddr(local, /*volatile*/ false); + return args.add(RValue::getComplex(complex), type); + } - if (hasAggregateLLVMType(ArgType)) - return RValue::getAggregate(Local); + if (hasAggregateLLVMType(type)) + return args.add(RValue::getAggregate(local), type); - unsigned Alignment = getContext().getDeclAlign(Param).getQuantity(); - return RValue::get(EmitLoadOfScalar(Local, false, Alignment, ArgType)); + unsigned alignment = getContext().getDeclAlign(param).getQuantity(); + llvm::Value *value = EmitLoadOfScalar(local, false, alignment, type); + return args.add(RValue::get(value), type); } -RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) { - if (ArgType->isReferenceType()) - return EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0); +void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, + QualType type) { + if (type->isReferenceType()) + return args.add(EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0), + type); - return EmitAnyExprToTemp(E); + args.add(EmitAnyExprToTemp(E), type); } /// Emits a call or invoke instruction to the given function, depending @@ -1177,18 +1217,18 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end(); I != E; ++I, ++info_it) { const ABIArgInfo &ArgInfo = info_it->info; - RValue RV = I->first; + RValue RV = I->RV; unsigned Alignment = - getContext().getTypeAlignInChars(I->second).getQuantity(); + getContext().getTypeAlignInChars(I->Ty).getQuantity(); switch (ArgInfo.getKind()) { case ABIArgInfo::Indirect: { if (RV.isScalar() || RV.isComplex()) { // Make a temporary alloca to pass the argument. - Args.push_back(CreateMemTemp(I->second)); + Args.push_back(CreateMemTemp(I->Ty)); if (RV.isScalar()) EmitStoreOfScalar(RV.getScalarVal(), Args.back(), false, - Alignment, I->second); + Alignment, I->Ty); else StoreComplexToAddr(RV.getComplexVal(), Args.back(), false); } else { @@ -1215,11 +1255,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // FIXME: Avoid the conversion through memory if possible. llvm::Value *SrcPtr; if (RV.isScalar()) { - SrcPtr = CreateMemTemp(I->second, "coerce"); - EmitStoreOfScalar(RV.getScalarVal(), SrcPtr, false, Alignment, - I->second); + SrcPtr = CreateMemTemp(I->Ty, "coerce"); + EmitStoreOfScalar(RV.getScalarVal(), SrcPtr, false, Alignment, I->Ty); } else if (RV.isComplex()) { - SrcPtr = CreateMemTemp(I->second, "coerce"); + SrcPtr = CreateMemTemp(I->Ty, "coerce"); StoreComplexToAddr(RV.getComplexVal(), SrcPtr, false); } else SrcPtr = RV.getAggregateAddr(); @@ -1257,7 +1296,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } case ABIArgInfo::Expand: - ExpandTypeToArgs(I->second, RV, Args); + ExpandTypeToArgs(I->Ty, RV, Args); break; } } @@ -1275,7 +1314,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (CE->getOpcode() == llvm::Instruction::BitCast && ActualFT->getReturnType() == CurFT->getReturnType() && ActualFT->getNumParams() == CurFT->getNumParams() && - ActualFT->getNumParams() == Args.size()) { + ActualFT->getNumParams() == Args.size() && + (CurFT->isVarArg() || !ActualFT->isVarArg())) { bool ArgsMatch = true; for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i) if (ActualFT->getParamType(i) != CurFT->getParamType(i)) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h index 41e707a204ca..3f600c04e59d 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h @@ -44,15 +44,29 @@ namespace clang { namespace CodeGen { typedef llvm::SmallVector AttributeListType; + struct CallArg { + RValue RV; + QualType Ty; + CallArg(RValue rv, QualType ty) + : RV(rv), Ty(ty) + { } + }; + /// CallArgList - Type for representing both the value and type of /// arguments in a call. - typedef llvm::SmallVector, 16> CallArgList; + class CallArgList : + public llvm::SmallVector { + public: + void add(RValue rvalue, QualType type) { + push_back(CallArg(rvalue, type)); + } + }; /// FunctionArgList - Type for representing both the decl and type /// of parameters to a function. The decl must be either a /// ParmVarDecl or ImplicitParamDecl. - typedef llvm::SmallVector, - 16> FunctionArgList; + class FunctionArgList : public llvm::SmallVector { + }; /// CGFunctionInfo - Class to encapsulate the information about a /// function definition. @@ -77,6 +91,7 @@ namespace CodeGen { ArgInfo *Args; /// How many arguments to pass inreg. + bool HasRegParm; unsigned RegParm; public: @@ -84,7 +99,7 @@ namespace CodeGen { typedef ArgInfo *arg_iterator; CGFunctionInfo(unsigned CallingConvention, bool NoReturn, - unsigned RegParm, CanQualType ResTy, + bool HasRegParm, unsigned RegParm, CanQualType ResTy, const CanQualType *ArgTys, unsigned NumArgTys); ~CGFunctionInfo() { delete[] Args; } @@ -110,6 +125,7 @@ namespace CodeGen { EffectiveCallingConvention = Value; } + bool getHasRegParm() const { return HasRegParm; } unsigned getRegParm() const { return RegParm; } CanQualType getReturnType() const { return Args[0].type; } @@ -120,6 +136,7 @@ namespace CodeGen { void Profile(llvm::FoldingSetNodeID &ID) { ID.AddInteger(getCallingConvention()); ID.AddBoolean(NoReturn); + ID.AddBoolean(HasRegParm); ID.AddInteger(RegParm); getReturnType().Profile(ID); for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it) @@ -133,6 +150,7 @@ namespace CodeGen { Iterator end) { ID.AddInteger(Info.getCC()); ID.AddBoolean(Info.getNoReturn()); + ID.AddBoolean(Info.getHasRegParm()); ID.AddInteger(Info.getRegParm()); ResTy.Profile(ID); for (; begin != end; ++begin) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp index cd28bbe44db5..ca8b6576c7ad 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp @@ -22,12 +22,12 @@ using namespace clang; using namespace CodeGen; -static uint64_t +static CharUnits ComputeNonVirtualBaseClassOffset(ASTContext &Context, const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, CastExpr::path_const_iterator End) { - uint64_t Offset = 0; + CharUnits Offset = CharUnits::Zero(); const CXXRecordDecl *RD = DerivedClass; @@ -42,13 +42,12 @@ ComputeNonVirtualBaseClassOffset(ASTContext &Context, cast(Base->getType()->getAs()->getDecl()); // Add the offset. - Offset += Layout.getBaseClassOffsetInBits(BaseDecl); + Offset += Layout.getBaseClassOffset(BaseDecl); RD = BaseDecl; } - // FIXME: We should not use / 8 here. - return Offset / 8; + return Offset; } llvm::Constant * @@ -57,16 +56,16 @@ CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, CastExpr::path_const_iterator PathEnd) { assert(PathBegin != PathEnd && "Base path should not be empty!"); - uint64_t Offset = + CharUnits Offset = ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl, PathBegin, PathEnd); - if (!Offset) + if (Offset.isZero()) return 0; const llvm::Type *PtrDiffTy = Types.ConvertType(getContext().getPointerDiffType()); - return llvm::ConstantInt::get(PtrDiffTy, Offset); + return llvm::ConstantInt::get(PtrDiffTy, Offset.getQuantity()); } /// Gets the address of a direct base class within a complete object. @@ -85,20 +84,20 @@ CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(llvm::Value *This, == ConvertType(Derived)); // Compute the offset of the virtual base. - uint64_t Offset; + CharUnits Offset; const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived); if (BaseIsVirtual) - Offset = Layout.getVBaseClassOffsetInBits(Base); + Offset = Layout.getVBaseClassOffset(Base); else - Offset = Layout.getBaseClassOffsetInBits(Base); + Offset = Layout.getBaseClassOffset(Base); // Shift and cast down to the base type. // TODO: for complete types, this should be possible with a GEP. llvm::Value *V = This; - if (Offset) { + if (Offset.isPositive()) { const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); V = Builder.CreateBitCast(V, Int8PtrTy); - V = Builder.CreateConstInBoundsGEP1_64(V, Offset / 8); + V = Builder.CreateConstInBoundsGEP1_64(V, Offset.getQuantity()); } V = Builder.CreateBitCast(V, ConvertType(Base)->getPointerTo()); @@ -107,13 +106,14 @@ CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(llvm::Value *This, static llvm::Value * ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ThisPtr, - uint64_t NonVirtual, llvm::Value *Virtual) { + CharUnits NonVirtual, llvm::Value *Virtual) { const llvm::Type *PtrDiffTy = CGF.ConvertType(CGF.getContext().getPointerDiffType()); llvm::Value *NonVirtualOffset = 0; - if (NonVirtual) - NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, NonVirtual); + if (!NonVirtual.isZero()) + NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, + NonVirtual.getQuantity()); llvm::Value *BaseOffset; if (Virtual) { @@ -150,7 +150,7 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value, ++Start; } - uint64_t NonVirtualOffset = + CharUnits NonVirtualOffset = ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : Derived, Start, PathEnd); @@ -158,7 +158,7 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value, const llvm::Type *BasePtrTy = ConvertType((PathEnd[-1])->getType())->getPointerTo(); - if (!NonVirtualOffset && !VBase) { + if (NonVirtualOffset.isZero() && !VBase) { // Just cast back. return Builder.CreateBitCast(Value, BasePtrTy); } @@ -172,9 +172,7 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value, CastNotNull = createBasicBlock("cast.notnull"); CastEnd = createBasicBlock("cast.end"); - llvm::Value *IsNull = - Builder.CreateICmpEQ(Value, - llvm::Constant::getNullValue(Value->getType())); + llvm::Value *IsNull = Builder.CreateIsNull(Value); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } @@ -187,14 +185,15 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value, const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived); - uint64_t VBaseOffset = Layout.getVBaseClassOffsetInBits(VBase); - NonVirtualOffset += VBaseOffset / 8; + CharUnits VBaseOffset = Layout.getVBaseClassOffset(VBase); + NonVirtualOffset += VBaseOffset; } else VirtualOffset = GetVirtualBaseClassOffset(Value, Derived, VBase); } // Apply the offsets. - Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset, + Value = ApplyNonVirtualAndVirtualOffset(*this, Value, + NonVirtualOffset, VirtualOffset); // Cast back. @@ -206,8 +205,7 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value, Builder.CreateBr(CastEnd); EmitBlock(CastEnd); - llvm::PHINode *PHI = Builder.CreatePHI(Value->getType()); - PHI->reserveOperandSpace(2); + llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); PHI->addIncoming(Value, CastNotNull); PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); @@ -246,9 +244,7 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value, CastNotNull = createBasicBlock("cast.notnull"); CastEnd = createBasicBlock("cast.end"); - llvm::Value *IsNull = - Builder.CreateICmpEQ(Value, - llvm::Constant::getNullValue(Value->getType())); + llvm::Value *IsNull = Builder.CreateIsNull(Value); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } @@ -267,8 +263,7 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value, Builder.CreateBr(CastEnd); EmitBlock(CastEnd); - llvm::PHINode *PHI = Builder.CreatePHI(Value->getType()); - PHI->reserveOperandSpace(2); + llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); PHI->addIncoming(Value, CastNotNull); PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); @@ -304,9 +299,9 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD, } else { const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(RD); - uint64_t BaseOffset = ForVirtualBase ? - Layout.getVBaseClassOffsetInBits(Base) : - Layout.getBaseClassOffsetInBits(Base); + CharUnits BaseOffset = ForVirtualBase ? + Layout.getVBaseClassOffset(Base) : + Layout.getBaseClassOffset(Base); SubVTTIndex = CGF.CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset)); @@ -407,7 +402,7 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, CGF.EmitAggExpr(BaseInit->getInit(), AggSlot); - if (CGF.CGM.getLangOptions().areExceptionsEnabled() && + if (CGF.CGM.getLangOptions().Exceptions && !BaseClassDecl->hasTrivialDestructor()) CGF.EHStack.pushCleanup(EHCleanup, BaseClassDecl, isBaseVirtual); @@ -589,8 +584,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, // we know we're in a copy constructor. unsigned SrcArgIndex = Args.size() - 1; llvm::Value *SrcPtr - = CGF.Builder.CreateLoad( - CGF.GetAddrOfLocalVar(Args[SrcArgIndex].first)); + = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex])); LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0); // Copy the aggregate. @@ -606,7 +600,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit, FieldType, 0); - if (!CGF.CGM.getLangOptions().areExceptionsEnabled()) + if (!CGF.CGM.getLangOptions().Exceptions) return; // FIXME: If we have an array of classes w/ non-trivial destructors, @@ -664,6 +658,10 @@ static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor) { if (Ctor->getType()->getAs()->isVariadic()) return false; + // FIXME: Decide if we can do a delegation of a delegating constructor. + if (Ctor->isDelegatingConstructor()) + return false; + return true; } @@ -716,6 +714,9 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType CtorType, FunctionArgList &Args) { + if (CD->isDelegatingConstructor()) + return EmitDelegatingCXXConstructorCall(CD, Args); + const CXXRecordDecl *ClassDecl = CD->getParent(); llvm::SmallVector MemberInitializers; @@ -727,8 +728,10 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, if (Member->isBaseInitializer()) EmitBaseInitializer(*this, ClassDecl, Member, CtorType); - else + else if (Member->isAnyMemberInitializer()) MemberInitializers.push_back(Member); + else + llvm_unreachable("Delegating initializer on non-delegating constructor"); } InitializeVTablePointers(ClassDecl); @@ -1196,15 +1199,14 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, CallArgList Args; // Push the this ptr. - Args.push_back(std::make_pair(RValue::get(This), - D->getThisType(getContext()))); + Args.add(RValue::get(This), D->getThisType(getContext())); // Push the src ptr. QualType QT = *(FPT->arg_type_begin()); const llvm::Type *t = CGM.getTypes().ConvertType(QT); Src = Builder.CreateBitCast(Src, t); - Args.push_back(std::make_pair(RValue::get(Src), QT)); + Args.add(RValue::get(Src), QT); // Skip over first argument (Src). ++ArgBeg; @@ -1212,9 +1214,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin()+1, E = FPT->arg_type_end(); I != E; ++I, ++Arg) { assert(Arg != ArgEnd && "Running over edge of argument list!"); - QualType ArgType = *I; - Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType), - ArgType)); + EmitCallArg(Args, *Arg, *I); } // Either we've emitted all the call args, or we have a call to a // variadic function. @@ -1223,8 +1223,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, // If we still have any arguments, emit them using the type of the argument. for (; Arg != ArgEnd; ++Arg) { QualType ArgType = Arg->getType(); - Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType), - ArgType)); + EmitCallArg(Args, *Arg, ArgType); } QualType ResultType = FPT->getResultType(); @@ -1243,30 +1242,26 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, assert(I != E && "no parameters to constructor"); // this - DelegateArgs.push_back(std::make_pair(RValue::get(LoadCXXThis()), - I->second)); + DelegateArgs.add(RValue::get(LoadCXXThis()), (*I)->getType()); ++I; // vtt if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType), /*ForVirtualBase=*/false)) { QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy); - DelegateArgs.push_back(std::make_pair(RValue::get(VTT), VoidPP)); + DelegateArgs.add(RValue::get(VTT), VoidPP); if (CodeGenVTables::needsVTTParameter(CurGD)) { assert(I != E && "cannot skip vtt parameter, already done with args"); - assert(I->second == VoidPP && "skipping parameter not of vtt type"); + assert((*I)->getType() == VoidPP && "skipping parameter not of vtt type"); ++I; } } // Explicit arguments. for (; I != E; ++I) { - const VarDecl *Param = I->first; - QualType ArgType = Param->getType(); // because we're passing it to itself - RValue Arg = EmitDelegateCallArg(Param); - - DelegateArgs.push_back(std::make_pair(Arg, ArgType)); + const VarDecl *param = *I; + EmitDelegateCallArg(DelegateArgs, param); } EmitCall(CGM.getTypes().getFunctionInfo(Ctor, CtorType), @@ -1274,6 +1269,19 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, ReturnValueSlot(), DelegateArgs, Ctor); } +void +CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, + const FunctionArgList &Args) { + assert(Ctor->isDelegatingConstructor()); + + llvm::Value *ThisPtr = LoadCXXThis(); + + AggValueSlot AggSlot = AggValueSlot::forAddr(ThisPtr, false, /*Lifetime*/ true); + + EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot); +} + + void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, @@ -1317,6 +1325,7 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) { if (ClassDecl->hasTrivialDestructor()) return; const CXXDestructorDecl *D = ClassDecl->getDestructor(); + assert(D && D->isUsed() && "destructor not marked as used!"); PushDestructorCleanup(D, Addr); } @@ -1325,11 +1334,12 @@ CodeGenFunction::GetVirtualBaseClassOffset(llvm::Value *This, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl) { llvm::Value *VTablePtr = GetVTablePtr(This, Int8PtrTy); - int64_t VBaseOffsetOffset = + CharUnits VBaseOffsetOffset = CGM.getVTables().getVirtualBaseOffsetOffset(ClassDecl, BaseClassDecl); llvm::Value *VBaseOffsetPtr = - Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset, "vbase.offset.ptr"); + Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset.getQuantity(), + "vbase.offset.ptr"); const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); @@ -1344,7 +1354,7 @@ CodeGenFunction::GetVirtualBaseClassOffset(llvm::Value *This, void CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, const CXXRecordDecl *NearestVBase, - uint64_t OffsetFromNearestVBase, + CharUnits OffsetFromNearestVBase, llvm::Constant *VTable, const CXXRecordDecl *VTableClass) { const CXXRecordDecl *RD = Base.getBase(); @@ -1374,23 +1384,23 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, // Compute where to store the address point. llvm::Value *VirtualOffset = 0; - uint64_t NonVirtualOffset = 0; + CharUnits NonVirtualOffset = CharUnits::Zero(); if (CodeGenVTables::needsVTTParameter(CurGD) && NearestVBase) { // We need to use the virtual base offset offset because the virtual base // might have a different offset in the most derived class. VirtualOffset = GetVirtualBaseClassOffset(LoadCXXThis(), VTableClass, NearestVBase); - NonVirtualOffset = OffsetFromNearestVBase / 8; + NonVirtualOffset = OffsetFromNearestVBase; } else { // We can just use the base offset in the complete class. - NonVirtualOffset = Base.getBaseOffset() / 8; + NonVirtualOffset = Base.getBaseOffset(); } // Apply the offsets. llvm::Value *VTableField = LoadCXXThis(); - if (NonVirtualOffset || VirtualOffset) + if (!NonVirtualOffset.isZero() || VirtualOffset) VTableField = ApplyNonVirtualAndVirtualOffset(*this, VTableField, NonVirtualOffset, VirtualOffset); @@ -1405,7 +1415,7 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, void CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, const CXXRecordDecl *NearestVBase, - uint64_t OffsetFromNearestVBase, + CharUnits OffsetFromNearestVBase, bool BaseIsNonVirtualPrimaryBase, llvm::Constant *VTable, const CXXRecordDecl *VTableClass, @@ -1430,8 +1440,8 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, if (!BaseDecl->isDynamicClass()) continue; - uint64_t BaseOffset; - uint64_t BaseOffsetFromNearestVBase; + CharUnits BaseOffset; + CharUnits BaseOffsetFromNearestVBase; bool BaseDeclIsNonVirtualPrimaryBase; if (I->isVirtual()) { @@ -1442,16 +1452,15 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, const ASTRecordLayout &Layout = getContext().getASTRecordLayout(VTableClass); - BaseOffset = Layout.getVBaseClassOffsetInBits(BaseDecl); - BaseOffsetFromNearestVBase = 0; + BaseOffset = Layout.getVBaseClassOffset(BaseDecl); + BaseOffsetFromNearestVBase = CharUnits::Zero(); BaseDeclIsNonVirtualPrimaryBase = false; } else { const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - BaseOffset = - Base.getBaseOffset() + Layout.getBaseClassOffsetInBits(BaseDecl); + BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl); BaseOffsetFromNearestVBase = - OffsetFromNearestVBase + Layout.getBaseClassOffsetInBits(BaseDecl); + OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl); BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl; } @@ -1473,8 +1482,9 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) { // Initialize the vtable pointers for this class and all of its bases. VisitedVirtualBasesSetTy VBases; - InitializeVTablePointers(BaseSubobject(RD, 0), /*NearestVBase=*/0, - /*OffsetFromNearestVBase=*/0, + InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()), + /*NearestVBase=*/0, + /*OffsetFromNearestVBase=*/CharUnits::Zero(), /*BaseIsNonVirtualPrimaryBase=*/false, VTable, RD, VBases); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp index 1d7901a2db4c..41ecd8111790 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp @@ -870,6 +870,29 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { } } +/// isObviouslyBranchWithoutCleanups - Return true if a branch to the +/// specified destination obviously has no cleanups to run. 'false' is always +/// a conservatively correct answer for this method. +bool CodeGenFunction::isObviouslyBranchWithoutCleanups(JumpDest Dest) const { + assert(Dest.getScopeDepth().encloses(EHStack.stable_begin()) + && "stale jump destination"); + + // Calculate the innermost active normal cleanup. + EHScopeStack::stable_iterator TopCleanup = + EHStack.getInnermostActiveNormalCleanup(); + + // If we're not in an active normal cleanup scope, or if the + // destination scope is within the innermost active normal cleanup + // scope, we don't need to worry about fixups. + if (TopCleanup == EHStack.stable_end() || + TopCleanup.encloses(Dest.getScopeDepth())) // works for invalid + return true; + + // Otherwise, we might need some cleanups. + return false; +} + + /// Terminate the current block by emitting a branch which might leave /// the current cleanup-protected scope. The target scope may not yet /// be known, in which case this will require a fixup. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp index dfd9f56b12e3..f2e1c024dd05 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp @@ -119,6 +119,17 @@ llvm::StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { return llvm::StringRef(StrPtr, OS.tell()); } +/// getSelectorName - Return selector name. This is used for debugging +/// info. +llvm::StringRef CGDebugInfo::getSelectorName(Selector S) { + llvm::SmallString<256> SName; + llvm::raw_svector_ostream OS(SName); + OS << S.getAsString(); + char *StrPtr = DebugInfoNames.Allocate(OS.tell()); + memcpy(StrPtr, SName.begin(), OS.tell()); + return llvm::StringRef(StrPtr, OS.tell()); +} + /// getClassName - Get class name including template argument list. llvm::StringRef CGDebugInfo::getClassName(RecordDecl *RD) { @@ -306,8 +317,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { DBuilder.createMemberType("isa", getOrCreateMainFile(), 0,Size, 0, 0, 0, ISATy); EltTys.push_back(FieldTy); - llvm::DIArray Elements = - DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); + llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); return DBuilder.createStructType(TheCU, "objc_object", getOrCreateMainFile(), @@ -462,8 +472,8 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, // Bit size, align and offset of the type. // Size is always the size of a pointer. We can't use getTypeSize here // because that does not return the correct value for references. - uint64_t Size = - CGM.getContext().Target.getPointerWidth(PointeeTy.getAddressSpace()); + unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); + uint64_t Size = CGM.getContext().Target.getPointerWidth(AS); uint64_t Align = CGM.getContext().getTypeAlign(Ty); return @@ -488,7 +498,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset)); EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset)); - Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); + Elements = DBuilder.getOrCreateArray(EltTys); EltTys.clear(); unsigned Flags = llvm::DIDescriptor::FlagAppleBlock; @@ -522,7 +532,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, EltTys.push_back(FieldTy); FieldOffset += FieldSize; - Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); + Elements = DBuilder.getOrCreateArray(EltTys); EltTy = DBuilder.createStructType(Unit, "__block_literal_generic", Unit, LineNo, FieldOffset, 0, @@ -564,8 +574,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit)); } - llvm::DIArray EltTypeArray = - DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); + llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys); llvm::DIType DbgTy = DBuilder.createSubroutineType(Unit, EltTypeArray); return DbgTy; @@ -609,18 +618,32 @@ void CGDebugInfo:: CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit, llvm::SmallVectorImpl &elements) { unsigned fieldNo = 0; + const FieldDecl *LastFD = 0; + bool IsMsStruct = record->hasAttr(); + const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record); for (RecordDecl::field_iterator I = record->field_begin(), E = record->field_end(); I != E; ++I, ++fieldNo) { FieldDecl *field = *I; + if (IsMsStruct) { + // Zero-length bitfields following non-bitfield members are ignored + if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD) || + CGM.getContext().ZeroBitfieldFollowsBitfield((field), LastFD)) { + --fieldNo; + continue; + } + LastFD = field; + } llvm::StringRef name = field->getName(); QualType type = field->getType(); // Ignore unnamed fields unless they're anonymous structs/unions. - if (name.empty() && !type->isRecordType()) + if (name.empty() && !type->isRecordType()) { + LastFD = field; continue; + } llvm::DIType fieldType = createFieldType(name, type, field->getBitWidth(), @@ -655,9 +678,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, if (!Method->isStatic()) { // "this" pointer is always first argument. - ASTContext &Context = CGM.getContext(); - QualType ThisPtr = - Context.getPointerType(Context.getTagDeclType(Method->getParent())); + QualType ThisPtr = Method->getThisType(CGM.getContext()); llvm::DIType ThisPtrType = DBuilder.createArtificialType(getOrCreateType(ThisPtr, Unit)); @@ -669,8 +690,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i) Elts.push_back(Args.getElement(i)); - llvm::DIArray EltTypeArray = - DBuilder.getOrCreateArray(Elts.data(), Elts.size()); + llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); return DBuilder.createSubroutineType(Unit, EltTypeArray); } @@ -753,10 +773,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, Virtuality, VIndex, ContainingType, Flags, CGM.getLangOptions().Optimize); - // Don't cache ctors or dtors since we have to emit multiple functions for - // a single ctor or dtor. - if (!IsCtorOrDtor && Method->isThisDeclarationADefinition()) - SPCache[Method] = llvm::WeakVH(SP); + SPCache[Method] = llvm::WeakVH(SP); return SP; } @@ -816,10 +833,13 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit, if (BI->isVirtual()) { // virtual base offset offset is -ve. The code generator emits dwarf // expression where it expects +ve number. - BaseOffset = 0 - CGM.getVTables().getVirtualBaseOffsetOffset(RD, Base); + BaseOffset = + 0 - CGM.getVTables().getVirtualBaseOffsetOffset(RD, Base).getQuantity(); BFlags = llvm::DIDescriptor::FlagVirtual; } else BaseOffset = RL.getBaseClassOffsetInBits(Base); + // FIXME: Inconsistent units for BaseOffset. It is in bytes when + // BI->isVirtual() and bits when not. AccessSpecifier Access = BI->getAccessSpecifier(); if (Access == clang::AS_private) @@ -835,6 +855,60 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit, } } +/// CollectTemplateParams - A helper function to collect template parameters. +llvm::DIArray CGDebugInfo:: +CollectTemplateParams(const TemplateParameterList *TPList, + const TemplateArgumentList &TAList, + llvm::DIFile Unit) { + llvm::SmallVector TemplateParams; + for (unsigned i = 0, e = TAList.size(); i != e; ++i) { + const TemplateArgument &TA = TAList[i]; + const NamedDecl *ND = TPList->getParam(i); + if (TA.getKind() == TemplateArgument::Type) { + llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit); + llvm::DITemplateTypeParameter TTP = + DBuilder.createTemplateTypeParameter(TheCU, ND->getName(), TTy); + TemplateParams.push_back(TTP); + } else if (TA.getKind() == TemplateArgument::Integral) { + llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit); + llvm::DITemplateValueParameter TVP = + DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy, + TA.getAsIntegral()->getZExtValue()); + TemplateParams.push_back(TVP); + } + } + return DBuilder.getOrCreateArray(TemplateParams); +} + +/// CollectFunctionTemplateParams - A helper function to collect debug +/// info for function template parameters. +llvm::DIArray CGDebugInfo:: +CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit) { + if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplateSpecialization){ + const TemplateParameterList *TList = + FD->getTemplateSpecializationInfo()->getTemplate()->getTemplateParameters(); + return + CollectTemplateParams(TList, *FD->getTemplateSpecializationArgs(), Unit); + } + return llvm::DIArray(); +} + +/// CollectCXXTemplateParams - A helper function to collect debug info for +/// template parameters. +llvm::DIArray CGDebugInfo:: +CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial, + llvm::DIFile Unit) { + llvm::PointerUnion + PU = TSpecial->getSpecializedTemplateOrPartial(); + + TemplateParameterList *TPList = PU.is() ? + PU.get()->getTemplateParameters() : + PU.get()->getTemplateParameters(); + const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs(); + return CollectTemplateParams(TPList, TAList, Unit); +} + /// getOrCreateVTablePtrType - Return debug info descriptor for vtable. llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) { if (VTablePtrType.isValid()) @@ -844,7 +918,7 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) { /* Function type */ llvm::Value *STy = getOrCreateType(Context.IntTy, Unit); - llvm::DIArray SElements = DBuilder.getOrCreateArray(&STy, 1); + llvm::DIArray SElements = DBuilder.getOrCreateArray(STy); llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements); unsigned Size = Context.getTypeSize(Context.VoidPtrTy); llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0, @@ -971,30 +1045,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { } CollectRecordFields(RD, Unit, EltTys); - llvm::SmallVector TemplateParams; + llvm::DIArray TParamsArray; if (CXXDecl) { CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl); CollectCXXFriends(CXXDecl, Unit, EltTys, FwdDecl); - if (ClassTemplateSpecializationDecl *TSpecial - = dyn_cast(RD)) { - const TemplateArgumentList &TAL = TSpecial->getTemplateArgs(); - for (unsigned i = 0, e = TAL.size(); i != e; ++i) { - const TemplateArgument &TA = TAL[i]; - if (TA.getKind() == TemplateArgument::Type) { - llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit); - llvm::DITemplateTypeParameter TTP = - DBuilder.createTemplateTypeParameter(TheCU, TTy.getName(), TTy); - TemplateParams.push_back(TTP); - } else if (TA.getKind() == TemplateArgument::Integral) { - llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit); - // FIXME: Get parameter name, instead of parameter type name. - llvm::DITemplateValueParameter TVP = - DBuilder.createTemplateValueParameter(TheCU, TTy.getName(), TTy, - TA.getAsIntegral()->getZExtValue()); - TemplateParams.push_back(TVP); - } - } - } + if (const ClassTemplateSpecializationDecl *TSpecial + = dyn_cast(RD)) + TParamsArray = CollectCXXTemplateParams(TSpecial, Unit); } RegionStack.pop_back(); @@ -1008,18 +1065,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { llvm::StringRef RDName = RD->getName(); uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); - llvm::DIArray Elements = - DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); + llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); llvm::MDNode *RealDecl = NULL; - if (RD->isStruct()) - RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line, - Size, Align, 0, Elements); - else if (RD->isUnion()) + if (RD->isUnion()) RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line, - Size, Align, 0, Elements); - else { - assert(RD->isClass() && "Unknown RecordType!"); + Size, Align, 0, Elements); + else if (CXXDecl) { RDName = getClassName(RD); // A class's primary base or the class itself contains the vtable. llvm::MDNode *ContainingType = NULL; @@ -1039,13 +1091,14 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { } else if (CXXDecl->isDynamicClass()) ContainingType = FwdDecl; - llvm::DIArray TParamsArray = - DBuilder.getOrCreateArray(TemplateParams.data(), TemplateParams.size()); + RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(), Elements, ContainingType, TParamsArray); - } + } else + RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line, + Size, Align, 0, Elements); // Now that we have a real decl for the struct, replace anything using the // old decl with the new one. This will recursively update the debug info. @@ -1156,14 +1209,26 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, else if (Field->getAccessControl() == ObjCIvarDecl::Private) Flags = llvm::DIDescriptor::FlagPrivate; - FieldTy = DBuilder.createMemberType(FieldName, FieldDefUnit, - FieldLine, FieldSize, FieldAlign, - FieldOffset, Flags, FieldTy); + llvm::StringRef PropertyName; + llvm::StringRef PropertyGetter; + llvm::StringRef PropertySetter; + unsigned PropertyAttributes = 0; + if (ObjCPropertyDecl *PD = + ID->FindPropertyVisibleInPrimaryClass(Field->getIdentifier())) { + PropertyName = PD->getName(); + PropertyGetter = getSelectorName(PD->getGetterName()); + PropertySetter = getSelectorName(PD->getSetterName()); + PropertyAttributes = PD->getPropertyAttributes(); + } + FieldTy = DBuilder.createObjCIVar(FieldName, FieldDefUnit, + FieldLine, FieldSize, FieldAlign, + FieldOffset, Flags, FieldTy, + PropertyName, PropertyGetter, + PropertySetter, PropertyAttributes); EltTys.push_back(FieldTy); } - llvm::DIArray Elements = - DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); + llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); RegionStack.pop_back(); llvm::DenseMap::iterator RI = @@ -1200,12 +1265,17 @@ llvm::DIType CGDebugInfo::CreateType(const TagType *Ty) { llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) { llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit); - uint64_t NumElems = Ty->getNumElements(); - if (NumElems > 0) + int64_t NumElems = Ty->getNumElements(); + int64_t LowerBound = 0; + if (NumElems == 0) + // If number of elements are not known then this is an unbounded array. + // Use Low = 1, Hi = 0 to express such arrays. + LowerBound = 1; + else --NumElems; - llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, NumElems); - llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(&Subscript, 1); + llvm::Value *Subscript = DBuilder.getOrCreateSubrange(LowerBound, NumElems); + llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscript); uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); @@ -1228,6 +1298,9 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, } else if (Ty->isIncompleteArrayType()) { Size = 0; Align = CGM.getContext().getTypeAlign(Ty->getElementType()); + } else if (Ty->isDependentSizedArrayType() || Ty->isIncompleteType()) { + Size = 0; + Align = 0; } else { // Size and align of the whole array, not the element type. Size = CGM.getContext().getTypeSize(Ty); @@ -1243,18 +1316,23 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, EltTy = Ty->getElementType(); else { while ((Ty = dyn_cast(EltTy))) { - uint64_t Upper = 0; - if (const ConstantArrayType *CAT = dyn_cast(Ty)) + int64_t UpperBound = 0; + int64_t LowerBound = 0; + if (const ConstantArrayType *CAT = dyn_cast(Ty)) { if (CAT->getSize().getZExtValue()) - Upper = CAT->getSize().getZExtValue() - 1; + UpperBound = CAT->getSize().getZExtValue() - 1; + } else + // This is an unbounded array. Use Low = 1, Hi = 0 to express such + // arrays. + LowerBound = 1; + // FIXME: Verify this is right for VLAs. - Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Upper)); + Subscripts.push_back(DBuilder.getOrCreateSubrange(LowerBound, UpperBound)); EltTy = Ty->getElementType(); } } - llvm::DIArray SubscriptArray = - DBuilder.getOrCreateArray(Subscripts.data(), Subscripts.size()); + llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts); llvm::DIType DbgTy = DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit), @@ -1303,9 +1381,7 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, Info.first, Info.second, FieldOffset, 0, PointerDiffDITy); - llvm::DIArray Elements = - DBuilder.getOrCreateArray(&ElementTypes[0], - llvm::array_lengthof(ElementTypes)); + llvm::DIArray Elements = DBuilder.getOrCreateArray(ElementTypes); return DBuilder.createStructType(U, llvm::StringRef("test"), U, 0, FieldOffset, @@ -1327,8 +1403,7 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) { } // Return a CompositeType for the enum itself. - llvm::DIArray EltArray = - DBuilder.getOrCreateArray(Enumerators.data(), Enumerators.size()); + llvm::DIArray EltArray = DBuilder.getOrCreateArray(Enumerators); llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation()); unsigned Line = getLineNumber(ED->getLocation()); @@ -1366,6 +1441,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T) { break; case Type::Attributed: T = cast(T)->getEquivalentType(); + break; case Type::Elaborated: T = cast(T)->getNamedType(); break; @@ -1375,6 +1451,9 @@ static QualType UnwrapTypeForDebugInfo(QualType T) { case Type::SubstTemplateTypeParm: T = cast(T)->getReplacementType(); break; + case Type::Auto: + T = cast(T)->getDeducedType(); + break; } assert(T != LastT && "Type unwrapping failed to unwrap!"); @@ -1394,7 +1473,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, // Unwrap the type as needed for debug information. Ty = UnwrapTypeForDebugInfo(Ty); - + // Check for existing entry. llvm::DenseMap::iterator it = TypeCache.find(Ty.getAsOpaquePtr()); @@ -1502,6 +1581,37 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType, return Ty; } +/// getFunctionDeclaration - Return debug info descriptor to describe method +/// declaration for the given method definition. +llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) { + const FunctionDecl *FD = dyn_cast(D); + if (!FD) return llvm::DISubprogram(); + + // Setup context. + getContextDescriptor(cast(D->getDeclContext())); + + llvm::DenseMap::iterator + MI = SPCache.find(FD); + if (MI != SPCache.end()) { + llvm::DISubprogram SP(dyn_cast_or_null(&*MI->second)); + if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition()) + return SP; + } + + for (FunctionDecl::redecl_iterator I = FD->redecls_begin(), + E = FD->redecls_end(); I != E; ++I) { + const FunctionDecl *NextFD = *I; + llvm::DenseMap::iterator + MI = SPCache.find(NextFD); + if (MI != SPCache.end()) { + llvm::DISubprogram SP(dyn_cast_or_null(&*MI->second)); + if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition()) + return SP; + } + } + return llvm::DISubprogram(); +} + /// EmitFunctionStart - Constructs the debug code for entering a function - /// "llvm.dbg.func.start.". void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, @@ -1514,9 +1624,11 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, FnBeginRegionCount.push_back(RegionStack.size()); const Decl *D = GD.getDecl(); + unsigned Flags = 0; llvm::DIFile Unit = getOrCreateFile(CurLoc); llvm::DIDescriptor FDContext(Unit); + llvm::DIArray TParamsArray; if (const FunctionDecl *FD = dyn_cast(D)) { // If there is a DISubprogram for this function available then use it. llvm::DenseMap::iterator @@ -1540,6 +1652,9 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, if (const NamespaceDecl *NSDecl = dyn_cast_or_null(FD->getDeclContext())) FDContext = getOrCreateNameSpace(NSDecl); + + // Collect template parameters. + TParamsArray = CollectFunctionTemplateParams(FD, Unit); } else if (const ObjCMethodDecl *OMD = dyn_cast(D)) { Name = getObjCMethodName(OMD); Flags |= llvm::DIDescriptor::FlagPrototyped; @@ -1557,11 +1672,14 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, unsigned LineNo = getLineNumber(CurLoc); if (D->isImplicit()) Flags |= llvm::DIDescriptor::FlagArtificial; + llvm::DIType SPTy = getOrCreateType(FnType, Unit); + llvm::DISubprogram SPDecl = getFunctionDeclaration(D); llvm::DISubprogram SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit, - LineNo, getOrCreateType(FnType, Unit), + LineNo, SPTy, Fn->hasInternalLinkage(), true/*definition*/, - Flags, CGM.getLangOptions().Optimize, Fn); + Flags, CGM.getLangOptions().Optimize, Fn, + TParamsArray, SPDecl); // Push function on region stack. llvm::MDNode *SPN = SP; @@ -1714,15 +1832,17 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, } CharUnits Align = CGM.getContext().getDeclAlign(VD); - if (Align > CharUnits::fromQuantity( - CGM.getContext().Target.getPointerAlign(0) / 8)) { - unsigned AlignedOffsetInBytes - = llvm::RoundUpToAlignment(FieldOffset/8, Align.getQuantity()); - unsigned NumPaddingBytes - = AlignedOffsetInBytes - FieldOffset/8; + if (Align > CGM.getContext().toCharUnitsFromBits( + CGM.getContext().Target.getPointerAlign(0))) { + CharUnits FieldOffsetInBytes + = CGM.getContext().toCharUnitsFromBits(FieldOffset); + CharUnits AlignedOffsetInBytes + = FieldOffsetInBytes.RoundUpToAlignment(Align); + CharUnits NumPaddingBytes + = AlignedOffsetInBytes - FieldOffsetInBytes; - if (NumPaddingBytes > 0) { - llvm::APInt pad(32, NumPaddingBytes); + if (NumPaddingBytes.isPositive()) { + llvm::APInt pad(32, NumPaddingBytes.getQuantity()); FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy, pad, ArrayType::Normal, 0); EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset)); @@ -1732,7 +1852,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FType = Type; llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); FieldSize = CGM.getContext().getTypeSize(FType); - FieldAlign = Align.getQuantity()*8; + FieldAlign = CGM.getContext().toBits(Align); *XOffset = FieldOffset; FieldTy = DBuilder.createMemberType(VD->getName(), Unit, @@ -1741,8 +1861,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, EltTys.push_back(FieldTy); FieldOffset += FieldSize; - llvm::DIArray Elements = - DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); + llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct; @@ -1752,7 +1871,8 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, /// EmitDeclare - Emit local variable declaration debug info. void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, - llvm::Value *Storage, CGBuilderTy &Builder) { + llvm::Value *Storage, + unsigned ArgNo, CGBuilderTy &Builder) { assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); @@ -1798,13 +1918,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext()); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of __forwarding field - offset = - CharUnits::fromQuantity(CGM.getContext().Target.getPointerWidth(0)/8); + offset = CGM.getContext().toCharUnitsFromBits( + CGM.getContext().Target.getPointerWidth(0)); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of x field - offset = CharUnits::fromQuantity(XOffset/8); + offset = CGM.getContext().toCharUnitsFromBits(XOffset); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); // Create the descriptor for the variable. @@ -1812,7 +1932,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, DBuilder.createComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()), VD->getName(), Unit, Line, Ty, - addr.data(), addr.size()); + addr, ArgNo); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = @@ -1825,7 +1945,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, llvm::DIVariable D = DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), Name, Unit, Line, Ty, - CGM.getLangOptions().Optimize, Flags); + CGM.getLangOptions().Optimize, Flags, ArgNo); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = @@ -1855,7 +1975,8 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, llvm::DIVariable D = DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), FieldName, Unit, Line, FieldTy, - CGM.getLangOptions().Optimize, Flags); + CGM.getLangOptions().Optimize, Flags, + ArgNo); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = @@ -1867,17 +1988,22 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, } } -/// EmitDeclare - Emit local variable declaration debug info. -void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, - llvm::Value *Storage, CGBuilderTy &Builder, - const CGBlockInfo &blockInfo) { - assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); +void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, + llvm::Value *Storage, + CGBuilderTy &Builder) { + EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder); +} +void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( + const VarDecl *VD, llvm::Value *Storage, CGBuilderTy &Builder, + const CGBlockInfo &blockInfo) { + assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); + if (Builder.GetInsertBlock() == 0) return; - + bool isByRef = VD->hasAttr(); - + uint64_t XOffset = 0; llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); llvm::DIType Ty; @@ -1904,46 +2030,34 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of __forwarding field - offset = CharUnits::fromQuantity(target.getPointerSize()/8); + offset = CGM.getContext().toCharUnitsFromBits(target.getPointerSizeInBits()); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of x field - offset = CharUnits::fromQuantity(XOffset/8); + offset = CGM.getContext().toCharUnitsFromBits(XOffset); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); } // Create the descriptor for the variable. llvm::DIVariable D = - DBuilder.createComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()), - VD->getName(), Unit, Line, Ty, - addr.data(), addr.size()); + DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable, + llvm::DIDescriptor(RegionStack.back()), + VD->getName(), Unit, Line, Ty, addr); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = - DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); + DBuilder.insertDeclare(Storage, D, Builder.GetInsertPoint()); llvm::MDNode *Scope = RegionStack.back(); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); } -void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, - llvm::Value *Storage, - CGBuilderTy &Builder) { - EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder); -} - -void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( - const VarDecl *variable, llvm::Value *Storage, CGBuilderTy &Builder, - const CGBlockInfo &blockInfo) { - EmitDeclare(variable, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder, - blockInfo); -} - /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument /// variable declaration. void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI, + unsigned ArgNo, CGBuilderTy &Builder) { - EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, Builder); + EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder); } namespace { @@ -1969,8 +2083,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, unsigned column = getColumnNumber(loc); // Build the debug-info type for the block literal. - llvm::DIDescriptor enclosingContext = - getContextDescriptor(cast(blockDecl->getDeclContext())); + getContextDescriptor(cast(blockDecl->getDeclContext())); const llvm::StructLayout *blockLayout = CGM.getTargetData().getStructLayout(block.StructureType); @@ -2048,18 +2161,31 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, } const VarDecl *variable = capture->getVariable(); - QualType type = (capture->isByRef() ? C.VoidPtrTy : variable->getType()); llvm::StringRef name = variable->getName(); - fields.push_back(createFieldType(name, type, 0, loc, AS_public, - offsetInBits, tunit)); + + llvm::DIType fieldType; + if (capture->isByRef()) { + std::pair ptrInfo = C.getTypeInfo(C.VoidPtrTy); + + // FIXME: this creates a second copy of this type! + uint64_t xoffset; + fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset); + fieldType = DBuilder.createPointerType(fieldType, ptrInfo.first); + fieldType = DBuilder.createMemberType(name, tunit, line, + ptrInfo.first, ptrInfo.second, + offsetInBits, 0, fieldType); + } else { + fieldType = createFieldType(name, variable->getType(), 0, + loc, AS_public, offsetInBits, tunit); + } + fields.push_back(fieldType); } llvm::SmallString<36> typeName; llvm::raw_svector_ostream(typeName) << "__block_literal_" << CGM.getUniqueBlockCount(); - llvm::DIArray fieldsArray = - DBuilder.getOrCreateArray(fields.data(), fields.size()); + llvm::DIArray fieldsArray = DBuilder.getOrCreateArray(fields); llvm::DIType type = DBuilder.createStructType(tunit, typeName.str(), tunit, line, @@ -2078,7 +2204,8 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable, llvm::DIDescriptor(scope), name, tunit, line, type, - CGM.getLangOptions().Optimize, flags); + CGM.getLangOptions().Optimize, flags, + cast(addr)->getArgNo() + 1); // Insert an llvm.dbg.value into the current block. llvm::Instruction *declare = @@ -2185,3 +2312,17 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) { NameSpaceCache[NSDecl] = llvm::WeakVH(NS); return NS; } + +/// UpdateCompletedType - Update type cache because the type is now +/// translated. +void CGDebugInfo::UpdateCompletedType(const TagDecl *TD) { + QualType Ty = CGM.getContext().getTagDeclType(TD); + + // If the type exist in type cache then remove it from the cache. + // There is no need to prepare debug info for the completed type + // right now. It will be generated on demand lazily. + llvm::DenseMap::iterator it = + TypeCache.find(Ty.getAsOpaquePtr()); + if (it != TypeCache.end()) + TypeCache.erase(it); +} diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h index a39078860fa9..27d991bbee42 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h @@ -32,6 +32,7 @@ namespace llvm { namespace clang { class VarDecl; class ObjCInterfaceDecl; + class ClassTemplateSpecializationDecl; namespace CodeGen { class CodeGenModule; @@ -122,6 +123,16 @@ class CGDebugInfo { llvm::DIFile F, llvm::SmallVectorImpl &EltTys, llvm::DIType RecordTy); + + llvm::DIArray + CollectTemplateParams(const TemplateParameterList *TPList, + const TemplateArgumentList &TAList, + llvm::DIFile Unit); + llvm::DIArray + CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit); + llvm::DIArray + CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TS, + llvm::DIFile F); llvm::DIType createFieldType(llvm::StringRef name, QualType type, Expr *bitWidth, SourceLocation loc, @@ -158,6 +169,10 @@ class CGDebugInfo { /// has introduced scope change. void UpdateLineDirectiveRegion(CGBuilderTy &Builder); + /// UpdateCompletedType - Update type cache because the type is now + /// translated. + void UpdateCompletedType(const TagDecl *TD); + /// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start /// of a new block. void EmitRegionStart(CGBuilderTy &Builder); @@ -181,7 +196,7 @@ class CGDebugInfo { /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument /// variable declaration. void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, - CGBuilderTy &Builder); + unsigned ArgNo, CGBuilderTy &Builder); /// EmitDeclareOfBlockLiteralArgVariable - Emit call to /// llvm.dbg.declare for the block-literal argument to a block @@ -204,12 +219,7 @@ class CGDebugInfo { private: /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration. void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI, - CGBuilderTy &Builder); - - /// EmitDeclare - Emit call to llvm.dbg.declare for a variable - /// declaration from an enclosing block. - void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI, - CGBuilderTy &Builder, const CGBlockInfo &blockInfo); + unsigned ArgNo, CGBuilderTy &Builder); // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref. // See BuildByRefType. @@ -243,6 +253,10 @@ class CGDebugInfo { llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType, llvm::StringRef Name, uint64_t *Offset); + /// getFunctionDeclaration - Return debug info descriptor to describe method + /// declaration for the given method definition. + llvm::DISubprogram getFunctionDeclaration(const Decl *D); + /// getFunctionName - Get function name for the given FunctionDecl. If the /// name is constructred on demand (e.g. C++ destructor) then the name /// is stored on the side. @@ -252,6 +266,10 @@ class CGDebugInfo { /// This is the display name for the debugging info. llvm::StringRef getObjCMethodName(const ObjCMethodDecl *FD); + /// getSelectorName - Return selector name. This is used for debugging + /// info. + llvm::StringRef getSelectorName(Selector S); + /// getClassName - Get class name including template argument list. llvm::StringRef getClassName(RecordDecl *RD); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp index f4db01d2570b..c02737581814 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp @@ -14,7 +14,6 @@ #include "CGDebugInfo.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" -#include "CGBlocks.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" @@ -70,7 +69,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Friend: case Decl::FriendTemplate: case Decl::Block: - assert(0 && "Declaration not should not be in declstmts!"); + assert(0 && "Declaration should not be in declstmts!"); case Decl::Function: // void X(); case Decl::Record: // struct/union/class X; case Decl::Enum: // enum X; @@ -92,8 +91,9 @@ void CodeGenFunction::EmitDecl(const Decl &D) { return EmitVarDecl(VD); } - case Decl::Typedef: { // typedef int X; - const TypedefDecl &TD = cast(D); + case Decl::Typedef: // typedef int X; + case Decl::TypeAlias: { // using X = int; [C++0x] + const TypedefNameDecl &TD = cast(D); QualType Ty = TD.getUnderlyingType(); if (Ty->isVariablyModifiedType()) @@ -179,7 +179,8 @@ CodeGenFunction::CreateStaticVarDecl(const VarDecl &D, new llvm::GlobalVariable(CGM.getModule(), LTy, Ty.isConstant(getContext()), Linkage, CGM.EmitNullConstant(D.getType()), Name, 0, - D.isThreadSpecified(), Ty.getAddressSpace()); + D.isThreadSpecified(), + CGM.getContext().getTargetAddressSpace(Ty)); GV->setAlignment(getContext().getDeclAlign(&D).getQuantity()); if (Linkage != llvm::GlobalValue::InternalLinkage) GV->setVisibility(CurFn->getVisibility()); @@ -222,7 +223,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, OldGV->getLinkage(), Init, "", /*InsertBefore*/ OldGV, D.isThreadSpecified(), - D.getType().getAddressSpace()); + CGM.getContext().getTargetAddressSpace(D.getType())); GV->setVisibility(OldGV->getVisibility()); // Steal the name of the old global @@ -289,7 +290,8 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, // FIXME: It is really dangerous to store this in the map; if anyone // RAUW's the GV uses of this constant will be invalid. const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType()); - const llvm::Type *LPtrTy = LTy->getPointerTo(D.getType().getAddressSpace()); + const llvm::Type *LPtrTy = + LTy->getPointerTo(CGM.getContext().getTargetAddressSpace(D.getType())); DMEntry = llvm::ConstantExpr::getBitCast(GV, LPtrTy); // Emit global variable debug descriptor for static vars. @@ -300,114 +302,6 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, } } -unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const { - assert(ByRefValueInfo.count(VD) && "Did not find value!"); - - return ByRefValueInfo.find(VD)->second.second; -} - -llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr, - const VarDecl *V) { - llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding"); - Loc = Builder.CreateLoad(Loc); - Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V), - V->getNameAsString()); - return Loc; -} - -/// BuildByRefType - This routine changes a __block variable declared as T x -/// into: -/// -/// struct { -/// void *__isa; -/// void *__forwarding; -/// int32_t __flags; -/// int32_t __size; -/// void *__copy_helper; // only if needed -/// void *__destroy_helper; // only if needed -/// char padding[X]; // only if needed -/// T x; -/// } x -/// -const llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) { - std::pair &Info = ByRefValueInfo[D]; - if (Info.first) - return Info.first; - - QualType Ty = D->getType(); - - std::vector Types; - - llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(getLLVMContext()); - - // void *__isa; - Types.push_back(Int8PtrTy); - - // void *__forwarding; - Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder)); - - // int32_t __flags; - Types.push_back(Int32Ty); - - // int32_t __size; - Types.push_back(Int32Ty); - - bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty); - if (HasCopyAndDispose) { - /// void *__copy_helper; - Types.push_back(Int8PtrTy); - - /// void *__destroy_helper; - Types.push_back(Int8PtrTy); - } - - bool Packed = false; - CharUnits Align = getContext().getDeclAlign(D); - if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) { - // We have to insert padding. - - // The struct above has 2 32-bit integers. - unsigned CurrentOffsetInBytes = 4 * 2; - - // And either 2 or 4 pointers. - CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) * - CGM.getTargetData().getTypeAllocSize(Int8PtrTy); - - // Align the offset. - unsigned AlignedOffsetInBytes = - llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity()); - - unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes; - if (NumPaddingBytes > 0) { - const llvm::Type *Ty = llvm::Type::getInt8Ty(getLLVMContext()); - // FIXME: We need a sema error for alignment larger than the minimum of - // the maximal stack alignmint and the alignment of malloc on the system. - if (NumPaddingBytes > 1) - Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); - - Types.push_back(Ty); - - // We want a packed struct. - Packed = true; - } - } - - // T x; - Types.push_back(ConvertTypeForMem(Ty)); - - const llvm::Type *T = llvm::StructType::get(getLLVMContext(), Types, Packed); - - cast(ByRefTypeHolder.get())->refineAbstractTypeTo(T); - CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(), - ByRefTypeHolder.get()); - - Info.first = ByRefTypeHolder.get(); - - Info.second = Types.size() - 1; - - return Info.first; -} - namespace { struct CallArrayDtor : EHScopeStack::Cleanup { CallArrayDtor(const CXXDestructorDecl *Dtor, @@ -498,20 +392,11 @@ namespace { CGF.Builder.CreateBitCast(Addr, CGF.ConvertType(ArgTy)); CallArgList Args; - Args.push_back(std::make_pair(RValue::get(Arg), - CGF.getContext().getPointerType(Var.getType()))); + Args.add(RValue::get(Arg), + CGF.getContext().getPointerType(Var.getType())); CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args); } }; - - struct CallBlockRelease : EHScopeStack::Cleanup { - llvm::Value *Addr; - CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {} - - void Emit(CodeGenFunction &CGF, bool IsForEH) { - CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF); - } - }; } @@ -642,7 +527,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // candidate nor a __block variable, emit it as a global instead. if (CGM.getCodeGenOpts().MergeAllConstants && Ty.isConstQualified() && !NRVO && !isByRef) { - EmitStaticVarDecl(D, llvm::GlobalValue::PrivateLinkage); + EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage); emission.Address = 0; // signal this condition to later callbacks assert(emission.wasEmittedAsGlobal()); @@ -724,7 +609,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // Get the element type. const llvm::Type *LElemTy = ConvertTypeForMem(Ty); - const llvm::Type *LElemPtrTy = LElemTy->getPointerTo(Ty.getAddressSpace()); + const llvm::Type *LElemPtrTy = + LElemTy->getPointerTo(CGM.getContext().getTargetAddressSpace(Ty)); llvm::Value *VLASize = EmitVLASize(Ty); @@ -800,75 +686,14 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { EnsureInsertPoint(); } - CharUnits alignment = emission.Alignment; - - if (emission.IsByRef) { - llvm::Value *V; - - BlockFieldFlags fieldFlags; - bool fieldNeedsCopyDispose = false; - - if (type->isBlockPointerType()) { - fieldFlags |= BLOCK_FIELD_IS_BLOCK; - fieldNeedsCopyDispose = true; - } else if (getContext().isObjCNSObjectType(type) || - type->isObjCObjectPointerType()) { - fieldFlags |= BLOCK_FIELD_IS_OBJECT; - fieldNeedsCopyDispose = true; - } else if (getLangOptions().CPlusPlus) { - if (getContext().getBlockVarCopyInits(&D)) - fieldNeedsCopyDispose = true; - else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) - fieldNeedsCopyDispose = !record->hasTrivialDestructor(); - } - - llvm::Value *addr = emission.Address; - - // FIXME: Someone double check this. - if (type.isObjCGCWeak()) - fieldFlags |= BLOCK_FIELD_IS_WEAK; - - // Initialize the 'isa', which is just 0 or 1. - int isa = 0; - if (fieldFlags & BLOCK_FIELD_IS_WEAK) - isa = 1; - V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); - Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa")); - - // Store the address of the variable into its own forwarding pointer. - Builder.CreateStore(addr, - Builder.CreateStructGEP(addr, 1, "byref.forwarding")); - - // Blocks ABI: - // c) the flags field is set to either 0 if no helper functions are - // needed or BLOCK_HAS_COPY_DISPOSE if they are, - BlockFlags flags; - if (fieldNeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; - Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), - Builder.CreateStructGEP(addr, 2, "byref.flags")); - - const llvm::Type *V1; - V1 = cast(addr->getType())->getElementType(); - V = llvm::ConstantInt::get(IntTy, CGM.GetTargetTypeStoreSize(V1).getQuantity()); - Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size")); - - if (fieldNeedsCopyDispose) { - llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4); - Builder.CreateStore(CGM.BuildbyrefCopyHelper(addr->getType(), fieldFlags, - alignment.getQuantity(), &D), - copy_helper); - - llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5); - Builder.CreateStore(CGM.BuildbyrefDestroyHelper(addr->getType(), - fieldFlags, - alignment.getQuantity(), - &D), - destroy_helper); - } - } + // Initialize the structure of a __block variable. + if (emission.IsByRef) + emitByrefStructureInit(emission); if (!Init) return; + CharUnits alignment = emission.Alignment; + // Check whether this is a byref variable that's potentially // captured and moved by its own initializer. If so, we'll need to // emit the initializer first, then copy into the variable. @@ -877,67 +702,91 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { llvm::Value *Loc = capturedByInit ? emission.Address : emission.getObjectAddress(*this); - bool isVolatile = type.isVolatileQualified(); - + if (!emission.IsConstantAggregate) + return EmitExprAsInit(Init, &D, Loc, alignment, capturedByInit); + // If this is a simple aggregate initialization, we can optimize it // in various ways. - if (emission.IsConstantAggregate) { - assert(!capturedByInit && "constant init contains a capturing block?"); + assert(!capturedByInit && "constant init contains a capturing block?"); - llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), type, this); - assert(Init != 0 && "Wasn't a simple constant init?"); + bool isVolatile = type.isVolatileQualified(); - llvm::Value *SizeVal = - llvm::ConstantInt::get(IntPtrTy, - getContext().getTypeSizeInChars(type).getQuantity()); + llvm::Constant *constant = CGM.EmitConstantExpr(D.getInit(), type, this); + assert(constant != 0 && "Wasn't a simple constant init?"); - const llvm::Type *BP = Int8PtrTy; - if (Loc->getType() != BP) - Loc = Builder.CreateBitCast(Loc, BP, "tmp"); + llvm::Value *SizeVal = + llvm::ConstantInt::get(IntPtrTy, + getContext().getTypeSizeInChars(type).getQuantity()); - // If the initializer is all or mostly zeros, codegen with memset then do - // a few stores afterward. - if (shouldUseMemSetPlusStoresToInitialize(Init, - CGM.getTargetData().getTypeAllocSize(Init->getType()))) { - Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, - alignment.getQuantity(), isVolatile); - if (!Init->isNullValue()) { - Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo()); - emitStoresForInitAfterMemset(Init, Loc, isVolatile, Builder); - } - } else { - // Otherwise, create a temporary global with the initializer then - // memcpy from the global to the alloca. - std::string Name = GetStaticDeclName(*this, D, "."); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true, - llvm::GlobalValue::InternalLinkage, - Init, Name, 0, false, 0); - GV->setAlignment(alignment.getQuantity()); - - llvm::Value *SrcPtr = GV; - if (SrcPtr->getType() != BP) - SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); + const llvm::Type *BP = Int8PtrTy; + if (Loc->getType() != BP) + Loc = Builder.CreateBitCast(Loc, BP, "tmp"); - Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, alignment.getQuantity(), - isVolatile); + // If the initializer is all or mostly zeros, codegen with memset then do + // a few stores afterward. + if (shouldUseMemSetPlusStoresToInitialize(constant, + CGM.getTargetData().getTypeAllocSize(constant->getType()))) { + Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, + alignment.getQuantity(), isVolatile); + if (!constant->isNullValue()) { + Loc = Builder.CreateBitCast(Loc, constant->getType()->getPointerTo()); + emitStoresForInitAfterMemset(constant, Loc, isVolatile, Builder); } - } else if (type->isReferenceType()) { - RValue RV = EmitReferenceBindingToExpr(Init, &D); - if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D); - EmitStoreOfScalar(RV.getScalarVal(), Loc, false, alignment.getQuantity(), - type); + } else { + // Otherwise, create a temporary global with the initializer then + // memcpy from the global to the alloca. + std::string Name = GetStaticDeclName(*this, D, "."); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(CGM.getModule(), constant->getType(), true, + llvm::GlobalValue::InternalLinkage, + constant, Name, 0, false, 0); + GV->setAlignment(alignment.getQuantity()); + + llvm::Value *SrcPtr = GV; + if (SrcPtr->getType() != BP) + SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); + + Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, alignment.getQuantity(), + isVolatile); + } +} + +/// Emit an expression as an initializer for a variable at the given +/// location. The expression is not necessarily the normal +/// initializer for the variable, and the address is not necessarily +/// its normal location. +/// +/// \param init the initializing expression +/// \param var the variable to act as if we're initializing +/// \param loc the address to initialize; its type is a pointer +/// to the LLVM mapping of the variable's type +/// \param alignment the alignment of the address +/// \param capturedByInit true if the variable is a __block variable +/// whose address is potentially changed by the initializer +void CodeGenFunction::EmitExprAsInit(const Expr *init, + const VarDecl *var, + llvm::Value *loc, + CharUnits alignment, + bool capturedByInit) { + QualType type = var->getType(); + bool isVolatile = type.isVolatileQualified(); + + if (type->isReferenceType()) { + RValue RV = EmitReferenceBindingToExpr(init, var); + if (capturedByInit) loc = BuildBlockByrefAddress(loc, var); + EmitStoreOfScalar(RV.getScalarVal(), loc, false, + alignment.getQuantity(), type); } else if (!hasAggregateLLVMType(type)) { - llvm::Value *V = EmitScalarExpr(Init); - if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D); - EmitStoreOfScalar(V, Loc, isVolatile, alignment.getQuantity(), type); + llvm::Value *V = EmitScalarExpr(init); + if (capturedByInit) loc = BuildBlockByrefAddress(loc, var); + EmitStoreOfScalar(V, loc, isVolatile, alignment.getQuantity(), type); } else if (type->isAnyComplexType()) { - ComplexPairTy complex = EmitComplexExpr(Init); - if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D); - StoreComplexToAddr(complex, Loc, isVolatile); + ComplexPairTy complex = EmitComplexExpr(init); + if (capturedByInit) loc = BuildBlockByrefAddress(loc, var); + StoreComplexToAddr(complex, loc, isVolatile); } else { // TODO: how can we delay here if D is captured by its initializer? - EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false)); + EmitAggExpr(init, AggValueSlot::forAddr(loc, isVolatile, true, false)); } } @@ -993,14 +842,14 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { // If this is a block variable, call _Block_object_destroy // (on the unforwarded address). - if (emission.IsByRef && - CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) - EHStack.pushCleanup(NormalAndEHCleanup, emission.Address); + if (emission.IsByRef) + enterByrefCleanup(emission); } /// Emit an alloca (or GlobalValue depending on target) /// for the specified parameter and set up LocalDeclMap. -void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { +void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg, + unsigned ArgNo) { // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl? assert((isa(D) || isa(D)) && "Invalid argument to EmitParmDecl"); @@ -1046,6 +895,6 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { // Emit debug info for param declaration. if (CGDebugInfo *DI = getDebugInfo()) { DI->setLocation(D.getLocation()); - DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder); + DI->EmitDeclareOfArgVariable(&D, DeclPtr, ArgNo, Builder); } } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp index e295267896eb..45b0b969be67 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp @@ -138,6 +138,8 @@ CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, "__cxa_atexit"); + if (llvm::Function *Fn = dyn_cast(AtExitFn)) + Fn->setDoesNotThrow(); llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy, "__dso_handle"); @@ -149,6 +151,14 @@ CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr) { + // If we've been asked to forbid guard variables, emit an error now. + // This diagnostic is hard-coded for Darwin's use case; we can find + // better phrasing if someone else needs it. + if (CGM.getCodeGenOpts().ForbidGuardVariables) + CGM.Error(D.getLocation(), + "this initialization requires a guard variable, which " + "the kernel does not support"); + CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr); } @@ -166,7 +176,7 @@ CreateGlobalInitOrDestructFunction(CodeGenModule &CGM, Fn->setSection(Section); } - if (!CGM.getLangOptions().areExceptionsEnabled()) + if (!CGM.getLangOptions().Exceptions) Fn->setDoesNotThrow(); return Fn; @@ -260,12 +270,16 @@ void CodeGenModule::EmitCXXGlobalDtorFunc() { void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D, llvm::GlobalVariable *Addr) { - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), - SourceLocation()); + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, + getTypes().getNullaryFunctionInfo(), + FunctionArgList(), SourceLocation()); // Use guarded initialization if the global variable is weak due to - // being a class template's static data member. - if (Addr->hasWeakLinkage() && D->getInstantiatedFromStaticDataMember()) { + // being a class template's static data member. These will always + // have weak_odr linkage. + if (Addr->getLinkage() == llvm::GlobalValue::WeakODRLinkage && + D->isStaticDataMember() && + D->getInstantiatedFromStaticDataMember()) { EmitCXXGuardedInit(*D, Addr); } else { EmitCXXGlobalVarDeclInit(*D, Addr); @@ -277,8 +291,9 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, llvm::Constant **Decls, unsigned NumDecls) { - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), - SourceLocation()); + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, + getTypes().getNullaryFunctionInfo(), + FunctionArgList(), SourceLocation()); for (unsigned i = 0; i != NumDecls; ++i) if (Decls[i]) @@ -290,8 +305,9 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, const std::vector > &DtorsAndObjects) { - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), - SourceLocation()); + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, + getTypes().getNullaryFunctionInfo(), + FunctionArgList(), SourceLocation()); // Emit the dtors, in reverse order from construction. for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { @@ -313,21 +329,19 @@ llvm::Function * CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, const ArrayType *Array, llvm::Value *This) { - FunctionArgList Args; - ImplicitParamDecl *Dst = - ImplicitParamDecl::Create(getContext(), 0, - SourceLocation(), 0, - getContext().getPointerType(getContext().VoidTy)); - Args.push_back(std::make_pair(Dst, Dst->getType())); + FunctionArgList args; + ImplicitParamDecl dst(0, SourceLocation(), 0, getContext().VoidPtrTy); + args.push_back(&dst); const CGFunctionInfo &FI = - CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args, + CGM.getTypes().getFunctionInfo(getContext().VoidTy, args, FunctionType::ExtInfo()); const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false); llvm::Function *Fn = CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor"); - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation()); + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FI, args, + SourceLocation()); QualType BaseElementTy = getContext().getBaseElementType(Array); const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo(); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp index 4bce081e48dd..6cb9599e257d 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp @@ -28,24 +28,22 @@ using namespace CodeGen; static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) { // void *__cxa_allocate_exception(size_t thrown_size); - const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); - std::vector Args(1, SizeTy); + const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()), - Args, false); + llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()), + SizeTy, /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception"); } static llvm::Constant *getFreeExceptionFn(CodeGenFunction &CGF) { // void __cxa_free_exception(void *thrown_exception); - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - std::vector Args(1, Int8PtrTy); + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), - Args, false); + llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), + Int8PtrTy, /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception"); } @@ -55,11 +53,10 @@ static llvm::Constant *getThrowFn(CodeGenFunction &CGF) { // void (*dest) (void *)); const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - std::vector Args(3, Int8PtrTy); - + const llvm::Type *Args[3] = { Int8PtrTy, Int8PtrTy, Int8PtrTy }; const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), - Args, false); + Args, /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw"); } @@ -68,18 +65,18 @@ static llvm::Constant *getReThrowFn(CodeGenFunction &CGF) { // void __cxa_rethrow(); const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); + llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), + /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow"); } static llvm::Constant *getGetExceptionPtrFn(CodeGenFunction &CGF) { // void *__cxa_get_exception_ptr(void*); - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - std::vector Args(1, Int8PtrTy); + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); const llvm::FunctionType *FTy = - llvm::FunctionType::get(Int8PtrTy, Args, false); + llvm::FunctionType::get(Int8PtrTy, Int8PtrTy, /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr"); } @@ -88,10 +85,8 @@ static llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) { // void *__cxa_begin_catch(void*); const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - std::vector Args(1, Int8PtrTy); - const llvm::FunctionType *FTy = - llvm::FunctionType::get(Int8PtrTy, Args, false); + llvm::FunctionType::get(Int8PtrTy, Int8PtrTy, /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); } @@ -100,7 +95,8 @@ static llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) { // void __cxa_end_catch(); const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); + llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), + /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); } @@ -109,22 +105,18 @@ static llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) { // void __cxa_call_unexepcted(void *thrown_exception); const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - std::vector Args(1, Int8PtrTy); - const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), - Args, false); + Int8PtrTy, /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); } llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() { const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); - std::vector Args(1, Int8PtrTy); - const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), Args, - false); + llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), Int8PtrTy, + /*IsVarArgs=*/false); if (CGM.getLangOptions().SjLjExceptions) return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume_or_Rethrow"); @@ -135,7 +127,8 @@ static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) { // void __terminate(); const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); + llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), + /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, CGF.CGM.getLangOptions().CPlusPlus ? "_ZSt9terminatev" : "abort"); @@ -145,10 +138,9 @@ static llvm::Constant *getCatchallRethrowFn(CodeGenFunction &CGF, llvm::StringRef Name) { const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - std::vector Args(1, Int8PtrTy); - const llvm::Type *VoidTy = llvm::Type::getVoidTy(CGF.getLLVMContext()); - const llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, Args, false); + const llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, Int8PtrTy, + /*IsVarArgs=*/false); return CGF.CGM.CreateRuntimeFunction(FTy, Name); } @@ -160,6 +152,7 @@ const EHPersonality EHPersonality::GNU_CPlusPlus("__gxx_personality_v0"); const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ("__gxx_personality_sj0"); const EHPersonality EHPersonality::GNU_ObjC("__gnu_objc_personality_v0", "objc_exception_throw"); +const EHPersonality EHPersonality::GNU_ObjCXX("__gnustep_objcxx_personality_v0"); static const EHPersonality &getCPersonality(const LangOptions &L) { if (L.SjLjExceptions) @@ -201,7 +194,7 @@ static const EHPersonality &getObjCXXPersonality(const LangOptions &L) { // The GNU runtime's personality function inherently doesn't support // mixed EH. Use the C++ personality just to avoid returning null. - return getCXXPersonality(L); + return EHPersonality::GNU_ObjCXX; } const EHPersonality &EHPersonality::get(const LangOptions &L) { @@ -273,7 +266,7 @@ static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) { /// when it really needs it. void CodeGenModule::SimplifyPersonality() { // For now, this is really a Darwin-specific operation. - if (Context.Target.getTriple().getOS() != llvm::Triple::Darwin) + if (!Context.Target.getTriple().isOSDarwin()) return; // If we're not in ObjC++ -fexceptions, there's nothing to do. @@ -439,7 +432,7 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { } void CodeGenFunction::EmitStartEHSpec(const Decl *D) { - if (!CGM.getLangOptions().areExceptionsEnabled()) + if (!CGM.getLangOptions().CXXExceptions) return; const FunctionDecl* FD = dyn_cast_or_null(D); @@ -449,25 +442,28 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { if (Proto == 0) return; - assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack"); + ExceptionSpecificationType EST = Proto->getExceptionSpecType(); + if (isNoexceptExceptionSpec(EST)) { + if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) { + // noexcept functions are simple terminate scopes. + EHStack.pushTerminate(); + } + } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { + unsigned NumExceptions = Proto->getNumExceptions(); + EHFilterScope *Filter = EHStack.pushFilter(NumExceptions); - if (!Proto->hasExceptionSpec()) - return; - - unsigned NumExceptions = Proto->getNumExceptions(); - EHFilterScope *Filter = EHStack.pushFilter(NumExceptions); - - for (unsigned I = 0; I != NumExceptions; ++I) { - QualType Ty = Proto->getExceptionType(I); - QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType(); - llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType, - /*ForEH=*/true); - Filter->setFilter(I, EHType); + for (unsigned I = 0; I != NumExceptions; ++I) { + QualType Ty = Proto->getExceptionType(I); + QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType(); + llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType, + /*ForEH=*/true); + Filter->setFilter(I, EHType); + } } } void CodeGenFunction::EmitEndEHSpec(const Decl *D) { - if (!CGM.getLangOptions().areExceptionsEnabled()) + if (!CGM.getLangOptions().CXXExceptions) return; const FunctionDecl* FD = dyn_cast_or_null(D); @@ -477,10 +473,14 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) { if (Proto == 0) return; - if (!Proto->hasExceptionSpec()) - return; - - EHStack.popFilter(); + ExceptionSpecificationType EST = Proto->getExceptionSpecType(); + if (isNoexceptExceptionSpec(EST)) { + if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) { + EHStack.popTerminate(); + } + } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { + EHStack.popFilter(); + } } void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { @@ -541,7 +541,7 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { assert(EHStack.requiresLandingPad()); assert(!EHStack.empty()); - if (!CGM.getLangOptions().areExceptionsEnabled()) + if (!CGM.getLangOptions().Exceptions) return 0; // Check the innermost scope for a cached landing pad. If this is @@ -664,7 +664,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { assert(I.next() == EHStack.end() && "EH filter is not end of EH stack"); assert(!CatchAll.isValid() && "EH filter reached after catch-all"); - // Filter scopes get added to the selector in wierd ways. + // Filter scopes get added to the selector in weird ways. EHFilterScope &Filter = cast(*I); HasEHFilter = true; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.h b/contrib/llvm/tools/clang/lib/CodeGen/CGException.h index 1f9b8964dcae..5a743b51f66f 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.h @@ -41,6 +41,7 @@ class EHPersonality { static const EHPersonality GNU_C; static const EHPersonality GNU_C_SJLJ; static const EHPersonality GNU_ObjC; + static const EHPersonality GNU_ObjCXX; static const EHPersonality NeXT_ObjC; static const EHPersonality GNU_CPlusPlus; static const EHPersonality GNU_CPlusPlus_SJLJ; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp index 2abaadff4b6d..bc2cd35bc591 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp @@ -15,6 +15,7 @@ #include "CodeGenModule.h" #include "CGCall.h" #include "CGCXXABI.h" +#include "CGDebugInfo.h" #include "CGRecordLayout.h" #include "CGObjCRuntime.h" #include "clang/AST/ASTContext.h" @@ -215,24 +216,28 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, InitializedDecl); } + if (const ObjCPropertyRefExpr *PRE = + dyn_cast(E->IgnoreParenImpCasts())) + if (PRE->getGetterResultType()->isReferenceType()) + E = PRE; + RValue RV; if (E->isGLValue()) { // Emit the expression as an lvalue. LValue LV = CGF.EmitLValue(E); + if (LV.isPropertyRef()) { + RV = CGF.EmitLoadOfPropertyRefLValue(LV); + return RV.getScalarVal(); + } if (LV.isSimple()) return LV.getAddress(); // We have to load the lvalue. RV = CGF.EmitLoadOfLValue(LV, E->getType()); } else { - QualType ResultTy = E->getType(); - llvm::SmallVector Adjustments; while (true) { - if (const ParenExpr *PE = dyn_cast(E)) { - E = PE->getSubExpr(); - continue; - } + E = E->IgnoreParens(); if (const CastExpr *CE = dyn_cast(E)) { if ((CE->getCastKind() == CK_DerivedToBase || @@ -327,9 +332,8 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, } } - - const llvm::Type *ResultPtrTy = CGF.ConvertType(ResultTy)->getPointerTo(); - return CGF.Builder.CreateBitCast(Object, ResultPtrTy, "temp"); + + return Object; } } @@ -536,6 +540,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast(E)); case Expr::ParenExprClass:return EmitLValue(cast(E)->getSubExpr()); + case Expr::GenericSelectionExprClass: + return EmitLValue(cast(E)->getResultExpr()); case Expr::PredefinedExprClass: return EmitPredefinedLValue(cast(E)); case Expr::StringLiteralClass: @@ -718,21 +724,22 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, Ptr = Builder.CreateStructGEP(Ptr, AI.FieldIndex, "bf.field"); // Offset by the byte offset, if used. - if (AI.FieldByteOffset) { + if (!AI.FieldByteOffset.isZero()) { Ptr = EmitCastToVoidPtr(Ptr); - Ptr = Builder.CreateConstGEP1_32(Ptr, AI.FieldByteOffset,"bf.field.offs"); + Ptr = Builder.CreateConstGEP1_32(Ptr, AI.FieldByteOffset.getQuantity(), + "bf.field.offs"); } // Cast to the access type. const llvm::Type *PTy = llvm::Type::getIntNPtrTy(getLLVMContext(), AI.AccessWidth, - ExprType.getAddressSpace()); + CGM.getContext().getTargetAddressSpace(ExprType)); Ptr = Builder.CreateBitCast(Ptr, PTy); // Perform the load. llvm::LoadInst *Load = Builder.CreateLoad(Ptr, LV.isVolatileQualified()); - if (AI.AccessAlignment) - Load->setAlignment(AI.AccessAlignment); + if (!AI.AccessAlignment.isZero()) + Load->setAlignment(AI.AccessAlignment.getQuantity()); // Shift out unused low bits and mask out unused high bits. llvm::Value *Val = Load; @@ -921,9 +928,10 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, Ptr = Builder.CreateStructGEP(Ptr, AI.FieldIndex, "bf.field"); // Offset by the byte offset, if used. - if (AI.FieldByteOffset) { + if (!AI.FieldByteOffset.isZero()) { Ptr = EmitCastToVoidPtr(Ptr); - Ptr = Builder.CreateConstGEP1_32(Ptr, AI.FieldByteOffset,"bf.field.offs"); + Ptr = Builder.CreateConstGEP1_32(Ptr, AI.FieldByteOffset.getQuantity(), + "bf.field.offs"); } // Cast to the access type. @@ -954,8 +962,8 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, // If necessary, load and OR in bits that are outside of the bit-field. if (AI.TargetBitWidth != AI.AccessWidth) { llvm::LoadInst *Load = Builder.CreateLoad(Ptr, Dst.isVolatileQualified()); - if (AI.AccessAlignment) - Load->setAlignment(AI.AccessAlignment); + if (!AI.AccessAlignment.isZero()) + Load->setAlignment(AI.AccessAlignment.getQuantity()); // Compute the mask for zeroing the bits that are part of the bit-field. llvm::APInt InvMask = @@ -969,8 +977,8 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, // Write the value. llvm::StoreInst *Store = Builder.CreateStore(Val, Ptr, Dst.isVolatileQualified()); - if (AI.AccessAlignment) - Store->setAlignment(AI.AccessAlignment); + if (!AI.AccessAlignment.isZero()) + Store->setAlignment(AI.AccessAlignment.getQuantity()); } } @@ -1090,6 +1098,12 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, } return; } + + if (const GenericSelectionExpr *Exp = dyn_cast(E)) { + setObjCGCLValueClass(Ctx, Exp->getResultExpr(), LV); + return; + } + if (const ImplicitCastExpr *Exp = dyn_cast(E)) { setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); return; @@ -1415,6 +1429,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { // We know that the pointer points to a type of the correct size, unless the // size is a VLA or Objective-C interface. llvm::Value *Address = 0; + unsigned ArrayAlignment = 0; if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(E->getType())) { llvm::Value *VLASize = GetVLASize(VAT); @@ -1425,7 +1440,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { llvm::Value *Base = EmitScalarExpr(E->getBase()); Address = EmitCastToVoidPtr(Base); - Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx"); + if (getContext().getLangOptions().isSignedOverflowDefined()) + Address = Builder.CreateGEP(Address, Idx, "arrayidx"); + else + Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx"); Address = Builder.CreateBitCast(Address, Base->getType()); } else if (const ObjCObjectType *OIT = E->getType()->getAs()){ // Indexing over an interface, as in "NSString *P; P[4];" @@ -1447,22 +1465,38 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { // "gep x, i" here. Emit one "gep A, 0, i". assert(Array->getType()->isArrayType() && "Array to pointer decay must have array source type!"); - llvm::Value *ArrayPtr = EmitLValue(Array).getAddress(); + LValue ArrayLV = EmitLValue(Array); + llvm::Value *ArrayPtr = ArrayLV.getAddress(); llvm::Value *Zero = llvm::ConstantInt::get(Int32Ty, 0); llvm::Value *Args[] = { Zero, Idx }; - Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, Args+2, "arrayidx"); + // Propagate the alignment from the array itself to the result. + ArrayAlignment = ArrayLV.getAlignment(); + + if (getContext().getLangOptions().isSignedOverflowDefined()) + Address = Builder.CreateGEP(ArrayPtr, Args, Args+2, "arrayidx"); + else + Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, Args+2, "arrayidx"); } else { // The base must be a pointer, which is not an aggregate. Emit it. llvm::Value *Base = EmitScalarExpr(E->getBase()); - Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx"); + if (getContext().getLangOptions().isSignedOverflowDefined()) + Address = Builder.CreateGEP(Base, Idx, "arrayidx"); + else + Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx"); } QualType T = E->getBase()->getType()->getPointeeType(); assert(!T.isNull() && "CodeGenFunction::EmitArraySubscriptExpr(): Illegal base type"); - LValue LV = MakeAddrLValue(Address, T); + // Limit the alignment to that of the result type. + if (ArrayAlignment) { + unsigned Align = getContext().getTypeAlignInChars(T).getQuantity(); + ArrayAlignment = std::min(Align, ArrayAlignment); + } + + LValue LV = MakeAddrLValue(Address, T, ArrayAlignment); LV.getQuals().setAddressSpace(E->getBase()->getType().getAddressSpace()); if (getContext().getLangOptions().ObjC1 && @@ -1715,10 +1749,10 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) { } const Expr *condExpr = expr->getCond(); - - if (int condValue = ConstantFoldsToSimpleInteger(condExpr)) { + bool CondExprBool; + if (ConstantFoldsToSimpleInteger(condExpr, CondExprBool)) { const Expr *live = expr->getTrueExpr(), *dead = expr->getFalseExpr(); - if (condValue == -1) std::swap(live, dead); + if (!CondExprBool) std::swap(live, dead); if (!ContainsLabel(dead)) return EmitLValue(live); @@ -1756,9 +1790,8 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) { EmitBlock(contBlock); - llvm::PHINode *phi = Builder.CreatePHI(lhs.getAddress()->getType(), + llvm::PHINode *phi = Builder.CreatePHI(lhs.getAddress()->getType(), 2, "cond-lvalue"); - phi->reserveOperandSpace(2); phi->addIncoming(lhs.getAddress(), lhsBlock); phi->addIncoming(rhs.getAddress(), rhsBlock); return MakeAddrLValue(phi, expr->getType()); @@ -1927,6 +1960,12 @@ LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) { RValue CodeGenFunction::EmitCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue) { + if (CGDebugInfo *DI = getDebugInfo()) { + DI->setLocation(E->getLocStart()); + DI->UpdateLineDirectiveRegion(Builder); + DI->EmitStopPoint(Builder); + } + // Builtins never have block type. if (E->getCallee()->getType()->isBlockPointerType()) return EmitBlockCallExpr(E, ReturnValue); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp index f992dc7c9cb9..29c76887a7c9 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp @@ -81,6 +81,9 @@ class AggExprEmitter : public StmtVisitor { CGF.ErrorUnsupported(S, "aggregate expression"); } void VisitParenExpr(ParenExpr *PE) { Visit(PE->getSubExpr()); } + void VisitGenericSelectionExpr(GenericSelectionExpr *GE) { + Visit(GE->getResultExpr()); + } void VisitUnaryExtension(UnaryOperator *E) { Visit(E->getSubExpr()); } // l-values. @@ -179,11 +182,9 @@ bool AggExprEmitter::TypeRequiresGCollection(QualType T) { /// move will be performed. void AggExprEmitter::EmitGCMove(const Expr *E, RValue Src) { if (Dest.requiresGCollection()) { - std::pair TypeInfo = - CGF.getContext().getTypeInfo(E->getType()); - unsigned long size = TypeInfo.first/8; + CharUnits size = CGF.getContext().getTypeSizeInChars(E->getType()); const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); - llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size); + llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size.getQuantity()); CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, Dest.getAddr(), Src.getAggregateAddr(), SizeVal); @@ -212,11 +213,9 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) { } if (Dest.requiresGCollection()) { - std::pair TypeInfo = - CGF.getContext().getTypeInfo(E->getType()); - unsigned long size = TypeInfo.first/8; + CharUnits size = CGF.getContext().getTypeSizeInChars(E->getType()); const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); - llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size); + llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size.getQuantity()); CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, Dest.getAddr(), Src.getAggregateAddr(), @@ -249,11 +248,6 @@ void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) { } void AggExprEmitter::VisitCastExpr(CastExpr *E) { - if (Dest.isIgnored() && E->getCastKind() != CK_Dynamic) { - Visit(E->getSubExpr()); - return; - } - switch (E->getCastKind()) { case CK_Dynamic: { assert(isa(E) && "CK_Dynamic without a dynamic_cast?"); @@ -270,6 +264,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { } case CK_ToUnion: { + if (Dest.isIgnored()) break; + // GCC union extension QualType Ty = E->getSubExpr()->getType(); QualType PtrTy = CGF.getContext().getPointerType(Ty); @@ -309,7 +305,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_LValueBitCast: llvm_unreachable("should not be emitting lvalue bitcast as rvalue"); break; - + case CK_Dependent: case CK_BitCast: case CK_ArrayToPointerDecay: @@ -397,15 +393,38 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { E->getRHS()->getType()) && "Invalid assignment"); - // FIXME: __block variables need the RHS evaluated first! + if (const DeclRefExpr *DRE = dyn_cast(E->getLHS())) + if (const VarDecl *VD = dyn_cast(DRE->getDecl())) + if (VD->hasAttr() && + E->getRHS()->HasSideEffects(CGF.getContext())) { + // When __block variable on LHS, the RHS must be evaluated first + // as it may change the 'forwarding' field via call to Block_copy. + LValue RHS = CGF.EmitLValue(E->getRHS()); + LValue LHS = CGF.EmitLValue(E->getLHS()); + bool GCollection = false; + if (CGF.getContext().getLangOptions().getGCMode()) + GCollection = TypeRequiresGCollection(E->getLHS()->getType()); + Dest = AggValueSlot::forLValue(LHS, true, GCollection); + EmitFinalDestCopy(E, RHS, true); + return; + } + LValue LHS = CGF.EmitLValue(E->getLHS()); // We have to special case property setters, otherwise we must have // a simple lvalue (no aggregates inside vectors, bitfields). if (LHS.isPropertyRef()) { - AggValueSlot Slot = EnsureSlot(E->getRHS()->getType()); - CGF.EmitAggExpr(E->getRHS(), Slot); - CGF.EmitStoreThroughPropertyRefLValue(Slot.asRValue(), LHS); + const ObjCPropertyRefExpr *RE = LHS.getPropertyRefExpr(); + QualType ArgType = RE->getSetterArgType(); + RValue Src; + if (ArgType->isReferenceType()) + Src = CGF.EmitReferenceBindingToExpr(E->getRHS(), 0); + else { + AggValueSlot Slot = EnsureSlot(E->getRHS()->getType()); + CGF.EmitAggExpr(E->getRHS(), Slot); + Src = Slot.asRValue(); + } + CGF.EmitStoreThroughPropertyRefLValue(Src, LHS); } else { bool GCollection = false; if (CGF.getContext().getLangOptions().getGCMode()) @@ -513,9 +532,8 @@ void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { /// zero to memory, return true. This can return false if uncertain, so it just /// handles simple cases. static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) { - // (0) - if (const ParenExpr *PE = dyn_cast(E)) - return isSimpleZero(PE->getSubExpr(), CGF); + E = E->IgnoreParens(); + // 0 if (const IntegerLiteral *IL = dyn_cast(E)) return IL->getValue() == 0; @@ -619,6 +637,14 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { QualType ElementType = CGF.getContext().getCanonicalType(E->getType()); ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType(); + bool hasNonTrivialCXXConstructor = false; + if (CGF.getContext().getLangOptions().CPlusPlus) + if (const RecordType *RT = CGF.getContext() + .getBaseElementType(ElementType)->getAs()) { + const CXXRecordDecl *RD = cast(RT->getDecl()); + hasNonTrivialCXXConstructor = !RD->hasTrivialConstructor(); + } + // FIXME: were we intentionally ignoring address spaces and GC attributes? for (uint64_t i = 0; i != NumArrayElements; ++i) { @@ -626,7 +652,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // then we're done. if (i == NumInitElements && Dest.isZeroed() && - CGF.getTypes().isZeroInitializable(ElementType)) + CGF.getTypes().isZeroInitializable(ElementType) && + !hasNonTrivialCXXConstructor) break; llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array"); @@ -634,6 +661,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { if (i < NumInitElements) EmitInitializationToLValue(E->getInit(i), LV, ElementType); + else if (Expr *filler = E->getArrayFiller()) + EmitInitializationToLValue(filler, LV, ElementType); else EmitNullInitializationToLValue(LV, ElementType); @@ -737,18 +766,17 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { /// GetNumNonZeroBytesInInit - Get an approximate count of the number of /// non-zero bytes that will be stored when outputting the initializer for the /// specified initializer expression. -static uint64_t GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { - if (const ParenExpr *PE = dyn_cast(E)) - return GetNumNonZeroBytesInInit(PE->getSubExpr(), CGF); +static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { + E = E->IgnoreParens(); // 0 and 0.0 won't require any non-zero stores! - if (isSimpleZero(E, CGF)) return 0; + if (isSimpleZero(E, CGF)) return CharUnits::Zero(); // If this is an initlist expr, sum up the size of sizes of the (present) // elements. If this is something weird, assume the whole thing is non-zero. const InitListExpr *ILE = dyn_cast(E); if (ILE == 0 || !CGF.getTypes().isZeroInitializable(ILE->getType())) - return CGF.getContext().getTypeSize(E->getType())/8; + return CGF.getContext().getTypeSizeInChars(E->getType()); // InitListExprs for structs have to be handled carefully. If there are // reference members, we need to consider the size of the reference, not the @@ -756,7 +784,7 @@ static uint64_t GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { if (const RecordType *RT = E->getType()->getAs()) { if (!RT->isUnionType()) { RecordDecl *SD = E->getType()->getAs()->getDecl(); - uint64_t NumNonZeroBytes = 0; + CharUnits NumNonZeroBytes = CharUnits::Zero(); unsigned ILEElement = 0; for (RecordDecl::field_iterator Field = SD->field_begin(), @@ -773,7 +801,8 @@ static uint64_t GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { // Reference values are always non-null and have the width of a pointer. if (Field->getType()->isReferenceType()) - NumNonZeroBytes += CGF.getContext().Target.getPointerWidth(0); + NumNonZeroBytes += CGF.getContext().toCharUnitsFromBits( + CGF.getContext().Target.getPointerWidth(0)); else NumNonZeroBytes += GetNumNonZeroBytesInInit(E, CGF); } @@ -783,7 +812,7 @@ static uint64_t GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { } - uint64_t NumNonZeroBytes = 0; + CharUnits NumNonZeroBytes = CharUnits::Zero(); for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) NumNonZeroBytes += GetNumNonZeroBytesInInit(ILE->getInit(i), CGF); return NumNonZeroBytes; @@ -797,28 +826,38 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E, // If the slot is already known to be zeroed, nothing to do. Don't mess with // volatile stores. if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == 0) return; - + + // C++ objects with a user-declared constructor don't need zero'ing. + if (CGF.getContext().getLangOptions().CPlusPlus) + if (const RecordType *RT = CGF.getContext() + .getBaseElementType(E->getType())->getAs()) { + const CXXRecordDecl *RD = cast(RT->getDecl()); + if (RD->hasUserDeclaredConstructor()) + return; + } + // If the type is 16-bytes or smaller, prefer individual stores over memset. - std::pair TypeInfo = - CGF.getContext().getTypeInfo(E->getType()); - if (TypeInfo.first/8 <= 16) + std::pair TypeInfo = + CGF.getContext().getTypeInfoInChars(E->getType()); + if (TypeInfo.first <= CharUnits::fromQuantity(16)) return; // Check to see if over 3/4 of the initializer are known to be zero. If so, // we prefer to emit memset + individual stores for the rest. - uint64_t NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF); - if (NumNonZeroBytes*4 > TypeInfo.first/8) + CharUnits NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF); + if (NumNonZeroBytes*4 > TypeInfo.first) return; // Okay, it seems like a good idea to use an initial memset, emit the call. - llvm::Constant *SizeVal = CGF.Builder.getInt64(TypeInfo.first/8); - unsigned Align = TypeInfo.second/8; + llvm::Constant *SizeVal = CGF.Builder.getInt64(TypeInfo.first.getQuantity()); + CharUnits Align = TypeInfo.second; llvm::Value *Loc = Slot.getAddr(); const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); Loc = CGF.Builder.CreateBitCast(Loc, BP); - CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, Align, false); + CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, + Align.getQuantity(), false); // Tell the AggExprEmitter that the slot is known zero. Slot.setZeroed(); @@ -887,7 +926,8 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, // safely handle this, we can add a target hook. // Get size and alignment info for this aggregate. - std::pair TypeInfo = getContext().getTypeInfo(Ty); + std::pair TypeInfo = + getContext().getTypeInfoInChars(Ty); // FIXME: Handle variable sized types. @@ -917,9 +957,9 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, if (const RecordType *RecordTy = Ty->getAs()) { RecordDecl *Record = RecordTy->getDecl(); if (Record->hasObjectMember()) { - unsigned long size = TypeInfo.first/8; + CharUnits size = TypeInfo.first; const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); - llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size); + llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size.getQuantity()); CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, SizeVal); return; @@ -928,9 +968,10 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, QualType BaseType = getContext().getBaseElementType(Ty); if (const RecordType *RecordTy = BaseType->getAs()) { if (RecordTy->getDecl()->hasObjectMember()) { - unsigned long size = TypeInfo.first/8; + CharUnits size = TypeInfo.first; const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); - llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size); + llvm::Value *SizeVal = + llvm::ConstantInt::get(SizeTy, size.getQuantity()); CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, SizeVal); return; @@ -939,6 +980,7 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, } Builder.CreateMemCpy(DestPtr, SrcPtr, - llvm::ConstantInt::get(IntPtrTy, TypeInfo.first/8), - TypeInfo.second/8, isVolatile); + llvm::ConstantInt::get(IntPtrTy, + TypeInfo.first.getQuantity()), + TypeInfo.second.getQuantity(), isVolatile); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp index bba7864bff98..bdaa873f1832 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp @@ -17,6 +17,8 @@ #include "CGObjCRuntime.h" #include "CGDebugInfo.h" #include "llvm/Intrinsics.h" +#include "llvm/Support/CallSite.h" + using namespace clang; using namespace CodeGen; @@ -35,13 +37,12 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, CallArgList Args; // Push the this ptr. - Args.push_back(std::make_pair(RValue::get(This), - MD->getThisType(getContext()))); + Args.add(RValue::get(This), MD->getThisType(getContext())); // If there is a VTT parameter, emit it. if (VTT) { QualType T = getContext().getPointerType(getContext().VoidPtrTy); - Args.push_back(std::make_pair(RValue::get(VTT), T)); + Args.add(RValue::get(VTT), T); } // And the rest of the call args @@ -77,6 +78,31 @@ static const CXXRecordDecl *getMostDerivedClassDecl(const Expr *Base) { return cast(DerivedType->castAs()->getDecl()); } +// FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do +// quite what we want. +static const Expr *skipNoOpCastsAndParens(const Expr *E) { + while (true) { + if (const ParenExpr *PE = dyn_cast(E)) { + E = PE->getSubExpr(); + continue; + } + + if (const CastExpr *CE = dyn_cast(E)) { + if (CE->getCastKind() == CK_NoOp) { + E = CE->getSubExpr(); + continue; + } + } + if (const UnaryOperator *UO = dyn_cast(E)) { + if (UO->getOpcode() == UO_Extension) { + E = UO->getSubExpr(); + continue; + } + } + return E; + } +} + /// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given /// expr can be devirtualized. static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context, @@ -112,6 +138,7 @@ static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context, if (MD->getParent()->hasAttr()) return true; + Base = skipNoOpCastsAndParens(Base); if (const DeclRefExpr *DRE = dyn_cast(Base)) { if (const VarDecl *VD = dyn_cast(DRE->getDecl())) { // This is a record decl. We know the type and can devirtualize it. @@ -141,10 +168,12 @@ static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context, // extensions allowing explicit constructor function call. RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, ReturnValueSlot ReturnValue) { - if (isa(CE->getCallee()->IgnoreParens())) + const Expr *callee = CE->getCallee()->IgnoreParens(); + + if (isa(callee)) return EmitCXXMemberPointerCallExpr(CE, ReturnValue); - - const MemberExpr *ME = cast(CE->getCallee()->IgnoreParens()); + + const MemberExpr *ME = cast(callee); const CXXMethodDecl *MD = cast(ME->getMemberDecl()); CGDebugInfo *DI = getDebugInfo(); @@ -259,10 +288,10 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, const Expr *MemFnExpr = BO->getRHS(); const MemberPointerType *MPT = - MemFnExpr->getType()->getAs(); + MemFnExpr->getType()->castAs(); const FunctionProtoType *FPT = - MPT->getPointeeType()->getAs(); + MPT->getPointeeType()->castAs(); const CXXRecordDecl *RD = cast(MPT->getClass()->getAs()->getDecl()); @@ -287,12 +316,11 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, getContext().getPointerType(getContext().getTagDeclType(RD)); // Push the this ptr. - Args.push_back(std::make_pair(RValue::get(This), ThisType)); + Args.add(RValue::get(This), ThisType); // And the rest of the call args EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end()); - const FunctionType *BO_FPT = BO->getType()->getAs(); - return EmitCall(CGM.getTypes().getFunctionInfo(Args, BO_FPT), Callee, + return EmitCall(CGM.getTypes().getFunctionInfo(Args, FPT), Callee, ReturnValue, Args); } @@ -341,8 +369,9 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E, // If we require zero initialization before (or instead of) calling the // constructor, as can be the case with a non-user-provided default - // constructor, emit the zero initialization now. - if (E->requiresZeroInitialization()) + // constructor, emit the zero initialization now, unless destination is + // already zeroed. + if (E->requiresZeroInitialization() && !Dest.isZeroed()) EmitNullInitialization(Dest.getAddr(), E->getType()); // If this is a call to a trivial default constructor, do nothing. @@ -374,9 +403,16 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E, E->arg_begin(), E->arg_end()); } else { - CXXCtorType Type = - (E->getConstructionKind() == CXXConstructExpr::CK_Complete) - ? Ctor_Complete : Ctor_Base; + CXXCtorType Type; + CXXConstructExpr::ConstructionKind K = E->getConstructionKind(); + if (K == CXXConstructExpr::CK_Delegating) { + // We should be emitting a constructor; GlobalDecl will assert this + Type = CurGD.getCtorType(); + } else { + Type = (E->getConstructionKind() == CXXConstructExpr::CK_Complete) + ? Ctor_Complete : Ctor_Base; + } + bool ForVirtualBase = E->getConstructionKind() == CXXConstructExpr::CK_VirtualBase; @@ -595,7 +631,7 @@ static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context, Size = CGF.Builder.CreateExtractValue(AddRes, 0); llvm::Value *AddDidOverflow = CGF.Builder.CreateExtractValue(AddRes, 1); - DidOverflow = CGF.Builder.CreateAnd(DidOverflow, AddDidOverflow); + DidOverflow = CGF.Builder.CreateOr(DidOverflow, AddDidOverflow); } Size = CGF.Builder.CreateSelect(DidOverflow, @@ -800,15 +836,15 @@ namespace { // The first argument is always a void*. FunctionProtoType::arg_type_iterator AI = FPT->arg_type_begin(); - DeleteArgs.push_back(std::make_pair(RValue::get(Ptr), *AI++)); + DeleteArgs.add(RValue::get(Ptr), *AI++); // A member 'operator delete' can take an extra 'size_t' argument. if (FPT->getNumArgs() == NumPlacementArgs + 2) - DeleteArgs.push_back(std::make_pair(RValue::get(AllocSize), *AI++)); + DeleteArgs.add(RValue::get(AllocSize), *AI++); // Pass the rest of the arguments, which must match exactly. for (unsigned I = 0; I != NumPlacementArgs; ++I) - DeleteArgs.push_back(std::make_pair(getPlacementArgs()[I], *AI++)); + DeleteArgs.add(getPlacementArgs()[I], *AI++); // Call 'operator delete'. CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(DeleteArgs, FPT), @@ -857,18 +893,18 @@ namespace { // The first argument is always a void*. FunctionProtoType::arg_type_iterator AI = FPT->arg_type_begin(); - DeleteArgs.push_back(std::make_pair(Ptr.restore(CGF), *AI++)); + DeleteArgs.add(Ptr.restore(CGF), *AI++); // A member 'operator delete' can take an extra 'size_t' argument. if (FPT->getNumArgs() == NumPlacementArgs + 2) { RValue RV = AllocSize.restore(CGF); - DeleteArgs.push_back(std::make_pair(RV, *AI++)); + DeleteArgs.add(RV, *AI++); } // Pass the rest of the arguments, which must match exactly. for (unsigned I = 0; I != NumPlacementArgs; ++I) { RValue RV = getPlacementArgs()[I].restore(CGF); - DeleteArgs.push_back(std::make_pair(RV, *AI++)); + DeleteArgs.add(RV, *AI++); } // Call 'operator delete'. @@ -895,7 +931,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, E->getOperatorDelete(), NewPtr, AllocSize); for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) - Cleanup->setPlacementArg(I, NewArgs[I+1].first); + Cleanup->setPlacementArg(I, NewArgs[I+1].RV); return; } @@ -914,148 +950,154 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, SavedAllocSize); for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) Cleanup->setPlacementArg(I, - DominatingValue::save(CGF, NewArgs[I+1].first)); + DominatingValue::save(CGF, NewArgs[I+1].RV)); CGF.ActivateCleanupBlock(CGF.EHStack.stable_begin()); } llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { - QualType AllocType = E->getAllocatedType(); - if (AllocType->isArrayType()) - while (const ArrayType *AType = getContext().getAsArrayType(AllocType)) - AllocType = AType->getElementType(); + // The element type being allocated. + QualType allocType = getContext().getBaseElementType(E->getAllocatedType()); - FunctionDecl *NewFD = E->getOperatorNew(); - const FunctionProtoType *NewFTy = NewFD->getType()->getAs(); + // 1. Build a call to the allocation function. + FunctionDecl *allocator = E->getOperatorNew(); + const FunctionProtoType *allocatorType = + allocator->getType()->castAs(); - CallArgList NewArgs; + CallArgList allocatorArgs; // The allocation size is the first argument. - QualType SizeTy = getContext().getSizeType(); + QualType sizeType = getContext().getSizeType(); - llvm::Value *NumElements = 0; - llvm::Value *AllocSizeWithoutCookie = 0; - llvm::Value *AllocSize = EmitCXXNewAllocSize(getContext(), - *this, E, NumElements, - AllocSizeWithoutCookie); + llvm::Value *numElements = 0; + llvm::Value *allocSizeWithoutCookie = 0; + llvm::Value *allocSize = + EmitCXXNewAllocSize(getContext(), *this, E, numElements, + allocSizeWithoutCookie); - NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); + allocatorArgs.add(RValue::get(allocSize), sizeType); // Emit the rest of the arguments. // FIXME: Ideally, this should just use EmitCallArgs. - CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin(); + CXXNewExpr::const_arg_iterator placementArg = E->placement_arg_begin(); // First, use the types from the function type. // We start at 1 here because the first argument (the allocation size) // has already been emitted. - for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) { - QualType ArgType = NewFTy->getArgType(i); + for (unsigned i = 1, e = allocatorType->getNumArgs(); i != e; + ++i, ++placementArg) { + QualType argType = allocatorType->getArgType(i); - assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). - getTypePtr() == - getContext().getCanonicalType(NewArg->getType()).getTypePtr() && + assert(getContext().hasSameUnqualifiedType(argType.getNonReferenceType(), + placementArg->getType()) && "type mismatch in call argument!"); - NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), - ArgType)); - + EmitCallArg(allocatorArgs, *placementArg, argType); } // Either we've emitted all the call args, or we have a call to a // variadic function. - assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) && - "Extra arguments in non-variadic function!"); + assert((placementArg == E->placement_arg_end() || + allocatorType->isVariadic()) && + "Extra arguments to non-variadic function!"); // If we still have any arguments, emit them using the type of the argument. - for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end(); - NewArg != NewArgEnd; ++NewArg) { - QualType ArgType = NewArg->getType(); - NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), - ArgType)); + for (CXXNewExpr::const_arg_iterator placementArgsEnd = E->placement_arg_end(); + placementArg != placementArgsEnd; ++placementArg) { + EmitCallArg(allocatorArgs, *placementArg, placementArg->getType()); } - // Emit the call to new. + // Emit the allocation call. RValue RV = - EmitCall(CGM.getTypes().getFunctionInfo(NewArgs, NewFTy), - CGM.GetAddrOfFunction(NewFD), ReturnValueSlot(), NewArgs, NewFD); + EmitCall(CGM.getTypes().getFunctionInfo(allocatorArgs, allocatorType), + CGM.GetAddrOfFunction(allocator), ReturnValueSlot(), + allocatorArgs, allocator); - // If an allocation function is declared with an empty exception specification - // it returns null to indicate failure to allocate storage. [expr.new]p13. - // (We don't need to check for null when there's no new initializer and - // we're allocating a POD type). - bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() && - !(AllocType->isPODType() && !E->hasInitializer()); + // Emit a null check on the allocation result if the allocation + // function is allowed to return null (because it has a non-throwing + // exception spec; for this part, we inline + // CXXNewExpr::shouldNullCheckAllocation()) and we have an + // interesting initializer. + bool nullCheck = allocatorType->isNothrow(getContext()) && + !(allocType->isPODType() && !E->hasInitializer()); - llvm::BasicBlock *NullCheckSource = 0; - llvm::BasicBlock *NewNotNull = 0; - llvm::BasicBlock *NewEnd = 0; + llvm::BasicBlock *nullCheckBB = 0; + llvm::BasicBlock *contBB = 0; - llvm::Value *NewPtr = RV.getScalarVal(); - unsigned AS = cast(NewPtr->getType())->getAddressSpace(); + llvm::Value *allocation = RV.getScalarVal(); + unsigned AS = + cast(allocation->getType())->getAddressSpace(); - if (NullCheckResult) { - NullCheckSource = Builder.GetInsertBlock(); - NewNotNull = createBasicBlock("new.notnull"); - NewEnd = createBasicBlock("new.end"); + // The null-check means that the initializer is conditionally + // evaluated. + ConditionalEvaluation conditional(*this); - llvm::Value *IsNull = Builder.CreateIsNull(NewPtr, "new.isnull"); - Builder.CreateCondBr(IsNull, NewEnd, NewNotNull); - EmitBlock(NewNotNull); + if (nullCheck) { + conditional.begin(*this); + + nullCheckBB = Builder.GetInsertBlock(); + llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull"); + contBB = createBasicBlock("new.cont"); + + llvm::Value *isNull = Builder.CreateIsNull(allocation, "new.isnull"); + Builder.CreateCondBr(isNull, contBB, notNullBB); + EmitBlock(notNullBB); } - assert((AllocSize == AllocSizeWithoutCookie) == + assert((allocSize == allocSizeWithoutCookie) == CalculateCookiePadding(*this, E).isZero()); - if (AllocSize != AllocSizeWithoutCookie) { + if (allocSize != allocSizeWithoutCookie) { assert(E->isArray()); - NewPtr = CGM.getCXXABI().InitializeArrayCookie(*this, NewPtr, NumElements, - E, AllocType); + allocation = CGM.getCXXABI().InitializeArrayCookie(*this, allocation, + numElements, + E, allocType); } // If there's an operator delete, enter a cleanup to call it if an // exception is thrown. - EHScopeStack::stable_iterator CallOperatorDelete; + EHScopeStack::stable_iterator operatorDeleteCleanup; if (E->getOperatorDelete()) { - EnterNewDeleteCleanup(*this, E, NewPtr, AllocSize, NewArgs); - CallOperatorDelete = EHStack.stable_begin(); + EnterNewDeleteCleanup(*this, E, allocation, allocSize, allocatorArgs); + operatorDeleteCleanup = EHStack.stable_begin(); } - const llvm::Type *ElementPtrTy - = ConvertTypeForMem(AllocType)->getPointerTo(AS); - NewPtr = Builder.CreateBitCast(NewPtr, ElementPtrTy); + const llvm::Type *elementPtrTy + = ConvertTypeForMem(allocType)->getPointerTo(AS); + llvm::Value *result = Builder.CreateBitCast(allocation, elementPtrTy); if (E->isArray()) { - EmitNewInitializer(*this, E, NewPtr, NumElements, AllocSizeWithoutCookie); + EmitNewInitializer(*this, E, result, numElements, allocSizeWithoutCookie); // NewPtr is a pointer to the base element type. If we're // allocating an array of arrays, we'll need to cast back to the // array pointer type. - const llvm::Type *ResultTy = ConvertTypeForMem(E->getType()); - if (NewPtr->getType() != ResultTy) - NewPtr = Builder.CreateBitCast(NewPtr, ResultTy); + const llvm::Type *resultType = ConvertTypeForMem(E->getType()); + if (result->getType() != resultType) + result = Builder.CreateBitCast(result, resultType); } else { - EmitNewInitializer(*this, E, NewPtr, NumElements, AllocSizeWithoutCookie); + EmitNewInitializer(*this, E, result, numElements, allocSizeWithoutCookie); } // Deactivate the 'operator delete' cleanup if we finished // initialization. - if (CallOperatorDelete.isValid()) - DeactivateCleanupBlock(CallOperatorDelete); + if (operatorDeleteCleanup.isValid()) + DeactivateCleanupBlock(operatorDeleteCleanup); - if (NullCheckResult) { - Builder.CreateBr(NewEnd); - llvm::BasicBlock *NotNullSource = Builder.GetInsertBlock(); - EmitBlock(NewEnd); + if (nullCheck) { + conditional.end(*this); - llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType()); - PHI->reserveOperandSpace(2); - PHI->addIncoming(NewPtr, NotNullSource); - PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), - NullCheckSource); + llvm::BasicBlock *notNullBB = Builder.GetInsertBlock(); + EmitBlock(contBB); - NewPtr = PHI; + llvm::PHINode *PHI = Builder.CreatePHI(result->getType(), 2); + PHI->addIncoming(result, notNullBB); + PHI->addIncoming(llvm::Constant::getNullValue(result->getType()), + nullCheckBB); + + result = PHI; } - return NewPtr; + return result; } void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, @@ -1080,10 +1122,10 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, QualType ArgTy = DeleteFTy->getArgType(0); llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); - DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy)); + DeleteArgs.add(RValue::get(DeletePtr), ArgTy); if (Size) - DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy)); + DeleteArgs.add(RValue::get(Size), SizeTy); // Emit the call to delete. EmitCall(CGM.getTypes().getFunctionInfo(DeleteArgs, DeleteFTy), @@ -1180,7 +1222,7 @@ namespace { QualType VoidPtrTy = DeleteFTy->getArgType(0); llvm::Value *DeletePtr = CGF.Builder.CreateBitCast(Ptr, CGF.ConvertType(VoidPtrTy)); - Args.push_back(std::make_pair(RValue::get(DeletePtr), VoidPtrTy)); + Args.add(RValue::get(DeletePtr), VoidPtrTy); // Pass the original requested size as the second argument. if (DeleteFTy->getNumArgs() == 2) { @@ -1203,7 +1245,7 @@ namespace { Size = CGF.Builder.CreateAdd(Size, CookieSizeV); } - Args.push_back(std::make_pair(RValue::get(Size), size_t)); + Args.add(RValue::get(Size), size_t); } // Emit the call to delete. @@ -1264,9 +1306,7 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); - llvm::Value *IsNull = - Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()), - "isnull"); + llvm::Value *IsNull = Builder.CreateIsNull(Ptr, "isnull"); Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); EmitBlock(DeleteNotNull); @@ -1306,173 +1346,253 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { EmitBlock(DeleteEnd); } +static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) { + // void __cxa_bad_typeid(); + + const llvm::Type *VoidTy = llvm::Type::getVoidTy(CGF.getLLVMContext()); + const llvm::FunctionType *FTy = + llvm::FunctionType::get(VoidTy, false); + + return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); +} + +static void EmitBadTypeidCall(CodeGenFunction &CGF) { + llvm::Value *Fn = getBadTypeidFn(CGF); + CGF.EmitCallOrInvoke(Fn, 0, 0).setDoesNotReturn(); + CGF.Builder.CreateUnreachable(); +} + +static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, + const Expr *E, + const llvm::Type *StdTypeInfoPtrTy) { + // Get the vtable pointer. + llvm::Value *ThisPtr = CGF.EmitLValue(E).getAddress(); + + // C++ [expr.typeid]p2: + // If the glvalue expression is obtained by applying the unary * operator to + // a pointer and the pointer is a null pointer value, the typeid expression + // throws the std::bad_typeid exception. + if (const UnaryOperator *UO = dyn_cast(E->IgnoreParens())) { + if (UO->getOpcode() == UO_Deref) { + llvm::BasicBlock *BadTypeidBlock = + CGF.createBasicBlock("typeid.bad_typeid"); + llvm::BasicBlock *EndBlock = + CGF.createBasicBlock("typeid.end"); + + llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr); + CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock); + + CGF.EmitBlock(BadTypeidBlock); + EmitBadTypeidCall(CGF); + CGF.EmitBlock(EndBlock); + } + } + + llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, + StdTypeInfoPtrTy->getPointerTo()); + + // Load the type info. + Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL); + return CGF.Builder.CreateLoad(Value); +} + llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { - QualType Ty = E->getType(); - const llvm::Type *LTy = ConvertType(Ty)->getPointerTo(); + const llvm::Type *StdTypeInfoPtrTy = + ConvertType(E->getType())->getPointerTo(); if (E->isTypeOperand()) { llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand()); - return Builder.CreateBitCast(TypeInfo, LTy); + return Builder.CreateBitCast(TypeInfo, StdTypeInfoPtrTy); } - - Expr *subE = E->getExprOperand(); - Ty = subE->getType(); - CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); - Ty = CanTy.getUnqualifiedType().getNonReferenceType(); - if (const RecordType *RT = Ty->getAs()) { - const CXXRecordDecl *RD = cast(RT->getDecl()); - if (RD->isPolymorphic()) { - // FIXME: if subE is an lvalue do - LValue Obj = EmitLValue(subE); - llvm::Value *This = Obj.getAddress(); - // We need to do a zero check for *p, unless it has NonNullAttr. - // FIXME: PointerType->hasAttr() - bool CanBeZero = false; - if (UnaryOperator *UO = dyn_cast(subE->IgnoreParens())) - if (UO->getOpcode() == UO_Deref) - CanBeZero = true; - if (CanBeZero) { - llvm::BasicBlock *NonZeroBlock = createBasicBlock(); - llvm::BasicBlock *ZeroBlock = createBasicBlock(); - - llvm::Value *Zero = llvm::Constant::getNullValue(This->getType()); - Builder.CreateCondBr(Builder.CreateICmpNE(This, Zero), - NonZeroBlock, ZeroBlock); - EmitBlock(ZeroBlock); - /// Call __cxa_bad_typeid - const llvm::Type *ResultType = llvm::Type::getVoidTy(getLLVMContext()); - const llvm::FunctionType *FTy; - FTy = llvm::FunctionType::get(ResultType, false); - llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); - Builder.CreateCall(F)->setDoesNotReturn(); - Builder.CreateUnreachable(); - EmitBlock(NonZeroBlock); - } - llvm::Value *V = GetVTablePtr(This, LTy->getPointerTo()); - V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL); - V = Builder.CreateLoad(V); - return V; + + // C++ [expr.typeid]p2: + // When typeid is applied to a glvalue expression whose type is a + // polymorphic class type, the result refers to a std::type_info object + // representing the type of the most derived object (that is, the dynamic + // type) to which the glvalue refers. + if (E->getExprOperand()->isGLValue()) { + if (const RecordType *RT = + E->getExprOperand()->getType()->getAs()) { + const CXXRecordDecl *RD = cast(RT->getDecl()); + if (RD->isPolymorphic()) + return EmitTypeidFromVTable(*this, E->getExprOperand(), + StdTypeInfoPtrTy); } } - return Builder.CreateBitCast(CGM.GetAddrOfRTTIDescriptor(Ty), LTy); + + QualType OperandTy = E->getExprOperand()->getType(); + return Builder.CreateBitCast(CGM.GetAddrOfRTTIDescriptor(OperandTy), + StdTypeInfoPtrTy); } -llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, +static llvm::Constant *getDynamicCastFn(CodeGenFunction &CGF) { + // void *__dynamic_cast(const void *sub, + // const abi::__class_type_info *src, + // const abi::__class_type_info *dst, + // std::ptrdiff_t src2dst_offset); + + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); + const llvm::Type *PtrDiffTy = + CGF.ConvertType(CGF.getContext().getPointerDiffType()); + + const llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy }; + + const llvm::FunctionType *FTy = + llvm::FunctionType::get(Int8PtrTy, Args, false); + + return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"); +} + +static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) { + // void __cxa_bad_cast(); + + const llvm::Type *VoidTy = llvm::Type::getVoidTy(CGF.getLLVMContext()); + const llvm::FunctionType *FTy = + llvm::FunctionType::get(VoidTy, false); + + return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast"); +} + +static void EmitBadCastCall(CodeGenFunction &CGF) { + llvm::Value *Fn = getBadCastFn(CGF); + CGF.EmitCallOrInvoke(Fn, 0, 0).setDoesNotReturn(); + CGF.Builder.CreateUnreachable(); +} + +static llvm::Value * +EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value, + QualType SrcTy, QualType DestTy, + llvm::BasicBlock *CastEnd) { + const llvm::Type *PtrDiffLTy = + CGF.ConvertType(CGF.getContext().getPointerDiffType()); + const llvm::Type *DestLTy = CGF.ConvertType(DestTy); + + if (const PointerType *PTy = DestTy->getAs()) { + if (PTy->getPointeeType()->isVoidType()) { + // C++ [expr.dynamic.cast]p7: + // If T is "pointer to cv void," then the result is a pointer to the + // most derived object pointed to by v. + + // Get the vtable pointer. + llvm::Value *VTable = CGF.GetVTablePtr(Value, PtrDiffLTy->getPointerTo()); + + // Get the offset-to-top from the vtable. + llvm::Value *OffsetToTop = + CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL); + OffsetToTop = CGF.Builder.CreateLoad(OffsetToTop, "offset.to.top"); + + // Finally, add the offset to the pointer. + Value = CGF.EmitCastToVoidPtr(Value); + Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop); + + return CGF.Builder.CreateBitCast(Value, DestLTy); + } + } + + QualType SrcRecordTy; + QualType DestRecordTy; + + if (const PointerType *DestPTy = DestTy->getAs()) { + SrcRecordTy = SrcTy->castAs()->getPointeeType(); + DestRecordTy = DestPTy->getPointeeType(); + } else { + SrcRecordTy = SrcTy; + DestRecordTy = DestTy->castAs()->getPointeeType(); + } + + assert(SrcRecordTy->isRecordType() && "source type must be a record type!"); + assert(DestRecordTy->isRecordType() && "dest type must be a record type!"); + + llvm::Value *SrcRTTI = + CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType()); + llvm::Value *DestRTTI = + CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType()); + + // FIXME: Actually compute a hint here. + llvm::Value *OffsetHint = llvm::ConstantInt::get(PtrDiffLTy, -1ULL); + + // Emit the call to __dynamic_cast. + Value = CGF.EmitCastToVoidPtr(Value); + Value = CGF.Builder.CreateCall4(getDynamicCastFn(CGF), Value, + SrcRTTI, DestRTTI, OffsetHint); + Value = CGF.Builder.CreateBitCast(Value, DestLTy); + + /// C++ [expr.dynamic.cast]p9: + /// A failed cast to reference type throws std::bad_cast + if (DestTy->isReferenceType()) { + llvm::BasicBlock *BadCastBlock = + CGF.createBasicBlock("dynamic_cast.bad_cast"); + + llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value); + CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd); + + CGF.EmitBlock(BadCastBlock); + EmitBadCastCall(CGF); + } + + return Value; +} + +static llvm::Value *EmitDynamicCastToNull(CodeGenFunction &CGF, + QualType DestTy) { + const llvm::Type *DestLTy = CGF.ConvertType(DestTy); + if (DestTy->isPointerType()) + return llvm::Constant::getNullValue(DestLTy); + + /// C++ [expr.dynamic.cast]p9: + /// A failed cast to reference type throws std::bad_cast + EmitBadCastCall(CGF); + + CGF.EmitBlock(CGF.createBasicBlock("dynamic_cast.end")); + return llvm::UndefValue::get(DestLTy); +} + +llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value, const CXXDynamicCastExpr *DCE) { - QualType SrcTy = DCE->getSubExpr()->getType(); QualType DestTy = DCE->getTypeAsWritten(); - QualType InnerType = DestTy->getPointeeType(); + + if (DCE->isAlwaysNull()) + return EmitDynamicCastToNull(*this, DestTy); + + QualType SrcTy = DCE->getSubExpr()->getType(); + + // C++ [expr.dynamic.cast]p4: + // If the value of v is a null pointer value in the pointer case, the result + // is the null pointer value of type T. + bool ShouldNullCheckSrcValue = SrcTy->isPointerType(); - const llvm::Type *LTy = ConvertType(DCE->getType()); - - bool CanBeZero = false; - bool ToVoid = false; - bool ThrowOnBad = false; - if (DestTy->isPointerType()) { - // FIXME: if PointerType->hasAttr(), we don't set this - CanBeZero = true; - if (InnerType->isVoidType()) - ToVoid = true; - } else { - LTy = LTy->getPointerTo(); - - // FIXME: What if exceptions are disabled? - ThrowOnBad = true; - } - - if (SrcTy->isPointerType() || SrcTy->isReferenceType()) - SrcTy = SrcTy->getPointeeType(); - SrcTy = SrcTy.getUnqualifiedType(); - - if (DestTy->isPointerType() || DestTy->isReferenceType()) - DestTy = DestTy->getPointeeType(); - DestTy = DestTy.getUnqualifiedType(); - - llvm::BasicBlock *ContBlock = createBasicBlock(); - llvm::BasicBlock *NullBlock = 0; - llvm::BasicBlock *NonZeroBlock = 0; - if (CanBeZero) { - NonZeroBlock = createBasicBlock(); - NullBlock = createBasicBlock(); - Builder.CreateCondBr(Builder.CreateIsNotNull(V), NonZeroBlock, NullBlock); - EmitBlock(NonZeroBlock); - } - - llvm::BasicBlock *BadCastBlock = 0; - - const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); - - // See if this is a dynamic_cast(void*) - if (ToVoid) { - llvm::Value *This = V; - V = GetVTablePtr(This, PtrDiffTy->getPointerTo()); - V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL); - V = Builder.CreateLoad(V, "offset to top"); - This = EmitCastToVoidPtr(This); - V = Builder.CreateInBoundsGEP(This, V); - V = Builder.CreateBitCast(V, LTy); - } else { - /// Call __dynamic_cast - const llvm::Type *ResultType = Int8PtrTy; - const llvm::FunctionType *FTy; - std::vector ArgTys; - ArgTys.push_back(Int8PtrTy); - ArgTys.push_back(Int8PtrTy); - ArgTys.push_back(Int8PtrTy); - ArgTys.push_back(PtrDiffTy); - FTy = llvm::FunctionType::get(ResultType, ArgTys, false); - - // FIXME: Calculate better hint. - llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL); - - assert(SrcTy->isRecordType() && "Src type must be record type!"); - assert(DestTy->isRecordType() && "Dest type must be record type!"); - - llvm::Value *SrcArg - = CGM.GetAddrOfRTTIDescriptor(SrcTy.getUnqualifiedType()); - llvm::Value *DestArg - = CGM.GetAddrOfRTTIDescriptor(DestTy.getUnqualifiedType()); - - V = Builder.CreateBitCast(V, Int8PtrTy); - V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"), - V, SrcArg, DestArg, hint); - V = Builder.CreateBitCast(V, LTy); - - if (ThrowOnBad) { - BadCastBlock = createBasicBlock(); - Builder.CreateCondBr(Builder.CreateIsNotNull(V), ContBlock, BadCastBlock); - EmitBlock(BadCastBlock); - /// Invoke __cxa_bad_cast - ResultType = llvm::Type::getVoidTy(getLLVMContext()); - const llvm::FunctionType *FBadTy; - FBadTy = llvm::FunctionType::get(ResultType, false); - llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast"); - if (llvm::BasicBlock *InvokeDest = getInvokeDest()) { - llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); - Builder.CreateInvoke(F, Cont, InvokeDest)->setDoesNotReturn(); - EmitBlock(Cont); - } else { - // FIXME: Does this ever make sense? - Builder.CreateCall(F)->setDoesNotReturn(); - } - Builder.CreateUnreachable(); - } - } + llvm::BasicBlock *CastNull = 0; + llvm::BasicBlock *CastNotNull = 0; + llvm::BasicBlock *CastEnd = createBasicBlock("dynamic_cast.end"); - if (CanBeZero) { - Builder.CreateBr(ContBlock); - EmitBlock(NullBlock); - Builder.CreateBr(ContBlock); - } - EmitBlock(ContBlock); - if (CanBeZero) { - llvm::PHINode *PHI = Builder.CreatePHI(LTy); - PHI->reserveOperandSpace(2); - PHI->addIncoming(V, NonZeroBlock); - PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock); - V = PHI; + if (ShouldNullCheckSrcValue) { + CastNull = createBasicBlock("dynamic_cast.null"); + CastNotNull = createBasicBlock("dynamic_cast.notnull"); + + llvm::Value *IsNull = Builder.CreateIsNull(Value); + Builder.CreateCondBr(IsNull, CastNull, CastNotNull); + EmitBlock(CastNotNull); } - return V; + Value = EmitDynamicCastCall(*this, Value, SrcTy, DestTy, CastEnd); + + if (ShouldNullCheckSrcValue) { + EmitBranch(CastEnd); + + EmitBlock(CastNull); + EmitBranch(CastEnd); + } + + EmitBlock(CastEnd); + + if (ShouldNullCheckSrcValue) { + llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); + PHI->addIncoming(Value, CastNotNull); + PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); + + Value = PHI; + } + + return Value; } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp index 7b0292b8f225..bd1958602484 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp @@ -108,6 +108,9 @@ class ComplexExprEmitter } ComplexPairTy VisitExpr(Expr *S); ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());} + ComplexPairTy VisitGenericSelectionExpr(GenericSelectionExpr *GE) { + return Visit(GE->getResultExpr()); + } ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL); // l-values. @@ -668,14 +671,12 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { eval.end(CGF); // Create a PHI node for the real part. - llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), "cond.r"); - RealPN->reserveOperandSpace(2); + llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.r"); RealPN->addIncoming(LHS.first, LHSBlock); RealPN->addIncoming(RHS.first, RHSBlock); // Create a PHI node for the imaginary part. - llvm::PHINode *ImagPN = Builder.CreatePHI(LHS.first->getType(), "cond.i"); - ImagPN->reserveOperandSpace(2); + llvm::PHINode *ImagPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.i"); ImagPN->addIncoming(LHS.second, LHSBlock); ImagPN->addIncoming(RHS.second, RHSBlock); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp index 40d7b6c32e4b..463b913d9285 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp @@ -38,8 +38,8 @@ class ConstStructBuilder { CodeGenFunction *CGF; bool Packed; - unsigned NextFieldOffsetInBytes; - unsigned LLVMStructAlignment; + CharUnits NextFieldOffsetInChars; + CharUnits LLVMStructAlignment; std::vector Elements; public: static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF, @@ -47,8 +47,9 @@ class ConstStructBuilder { private: ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF) - : CGM(CGM), CGF(CGF), Packed(false), NextFieldOffsetInBytes(0), - LLVMStructAlignment(1) { } + : CGM(CGM), CGF(CGF), Packed(false), + NextFieldOffsetInChars(CharUnits::Zero()), + LLVMStructAlignment(CharUnits::One()) { } bool AppendField(const FieldDecl *Field, uint64_t FieldOffset, llvm::Constant *InitExpr); @@ -56,64 +57,71 @@ class ConstStructBuilder { void AppendBitField(const FieldDecl *Field, uint64_t FieldOffset, llvm::ConstantInt *InitExpr); - void AppendPadding(uint64_t NumBytes); + void AppendPadding(CharUnits PadSize); - void AppendTailPadding(uint64_t RecordSize); + void AppendTailPadding(CharUnits RecordSize); void ConvertStructToPacked(); bool Build(InitListExpr *ILE); - unsigned getAlignment(const llvm::Constant *C) const { - if (Packed) return 1; - return CGM.getTargetData().getABITypeAlignment(C->getType()); + CharUnits getAlignment(const llvm::Constant *C) const { + if (Packed) return CharUnits::One(); + return CharUnits::fromQuantity( + CGM.getTargetData().getABITypeAlignment(C->getType())); } - uint64_t getSizeInBytes(const llvm::Constant *C) const { - return CGM.getTargetData().getTypeAllocSize(C->getType()); + CharUnits getSizeInChars(const llvm::Constant *C) const { + return CharUnits::fromQuantity( + CGM.getTargetData().getTypeAllocSize(C->getType())); } }; bool ConstStructBuilder:: AppendField(const FieldDecl *Field, uint64_t FieldOffset, llvm::Constant *InitCst) { - uint64_t FieldOffsetInBytes = FieldOffset / 8; - assert(NextFieldOffsetInBytes <= FieldOffsetInBytes + const ASTContext &Context = CGM.getContext(); + + CharUnits FieldOffsetInChars = Context.toCharUnitsFromBits(FieldOffset); + + assert(NextFieldOffsetInChars <= FieldOffsetInChars && "Field offset mismatch!"); - unsigned FieldAlignment = getAlignment(InitCst); + CharUnits FieldAlignment = getAlignment(InitCst); // Round up the field offset to the alignment of the field type. - uint64_t AlignedNextFieldOffsetInBytes = - llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment); + CharUnits AlignedNextFieldOffsetInChars = + NextFieldOffsetInChars.RoundUpToAlignment(FieldAlignment); - if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) { + if (AlignedNextFieldOffsetInChars > FieldOffsetInChars) { assert(!Packed && "Alignment is wrong even with a packed struct!"); // Convert the struct to a packed struct. ConvertStructToPacked(); - AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes; + AlignedNextFieldOffsetInChars = NextFieldOffsetInChars; } - if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) { + if (AlignedNextFieldOffsetInChars < FieldOffsetInChars) { // We need to append padding. - AppendPadding(FieldOffsetInBytes - NextFieldOffsetInBytes); + AppendPadding( + FieldOffsetInChars - NextFieldOffsetInChars); - assert(NextFieldOffsetInBytes == FieldOffsetInBytes && + assert(NextFieldOffsetInChars == FieldOffsetInChars && "Did not add enough padding!"); - AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes; + AlignedNextFieldOffsetInChars = NextFieldOffsetInChars; } // Add the field. Elements.push_back(InitCst); - NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes + - getSizeInBytes(InitCst); + NextFieldOffsetInChars = AlignedNextFieldOffsetInChars + + getSizeInChars(InitCst); if (Packed) - assert(LLVMStructAlignment == 1 && "Packed struct not byte-aligned!"); + assert(LLVMStructAlignment == CharUnits::One() && + "Packed struct not byte-aligned!"); else LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment); @@ -123,17 +131,20 @@ AppendField(const FieldDecl *Field, uint64_t FieldOffset, void ConstStructBuilder::AppendBitField(const FieldDecl *Field, uint64_t FieldOffset, llvm::ConstantInt *CI) { - if (FieldOffset > NextFieldOffsetInBytes * 8) { + const ASTContext &Context = CGM.getContext(); + const uint64_t CharWidth = Context.getCharWidth(); + uint64_t NextFieldOffsetInBits = Context.toBits(NextFieldOffsetInChars); + if (FieldOffset > NextFieldOffsetInBits) { // We need to add padding. - uint64_t NumBytes = - llvm::RoundUpToAlignment(FieldOffset - - NextFieldOffsetInBytes * 8, 8) / 8; + CharUnits PadSize = Context.toCharUnitsFromBits( + llvm::RoundUpToAlignment(FieldOffset - NextFieldOffsetInBits, + Context.Target.getCharAlign())); - AppendPadding(NumBytes); + AppendPadding(PadSize); } uint64_t FieldSize = - Field->getBitWidth()->EvaluateAsInt(CGM.getContext()).getZExtValue(); + Field->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); llvm::APInt FieldValue = CI->getValue(); @@ -148,13 +159,13 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field, if (FieldSize < FieldValue.getBitWidth()) FieldValue = FieldValue.trunc(FieldSize); - if (FieldOffset < NextFieldOffsetInBytes * 8) { + NextFieldOffsetInBits = Context.toBits(NextFieldOffsetInChars); + if (FieldOffset < NextFieldOffsetInBits) { // Either part of the field or the entire field can go into the previous // byte. assert(!Elements.empty() && "Elements can't be empty!"); - unsigned BitsInPreviousByte = - NextFieldOffsetInBytes * 8 - FieldOffset; + unsigned BitsInPreviousByte = NextFieldOffsetInBits - FieldOffset; bool FitsCompletelyInPreviousByte = BitsInPreviousByte >= FieldValue.getBitWidth(); @@ -179,12 +190,12 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field, } } - Tmp = Tmp.zext(8); + Tmp = Tmp.zext(CharWidth); if (CGM.getTargetData().isBigEndian()) { if (FitsCompletelyInPreviousByte) Tmp = Tmp.shl(BitsInPreviousByte - FieldValue.getBitWidth()); } else { - Tmp = Tmp.shl(8 - BitsInPreviousByte); + Tmp = Tmp.shl(CharWidth - BitsInPreviousByte); } // 'or' in the bits that go into the previous byte. @@ -203,19 +214,19 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field, assert(isa(LastElt->getType()) && "Expected array padding of undefs"); const llvm::ArrayType *AT = cast(LastElt->getType()); - assert(AT->getElementType()->isIntegerTy(8) && + assert(AT->getElementType()->isIntegerTy(CharWidth) && AT->getNumElements() != 0 && "Expected non-empty array padding of undefs"); // Remove the padding array. - NextFieldOffsetInBytes -= AT->getNumElements(); + NextFieldOffsetInChars -= CharUnits::fromQuantity(AT->getNumElements()); Elements.pop_back(); // Add the padding back in two chunks. - AppendPadding(AT->getNumElements()-1); - AppendPadding(1); + AppendPadding(CharUnits::fromQuantity(AT->getNumElements()-1)); + AppendPadding(CharUnits::One()); assert(isa(Elements.back()) && - Elements.back()->getType()->isIntegerTy(8) && + Elements.back()->getType()->isIntegerTy(CharWidth) && "Padding addition didn't work right"); } } @@ -226,105 +237,104 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field, return; } - while (FieldValue.getBitWidth() > 8) { + while (FieldValue.getBitWidth() > CharWidth) { llvm::APInt Tmp; if (CGM.getTargetData().isBigEndian()) { // We want the high bits. - Tmp = FieldValue.lshr(FieldValue.getBitWidth() - 8).trunc(8); + Tmp = + FieldValue.lshr(FieldValue.getBitWidth() - CharWidth).trunc(CharWidth); } else { // We want the low bits. - Tmp = FieldValue.trunc(8); + Tmp = FieldValue.trunc(CharWidth); - FieldValue = FieldValue.lshr(8); + FieldValue = FieldValue.lshr(CharWidth); } Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp)); - NextFieldOffsetInBytes++; + ++NextFieldOffsetInChars; - FieldValue = FieldValue.trunc(FieldValue.getBitWidth() - 8); + FieldValue = FieldValue.trunc(FieldValue.getBitWidth() - CharWidth); } assert(FieldValue.getBitWidth() > 0 && "Should have at least one bit left!"); - assert(FieldValue.getBitWidth() <= 8 && + assert(FieldValue.getBitWidth() <= CharWidth && "Should not have more than a byte left!"); - if (FieldValue.getBitWidth() < 8) { + if (FieldValue.getBitWidth() < CharWidth) { if (CGM.getTargetData().isBigEndian()) { unsigned BitWidth = FieldValue.getBitWidth(); - FieldValue = FieldValue.zext(8) << (8 - BitWidth); + FieldValue = FieldValue.zext(CharWidth) << (CharWidth - BitWidth); } else - FieldValue = FieldValue.zext(8); + FieldValue = FieldValue.zext(CharWidth); } // Append the last element. Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), FieldValue)); - NextFieldOffsetInBytes++; + ++NextFieldOffsetInChars; } -void ConstStructBuilder::AppendPadding(uint64_t NumBytes) { - if (!NumBytes) +void ConstStructBuilder::AppendPadding(CharUnits PadSize) { + if (PadSize.isZero()) return; const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext()); - if (NumBytes > 1) - Ty = llvm::ArrayType::get(Ty, NumBytes); + if (PadSize > CharUnits::One()) + Ty = llvm::ArrayType::get(Ty, PadSize.getQuantity()); llvm::Constant *C = llvm::UndefValue::get(Ty); Elements.push_back(C); - assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!"); + assert(getAlignment(C) == CharUnits::One() && + "Padding must have 1 byte alignment!"); - NextFieldOffsetInBytes += getSizeInBytes(C); + NextFieldOffsetInChars += getSizeInChars(C); } -void ConstStructBuilder::AppendTailPadding(uint64_t RecordSize) { - assert(RecordSize % 8 == 0 && "Invalid record size!"); +void ConstStructBuilder::AppendTailPadding(CharUnits RecordSize) { + assert(NextFieldOffsetInChars <= RecordSize && + "Size mismatch!"); - uint64_t RecordSizeInBytes = RecordSize / 8; - assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!"); - - unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes; - AppendPadding(NumPadBytes); + AppendPadding(RecordSize - NextFieldOffsetInChars); } void ConstStructBuilder::ConvertStructToPacked() { std::vector PackedElements; - uint64_t ElementOffsetInBytes = 0; + CharUnits ElementOffsetInChars = CharUnits::Zero(); for (unsigned i = 0, e = Elements.size(); i != e; ++i) { llvm::Constant *C = Elements[i]; - unsigned ElementAlign = - CGM.getTargetData().getABITypeAlignment(C->getType()); - uint64_t AlignedElementOffsetInBytes = - llvm::RoundUpToAlignment(ElementOffsetInBytes, ElementAlign); + CharUnits ElementAlign = CharUnits::fromQuantity( + CGM.getTargetData().getABITypeAlignment(C->getType())); + CharUnits AlignedElementOffsetInChars = + ElementOffsetInChars.RoundUpToAlignment(ElementAlign); - if (AlignedElementOffsetInBytes > ElementOffsetInBytes) { + if (AlignedElementOffsetInChars > ElementOffsetInChars) { // We need some padding. - uint64_t NumBytes = - AlignedElementOffsetInBytes - ElementOffsetInBytes; + CharUnits NumChars = + AlignedElementOffsetInChars - ElementOffsetInChars; const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext()); - if (NumBytes > 1) - Ty = llvm::ArrayType::get(Ty, NumBytes); + if (NumChars > CharUnits::One()) + Ty = llvm::ArrayType::get(Ty, NumChars.getQuantity()); llvm::Constant *Padding = llvm::UndefValue::get(Ty); PackedElements.push_back(Padding); - ElementOffsetInBytes += getSizeInBytes(Padding); + ElementOffsetInChars += getSizeInChars(Padding); } PackedElements.push_back(C); - ElementOffsetInBytes += getSizeInBytes(C); + ElementOffsetInChars += getSizeInChars(C); } - assert(ElementOffsetInBytes == NextFieldOffsetInBytes && + assert(ElementOffsetInChars == NextFieldOffsetInChars && "Packing the struct changed its size!"); Elements = PackedElements; - LLVMStructAlignment = 1; + LLVMStructAlignment = CharUnits::One(); Packed = true; } @@ -334,16 +344,31 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) { unsigned FieldNo = 0; unsigned ElementNo = 0; + const FieldDecl *LastFD = 0; + bool IsMsStruct = RD->hasAttr(); + for (RecordDecl::field_iterator Field = RD->field_begin(), FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { + if (IsMsStruct) { + // Zero-length bitfields following non-bitfield members are + // ignored: + if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((*Field), LastFD) || + CGM.getContext().ZeroBitfieldFollowsBitfield((*Field), LastFD)) { + --FieldNo; + continue; + } + LastFD = (*Field); + } // If this is a union, skip all the fields that aren't being initialized. if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field) continue; // Don't emit anonymous bitfields, they just affect layout. - if (Field->isBitField() && !Field->getIdentifier()) + if (Field->isBitField() && !Field->getIdentifier()) { + LastFD = (*Field); continue; + } // Get the initializer. A struct can include fields without initializers, // we just use explicit null values for them. @@ -368,9 +393,9 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) { } } - uint64_t LayoutSizeInBytes = Layout.getSize().getQuantity(); + CharUnits LayoutSizeInChars = Layout.getSize(); - if (NextFieldOffsetInBytes > LayoutSizeInBytes) { + if (NextFieldOffsetInChars > LayoutSizeInChars) { // If the struct is bigger than the size of the record type, // we must have a flexible array member at the end. assert(RD->hasFlexibleArrayMember() && @@ -380,23 +405,23 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) { return true; } - uint64_t LLVMSizeInBytes = llvm::RoundUpToAlignment(NextFieldOffsetInBytes, - LLVMStructAlignment); + CharUnits LLVMSizeInChars = + NextFieldOffsetInChars.RoundUpToAlignment(LLVMStructAlignment); // Check if we need to convert the struct to a packed struct. - if (NextFieldOffsetInBytes <= LayoutSizeInBytes && - LLVMSizeInBytes > LayoutSizeInBytes) { + if (NextFieldOffsetInChars <= LayoutSizeInChars && + LLVMSizeInChars > LayoutSizeInChars) { assert(!Packed && "Size mismatch!"); ConvertStructToPacked(); - assert(NextFieldOffsetInBytes <= LayoutSizeInBytes && + assert(NextFieldOffsetInChars <= LayoutSizeInChars && "Converting to packed did not help!"); } // Append tail padding if necessary. - AppendTailPadding(CGM.getContext().toBits(Layout.getSize())); + AppendTailPadding(LayoutSizeInChars); - assert(Layout.getSize().getQuantity() == NextFieldOffsetInBytes && + assert(LayoutSizeInChars == NextFieldOffsetInChars && "Tail padding mismatch!"); return true; @@ -413,9 +438,9 @@ llvm::Constant *ConstStructBuilder:: llvm::ConstantStruct::get(CGM.getLLVMContext(), Builder.Elements, Builder.Packed); - assert(llvm::RoundUpToAlignment(Builder.NextFieldOffsetInBytes, - Builder.getAlignment(Result)) == - Builder.getSizeInBytes(Result) && "Size mismatch!"); + assert(Builder.NextFieldOffsetInChars.RoundUpToAlignment( + Builder.getAlignment(Result)) == + Builder.getSizeInChars(Result) && "Size mismatch!"); return Result; } @@ -447,6 +472,10 @@ class ConstExprEmitter : return Visit(PE->getSubExpr()); } + llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE) { + return Visit(GE->getResultExpr()); + } + llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { return Visit(E->getInitializer()); } @@ -480,18 +509,17 @@ class ConstExprEmitter : } llvm::Constant *VisitCastExpr(CastExpr* E) { + Expr *subExpr = E->getSubExpr(); + llvm::Constant *C = CGM.EmitConstantExpr(subExpr, subExpr->getType(), CGF); + if (!C) return 0; + + const llvm::Type *destType = ConvertType(E->getType()); + switch (E->getCastKind()) { case CK_ToUnion: { // GCC cast to union extension assert(E->getType()->isUnionType() && "Destination type is not union type!"); - const llvm::Type *Ty = ConvertType(E->getType()); - Expr *SubExpr = E->getSubExpr(); - - llvm::Constant *C = - CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF); - if (!C) - return 0; // Build a struct with the union sub-element as the first member, // and padded to the appropriate size @@ -500,7 +528,7 @@ class ConstExprEmitter : Elts.push_back(C); Types.push_back(C->getType()); unsigned CurSize = CGM.getTargetData().getTypeAllocSize(C->getType()); - unsigned TotalSize = CGM.getTargetData().getTypeAllocSize(Ty); + unsigned TotalSize = CGM.getTargetData().getTypeAllocSize(destType); assert(CurSize <= TotalSize && "Union size mismatch!"); if (unsigned NumPadBytes = TotalSize - CurSize) { @@ -520,40 +548,103 @@ class ConstExprEmitter : const MemberPointerType *MPT = E->getType()->getAs(); return CGM.getCXXABI().EmitNullMemberPointer(MPT); } - - case CK_BaseToDerivedMemberPointer: { - Expr *SubExpr = E->getSubExpr(); - llvm::Constant *C = - CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF); - if (!C) return 0; + case CK_DerivedToBaseMemberPointer: + case CK_BaseToDerivedMemberPointer: return CGM.getCXXABI().EmitMemberPointerConversion(C, E); - } - case CK_BitCast: - // This must be a member function pointer cast. - return Visit(E->getSubExpr()); + case CK_LValueToRValue: + case CK_NoOp: + return C; - default: { - // FIXME: This should be handled by the CK_NoOp cast kind. - // Explicit and implicit no-op casts - QualType Ty = E->getType(), SubTy = E->getSubExpr()->getType(); - if (CGM.getContext().hasSameUnqualifiedType(Ty, SubTy)) - return Visit(E->getSubExpr()); + case CK_AnyPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + case CK_LValueBitCast: + case CK_BitCast: + if (C->getType() == destType) return C; + return llvm::ConstantExpr::getBitCast(C, destType); - // Handle integer->integer casts for address-of-label differences. - if (Ty->isIntegerType() && SubTy->isIntegerType() && - CGF) { - llvm::Value *Src = Visit(E->getSubExpr()); - if (Src == 0) return 0; - - // Use EmitScalarConversion to perform the conversion. - return cast(CGF->EmitScalarConversion(Src, SubTy, Ty)); - } - + case CK_Dependent: llvm_unreachable("saw dependent cast!"); + + // These will never be supported. + case CK_ObjCObjectLValueCast: + case CK_GetObjCProperty: + case CK_ToVoid: + case CK_Dynamic: return 0; + + // These might need to be supported for constexpr. + case CK_UserDefinedConversion: + case CK_ConstructorConversion: + return 0; + + // These should eventually be supported. + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_BaseToDerived: + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_MemberPointerToBoolean: + case CK_VectorSplat: + case CK_FloatingRealToComplex: + case CK_FloatingComplexToReal: + case CK_FloatingComplexToBoolean: + case CK_FloatingComplexCast: + case CK_FloatingComplexToIntegralComplex: + case CK_IntegralRealToComplex: + case CK_IntegralComplexToReal: + case CK_IntegralComplexToBoolean: + case CK_IntegralComplexCast: + case CK_IntegralComplexToFloatingComplex: + return 0; + + case CK_PointerToIntegral: + if (!E->getType()->isBooleanType()) + return llvm::ConstantExpr::getPtrToInt(C, destType); + // fallthrough + + case CK_PointerToBoolean: + return llvm::ConstantExpr::getICmp(llvm::CmpInst::ICMP_EQ, C, + llvm::ConstantPointerNull::get(cast(C->getType()))); + + case CK_NullToPointer: + return llvm::ConstantPointerNull::get(cast(destType)); + + case CK_IntegralCast: { + bool isSigned = subExpr->getType()->isSignedIntegerType(); + return llvm::ConstantExpr::getIntegerCast(C, destType, isSigned); } + + case CK_IntegralToPointer: { + bool isSigned = subExpr->getType()->isSignedIntegerType(); + C = llvm::ConstantExpr::getIntegerCast(C, CGM.IntPtrTy, isSigned); + return llvm::ConstantExpr::getIntToPtr(C, destType); } + + case CK_IntegralToBoolean: + return llvm::ConstantExpr::getICmp(llvm::CmpInst::ICMP_EQ, C, + llvm::Constant::getNullValue(C->getType())); + + case CK_IntegralToFloating: + if (subExpr->getType()->isSignedIntegerType()) + return llvm::ConstantExpr::getSIToFP(C, destType); + else + return llvm::ConstantExpr::getUIToFP(C, destType); + + case CK_FloatingToIntegral: + if (E->getType()->isSignedIntegerType()) + return llvm::ConstantExpr::getFPToSI(C, destType); + else + return llvm::ConstantExpr::getFPToUI(C, destType); + + case CK_FloatingToBoolean: + return llvm::ConstantExpr::getFCmp(llvm::CmpInst::FCMP_UNE, C, + llvm::Constant::getNullValue(C->getType())); + + case CK_FloatingCast: + return llvm::ConstantExpr::getFPCast(C, destType); + } + llvm_unreachable("Invalid CastKind"); } llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { @@ -562,7 +653,7 @@ class ConstExprEmitter : llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) { unsigned NumInitElements = ILE->getNumInits(); - if (NumInitElements == 1 && + if (NumInitElements == 1 && ILE->getType() == ILE->getInit(0)->getType() && (isa(ILE->getInit(0)) || isa(ILE->getInit(0)))) return Visit(ILE->getInit(0)); @@ -591,8 +682,16 @@ class ConstExprEmitter : // Initialize remaining array elements. // FIXME: This doesn't handle member pointers correctly! + llvm::Constant *fillC; + if (Expr *filler = ILE->getArrayFiller()) + fillC = CGM.EmitConstantExpr(filler, filler->getType(), CGF); + else + fillC = llvm::Constant::getNullValue(ElemTy); + if (!fillC) + return 0; + RewriteType |= (fillC->getType() != ElemTy); for (; i < NumElements; ++i) - Elts.push_back(llvm::Constant::getNullValue(ElemTy)); + Elts.push_back(fillC); if (RewriteType) { // FIXME: Try to avoid packing the array @@ -730,7 +829,7 @@ class ConstExprEmitter : E->getType().isConstant(CGM.getContext()), llvm::GlobalValue::InternalLinkage, C, ".compoundliteral", 0, false, - E->getType().getAddressSpace()); + CGM.getContext().getTargetAddressSpace(E->getType())); return C; } case Expr::DeclRefExprClass: { @@ -907,12 +1006,29 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, llvm::SmallVector Inits; unsigned NumElts = Result.Val.getVectorLength(); - for (unsigned i = 0; i != NumElts; ++i) { - APValue &Elt = Result.Val.getVectorElt(i); - if (Elt.isInt()) - Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt())); - else - Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat())); + if (Context.getLangOptions().AltiVec && + isa(E) && + cast(E)->getCastKind() == CK_VectorSplat) { + // AltiVec vector initialization with a single literal + APValue &Elt = Result.Val.getVectorElt(0); + + llvm::Constant* InitValue = Elt.isInt() + ? cast + (llvm::ConstantInt::get(VMContext, Elt.getInt())) + : cast + (llvm::ConstantFP::get(VMContext, Elt.getFloat())); + + for (unsigned i = 0; i != NumElts; ++i) + Inits.push_back(InitValue); + + } else { + for (unsigned i = 0; i != NumElts; ++i) { + APValue &Elt = Result.Val.getVectorElt(i); + if (Elt.isInt()) + Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt())); + else + Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat())); + } } return llvm::ConstantVector::get(Inits); } @@ -963,7 +1079,8 @@ static void FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, std::vector &Elements, uint64_t StartOffset) { - assert(StartOffset % 8 == 0 && "StartOffset not byte aligned!"); + assert(StartOffset % CGM.getContext().getCharWidth() == 0 && + "StartOffset not byte aligned!"); if (CGM.getTypes().isZeroInitializable(T)) return; @@ -1022,8 +1139,8 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, assert(!T->getAs()->getPointeeType()->isFunctionType() && "Should only see pointers to data members here!"); - uint64_t StartIndex = StartOffset / 8; - uint64_t EndIndex = StartIndex + CGM.getContext().getTypeSize(T) / 8; + CharUnits StartIndex = CGM.getContext().toCharUnitsFromBits(StartOffset); + CharUnits EndIndex = StartIndex + CGM.getContext().getTypeSizeInChars(T); // FIXME: hardcodes Itanium member pointer representation! llvm::Constant *NegativeOne = @@ -1031,8 +1148,8 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, -1ULL, /*isSigned*/true); // Fill in the null data member pointer. - for (uint64_t I = StartIndex; I != EndIndex; ++I) - Elements[I] = NegativeOne; + for (CharUnits I = StartIndex; I != EndIndex; ++I) + Elements[I.getQuantity()] = NegativeOne; } } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp index 3e1debd820b4..6bcc425ce62f 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp @@ -140,9 +140,7 @@ class ScalarExprEmitter } } - const llvm::IntegerType *Ty = cast(V->getType()); - Value *Zero = llvm::ConstantInt::get(Ty, 0); - return Builder.CreateICmpNE(V, Zero, "tobool"); + return Builder.CreateIsNotNull(V, "tobool"); } //===--------------------------------------------------------------------===// @@ -163,10 +161,13 @@ class ScalarExprEmitter Value *VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr()); } + Value *VisitGenericSelectionExpr(GenericSelectionExpr *GE) { + return Visit(GE->getResultExpr()); + } // Leaves. Value *VisitIntegerLiteral(const IntegerLiteral *E) { - return llvm::ConstantInt::get(VMContext, E->getValue()); + return Builder.getInt(E->getValue()); } Value *VisitFloatingLiteral(const FloatingLiteral *E) { return llvm::ConstantFP::get(VMContext, E->getValue()); @@ -184,15 +185,14 @@ class ScalarExprEmitter return EmitNullValue(E->getType()); } Value *VisitOffsetOfExpr(OffsetOfExpr *E); - Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E); + Value *VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); Value *VisitAddrLabelExpr(const AddrLabelExpr *E) { llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel()); return Builder.CreateBitCast(V, ConvertType(E->getType())); } Value *VisitSizeOfPackExpr(SizeOfPackExpr *E) { - return llvm::ConstantInt::get(ConvertType(E->getType()), - E->getPackLength()); + return llvm::ConstantInt::get(ConvertType(E->getType()),E->getPackLength()); } Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) { @@ -212,13 +212,12 @@ class ScalarExprEmitter assert(!Result.HasSideEffects && "Constant declref with side-effect?!"); llvm::Constant *C; - if (Result.Val.isInt()) { - C = llvm::ConstantInt::get(VMContext, Result.Val.getInt()); - } else if (Result.Val.isFloat()) { + if (Result.Val.isInt()) + C = Builder.getInt(Result.Val.getInt()); + else if (Result.Val.isFloat()) C = llvm::ConstantFP::get(VMContext, Result.Val.getFloat()); - } else { + else return EmitLoadOfLValue(E); - } // Make sure we emit a debug reference to the global variable. if (VarDecl *VD = dyn_cast(E->getDecl())) { @@ -245,6 +244,9 @@ class ScalarExprEmitter return EmitLoadOfLValue(E); } Value *VisitObjCMessageExpr(ObjCMessageExpr *E) { + if (E->getMethodDecl() && + E->getMethodDecl()->getResultType()->isReferenceType()) + return EmitLoadOfLValue(E); return CGF.EmitObjCMessageExpr(E).getScalarVal(); } @@ -358,13 +360,21 @@ class ScalarExprEmitter return 0; } Value *VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) { - return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue()); + return Builder.getInt1(E->getValue()); } Value *VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) { return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); } + Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { + return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue()); + } + + Value *VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { + return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue()); + } + Value *VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E) { // C++ [expr.pseudo]p1: // The result shall only be used as the operand for the function call @@ -385,7 +395,7 @@ class ScalarExprEmitter } Value *VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { - return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue()); + return Builder.getInt1(E->getValue()); } // Binary Operators. @@ -579,14 +589,14 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, // Insert the element in element zero of an undef vector llvm::Value *UnV = llvm::UndefValue::get(DstTy); - llvm::Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, 0); + llvm::Value *Idx = Builder.getInt32(0); UnV = Builder.CreateInsertElement(UnV, Elt, Idx, "tmp"); // Splat the element across to all elements llvm::SmallVector Args; unsigned NumElements = cast(DstTy)->getNumElements(); for (unsigned i = 0; i != NumElements; ++i) - Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0)); + Args.push_back(Builder.getInt32(0)); llvm::Constant *Mask = llvm::ConstantVector::get(Args); llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat"); @@ -683,8 +693,8 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { // Shuffle LHS & RHS into one input vector. llvm::SmallVector concat; for (unsigned i = 0; i != LHSElts; ++i) { - concat.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 2*i)); - concat.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 2*i+1)); + concat.push_back(Builder.getInt32(2*i)); + concat.push_back(Builder.getInt32(2*i+1)); } Value* CV = llvm::ConstantVector::get(concat); @@ -726,18 +736,16 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { MTy->getNumElements()); Value* NewV = llvm::UndefValue::get(RTy); for (unsigned i = 0, e = MTy->getNumElements(); i != e; ++i) { - Value *Indx = llvm::ConstantInt::get(CGF.Int32Ty, i); + Value *Indx = Builder.getInt32(i); Indx = Builder.CreateExtractElement(Mask, Indx, "shuf_idx"); Indx = Builder.CreateZExt(Indx, CGF.Int32Ty, "idx_zext"); // Handle vec3 special since the index will be off by one for the RHS. if ((LHSElts == 6) && (E->getNumSubExprs() == 3)) { Value *cmpIndx, *newIndx; - cmpIndx = Builder.CreateICmpUGT(Indx, - llvm::ConstantInt::get(CGF.Int32Ty, 3), + cmpIndx = Builder.CreateICmpUGT(Indx, Builder.getInt32(3), "cmp_shuf_idx"); - newIndx = Builder.CreateSub(Indx, llvm::ConstantInt::get(CGF.Int32Ty,1), - "shuf_idx_adj"); + newIndx = Builder.CreateSub(Indx, Builder.getInt32(1), "shuf_idx_adj"); Indx = Builder.CreateSelect(cmpIndx, newIndx, Indx, "sel_shuf_idx"); } Value *VExt = Builder.CreateExtractElement(LHS, Indx, "shuf_elt"); @@ -775,7 +783,7 @@ Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) { CGF.EmitScalarExpr(E->getBase()); else EmitLValue(E->getBase()); - return llvm::ConstantInt::get(VMContext, Result.Val.getInt()); + return Builder.getInt(Result.Val.getInt()); } // Emit debug info for aggregate now, if it was delayed to reduce @@ -875,8 +883,7 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { llvm::ShuffleVectorInst *SVV = cast(V); for (unsigned j = 0; j != CurIdx; ++j) Args.push_back(getMaskElt(SVV, j, 0, CGF.Int32Ty)); - Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, - ResElts + C->getZExtValue())); + Args.push_back(Builder.getInt32(ResElts + C->getZExtValue())); for (unsigned j = CurIdx + 1; j != ResElts; ++j) Args.push_back(llvm::UndefValue::get(CGF.Int32Ty)); @@ -892,8 +899,8 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { } } } - Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, CurIdx); - V = Builder.CreateInsertElement(V, Init, Idx, "vecinit"); + V = Builder.CreateInsertElement(V, Init, Builder.getInt32(CurIdx), + "vecinit"); VIsUndefShuffle = false; ++CurIdx; continue; @@ -918,7 +925,7 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { Args.push_back(getMaskElt(cast(V), j, 0, CGF.Int32Ty)); } else { - Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, j)); + Args.push_back(Builder.getInt32(j)); } } for (unsigned j = 0, je = InitElts; j != je; ++j) @@ -937,7 +944,7 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { // to the vector initializer into V. if (Args.empty()) { for (unsigned j = 0; j != InitElts; ++j) - Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, j)); + Args.push_back(Builder.getInt32(j)); for (unsigned j = InitElts; j != ResElts; ++j) Args.push_back(llvm::UndefValue::get(CGF.Int32Ty)); llvm::Constant *Mask = llvm::ConstantVector::get(Args); @@ -946,9 +953,9 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { Args.clear(); for (unsigned j = 0; j != CurIdx; ++j) - Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, j)); + Args.push_back(Builder.getInt32(j)); for (unsigned j = 0; j != InitElts; ++j) - Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, j+Offset)); + Args.push_back(Builder.getInt32(j+Offset)); for (unsigned j = CurIdx + InitElts; j != ResElts; ++j) Args.push_back(llvm::UndefValue::get(CGF.Int32Ty)); } @@ -969,7 +976,7 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { // Emit remaining default initializers for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) { - Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, CurIdx); + Value *Idx = Builder.getInt32(CurIdx); llvm::Value *Init = llvm::Constant::getNullValue(EltTy); V = Builder.CreateInsertElement(V, Init, Idx, "vecinit"); } @@ -1123,7 +1130,7 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { RValue RV = CGF.EmitLoadOfLValue(CGF.EmitLValue(E), E->getType()); return RV.getScalarVal(); } - + case CK_LValueToRValue: assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy)); assert(E->isGLValue() && "lvalue-to-rvalue applied to r-value!"); @@ -1160,13 +1167,13 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { // Insert the element in element zero of an undef vector llvm::Value *UnV = llvm::UndefValue::get(DstTy); - llvm::Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, 0); + llvm::Value *Idx = Builder.getInt32(0); UnV = Builder.CreateInsertElement(UnV, Elt, Idx, "tmp"); // Splat the element across to all elements llvm::SmallVector Args; unsigned NumElements = cast(DstTy)->getNumElements(); - llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Int32Ty, 0); + llvm::Constant *Zero = Builder.getInt32(0); for (unsigned i = 0; i < NumElements; i++) Args.push_back(Zero); @@ -1218,10 +1225,8 @@ Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) { } Value *ScalarExprEmitter::VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) { - llvm::Value *V = CGF.GetAddrOfBlockDecl(E); - if (E->getType().isObjCGCWeak()) - return CGF.CGM.getObjCRuntime().EmitObjCWeakRead(CGF, V); - return CGF.EmitLoadOfScalar(V, false, 0, E->getType()); + LValue LV = CGF.EmitBlockDeclRefLValue(E); + return CGF.EmitLoadOfLValue(LV, E->getType()).getScalarVal(); } //===----------------------------------------------------------------------===// @@ -1278,10 +1283,12 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount); - if (type->isSignedIntegerType()) + // Note that signed integer inc/dec with width less than int can't + // overflow because of promotion rules; we're just eliding a few steps here. + if (type->isSignedIntegerType() && + value->getType()->getPrimitiveSizeInBits() >= + CGF.CGM.IntTy->getBitWidth()) value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc); - - // Unsigned integer inc is always two's complement. else value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec"); @@ -1295,21 +1302,30 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, CGF.GetVLASize(CGF.getContext().getAsVariableArrayType(type)); value = CGF.EmitCastToVoidPtr(value); if (!isInc) vlaSize = Builder.CreateNSWNeg(vlaSize, "vla.negsize"); - value = Builder.CreateInBoundsGEP(value, vlaSize, "vla.inc"); + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + value = Builder.CreateGEP(value, vlaSize, "vla.inc"); + else + value = Builder.CreateInBoundsGEP(value, vlaSize, "vla.inc"); value = Builder.CreateBitCast(value, input->getType()); // Arithmetic on function pointers (!) is just +-1. } else if (type->isFunctionType()) { - llvm::Value *amt = llvm::ConstantInt::get(CGF.Int32Ty, amount); + llvm::Value *amt = Builder.getInt32(amount); value = CGF.EmitCastToVoidPtr(value); - value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr"); + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + value = Builder.CreateGEP(value, amt, "incdec.funcptr"); + else + value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr"); value = Builder.CreateBitCast(value, input->getType()); // For everything else, we can just do a simple increment. } else { - llvm::Value *amt = llvm::ConstantInt::get(CGF.Int32Ty, amount); - value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr"); + llvm::Value *amt = Builder.getInt32(amount); + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + value = Builder.CreateGEP(value, amt, "incdec.ptr"); + else + value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr"); } // Vector increment/decrement. @@ -1357,7 +1373,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::Value *sizeValue = llvm::ConstantInt::get(CGF.SizeTy, size.getQuantity()); - value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr"); + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + value = Builder.CreateGEP(value, sizeValue, "incdec.objptr"); + else + value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr"); value = Builder.CreateBitCast(value, input->getType()); } @@ -1413,7 +1432,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { // Try folding the offsetof to a constant. Expr::EvalResult EvalResult; if (E->Evaluate(EvalResult, CGF.getContext())) - return llvm::ConstantInt::get(VMContext, EvalResult.Val.getInt()); + return Builder.getInt(EvalResult.Val.getInt()); // Loop over the components of the offsetof to compute the value. unsigned n = E->getNumComponents(); @@ -1499,12 +1518,13 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { return Result; } -/// VisitSizeOfAlignOfExpr - Return the size or alignment of the type of +/// VisitUnaryExprOrTypeTraitExpr - Return the size or alignment of the type of /// argument of the sizeof expression as an integer. Value * -ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { +ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr( + const UnaryExprOrTypeTraitExpr *E) { QualType TypeToSize = E->getTypeOfArgument(); - if (E->isSizeOf()) { + if (E->getKind() == UETT_SizeOf) { if (const VariableArrayType *VAT = CGF.getContext().getAsVariableArrayType(TypeToSize)) { if (E->isArgumentType()) { @@ -1524,7 +1544,7 @@ ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { // folding logic so we don't have to duplicate it here. Expr::EvalResult Result; E->Evaluate(Result, CGF.getContext()); - return llvm::ConstantInt::get(VMContext, Result.Val.getInt()); + return Builder.getInt(Result.Val.getInt()); } Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) { @@ -1664,8 +1684,7 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( if (Ops.Ty->hasSignedIntegerRepresentation()) { llvm::Value *IntMin = - llvm::ConstantInt::get(VMContext, - llvm::APInt::getSignedMinValue(Ty->getBitWidth())); + Builder.getInt(llvm::APInt::getSignedMinValue(Ty->getBitWidth())); llvm::Value *NegOne = llvm::ConstantInt::get(Ty, -1ULL); llvm::Value *Cond1 = Builder.CreateICmpEQ(Ops.RHS, Zero); @@ -1715,7 +1734,7 @@ Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) { EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, false); } - if (Ops.Ty->isUnsignedIntegerType()) + if (Ops.Ty->hasUnsignedIntegerRepresentation()) return Builder.CreateURem(Ops.LHS, Ops.RHS, "rem"); else return Builder.CreateSRem(Ops.LHS, Ops.RHS, "rem"); @@ -1801,8 +1820,7 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { Builder.CreateBr(continueBB); Builder.SetInsertPoint(continueBB); - llvm::PHINode *phi = Builder.CreatePHI(opTy); - phi->reserveOperandSpace(2); + llvm::PHINode *phi = Builder.CreatePHI(opTy, 2); phi->addIncoming(result, initialBB); phi->addIncoming(handlerResult, overflowBB); @@ -1889,6 +1907,8 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { return Builder.CreateBitCast(Res, Ptr->getType()); } + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + return Builder.CreateGEP(Ptr, Idx, "add.ptr"); return Builder.CreateInBoundsGEP(Ptr, Idx, "add.ptr"); } @@ -1964,38 +1984,39 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { return Builder.CreateBitCast(Res, Ops.LHS->getType()); } + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + return Builder.CreateGEP(Ops.LHS, Idx, "sub.ptr"); return Builder.CreateInBoundsGEP(Ops.LHS, Idx, "sub.ptr"); - } else { - // pointer - pointer - Value *LHS = Ops.LHS; - Value *RHS = Ops.RHS; - - CharUnits ElementSize; - - // Handle GCC extension for pointer arithmetic on void* and function pointer - // types. - if (LHSElementType->isVoidType() || LHSElementType->isFunctionType()) { - ElementSize = CharUnits::One(); - } else { - ElementSize = CGF.getContext().getTypeSizeInChars(LHSElementType); - } - - const llvm::Type *ResultType = ConvertType(Ops.Ty); - LHS = Builder.CreatePtrToInt(LHS, ResultType, "sub.ptr.lhs.cast"); - RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); - Value *BytesBetween = Builder.CreateSub(LHS, RHS, "sub.ptr.sub"); - - // Optimize out the shift for element size of 1. - if (ElementSize.isOne()) - return BytesBetween; - - // Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since - // pointer difference in C is only defined in the case where both operands - // are pointing to elements of an array. - Value *BytesPerElt = - llvm::ConstantInt::get(ResultType, ElementSize.getQuantity()); - return Builder.CreateExactSDiv(BytesBetween, BytesPerElt, "sub.ptr.div"); } + + // pointer - pointer + Value *LHS = Ops.LHS; + Value *RHS = Ops.RHS; + + CharUnits ElementSize; + + // Handle GCC extension for pointer arithmetic on void* and function pointer + // types. + if (LHSElementType->isVoidType() || LHSElementType->isFunctionType()) + ElementSize = CharUnits::One(); + else + ElementSize = CGF.getContext().getTypeSizeInChars(LHSElementType); + + const llvm::Type *ResultType = ConvertType(Ops.Ty); + LHS = Builder.CreatePtrToInt(LHS, ResultType, "sub.ptr.lhs.cast"); + RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); + Value *BytesBetween = Builder.CreateSub(LHS, RHS, "sub.ptr.sub"); + + // Optimize out the shift for element size of 1. + if (ElementSize.isOne()) + return BytesBetween; + + // Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since + // pointer difference in C is only defined in the case where both operands + // are pointing to elements of an array. + Value *BytesPerElt = + llvm::ConstantInt::get(ResultType, ElementSize.getQuantity()); + return Builder.CreateExactSDiv(BytesBetween, BytesPerElt, "sub.ptr.div"); } Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { @@ -2100,7 +2121,7 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc, // If AltiVec, the comparison results in a numeric type, so we use // intrinsics comparing vectors and giving 0 or 1 as a result - if (LHSTy->isVectorType() && CGF.getContext().getLangOptions().AltiVec) { + if (LHSTy->isVectorType() && !E->getType()->isVectorType()) { // constants for mapping CR6 register bits to predicate result enum { CR6_EQ=0, CR6_EQ_REV, CR6_LT, CR6_LT_REV } CR6; @@ -2157,7 +2178,7 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc, break; } - Value *CR6Param = llvm::ConstantInt::get(CGF.Int32Ty, CR6); + Value *CR6Param = Builder.getInt32(CR6); llvm::Function *F = CGF.CGM.getIntrinsic(ID); Result = Builder.CreateCall3(F, CR6Param, FirstVecArg, SecondVecArg, ""); return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType()); @@ -2257,8 +2278,9 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { // If we have 0 && RHS, see if we can elide RHS, if so, just return 0. // If we have 1 && X, just emit X without inserting the control flow. - if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) { - if (Cond == 1) { // If we have 1 && X, just emit X. + bool LHSCondVal; + if (CGF.ConstantFoldsToSimpleInteger(E->getLHS(), LHSCondVal)) { + if (LHSCondVal) { // If we have 1 && X, just emit X. Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); // ZExt result to int or bool. return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "land.ext"); @@ -2280,9 +2302,8 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { // Any edges into the ContBlock are now from an (indeterminate number of) // edges from this first condition. All of these values will be false. Start // setting up the PHI node in the Cont Block for this. - llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext), + llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext), 2, "", ContBlock); - PN->reserveOperandSpace(2); // Normal case, two inputs. for (llvm::pred_iterator PI = pred_begin(ContBlock), PE = pred_end(ContBlock); PI != PE; ++PI) PN->addIncoming(llvm::ConstantInt::getFalse(VMContext), *PI); @@ -2297,6 +2318,9 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { // Emit an unconditional branch from this block to ContBlock. Insert an entry // into the phi node for the edge with the value of RHSCond. + if (CGF.getDebugInfo()) + // There is no need to emit line number for unconditional branch. + Builder.SetCurrentDebugLocation(llvm::DebugLoc()); CGF.EmitBlock(ContBlock); PN->addIncoming(RHSCond, RHSBlock); @@ -2309,8 +2333,9 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) { // If we have 1 || RHS, see if we can elide RHS, if so, just return 1. // If we have 0 || X, just emit X without inserting the control flow. - if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) { - if (Cond == -1) { // If we have 0 || X, just emit X. + bool LHSCondVal; + if (CGF.ConstantFoldsToSimpleInteger(E->getLHS(), LHSCondVal)) { + if (!LHSCondVal) { // If we have 0 || X, just emit X. Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); // ZExt result to int or bool. return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "lor.ext"); @@ -2332,9 +2357,8 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) { // Any edges into the ContBlock are now from an (indeterminate number of) // edges from this first condition. All of these values will be true. Start // setting up the PHI node in the Cont Block for this. - llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext), + llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext), 2, "", ContBlock); - PN->reserveOperandSpace(2); // Normal case, two inputs. for (llvm::pred_iterator PI = pred_begin(ContBlock), PE = pred_end(ContBlock); PI != PE; ++PI) PN->addIncoming(llvm::ConstantInt::getTrue(VMContext), *PI); @@ -2375,12 +2399,10 @@ Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) { /// flow into selects in some cases. static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E, CodeGenFunction &CGF) { - if (const ParenExpr *PE = dyn_cast(E)) - return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr(), CGF); + E = E->IgnoreParens(); - // TODO: Allow anything we can constant fold to an integer or fp constant. - if (isa(E) || isa(E) || - isa(E)) + // Anything that is an integer or floating point constant is fine. + if (E->isConstantInitializer(CGF.getContext(), false)) return true; // Non-volatile automatic variables too, to get "cond ? X : Y" where @@ -2409,9 +2431,10 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { // If the condition constant folds and can be elided, try to avoid emitting // the condition and the dead arm. - if (int Cond = CGF.ConstantFoldsToSimpleInteger(condExpr)){ + bool CondExprBool; + if (CGF.ConstantFoldsToSimpleInteger(condExpr, CondExprBool)) { Expr *live = lhsExpr, *dead = rhsExpr; - if (Cond == -1) std::swap(live, dead); + if (!CondExprBool) std::swap(live, dead); // If the dead side doesn't have labels we need, and if the Live side isn't // the gnu missing ?: extension (which we could handle, but don't bother @@ -2436,7 +2459,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { std::vector Zvals; for (unsigned i = 0; i < numElem; ++i) - Zvals.push_back(llvm::ConstantInt::get(elemType,0)); + Zvals.push_back(llvm::ConstantInt::get(elemType, 0)); llvm::Value *zeroVec = llvm::ConstantVector::get(Zvals); llvm::Value *TestMSB = Builder.CreateICmpSLT(CondV, zeroVec); @@ -2507,8 +2530,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { return LHS; // Create a PHI node for the real part. - llvm::PHINode *PN = Builder.CreatePHI(LHS->getType(), "cond"); - PN->reserveOperandSpace(2); + llvm::PHINode *PN = Builder.CreatePHI(LHS->getType(), 2, "cond"); PN->addIncoming(LHS, LHSBlock); PN->addIncoming(RHS, RHSBlock); return PN; @@ -2544,8 +2566,13 @@ Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) { assert(E && !hasAggregateLLVMType(E->getType()) && "Invalid scalar expression to emit"); - return ScalarExprEmitter(*this, IgnoreResultAssign) + if (isa(E)) + disableDebugInfo(); + Value *V = ScalarExprEmitter(*this, IgnoreResultAssign) .Visit(const_cast(E)); + if (isa(E)) + enableDebugInfo(); + return V; } /// EmitScalarConversion - Emit a conversion from the specified type to the diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp index 5d3490769991..5b0d41e776f2 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp @@ -119,28 +119,26 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, /// CodeGenFunction. void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD) { - FunctionArgList Args; + FunctionArgList args; // Check if we should generate debug info for this method. - if (CGM.getDebugInfo() && !OMD->hasAttr()) - DebugInfo = CGM.getDebugInfo(); + if (CGM.getModuleDebugInfo() && !OMD->hasAttr()) + DebugInfo = CGM.getModuleDebugInfo(); llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD); const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD); CGM.SetInternalFunctionAttributes(OMD, Fn, FI); - Args.push_back(std::make_pair(OMD->getSelfDecl(), - OMD->getSelfDecl()->getType())); - Args.push_back(std::make_pair(OMD->getCmdDecl(), - OMD->getCmdDecl()->getType())); + args.push_back(OMD->getSelfDecl()); + args.push_back(OMD->getCmdDecl()); for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), E = OMD->param_end(); PI != E; ++PI) - Args.push_back(std::make_pair(*PI, (*PI)->getType())); + args.push_back(*PI); CurGD = OMD; - StartFunction(OMD, OMD->getResultType(), Fn, Args, OMD->getLocStart()); + StartFunction(OMD, OMD->getResultType(), Fn, FI, args, OMD->getLocStart()); } void CodeGenFunction::GenerateObjCGetterBody(ObjCIvarDecl *Ivar, @@ -155,27 +153,24 @@ void CodeGenFunction::GenerateObjCGetterBody(ObjCIvarDecl *Ivar, CallArgList Args; RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue, Types.ConvertType(getContext().VoidPtrTy))); - Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); + Args.add(RV, getContext().VoidPtrTy); RV = RValue::get(Builder.CreateBitCast(LV.getAddress(), Types.ConvertType(getContext().VoidPtrTy))); - Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); + Args.add(RV, getContext().VoidPtrTy); // sizeof (Type of Ivar) CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType()); llvm::Value *SizeVal = llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size.getQuantity()); - Args.push_back(std::make_pair(RValue::get(SizeVal), - getContext().LongTy)); + Args.add(RValue::get(SizeVal), getContext().LongTy); llvm::Value *isAtomic = llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), IsAtomic ? 1 : 0); - Args.push_back(std::make_pair(RValue::get(isAtomic), - getContext().BoolTy)); + Args.add(RValue::get(isAtomic), getContext().BoolTy); llvm::Value *hasStrong = llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), IsStrong ? 1 : 0); - Args.push_back(std::make_pair(RValue::get(hasStrong), - getContext().BoolTy)); + Args.add(RValue::get(hasStrong), getContext().BoolTy); EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, FunctionType::ExtInfo()), GetCopyStructFn, ReturnValueSlot(), Args); @@ -236,10 +231,10 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, llvm::Value *True = llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); CallArgList Args; - Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); - Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); - Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); - Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); + Args.add(RValue::get(SelfAsId), IdTy); + Args.add(RValue::get(CmdVal), Cmd->getType()); + Args.add(RValue::get(Offset), getContext().getPointerDiffType()); + Args.add(RValue::get(True), getContext().BoolTy); // FIXME: We shouldn't need to get the function info here, the // runtime already should have computed it to build the function. RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args, @@ -263,6 +258,22 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, CGM.getObjCRuntime().GetGetStructFunction()) { GenerateObjCGetterBody(Ivar, true, false); } + else if (IsAtomic && + (IVART->isScalarType() && !IVART->isRealFloatingType()) && + Triple.getArch() == llvm::Triple::x86 && + (getContext().getTypeSizeInChars(IVART) + > CharUnits::fromQuantity(4)) && + CGM.getObjCRuntime().GetGetStructFunction()) { + GenerateObjCGetterBody(Ivar, true, false); + } + else if (IsAtomic && + (IVART->isScalarType() && !IVART->isRealFloatingType()) && + Triple.getArch() == llvm::Triple::x86_64 && + (getContext().getTypeSizeInChars(IVART) + > CharUnits::fromQuantity(8)) && + CGM.getObjCRuntime().GetGetStructFunction()) { + GenerateObjCGetterBody(Ivar, true, false); + } else if (IVART->isAnyComplexType()) { LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); @@ -272,18 +283,36 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, } else if (hasAggregateLLVMType(IVART)) { bool IsStrong = false; - if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(IVART))) + if ((IsStrong = IvarTypeWithAggrGCObjects(IVART)) && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && CGM.getObjCRuntime().GetGetStructFunction()) { GenerateObjCGetterBody(Ivar, IsAtomic, IsStrong); } else { - if (PID->getGetterCXXConstructor()) { + const CXXRecordDecl *classDecl = IVART->getAsCXXRecordDecl(); + + if (PID->getGetterCXXConstructor() && + classDecl && !classDecl->hasTrivialConstructor()) { ReturnStmt *Stmt = new (getContext()) ReturnStmt(SourceLocation(), PID->getGetterCXXConstructor(), 0); EmitReturnStmt(*Stmt); + } else if (IsAtomic && + !IVART->isAnyComplexType() && + Triple.getArch() == llvm::Triple::x86 && + (getContext().getTypeSizeInChars(IVART) + > CharUnits::fromQuantity(4)) && + CGM.getObjCRuntime().GetGetStructFunction()) { + GenerateObjCGetterBody(Ivar, true, false); + } + else if (IsAtomic && + !IVART->isAnyComplexType() && + Triple.getArch() == llvm::Triple::x86_64 && + (getContext().getTypeSizeInChars(IVART) + > CharUnits::fromQuantity(8)) && + CGM.getObjCRuntime().GetGetStructFunction()) { + GenerateObjCGetterBody(Ivar, true, false); } else { LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), @@ -295,11 +324,17 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, else { LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); - CodeGenTypes &Types = CGM.getTypes(); - RValue RV = EmitLoadOfLValue(LV, IVART); - RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), + if (PD->getType()->isReferenceType()) { + RValue RV = RValue::get(LV.getAddress()); + EmitReturnOfRValue(RV, PD->getType()); + } + else { + CodeGenTypes &Types = CGM.getTypes(); + RValue RV = EmitLoadOfLValue(LV, IVART); + RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), Types.ConvertType(PD->getType()))); - EmitReturnOfRValue(RV, PD->getType()); + EmitReturnOfRValue(RV, PD->getType()); + } } } @@ -318,31 +353,42 @@ void CodeGenFunction::GenerateObjCAtomicSetterBody(ObjCMethodDecl *OMD, RValue RV = RValue::get(Builder.CreateBitCast(LV.getAddress(), Types.ConvertType(getContext().VoidPtrTy))); - Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); + Args.add(RV, getContext().VoidPtrTy); llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; llvm::Value *ArgAsPtrTy = Builder.CreateBitCast(Arg, Types.ConvertType(getContext().VoidPtrTy)); RV = RValue::get(ArgAsPtrTy); - Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); + Args.add(RV, getContext().VoidPtrTy); // sizeof (Type of Ivar) CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType()); llvm::Value *SizeVal = llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size.getQuantity()); - Args.push_back(std::make_pair(RValue::get(SizeVal), - getContext().LongTy)); + Args.add(RValue::get(SizeVal), getContext().LongTy); llvm::Value *True = llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); - Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); + Args.add(RValue::get(True), getContext().BoolTy); llvm::Value *False = llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); - Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy)); + Args.add(RValue::get(False), getContext().BoolTy); EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, FunctionType::ExtInfo()), GetCopyStructFn, ReturnValueSlot(), Args); } +static bool +IvarAssignHasTrvialAssignment(const ObjCPropertyImplDecl *PID, + QualType IvarT) { + bool HasTrvialAssignment = true; + if (PID->getSetterCXXAssignment()) { + const CXXRecordDecl *classDecl = IvarT->getAsCXXRecordDecl(); + HasTrvialAssignment = + (!classDecl || classDecl->hasTrivialCopyAssignment()); + } + return HasTrvialAssignment; +} + /// GenerateObjCSetter - Generate an Objective-C property setter /// function. The given Decl must be an ObjCImplementationDecl. @synthesize /// is illegal within a category. @@ -353,7 +399,8 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); assert(OMD && "Invalid call to generate setter (empty method)"); StartObjCMethod(OMD, IMP->getClassInterface()); - + const llvm::Triple &Triple = getContext().Target.getTriple(); + QualType IVART = Ivar->getType(); bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; bool IsAtomic = !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); @@ -394,32 +441,34 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, llvm::Value *False = llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); CallArgList Args; - Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); - Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); - Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); - Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy)); - Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False), - getContext().BoolTy)); - Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False), - getContext().BoolTy)); + Args.add(RValue::get(SelfAsId), IdTy); + Args.add(RValue::get(CmdVal), Cmd->getType()); + Args.add(RValue::get(Offset), getContext().getPointerDiffType()); + Args.add(RValue::get(ArgAsId), IdTy); + Args.add(RValue::get(IsAtomic ? True : False), getContext().BoolTy); + Args.add(RValue::get(IsCopy ? True : False), getContext().BoolTy); // FIXME: We shouldn't need to get the function info here, the runtime // already should have computed it to build the function. EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, FunctionType::ExtInfo()), SetPropertyFn, ReturnValueSlot(), Args); - } else if (IsAtomic && hasAggregateLLVMType(Ivar->getType()) && - !Ivar->getType()->isAnyComplexType() && - IndirectObjCSetterArg(*CurFnInfo) + } else if (IsAtomic && hasAggregateLLVMType(IVART) && + !IVART->isAnyComplexType() && + IvarAssignHasTrvialAssignment(PID, IVART) && + ((Triple.getArch() == llvm::Triple::x86 && + (getContext().getTypeSizeInChars(IVART) + > CharUnits::fromQuantity(4))) || + (Triple.getArch() == llvm::Triple::x86_64 && + (getContext().getTypeSizeInChars(IVART) + > CharUnits::fromQuantity(8)))) && CGM.getObjCRuntime().GetSetStructFunction()) { - // objc_copyStruct (&structIvar, &Arg, - // sizeof (struct something), true, false); + // objc_copyStruct (&structIvar, &Arg, + // sizeof (struct something), true, false); GenerateObjCAtomicSetterBody(OMD, Ivar); } else if (PID->getSetterCXXAssignment()) { EmitIgnoredExpr(PID->getSetterCXXAssignment()); } else { - const llvm::Triple &Triple = getContext().Target.getTriple(); - QualType IVART = Ivar->getType(); if (IsAtomic && IVART->isScalarType() && (Triple.getArch() == llvm::Triple::arm || @@ -429,6 +478,22 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, CGM.getObjCRuntime().GetGetStructFunction()) { GenerateObjCAtomicSetterBody(OMD, Ivar); } + else if (IsAtomic && + (IVART->isScalarType() && !IVART->isRealFloatingType()) && + Triple.getArch() == llvm::Triple::x86 && + (getContext().getTypeSizeInChars(IVART) + > CharUnits::fromQuantity(4)) && + CGM.getObjCRuntime().GetGetStructFunction()) { + GenerateObjCAtomicSetterBody(OMD, Ivar); + } + else if (IsAtomic && + (IVART->isScalarType() && !IVART->isRealFloatingType()) && + Triple.getArch() == llvm::Triple::x86_64 && + (getContext().getTypeSizeInChars(IVART) + > CharUnits::fromQuantity(8)) && + CGM.getObjCRuntime().GetGetStructFunction()) { + GenerateObjCAtomicSetterBody(OMD, Ivar); + } else { // FIXME: Find a clean way to avoid AST node creation. SourceLocation Loc = PD->getLocation(); @@ -436,7 +501,10 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); DeclRefExpr Base(Self, Self->getType(), VK_RValue, Loc); ParmVarDecl *ArgDecl = *OMD->param_begin(); - DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), VK_LValue, Loc); + QualType T = ArgDecl->getType(); + if (T->isReferenceType()) + T = cast(T)->getPointeeType(); + DeclRefExpr Arg(ArgDecl, T, VK_LValue, Loc); ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true); // The property type can differ from the ivar type in some situations with @@ -460,20 +528,104 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, FinishFunction(); } +// FIXME: these are stolen from CGClass.cpp, which is lame. +namespace { + struct CallArrayIvarDtor : EHScopeStack::Cleanup { + const ObjCIvarDecl *ivar; + llvm::Value *self; + CallArrayIvarDtor(const ObjCIvarDecl *ivar, llvm::Value *self) + : ivar(ivar), self(self) {} + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + LValue lvalue = + CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), self, ivar, 0); + + QualType type = ivar->getType(); + const ConstantArrayType *arrayType + = CGF.getContext().getAsConstantArrayType(type); + QualType baseType = CGF.getContext().getBaseElementType(arrayType); + const CXXRecordDecl *classDecl = baseType->getAsCXXRecordDecl(); + + llvm::Value *base + = CGF.Builder.CreateBitCast(lvalue.getAddress(), + CGF.ConvertType(baseType)->getPointerTo()); + CGF.EmitCXXAggrDestructorCall(classDecl->getDestructor(), + arrayType, base); + } + }; + + struct CallIvarDtor : EHScopeStack::Cleanup { + const ObjCIvarDecl *ivar; + llvm::Value *self; + CallIvarDtor(const ObjCIvarDecl *ivar, llvm::Value *self) + : ivar(ivar), self(self) {} + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + LValue lvalue = + CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), self, ivar, 0); + + QualType type = ivar->getType(); + const CXXRecordDecl *classDecl = type->getAsCXXRecordDecl(); + + CGF.EmitCXXDestructorCall(classDecl->getDestructor(), + Dtor_Complete, /*ForVirtualBase=*/false, + lvalue.getAddress()); + } + }; +} + +static void emitCXXDestructMethod(CodeGenFunction &CGF, + ObjCImplementationDecl *impl) { + CodeGenFunction::RunCleanupsScope scope(CGF); + + llvm::Value *self = CGF.LoadObjCSelf(); + + ObjCInterfaceDecl *iface + = const_cast(impl->getClassInterface()); + for (ObjCIvarDecl *ivar = iface->all_declared_ivar_begin(); + ivar; ivar = ivar->getNextIvar()) { + QualType type = ivar->getType(); + + // Drill down to the base element type. + QualType baseType = type; + const ConstantArrayType *arrayType = + CGF.getContext().getAsConstantArrayType(baseType); + if (arrayType) baseType = CGF.getContext().getBaseElementType(arrayType); + + // Check whether the ivar is a destructible type. + QualType::DestructionKind destructKind = baseType.isDestructedType(); + assert(destructKind == type.isDestructedType()); + + switch (destructKind) { + case QualType::DK_none: + continue; + + case QualType::DK_cxx_destructor: + if (arrayType) + CGF.EHStack.pushCleanup(NormalAndEHCleanup, + ivar, self); + else + CGF.EHStack.pushCleanup(NormalAndEHCleanup, + ivar, self); + break; + } + } + + assert(scope.requiresCleanups() && "nothing to do in .cxx_destruct?"); +} + void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, ObjCMethodDecl *MD, bool ctor) { - llvm::SmallVector IvarInitializers; MD->createImplicitParams(CGM.getContext(), IMP->getClassInterface()); StartObjCMethod(MD, IMP->getClassInterface()); - for (ObjCImplementationDecl::init_const_iterator B = IMP->init_begin(), - E = IMP->init_end(); B != E; ++B) { - CXXCtorInitializer *Member = (*B); - IvarInitializers.push_back(Member); - } + + // Emit .cxx_construct. if (ctor) { - for (unsigned I = 0, E = IvarInitializers.size(); I != E; ++I) { - CXXCtorInitializer *IvarInit = IvarInitializers[I]; + llvm::SmallVector IvarInitializers; + for (ObjCImplementationDecl::init_const_iterator B = IMP->init_begin(), + E = IMP->init_end(); B != E; ++B) { + CXXCtorInitializer *IvarInit = (*B); FieldDecl *Field = IvarInit->getAnyMember(); ObjCIvarDecl *Ivar = cast(Field); LValue LV = EmitLValueForIvar(TypeOfSelfObject(), @@ -486,37 +638,10 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, llvm::Value *SelfAsId = Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); EmitReturnOfRValue(RValue::get(SelfAsId), IdTy); + + // Emit .cxx_destruct. } else { - // dtor - for (size_t i = IvarInitializers.size(); i > 0; --i) { - FieldDecl *Field = IvarInitializers[i - 1]->getAnyMember(); - QualType FieldType = Field->getType(); - const ConstantArrayType *Array = - getContext().getAsConstantArrayType(FieldType); - if (Array) - FieldType = getContext().getBaseElementType(FieldType); - - ObjCIvarDecl *Ivar = cast(Field); - LValue LV = EmitLValueForIvar(TypeOfSelfObject(), - LoadObjCSelf(), Ivar, 0); - const RecordType *RT = FieldType->getAs(); - CXXRecordDecl *FieldClassDecl = cast(RT->getDecl()); - CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(); - if (!Dtor->isTrivial()) { - if (Array) { - const llvm::Type *BasePtr = ConvertType(FieldType); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - llvm::Value *BaseAddrPtr = - Builder.CreateBitCast(LV.getAddress(), BasePtr); - EmitCXXAggrDestructorCall(Dtor, - Array, BaseAddrPtr); - } else { - EmitCXXDestructorCall(Dtor, - Dtor_Complete, /*ForVirtualBase=*/false, - LV.getAddress()); - } - } - } + emitCXXDestructMethod(*this, IMP); } FinishFunction(); } @@ -585,16 +710,14 @@ static RValue GenerateMessageSendSuper(CodeGenFunction &CGF, RValue CodeGenFunction::EmitLoadOfPropertyRefLValue(LValue LV, ReturnValueSlot Return) { const ObjCPropertyRefExpr *E = LV.getPropertyRefExpr(); - QualType ResultType; + QualType ResultType = E->getGetterResultType(); Selector S; if (E->isExplicitProperty()) { const ObjCPropertyDecl *Property = E->getExplicitProperty(); S = Property->getGetterName(); - ResultType = E->getType(); } else { const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter(); S = Getter->getSelector(); - ResultType = Getter->getResultType(); // with reference! } llvm::Value *Receiver = LV.getPropertyRefBaseAddr(); @@ -615,14 +738,8 @@ void CodeGenFunction::EmitStoreThroughPropertyRefLValue(RValue Src, LValue Dst) { const ObjCPropertyRefExpr *E = Dst.getPropertyRefExpr(); Selector S = E->getSetterSelector(); - QualType ArgType; - if (E->isImplicitProperty()) { - const ObjCMethodDecl *Setter = E->getImplicitPropertySetter(); - ObjCMethodDecl::param_iterator P = Setter->param_begin(); - ArgType = (*P)->getType(); - } else { - ArgType = E->getType(); - } + QualType ArgType = E->getSetterArgType(); + // FIXME. Other than scalars, AST is not adequate for setter and // getter type mismatches which require conversion. if (Src.isScalar()) { @@ -635,7 +752,7 @@ void CodeGenFunction::EmitStoreThroughPropertyRefLValue(RValue Src, } CallArgList Args; - Args.push_back(std::make_pair(Src, ArgType)); + Args.add(Src, ArgType); llvm::Value *Receiver = Dst.getPropertyRefBaseAddr(); QualType ResultType = getContext().VoidTy; @@ -707,22 +824,19 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ CallArgList Args; // The first argument is a temporary of the enumeration-state type. - Args.push_back(std::make_pair(RValue::get(StatePtr), - getContext().getPointerType(StateTy))); + Args.add(RValue::get(StatePtr), getContext().getPointerType(StateTy)); // The second argument is a temporary array with space for NumItems // pointers. We'll actually be loading elements from the array // pointer written into the control state; this buffer is so that // collections that *aren't* backed by arrays can still queue up // batches of elements. - Args.push_back(std::make_pair(RValue::get(ItemsPtr), - getContext().getPointerType(ItemsTy))); + Args.add(RValue::get(ItemsPtr), getContext().getPointerType(ItemsTy)); // The third argument is the capacity of that temporary array. const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy); llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems); - Args.push_back(std::make_pair(RValue::get(Count), - getContext().UnsignedLongTy)); + Args.add(RValue::get(Count), getContext().UnsignedLongTy); // Start the enumeration. RValue CountRV = @@ -764,11 +878,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ EmitBlock(LoopBodyBB); // The current index into the buffer. - llvm::PHINode *index = Builder.CreatePHI(UnsignedLongLTy, "forcoll.index"); + llvm::PHINode *index = Builder.CreatePHI(UnsignedLongLTy, 3, "forcoll.index"); index->addIncoming(zero, LoopInitBB); // The current buffer size. - llvm::PHINode *count = Builder.CreatePHI(UnsignedLongLTy, "forcoll.count"); + llvm::PHINode *count = Builder.CreatePHI(UnsignedLongLTy, 3, "forcoll.count"); count->addIncoming(initialBufferLimit, LoopInitBB); // Check whether the mutations value has changed from where it was @@ -779,7 +893,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ = Builder.CreateLoad(StateMutationsPtr, "statemutations"); llvm::BasicBlock *WasMutatedBB = createBasicBlock("forcoll.mutated"); - llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcool.notmutated"); + llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcoll.notmutated"); Builder.CreateCondBr(Builder.CreateICmpEQ(currentMutations, initialMutations), WasNotMutatedBB, WasMutatedBB); @@ -791,8 +905,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ ConvertType(getContext().getObjCIdType()), "tmp"); CallArgList Args2; - Args2.push_back(std::make_pair(RValue::get(V), - getContext().getObjCIdType())); + Args2.add(RValue::get(V), getContext().getObjCIdType()); // FIXME: We shouldn't need to get the function info here, the runtime already // should have computed it to build the function. EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp index 5f19dc6e5647..c4dc4c41da6d 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This provides Objective-C code generation targetting the GNU runtime. The +// This provides Objective-C code generation targeting the GNU runtime. The // class in this file generates structures used by the GNU Objective-C runtime // library. These structures are defined in objc/objc.h and objc/objc-api.h in // the GNU runtime distribution. @@ -24,90 +24,342 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtObjC.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/FileManager.h" #include "llvm/Intrinsics.h" #include "llvm/Module.h" #include "llvm/LLVMContext.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/Compiler.h" #include "llvm/Target/TargetData.h" -#include +#include using namespace clang; using namespace CodeGen; using llvm::dyn_cast; -// The version of the runtime that this class targets. Must match the version -// in the runtime. -static const int RuntimeVersion = 8; -static const int NonFragileRuntimeVersion = 9; -static const int ProtocolVersion = 2; -static const int NonFragileProtocolVersion = 3; namespace { -class CGObjCGNU : public CodeGen::CGObjCRuntime { -private: - CodeGen::CodeGenModule &CGM; +/// Class that lazily initialises the runtime function. Avoids inserting the +/// types and the function declaration into a module if they're not used, and +/// avoids constructing the type more than once if it's used more than once. +class LazyRuntimeFunction { + CodeGenModule *CGM; + std::vector ArgTys; + const char *FunctionName; + llvm::Function *Function; + public: + /// Constructor leaves this class uninitialized, because it is intended to + /// be used as a field in another class and not all of the types that are + /// used as arguments will necessarily be available at construction time. + LazyRuntimeFunction() : CGM(0), FunctionName(0), Function(0) {} + + /// Initialises the lazy function with the name, return type, and the types + /// of the arguments. + END_WITH_NULL + void init(CodeGenModule *Mod, const char *name, + const llvm::Type *RetTy, ...) { + CGM =Mod; + FunctionName = name; + Function = 0; + ArgTys.clear(); + va_list Args; + va_start(Args, RetTy); + while (const llvm::Type *ArgTy = va_arg(Args, const llvm::Type*)) + ArgTys.push_back(ArgTy); + va_end(Args); + // Push the return type on at the end so we can pop it off easily + ArgTys.push_back(RetTy); + } + /// Overloaded cast operator, allows the class to be implicitly cast to an + /// LLVM constant. + operator llvm::Function*() { + if (!Function) { + if (0 == FunctionName) return 0; + // We put the return type on the end of the vector, so pop it back off + const llvm::Type *RetTy = ArgTys.back(); + ArgTys.pop_back(); + llvm::FunctionType *FTy = llvm::FunctionType::get(RetTy, ArgTys, false); + Function = + cast(CGM->CreateRuntimeFunction(FTy, FunctionName)); + // We won't need to use the types again, so we may as well clean up the + // vector now + ArgTys.resize(0); + } + return Function; + } +}; + + +/// GNU Objective-C runtime code generation. This class implements the parts of +/// Objective-C support that are specific to the GNU family of runtimes (GCC and +/// GNUstep). +class CGObjCGNU : public CGObjCRuntime { +protected: + /// The module that is using this class + CodeGenModule &CGM; + /// The LLVM module into which output is inserted llvm::Module &TheModule; + /// strut objc_super. Used for sending messages to super. This structure + /// contains the receiver (object) and the expected class. + const llvm::StructType *ObjCSuperTy; + /// struct objc_super*. The type of the argument to the superclass message + /// lookup functions. + const llvm::PointerType *PtrToObjCSuperTy; + /// LLVM type for selectors. Opaque pointer (i8*) unless a header declaring + /// SEL is included in a header somewhere, in which case it will be whatever + /// type is declared in that header, most likely {i8*, i8*}. const llvm::PointerType *SelectorTy; + /// LLVM i8 type. Cached here to avoid repeatedly getting it in all of the + /// places where it's used const llvm::IntegerType *Int8Ty; + /// Pointer to i8 - LLVM type of char*, for all of the places where the + /// runtime needs to deal with C strings. const llvm::PointerType *PtrToInt8Ty; - const llvm::FunctionType *IMPTy; + /// Instance Method Pointer type. This is a pointer to a function that takes, + /// at a minimum, an object and a selector, and is the generic type for + /// Objective-C methods. Due to differences between variadic / non-variadic + /// calling conventions, it must always be cast to the correct type before + /// actually being used. + const llvm::PointerType *IMPTy; + /// Type of an untyped Objective-C object. Clang treats id as a built-in type + /// when compiling Objective-C code, so this may be an opaque pointer (i8*), + /// but if the runtime header declaring it is included then it may be a + /// pointer to a structure. const llvm::PointerType *IdTy; + /// Pointer to a pointer to an Objective-C object. Used in the new ABI + /// message lookup function and some GC-related functions. const llvm::PointerType *PtrToIdTy; + /// The clang type of id. Used when using the clang CGCall infrastructure to + /// call Objective-C methods. CanQualType ASTIdTy; + /// LLVM type for C int type. const llvm::IntegerType *IntTy; + /// LLVM type for an opaque pointer. This is identical to PtrToInt8Ty, but is + /// used in the code to document the difference between i8* meaning a pointer + /// to a C string and i8* meaning a pointer to some opaque type. const llvm::PointerType *PtrTy; + /// LLVM type for C long type. The runtime uses this in a lot of places where + /// it should be using intptr_t, but we can't fix this without breaking + /// compatibility with GCC... const llvm::IntegerType *LongTy; + /// LLVM type for C size_t. Used in various runtime data structures. const llvm::IntegerType *SizeTy; + /// LLVM type for C ptrdiff_t. Mainly used in property accessor functions. const llvm::IntegerType *PtrDiffTy; + /// LLVM type for C int*. Used for GCC-ABI-compatible non-fragile instance + /// variables. const llvm::PointerType *PtrToIntTy; + /// LLVM type for Objective-C BOOL type. const llvm::Type *BoolTy; - llvm::GlobalAlias *ClassPtrAlias; - llvm::GlobalAlias *MetaClassPtrAlias; - std::vector Classes; - std::vector Categories; - std::vector ConstantStrings; - llvm::StringMap ObjCStrings; - llvm::Function *LoadFunction; - llvm::StringMap ExistingProtocols; - typedef std::pair TypedSelector; - std::map TypedSelectors; - llvm::StringMap UntypedSelectors; - // Selectors that we don't emit in GC mode - Selector RetainSel, ReleaseSel, AutoreleaseSel; - // Functions used for GC. - llvm::Constant *IvarAssignFn, *StrongCastAssignFn, *MemMoveFn, *WeakReadFn, - *WeakAssignFn, *GlobalAssignFn; + /// Metadata kind used to tie method lookups to message sends. The GNUstep + /// runtime provides some LLVM passes that can use this to do things like + /// automatic IMP caching and speculative inlining. + unsigned msgSendMDKind; + /// Helper function that generates a constant string and returns a pointer to + /// the start of the string. The result of this function can be used anywhere + /// where the C code specifies const char*. + llvm::Constant *MakeConstantString(const std::string &Str, + const std::string &Name="") { + llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str()); + return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); + } + /// Emits a linkonce_odr string, whose name is the prefix followed by the + /// string value. This allows the linker to combine the strings between + /// different modules. Used for EH typeinfo names, selector strings, and a + /// few other things. + llvm::Constant *ExportUniqueString(const std::string &Str, + const std::string prefix) { + std::string name = prefix + Str; + llvm::Constant *ConstStr = TheModule.getGlobalVariable(name); + if (!ConstStr) { + llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true); + ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true, + llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str); + } + return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); + } + /// Generates a global structure, initialized by the elements in the vector. + /// The element types must match the types of the structure elements in the + /// first argument. + llvm::GlobalVariable *MakeGlobal(const llvm::StructType *Ty, + std::vector &V, + llvm::StringRef Name="", + llvm::GlobalValue::LinkageTypes linkage + =llvm::GlobalValue::InternalLinkage) { + llvm::Constant *C = llvm::ConstantStruct::get(Ty, V); + return new llvm::GlobalVariable(TheModule, Ty, false, + linkage, C, Name); + } + /// Generates a global array. The vector must contain the same number of + /// elements that the array type declares, of the type specified as the array + /// element type. + llvm::GlobalVariable *MakeGlobal(const llvm::ArrayType *Ty, + std::vector &V, + llvm::StringRef Name="", + llvm::GlobalValue::LinkageTypes linkage + =llvm::GlobalValue::InternalLinkage) { + llvm::Constant *C = llvm::ConstantArray::get(Ty, V); + return new llvm::GlobalVariable(TheModule, Ty, false, + linkage, C, Name); + } + /// Generates a global array, inferring the array type from the specified + /// element type and the size of the initialiser. + llvm::GlobalVariable *MakeGlobalArray(const llvm::Type *Ty, + std::vector &V, + llvm::StringRef Name="", + llvm::GlobalValue::LinkageTypes linkage + =llvm::GlobalValue::InternalLinkage) { + llvm::ArrayType *ArrayTy = llvm::ArrayType::get(Ty, V.size()); + return MakeGlobal(ArrayTy, V, Name, linkage); + } + /// Ensures that the value has the required type, by inserting a bitcast if + /// required. This function lets us avoid inserting bitcasts that are + /// redundant. + llvm::Value* EnforceType(CGBuilderTy B, llvm::Value *V, const llvm::Type *Ty){ + if (V->getType() == Ty) return V; + return B.CreateBitCast(V, Ty); + } // Some zeros used for GEPs in lots of places. llvm::Constant *Zeros[2]; + /// Null pointer value. Mainly used as a terminator in various arrays. llvm::Constant *NULLPtr; + /// LLVM context. llvm::LLVMContext &VMContext; - /// Metadata kind used to tie method lookups to message sends. - unsigned msgSendMDKind; private: + /// Placeholder for the class. Lots of things refer to the class before we've + /// actually emitted it. We use this alias as a placeholder, and then replace + /// it with a pointer to the class structure before finally emitting the + /// module. + llvm::GlobalAlias *ClassPtrAlias; + /// Placeholder for the metaclass. Lots of things refer to the class before + /// we've / actually emitted it. We use this alias as a placeholder, and then + /// replace / it with a pointer to the metaclass structure before finally + /// emitting the / module. + llvm::GlobalAlias *MetaClassPtrAlias; + /// All of the classes that have been generated for this compilation units. + std::vector Classes; + /// All of the categories that have been generated for this compilation units. + std::vector Categories; + /// All of the Objective-C constant strings that have been generated for this + /// compilation units. + std::vector ConstantStrings; + /// Map from string values to Objective-C constant strings in the output. + /// Used to prevent emitting Objective-C strings more than once. This should + /// not be required at all - CodeGenModule should manage this list. + llvm::StringMap ObjCStrings; + /// All of the protocols that have been declared. + llvm::StringMap ExistingProtocols; + /// For each variant of a selector, we store the type encoding and a + /// placeholder value. For an untyped selector, the type will be the empty + /// string. Selector references are all done via the module's selector table, + /// so we create an alias as a placeholder and then replace it with the real + /// value later. + typedef std::pair TypedSelector; + /// Type of the selector map. This is roughly equivalent to the structure + /// used in the GNUstep runtime, which maintains a list of all of the valid + /// types for a selector in a table. + typedef llvm::DenseMap > + SelectorMap; + /// A map from selectors to selector types. This allows us to emit all + /// selectors of the same name and type together. + SelectorMap SelectorTable; + + /// Selectors related to memory management. When compiling in GC mode, we + /// omit these. + Selector RetainSel, ReleaseSel, AutoreleaseSel; + /// Runtime functions used for memory management in GC mode. Note that clang + /// supports code generation for calling these functions, but neither GNU + /// runtime actually supports this API properly yet. + LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn, + WeakAssignFn, GlobalAssignFn; + +protected: + /// Function used for throwing Objective-C exceptions. + LazyRuntimeFunction ExceptionThrowFn; + /// Function used for rethrowing exceptions, used at the end of @finally or + /// @synchronize blocks. + LazyRuntimeFunction ExceptionReThrowFn; + /// Function called when entering a catch function. This is required for + /// differentiating Objective-C exceptions and foreign exceptions. + LazyRuntimeFunction EnterCatchFn; + /// Function called when exiting from a catch block. Used to do exception + /// cleanup. + LazyRuntimeFunction ExitCatchFn; + /// Function called when entering an @synchronize block. Acquires the lock. + LazyRuntimeFunction SyncEnterFn; + /// Function called when exiting an @synchronize block. Releases the lock. + LazyRuntimeFunction SyncExitFn; + +private: + + /// Function called if fast enumeration detects that the collection is + /// modified during the update. + LazyRuntimeFunction EnumerationMutationFn; + /// Function for implementing synthesized property getters that return an + /// object. + LazyRuntimeFunction GetPropertyFn; + /// Function for implementing synthesized property setters that return an + /// object. + LazyRuntimeFunction SetPropertyFn; + /// Function used for non-object declared property getters. + LazyRuntimeFunction GetStructPropertyFn; + /// Function used for non-object declared property setters. + LazyRuntimeFunction SetStructPropertyFn; + + /// The version of the runtime that this class targets. Must match the + /// version in the runtime. + const int RuntimeVersion; + /// The version of the protocol class. Used to differentiate between ObjC1 + /// and ObjC2 protocols. Objective-C 1 protocols can not contain optional + /// components and can not contain declared properties. We always emit + /// Objective-C 2 property structures, but we have to pretend that they're + /// Objective-C 1 property structures when targeting the GCC runtime or it + /// will abort. + const int ProtocolVersion; +private: + /// Generates an instance variable list structure. This is a structure + /// containing a size and an array of structures containing instance variable + /// metadata. This is used purely for introspection in the fragile ABI. In + /// the non-fragile ABI, it's used for instance variable fixup. llvm::Constant *GenerateIvarList( const llvm::SmallVectorImpl &IvarNames, const llvm::SmallVectorImpl &IvarTypes, const llvm::SmallVectorImpl &IvarOffsets); - llvm::Constant *GenerateMethodList(const std::string &ClassName, - const std::string &CategoryName, + /// Generates a method list structure. This is a structure containing a size + /// and an array of structures containing method metadata. + /// + /// This structure is used by both classes and categories, and contains a next + /// pointer allowing them to be chained together in a linked list. + llvm::Constant *GenerateMethodList(const llvm::StringRef &ClassName, + const llvm::StringRef &CategoryName, const llvm::SmallVectorImpl &MethodSels, const llvm::SmallVectorImpl &MethodTypes, bool isClassMethodList); + /// Emits an empty protocol. This is used for @protocol() where no protocol + /// is found. The runtime will (hopefully) fix up the pointer to refer to the + /// real protocol. llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName); + /// Generates a list of property metadata structures. This follows the same + /// pattern as method and instance variable metadata lists. llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID, llvm::SmallVectorImpl &InstanceMethodSels, llvm::SmallVectorImpl &InstanceMethodTypes); + /// Generates a list of referenced protocols. Classes, categories, and + /// protocols all use this structure. llvm::Constant *GenerateProtocolList( const llvm::SmallVectorImpl &Protocols); - // To ensure that all protocols are seen by the runtime, we add a category on - // a class defined in the runtime, declaring no methods, but adopting the - // protocols. + /// To ensure that all protocols are seen by the runtime, we add a category on + /// a class defined in the runtime, declaring no methods, but adopting the + /// protocols. This is a horribly ugly hack, but it allows us to collect all + /// of the protocols without changing the ABI. void GenerateProtocolHolderCategory(void); + /// Generates a class structure. llvm::Constant *GenerateClassStructure( llvm::Constant *MetaClass, llvm::Constant *SuperClass, @@ -121,31 +373,43 @@ class CGObjCGNU : public CodeGen::CGObjCRuntime { llvm::Constant *IvarOffsets, llvm::Constant *Properties, bool isMeta=false); + /// Generates a method list. This is used by protocols to define the required + /// and optional methods. llvm::Constant *GenerateProtocolMethodList( const llvm::SmallVectorImpl &MethodNames, const llvm::SmallVectorImpl &MethodTypes); - llvm::Constant *MakeConstantString(const std::string &Str, const std::string - &Name=""); - llvm::Constant *ExportUniqueString(const std::string &Str, const std::string - prefix); - llvm::Constant *MakeGlobal(const llvm::StructType *Ty, - std::vector &V, llvm::StringRef Name="", - llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage); - llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty, - std::vector &V, llvm::StringRef Name="", - llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage); + /// Returns a selector with the specified type encoding. An empty string is + /// used to return an untyped selector (with the types field set to NULL). + llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel, + const std::string &TypeEncoding, bool lval); + /// Returns the variable used to store the offset of an instance variable. llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, const ObjCIvarDecl *Ivar); + /// Emits a reference to a class. This allows the linker to object if there + /// is no class of the matching name. void EmitClassRef(const std::string &className); - llvm::Value* EnforceType(CGBuilderTy B, llvm::Value *V, const llvm::Type *Ty){ - if (V->getType() == Ty) return V; - return B.CreateBitCast(V, Ty); - } +protected: + /// Looks up the method for sending a message to the specified object. This + /// mechanism differs between the GCC and GNU runtimes, so this method must be + /// overridden in subclasses. + virtual llvm::Value *LookupIMP(CodeGenFunction &CGF, + llvm::Value *&Receiver, + llvm::Value *cmd, + llvm::MDNode *node) = 0; + /// Looks up the method for sending a message to a superclass. This mechanism + /// differs between the GCC and GNU runtimes, so this method must be + /// overridden in subclasses. + virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, + llvm::Value *ObjCSuper, + llvm::Value *cmd) = 0; public: - CGObjCGNU(CodeGen::CodeGenModule &cgm); + CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, + unsigned protocolClassVersion); + virtual llvm::Constant *GenerateConstantString(const StringLiteral *); - virtual CodeGen::RValue - GenerateMessageSend(CodeGen::CodeGenFunction &CGF, + + virtual RValue + GenerateMessageSend(CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, Selector Sel, @@ -153,8 +417,8 @@ class CGObjCGNU : public CodeGen::CGObjCRuntime { const CallArgList &CallArgs, const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method); - virtual CodeGen::RValue - GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, + virtual RValue + GenerateMessageSendSuper(CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, Selector Sel, @@ -186,41 +450,174 @@ class CGObjCGNU : public CodeGen::CGObjCRuntime { virtual llvm::Function *GetGetStructFunction(); virtual llvm::Constant *EnumerationMutationFunction(); - virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF, + virtual void EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S); - virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, + virtual void EmitSynchronizedStmt(CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S); - virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, + virtual void EmitThrowStmt(CodeGenFunction &CGF, const ObjCAtThrowStmt &S); - virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, + virtual llvm::Value * EmitObjCWeakRead(CodeGenFunction &CGF, llvm::Value *AddrWeakObj); - virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, + virtual void EmitObjCWeakAssign(CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst); - virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, + virtual void EmitObjCGlobalAssign(CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest, bool threadlocal=false); - virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, + virtual void EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest, llvm::Value *ivarOffset); - virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, + virtual void EmitObjCStrongCastAssign(CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest); - virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, + virtual void EmitGCMemmoveCollectable(CodeGenFunction &CGF, llvm::Value *DestPtr, llvm::Value *SrcPtr, llvm::Value *Size); - virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, + virtual LValue EmitObjCValueForIvar(CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers); - virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, + virtual llvm::Value *EmitIvarOffset(CodeGenFunction &CGF, const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); - virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, + virtual llvm::Constant *BuildGCBlockLayout(CodeGenModule &CGM, const CGBlockInfo &blockInfo) { return NULLPtr; } }; +/// Class representing the legacy GCC Objective-C ABI. This is the default when +/// -fobjc-nonfragile-abi is not specified. +/// +/// The GCC ABI target actually generates code that is approximately compatible +/// with the new GNUstep runtime ABI, but refrains from using any features that +/// would not work with the GCC runtime. For example, clang always generates +/// the extended form of the class structure, and the extra fields are simply +/// ignored by GCC libobjc. +class CGObjCGCC : public CGObjCGNU { + /// The GCC ABI message lookup function. Returns an IMP pointing to the + /// method implementation for this message. + LazyRuntimeFunction MsgLookupFn; + /// The GCC ABI superclass message lookup function. Takes a pointer to a + /// structure describing the receiver and the class, and a selector as + /// arguments. Returns the IMP for the corresponding method. + LazyRuntimeFunction MsgLookupSuperFn; +protected: + virtual llvm::Value *LookupIMP(CodeGenFunction &CGF, + llvm::Value *&Receiver, + llvm::Value *cmd, + llvm::MDNode *node) { + CGBuilderTy &Builder = CGF.Builder; + llvm::Value *imp = Builder.CreateCall2(MsgLookupFn, + EnforceType(Builder, Receiver, IdTy), + EnforceType(Builder, cmd, SelectorTy)); + cast(imp)->setMetadata(msgSendMDKind, node); + return imp; + } + virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, + llvm::Value *ObjCSuper, + llvm::Value *cmd) { + CGBuilderTy &Builder = CGF.Builder; + llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper, + PtrToObjCSuperTy), cmd}; + return Builder.CreateCall(MsgLookupSuperFn, lookupArgs, lookupArgs+2); + } + public: + CGObjCGCC(CodeGenModule &Mod) : CGObjCGNU(Mod, 8, 2) { + // IMP objc_msg_lookup(id, SEL); + MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, NULL); + // IMP objc_msg_lookup_super(struct objc_super*, SEL); + MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy, + PtrToObjCSuperTy, SelectorTy, NULL); + } +}; +/// Class used when targeting the new GNUstep runtime ABI. +class CGObjCGNUstep : public CGObjCGNU { + /// The slot lookup function. Returns a pointer to a cacheable structure + /// that contains (among other things) the IMP. + LazyRuntimeFunction SlotLookupFn; + /// The GNUstep ABI superclass message lookup function. Takes a pointer to + /// a structure describing the receiver and the class, and a selector as + /// arguments. Returns the slot for the corresponding method. Superclass + /// message lookup rarely changes, so this is a good caching opportunity. + LazyRuntimeFunction SlotLookupSuperFn; + /// Type of an slot structure pointer. This is returned by the various + /// lookup functions. + llvm::Type *SlotTy; + protected: + virtual llvm::Value *LookupIMP(CodeGenFunction &CGF, + llvm::Value *&Receiver, + llvm::Value *cmd, + llvm::MDNode *node) { + CGBuilderTy &Builder = CGF.Builder; + llvm::Function *LookupFn = SlotLookupFn; + + // Store the receiver on the stack so that we can reload it later + llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType()); + Builder.CreateStore(Receiver, ReceiverPtr); + + llvm::Value *self; + + if (isa(CGF.CurCodeDecl)) { + self = CGF.LoadObjCSelf(); + } else { + self = llvm::ConstantPointerNull::get(IdTy); + } + + // The lookup function is guaranteed not to capture the receiver pointer. + LookupFn->setDoesNotCapture(1); + + llvm::CallInst *slot = + Builder.CreateCall3(LookupFn, + EnforceType(Builder, ReceiverPtr, PtrToIdTy), + EnforceType(Builder, cmd, SelectorTy), + EnforceType(Builder, self, IdTy)); + slot->setOnlyReadsMemory(); + slot->setMetadata(msgSendMDKind, node); + + // Load the imp from the slot + llvm::Value *imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4)); + + // The lookup function may have changed the receiver, so make sure we use + // the new one. + Receiver = Builder.CreateLoad(ReceiverPtr, true); + return imp; + } + virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, + llvm::Value *ObjCSuper, + llvm::Value *cmd) { + CGBuilderTy &Builder = CGF.Builder; + llvm::Value *lookupArgs[] = {ObjCSuper, cmd}; + + llvm::CallInst *slot = Builder.CreateCall(SlotLookupSuperFn, lookupArgs, + lookupArgs+2); + slot->setOnlyReadsMemory(); + + return Builder.CreateLoad(Builder.CreateStructGEP(slot, 4)); + } + public: + CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNU(Mod, 9, 3) { + llvm::StructType *SlotStructTy = llvm::StructType::get(VMContext, PtrTy, + PtrTy, PtrTy, IntTy, IMPTy, NULL); + SlotTy = llvm::PointerType::getUnqual(SlotStructTy); + // Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender); + SlotLookupFn.init(&CGM, "objc_msg_lookup_sender", SlotTy, PtrToIdTy, + SelectorTy, IdTy, NULL); + // Slot_t objc_msg_lookup_super(struct objc_super*, SEL); + SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy, + PtrToObjCSuperTy, SelectorTy, NULL); + // If we're in ObjC++ mode, then we want to make + if (CGM.getLangOptions().CPlusPlus) { + const llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); + // void *__cxa_begin_catch(void *e) + EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy, NULL); + // void __cxa_end_catch(void) + EnterCatchFn.init(&CGM, "__cxa_end_catch", VoidTy, NULL); + // void _Unwind_Resume_or_Rethrow(void*) + ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy, PtrTy, NULL); + } + } +}; + } // end anonymous namespace @@ -242,45 +639,34 @@ void CGObjCGNU::EmitClassRef(const std::string &className) { llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef); } -static std::string SymbolNameForMethod(const std::string &ClassName, const - std::string &CategoryName, const std::string &MethodName, bool isClassMethod) -{ - std::string MethodNameColonStripped = MethodName; +static std::string SymbolNameForMethod(const llvm::StringRef &ClassName, + const llvm::StringRef &CategoryName, const Selector MethodName, + bool isClassMethod) { + std::string MethodNameColonStripped = MethodName.getAsString(); std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(), ':', '_'); - return std::string(isClassMethod ? "_c_" : "_i_") + ClassName + "_" + - CategoryName + "_" + MethodNameColonStripped; -} -static std::string MangleSelectorTypes(const std::string &TypeString) { - std::string Mangled = TypeString; - // Simple mangling to avoid breaking when we mix JIT / static code. - // Not part of the ABI, subject to change without notice. - std::replace(Mangled.begin(), Mangled.end(), '@', '_'); - std::replace(Mangled.begin(), Mangled.end(), ':', 'J'); - std::replace(Mangled.begin(), Mangled.end(), '*', 'e'); - std::replace(Mangled.begin(), Mangled.end(), '#', 'E'); - std::replace(Mangled.begin(), Mangled.end(), ':', 'j'); - std::replace(Mangled.begin(), Mangled.end(), '(', 'g'); - std::replace(Mangled.begin(), Mangled.end(), ')', 'G'); - std::replace(Mangled.begin(), Mangled.end(), '[', 'h'); - std::replace(Mangled.begin(), Mangled.end(), ']', 'H'); - return Mangled; + return (llvm::Twine(isClassMethod ? "_c_" : "_i_") + ClassName + "_" + + CategoryName + "_" + MethodNameColonStripped).str(); } -CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm) - : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0), - MetaClassPtrAlias(0), VMContext(cgm.getLLVMContext()) { +CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, + unsigned protocolClassVersion) + : CGM(cgm), TheModule(CGM.getModule()), VMContext(cgm.getLLVMContext()), + ClassPtrAlias(0), MetaClassPtrAlias(0), RuntimeVersion(runtimeABIVersion), + ProtocolVersion(protocolClassVersion) { + msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend"); + CodeGenTypes &Types = CGM.getTypes(); IntTy = cast( - CGM.getTypes().ConvertType(CGM.getContext().IntTy)); + Types.ConvertType(CGM.getContext().IntTy)); LongTy = cast( - CGM.getTypes().ConvertType(CGM.getContext().LongTy)); + Types.ConvertType(CGM.getContext().LongTy)); SizeTy = cast( - CGM.getTypes().ConvertType(CGM.getContext().getSizeType())); + Types.ConvertType(CGM.getContext().getSizeType())); PtrDiffTy = cast( - CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType())); + Types.ConvertType(CGM.getContext().getPointerDiffType())); BoolTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy); Int8Ty = llvm::Type::getInt8Ty(VMContext); @@ -302,20 +688,54 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm) PtrTy = PtrToInt8Ty; // Object type - ASTIdTy = CGM.getContext().getCanonicalType(CGM.getContext().getObjCIdType()); - if (QualType() == ASTIdTy) { - IdTy = PtrToInt8Ty; - } else { + QualType UnqualIdTy = CGM.getContext().getObjCIdType(); + ASTIdTy = CanQualType(); + if (UnqualIdTy != QualType()) { + ASTIdTy = CGM.getContext().getCanonicalType(UnqualIdTy); IdTy = cast(CGM.getTypes().ConvertType(ASTIdTy)); + } else { + IdTy = PtrToInt8Ty; } PtrToIdTy = llvm::PointerType::getUnqual(IdTy); + ObjCSuperTy = llvm::StructType::get(VMContext, IdTy, IdTy, NULL); + PtrToObjCSuperTy = llvm::PointerType::getUnqual(ObjCSuperTy); + + const llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); + + // void objc_exception_throw(id); + ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy, NULL); + ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy, NULL); + // int objc_sync_enter(id); + SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy, NULL); + // int objc_sync_exit(id); + SyncExitFn.init(&CGM, "objc_sync_exit", IntTy, IdTy, NULL); + + // void objc_enumerationMutation (id) + EnumerationMutationFn.init(&CGM, "objc_enumerationMutation", VoidTy, + IdTy, NULL); + + // id objc_getProperty(id, SEL, ptrdiff_t, BOOL) + GetPropertyFn.init(&CGM, "objc_getProperty", IdTy, IdTy, SelectorTy, + PtrDiffTy, BoolTy, NULL); + // void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, BOOL) + SetPropertyFn.init(&CGM, "objc_setProperty", VoidTy, IdTy, SelectorTy, + PtrDiffTy, IdTy, BoolTy, BoolTy, NULL); + // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL) + GetStructPropertyFn.init(&CGM, "objc_getPropertyStruct", VoidTy, PtrTy, PtrTy, + PtrDiffTy, BoolTy, BoolTy, NULL); + // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL) + SetStructPropertyFn.init(&CGM, "objc_setPropertyStruct", VoidTy, PtrTy, PtrTy, + PtrDiffTy, BoolTy, BoolTy, NULL); + // IMP type std::vector IMPArgs; IMPArgs.push_back(IdTy); IMPArgs.push_back(SelectorTy); - IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true); + IMPTy = llvm::PointerType::getUnqual(llvm::FunctionType::get(IdTy, IMPArgs, + true)); + // Don't bother initialising the GC stuff unless we're compiling in GC mode if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { // Get selectors needed in GC mode RetainSel = GetNullarySelector("retain", CGM.getContext()); @@ -325,34 +745,21 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm) // Get functions needed in GC mode // id objc_assign_ivar(id, id, ptrdiff_t); - std::vector Args(1, IdTy); - Args.push_back(PtrToIdTy); - Args.push_back(PtrDiffTy); - llvm::FunctionType *FTy = llvm::FunctionType::get(IdTy, Args, false); - IvarAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); + IvarAssignFn.init(&CGM, "objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy, + NULL); // id objc_assign_strongCast (id, id*) - Args.pop_back(); - FTy = llvm::FunctionType::get(IdTy, Args, false); - StrongCastAssignFn = - CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); + StrongCastAssignFn.init(&CGM, "objc_assign_strongCast", IdTy, IdTy, + PtrToIdTy, NULL); // id objc_assign_global(id, id*); - FTy = llvm::FunctionType::get(IdTy, Args, false); - GlobalAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); + GlobalAssignFn.init(&CGM, "objc_assign_global", IdTy, IdTy, PtrToIdTy, + NULL); // id objc_assign_weak(id, id*); - FTy = llvm::FunctionType::get(IdTy, Args, false); - WeakAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); + WeakAssignFn.init(&CGM, "objc_assign_weak", IdTy, IdTy, PtrToIdTy, NULL); // id objc_read_weak(id*); - Args.clear(); - Args.push_back(PtrToIdTy); - FTy = llvm::FunctionType::get(IdTy, Args, false); - WeakReadFn = CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); + WeakReadFn.init(&CGM, "objc_read_weak", IdTy, PtrToIdTy, NULL); // void *objc_memmove_collectable(void*, void *, size_t); - Args.clear(); - Args.push_back(PtrToInt8Ty); - Args.push_back(PtrToInt8Ty); - Args.push_back(SizeTy); - FTy = llvm::FunctionType::get(IdTy, Args, false); - MemMoveFn = CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); + MemMoveFn.init(&CGM, "objc_memmove_collectable", PtrTy, PtrTy, PtrTy, + SizeTy, NULL); } } @@ -377,80 +784,128 @@ llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder, return Builder.CreateCall(ClassLookupFn, ClassName); } +llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel, + const std::string &TypeEncoding, bool lval) { + + llvm::SmallVector &Types = SelectorTable[Sel]; + llvm::GlobalAlias *SelValue = 0; + + + for (llvm::SmallVectorImpl::iterator i = Types.begin(), + e = Types.end() ; i!=e ; i++) { + if (i->first == TypeEncoding) { + SelValue = i->second; + break; + } + } + if (0 == SelValue) { + SelValue = new llvm::GlobalAlias(SelectorTy, + llvm::GlobalValue::PrivateLinkage, + ".objc_selector_"+Sel.getAsString(), NULL, + &TheModule); + Types.push_back(TypedSelector(TypeEncoding, SelValue)); + } + + if (lval) { + llvm::Value *tmp = Builder.CreateAlloca(SelValue->getType()); + Builder.CreateStore(SelValue, tmp); + return tmp; + } + return SelValue; +} + llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel, bool lval) { - llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()]; - if (US == 0) - US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy), - llvm::GlobalValue::PrivateLinkage, - ".objc_untyped_selector_alias"+Sel.getAsString(), - NULL, &TheModule); - if (lval) - return US; - return Builder.CreateLoad(US); + return GetSelector(Builder, Sel, std::string(), lval); } llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl *Method) { - - std::string SelName = Method->getSelector().getAsString(); std::string SelTypes; CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes); - // Typed selectors - TypedSelector Selector = TypedSelector(SelName, - SelTypes); - - // If it's already cached, return it. - if (TypedSelectors[Selector]) { - return Builder.CreateLoad(TypedSelectors[Selector]); - } - - // If it isn't, cache it. - llvm::GlobalAlias *Sel = new llvm::GlobalAlias( - llvm::PointerType::getUnqual(SelectorTy), - llvm::GlobalValue::PrivateLinkage, ".objc_selector_alias" + SelName, - NULL, &TheModule); - TypedSelectors[Selector] = Sel; - - return Builder.CreateLoad(Sel); + return GetSelector(Builder, Method->getSelector(), SelTypes, false); } llvm::Constant *CGObjCGNU::GetEHType(QualType T) { - llvm_unreachable("asking for catch type for ObjC type in GNU runtime"); - return 0; -} + if (!CGM.getLangOptions().CPlusPlus) { + if (T->isObjCIdType() + || T->isObjCQualifiedIdType()) { + // With the old ABI, there was only one kind of catchall, which broke + // foreign exceptions. With the new ABI, we use __objc_id_typeinfo as + // a pointer indicating object catchalls, and NULL to indicate real + // catchalls + if (CGM.getLangOptions().ObjCNonFragileABI) { + return MakeConstantString("@id"); + } else { + return 0; + } + } -llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str, - const std::string &Name) { - llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str()); - return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); -} -llvm::Constant *CGObjCGNU::ExportUniqueString(const std::string &Str, - const std::string prefix) { - std::string name = prefix + Str; - llvm::Constant *ConstStr = TheModule.getGlobalVariable(name); - if (!ConstStr) { - llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true); - ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true, - llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str); + // All other types should be Objective-C interface pointer types. + const ObjCObjectPointerType *OPT = + T->getAs(); + assert(OPT && "Invalid @catch type."); + const ObjCInterfaceDecl *IDecl = + OPT->getObjectType()->getInterface(); + assert(IDecl && "Invalid @catch type."); + return MakeConstantString(IDecl->getIdentifier()->getName()); } - return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); -} + // For Objective-C++, we want to provide the ability to catch both C++ and + // Objective-C objects in the same function. -llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty, - std::vector &V, llvm::StringRef Name, - llvm::GlobalValue::LinkageTypes linkage) { - llvm::Constant *C = llvm::ConstantStruct::get(Ty, V); - return new llvm::GlobalVariable(TheModule, Ty, false, - linkage, C, Name); -} + // There's a particular fixed type info for 'id'. + if (T->isObjCIdType() || + T->isObjCQualifiedIdType()) { + llvm::Constant *IDEHType = + CGM.getModule().getGlobalVariable("__objc_id_type_info"); + if (!IDEHType) + IDEHType = + new llvm::GlobalVariable(CGM.getModule(), PtrToInt8Ty, + false, + llvm::GlobalValue::ExternalLinkage, + 0, "__objc_id_type_info"); + return llvm::ConstantExpr::getBitCast(IDEHType, PtrToInt8Ty); + } -llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty, - std::vector &V, llvm::StringRef Name, - llvm::GlobalValue::LinkageTypes linkage) { - llvm::Constant *C = llvm::ConstantArray::get(Ty, V); - return new llvm::GlobalVariable(TheModule, Ty, false, - linkage, C, Name); + const ObjCObjectPointerType *PT = + T->getAs(); + assert(PT && "Invalid @catch type."); + const ObjCInterfaceType *IT = PT->getInterfaceType(); + assert(IT && "Invalid @catch type."); + std::string className = IT->getDecl()->getIdentifier()->getName(); + + std::string typeinfoName = "__objc_eh_typeinfo_" + className; + + // Return the existing typeinfo if it exists + llvm::Constant *typeinfo = TheModule.getGlobalVariable(typeinfoName); + if (typeinfo) return typeinfo; + + // Otherwise create it. + + // vtable for gnustep::libobjc::__objc_class_type_info + // It's quite ugly hard-coding this. Ideally we'd generate it using the host + // platform's name mangling. + const char *vtableName = "_ZTVN7gnustep7libobjc22__objc_class_type_infoE"; + llvm::Constant *Vtable = TheModule.getGlobalVariable(vtableName); + if (!Vtable) { + Vtable = new llvm::GlobalVariable(TheModule, PtrToInt8Ty, true, + llvm::GlobalValue::ExternalLinkage, 0, vtableName); + } + llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2); + Vtable = llvm::ConstantExpr::getGetElementPtr(Vtable, &Two, 1); + Vtable = llvm::ConstantExpr::getBitCast(Vtable, PtrToInt8Ty); + + llvm::Constant *typeName = + ExportUniqueString(className, "__objc_eh_typename_"); + + std::vector fields; + fields.push_back(Vtable); + fields.push_back(typeName); + llvm::Constant *TI = + MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, + NULL), fields, "__objc_eh_typeinfo_" + className, + llvm::GlobalValue::LinkOnceODRLinkage); + return llvm::ConstantExpr::getBitCast(TI, PtrToInt8Ty); } /// Generate an NSConstantString object. @@ -479,8 +934,8 @@ llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) { ///Generates a message send where the super is the receiver. This is a message ///send to self with special delivery semantics indicating which class's method ///should be called. -CodeGen::RValue -CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, +RValue +CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, Selector Sel, @@ -505,18 +960,13 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, CallArgList ActualArgs; - ActualArgs.push_back( - std::make_pair(RValue::get(Builder.CreateBitCast(Receiver, IdTy)), - ASTIdTy)); - ActualArgs.push_back(std::make_pair(RValue::get(cmd), - CGF.getContext().getObjCSelType())); + ActualArgs.add(RValue::get(EnforceType(Builder, Receiver, IdTy)), ASTIdTy); + ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType()); ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); CodeGenTypes &Types = CGM.getTypes(); const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, FunctionType::ExtInfo()); - const llvm::FunctionType *impType = - Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); llvm::Value *ReceiverClass = 0; if (isCategoryImpl) { @@ -570,43 +1020,20 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0)); Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1)); + ObjCSuper = EnforceType(Builder, ObjCSuper, PtrToObjCSuperTy); + const llvm::FunctionType *impType = + Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); + // Get the IMP - std::vector Params; - Params.push_back(llvm::PointerType::getUnqual(ObjCSuperTy)); - Params.push_back(SelectorTy); - - llvm::Value *lookupArgs[] = {ObjCSuper, cmd}; - llvm::Value *imp; - - if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { - // The lookup function returns a slot, which can be safely cached. - llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy, - IntTy, llvm::PointerType::getUnqual(impType), NULL); - - llvm::Constant *lookupFunction = - CGM.CreateRuntimeFunction(llvm::FunctionType::get( - llvm::PointerType::getUnqual(SlotTy), Params, true), - "objc_slot_lookup_super"); - - llvm::CallInst *slot = Builder.CreateCall(lookupFunction, lookupArgs, - lookupArgs+2); - slot->setOnlyReadsMemory(); - - imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4)); - } else { - llvm::Constant *lookupFunction = - CGM.CreateRuntimeFunction(llvm::FunctionType::get( - llvm::PointerType::getUnqual(impType), Params, true), - "objc_msg_lookup_super"); - imp = Builder.CreateCall(lookupFunction, lookupArgs, lookupArgs+2); - } + llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd); + imp = EnforceType(Builder, imp, llvm::PointerType::getUnqual(impType)); llvm::Value *impMD[] = { llvm::MDString::get(VMContext, Sel.getAsString()), llvm::MDString::get(VMContext, Class->getSuperClass()->getNameAsString()), llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsClassMessage) }; - llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD, 3); + llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD); llvm::Instruction *call; RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs, @@ -616,8 +1043,8 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, } /// Generate code for a message send expression. -CodeGen::RValue -CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, +RValue +CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, Selector Sel, @@ -646,11 +1073,10 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, // paragraph and insist on sending messages to nil that have structure // returns. With GCC, this generates a random return value (whatever happens // to be on the stack / in those registers at the time) on most platforms, - // and generates a SegV on SPARC. With LLVM it corrupts the stack. - bool isPointerSizedReturn = false; - if (ResultType->isAnyPointerType() || - ResultType->isIntegralOrEnumerationType() || ResultType->isVoidType()) - isPointerSizedReturn = true; + // and generates an illegal instruction trap on SPARC. With LLVM it corrupts + // the stack. + bool isPointerSizedReturn = (ResultType->isAnyPointerType() || + ResultType->isIntegralOrEnumerationType() || ResultType->isVoidType()); llvm::BasicBlock *startBB = 0; llvm::BasicBlock *messageBB = 0; @@ -673,13 +1099,22 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, cmd = GetSelector(Builder, Method); else cmd = GetSelector(Builder, Sel); - CallArgList ActualArgs; + cmd = EnforceType(Builder, cmd, SelectorTy); + Receiver = EnforceType(Builder, Receiver, IdTy); - Receiver = Builder.CreateBitCast(Receiver, IdTy); - ActualArgs.push_back( - std::make_pair(RValue::get(Receiver), ASTIdTy)); - ActualArgs.push_back(std::make_pair(RValue::get(cmd), - CGF.getContext().getObjCSelType())); + llvm::Value *impMD[] = { + llvm::MDString::get(VMContext, Sel.getAsString()), + llvm::MDString::get(VMContext, Class ? Class->getNameAsString() :""), + llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), Class!=0) + }; + llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD); + + // Get the IMP to call + llvm::Value *imp = LookupIMP(CGF, Receiver, cmd, node); + + CallArgList ActualArgs; + ActualArgs.add(RValue::get(Receiver), ASTIdTy); + ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType()); ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); CodeGenTypes &Types = CGM.getTypes(); @@ -687,72 +1122,12 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, FunctionType::ExtInfo()); const llvm::FunctionType *impType = Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); - - llvm::Value *impMD[] = { - llvm::MDString::get(VMContext, Sel.getAsString()), - llvm::MDString::get(VMContext, Class ? Class->getNameAsString() :""), - llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), Class!=0) - }; - llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD, 3); + imp = EnforceType(Builder, imp, llvm::PointerType::getUnqual(impType)); - llvm::Value *imp; // For sender-aware dispatch, we pass the sender as the third argument to a // lookup function. When sending messages from C code, the sender is nil. // objc_msg_lookup_sender(id *receiver, SEL selector, id sender); - if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { - - std::vector Params; - llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType()); - Builder.CreateStore(Receiver, ReceiverPtr); - Params.push_back(ReceiverPtr->getType()); - Params.push_back(SelectorTy); - llvm::Value *self; - - if (isa(CGF.CurCodeDecl)) { - self = CGF.LoadObjCSelf(); - } else { - self = llvm::ConstantPointerNull::get(IdTy); - } - - Params.push_back(self->getType()); - - // The lookup function returns a slot, which can be safely cached. - llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy, - IntTy, llvm::PointerType::getUnqual(impType), NULL); - llvm::Constant *lookupFunction = - CGM.CreateRuntimeFunction(llvm::FunctionType::get( - llvm::PointerType::getUnqual(SlotTy), Params, true), - "objc_msg_lookup_sender"); - - // The lookup function is guaranteed not to capture the receiver pointer. - if (llvm::Function *LookupFn = dyn_cast(lookupFunction)) { - LookupFn->setDoesNotCapture(1); - } - - llvm::CallInst *slot = - Builder.CreateCall3(lookupFunction, ReceiverPtr, cmd, self); - slot->setOnlyReadsMemory(); - slot->setMetadata(msgSendMDKind, node); - - imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4)); - - // The lookup function may have changed the receiver, so make sure we use - // the new one. - ActualArgs[0] = std::make_pair(RValue::get( - Builder.CreateLoad(ReceiverPtr, true)), ASTIdTy); - } else { - std::vector Params; - Params.push_back(Receiver->getType()); - Params.push_back(SelectorTy); - llvm::Constant *lookupFunction = - CGM.CreateRuntimeFunction(llvm::FunctionType::get( - llvm::PointerType::getUnqual(impType), Params, true), - "objc_msg_lookup"); - - imp = Builder.CreateCall2(lookupFunction, Receiver, cmd); - cast(imp)->setMetadata(msgSendMDKind, node); - } llvm::Instruction *call; RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs, 0, &call); @@ -765,13 +1140,13 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, CGF.EmitBlock(continueBB); if (msgRet.isScalar()) { llvm::Value *v = msgRet.getScalarVal(); - llvm::PHINode *phi = Builder.CreatePHI(v->getType()); + llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2); phi->addIncoming(v, messageBB); phi->addIncoming(llvm::Constant::getNullValue(v->getType()), startBB); msgRet = RValue::get(phi); } else if (msgRet.isAggregate()) { llvm::Value *v = msgRet.getAggregateAddr(); - llvm::PHINode *phi = Builder.CreatePHI(v->getType()); + llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2); const llvm::PointerType *RetTy = cast(v->getType()); llvm::AllocaInst *NullVal = CGF.CreateTempAlloca(RetTy->getElementType(), "null"); @@ -782,11 +1157,11 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, msgRet = RValue::getAggregate(phi); } else /* isComplex() */ { std::pair v = msgRet.getComplexVal(); - llvm::PHINode *phi = Builder.CreatePHI(v.first->getType()); + llvm::PHINode *phi = Builder.CreatePHI(v.first->getType(), 2); phi->addIncoming(v.first, messageBB); phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()), startBB); - llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType()); + llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType(), 2); phi2->addIncoming(v.second, messageBB); phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()), startBB); @@ -798,8 +1173,8 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, /// Generates a MethodList. Used in construction of a objc_class and /// objc_category structures. -llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName, - const std::string &CategoryName, +llvm::Constant *CGObjCGNU::GenerateMethodList(const llvm::StringRef &ClassName, + const llvm::StringRef &CategoryName, const llvm::SmallVectorImpl &MethodSels, const llvm::SmallVectorImpl &MethodTypes, bool isClassMethodList) { @@ -809,24 +1184,24 @@ llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName, llvm::StructType *ObjCMethodTy = llvm::StructType::get(VMContext, PtrToInt8Ty, // Really a selector, but the runtime creates it us. PtrToInt8Ty, // Method types - llvm::PointerType::getUnqual(IMPTy), //Method pointer + IMPTy, //Method pointer NULL); std::vector Methods; std::vector Elements; for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) { Elements.clear(); - if (llvm::Constant *Method = + llvm::Constant *Method = TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName, - MethodSels[i].getAsString(), - isClassMethodList))) { - llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString()); - Elements.push_back(C); - Elements.push_back(MethodTypes[i]); - Method = llvm::ConstantExpr::getBitCast(Method, - llvm::PointerType::getUnqual(IMPTy)); - Elements.push_back(Method); - Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements)); - } + MethodSels[i], + isClassMethodList)); + assert(Method && "Can't generate metadata for method that doesn't exist"); + llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString()); + Elements.push_back(C); + Elements.push_back(MethodTypes[i]); + Method = llvm::ConstantExpr::getBitCast(Method, + IMPTy); + Elements.push_back(Method); + Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements)); } // Array of method structures @@ -951,8 +1326,10 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( Elements.push_back(llvm::ConstantInt::get(LongTy, info)); if (isMeta) { llvm::TargetData td(&TheModule); - Elements.push_back(llvm::ConstantInt::get(LongTy, - td.getTypeSizeInBits(ClassTy)/8)); + Elements.push_back( + llvm::ConstantInt::get(LongTy, + td.getTypeSizeInBits(ClassTy) / + CGM.getContext().getCharWidth())); } else Elements.push_back(InstanceSize); Elements.push_back(IVars); @@ -1063,10 +1440,9 @@ llvm::Constant *CGObjCGNU::GenerateEmptyProtocol( std::vector Elements; // The isa pointer must be set to a magic number so the runtime knows it's // the correct layout. - int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ? - NonFragileProtocolVersion : ProtocolVersion; Elements.push_back(llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), + ProtocolVersion), IdTy)); Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name")); Elements.push_back(ProtocolList); Elements.push_back(MethodList); @@ -1225,10 +1601,9 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { std::vector Elements; // The isa pointer must be set to a magic number so the runtime knows it's // the correct layout. - int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ? - NonFragileProtocolVersion : ProtocolVersion; Elements.push_back(llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), + ProtocolVersion), IdTy)); Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name")); Elements.push_back(ProtocolList); Elements.push_back(InstanceMethodList); @@ -1486,13 +1861,9 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { "__objc_ivar_offset_value_" + ClassName +"." + IVD->getNameAsString())); } - llvm::Constant *IvarOffsetArrayInit = - llvm::ConstantArray::get(llvm::ArrayType::get(PtrToIntTy, - IvarOffsetValues.size()), IvarOffsetValues); - llvm::GlobalVariable *IvarOffsetArray = new llvm::GlobalVariable(TheModule, - IvarOffsetArrayInit->getType(), false, - llvm::GlobalValue::InternalLinkage, IvarOffsetArrayInit, - ".ivar.offsets"); + llvm::GlobalVariable *IvarOffsetArray = + MakeGlobalArray(PtrToIntTy, IvarOffsetValues, ".ivar.offsets"); + // Collect information about instance methods llvm::SmallVector InstanceMethodSels; @@ -1620,8 +1991,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { llvm::Function *CGObjCGNU::ModuleInitFunction() { // Only emit an ObjC load function if no Objective-C stuff has been called if (Classes.empty() && Categories.empty() && ConstantStrings.empty() && - ExistingProtocols.empty() && TypedSelectors.empty() && - UntypedSelectors.empty()) + ExistingProtocols.empty() && SelectorTable.empty()) return NULL; // Add all referenced protocols to a category. @@ -1630,12 +2000,10 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { const llvm::StructType *SelStructTy = dyn_cast( SelectorTy->getElementType()); const llvm::Type *SelStructPtrTy = SelectorTy; - bool isSelOpaque = false; if (SelStructTy == 0) { SelStructTy = llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, NULL); SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy); - isSelOpaque = true; } // Name the ObjC types to make the IR a bit easier to read @@ -1652,7 +2020,9 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { ConstantStrings.push_back(NULLPtr); llvm::StringRef StringClass = CGM.getLangOptions().ObjCConstantStringClass; + if (StringClass.empty()) StringClass = "NXConstantString"; + Elements.push_back(MakeConstantString(StringClass, ".objc_static_class_name")); Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy, @@ -1682,75 +2052,62 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { Elements.clear(); // Pointer to an array of selectors used in this module. std::vector Selectors; - for (std::map::iterator - iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end(); - iter != iterEnd ; ++iter) { - Elements.push_back(ExportUniqueString(iter->first.first, ".objc_sel_name")); - Elements.push_back(MakeConstantString(iter->first.second, - ".objc_sel_types")); - Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); - Elements.clear(); - } - for (llvm::StringMap::iterator - iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end(); - iter != iterEnd; ++iter) { - Elements.push_back( - ExportUniqueString(iter->getKeyData(), ".objc_sel_name")); - Elements.push_back(NULLPtr); - Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); - Elements.clear(); + std::vector SelectorAliases; + for (SelectorMap::iterator iter = SelectorTable.begin(), + iterEnd = SelectorTable.end(); iter != iterEnd ; ++iter) { + + std::string SelNameStr = iter->first.getAsString(); + llvm::Constant *SelName = ExportUniqueString(SelNameStr, ".objc_sel_name"); + + llvm::SmallVectorImpl &Types = iter->second; + for (llvm::SmallVectorImpl::iterator i = Types.begin(), + e = Types.end() ; i!=e ; i++) { + + llvm::Constant *SelectorTypeEncoding = NULLPtr; + if (!i->first.empty()) + SelectorTypeEncoding = MakeConstantString(i->first, ".objc_sel_types"); + + Elements.push_back(SelName); + Elements.push_back(SelectorTypeEncoding); + Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); + Elements.clear(); + + // Store the selector alias for later replacement + SelectorAliases.push_back(i->second); + } } + unsigned SelectorCount = Selectors.size(); + // NULL-terminate the selector list. This should not actually be required, + // because the selector list has a length field. Unfortunately, the GCC + // runtime decides to ignore the length field and expects a NULL terminator, + // and GCC cooperates with this by always setting the length to 0. Elements.push_back(NULLPtr); Elements.push_back(NULLPtr); Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); Elements.clear(); + // Number of static selectors - Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() )); - llvm::Constant *SelectorList = MakeGlobal( - llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors, + Elements.push_back(llvm::ConstantInt::get(LongTy, SelectorCount)); + llvm::Constant *SelectorList = MakeGlobalArray(SelStructTy, Selectors, ".objc_selector_list"); Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, SelStructPtrTy)); // Now that all of the static selectors exist, create pointers to them. - int index = 0; - for (std::map::iterator - iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end(); - iter != iterEnd; ++iter) { + for (unsigned int i=0 ; ifirst.first+"."+ - iter->first.second)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), i), Zeros[0]}; + // FIXME: We're generating redundant loads and stores here! + llvm::Constant *SelPtr = llvm::ConstantExpr::getGetElementPtr(SelectorList, + Idxs, 2); // If selectors are defined as an opaque type, cast the pointer to this // type. - if (isSelOpaque) { - SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, - llvm::PointerType::getUnqual(SelectorTy)); - } - (*iter).second->replaceAllUsesWith(SelPtr); - (*iter).second->eraseFromParent(); - } - for (llvm::StringMap::iterator - iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end(); - iter != iterEnd; iter++) { - llvm::Constant *Idxs[] = {Zeros[0], - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]}; - llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy, - true, llvm::GlobalValue::LinkOnceODRLinkage, - llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), - MangleSelectorTypes(std::string(".objc_sel_ptr")+iter->getKey().str())); - // If selectors are defined as an opaque type, cast the pointer to this - // type. - if (isSelOpaque) { - SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, - llvm::PointerType::getUnqual(SelectorTy)); - } - (*iter).second->replaceAllUsesWith(SelPtr); - (*iter).second->eraseFromParent(); + SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, SelectorTy); + SelectorAliases[i]->replaceAllUsesWith(SelPtr); + SelectorAliases[i]->eraseFromParent(); } + // Number of classes defined. Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), Classes.size())); @@ -1772,19 +2129,22 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { llvm::StructType * ModuleTy = llvm::StructType::get(VMContext, LongTy, LongTy, PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL); Elements.clear(); - // Runtime version used for compatibility checking. - if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { - Elements.push_back(llvm::ConstantInt::get(LongTy, - NonFragileRuntimeVersion)); - } else { - Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion)); - } + // Runtime version, used for ABI compatibility checking. + Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion)); // sizeof(ModuleTy) llvm::TargetData td(&TheModule); - Elements.push_back(llvm::ConstantInt::get(LongTy, - td.getTypeSizeInBits(ModuleTy)/8)); - //FIXME: Should be the path to the file where this module was declared - Elements.push_back(NULLPtr); + Elements.push_back( + llvm::ConstantInt::get(LongTy, + td.getTypeSizeInBits(ModuleTy) / + CGM.getContext().getCharWidth())); + + // The path to the source file where this module was declared + SourceManager &SM = CGM.getContext().getSourceManager(); + const FileEntry *mainFile = SM.getFileEntryForID(SM.getMainFileID()); + std::string path = + std::string(mainFile->getDir()->getName()) + '/' + mainFile->getName(); + Elements.push_back(MakeConstantString(path, ".objc_source_file_name")); + Elements.push_back(SymTab); llvm::Value *Module = MakeGlobal(ModuleTy, Elements); @@ -1813,9 +2173,9 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD) { const ObjCCategoryImplDecl *OCD = dyn_cast(OMD->getDeclContext()); - std::string CategoryName = OCD ? OCD->getNameAsString() : ""; - std::string ClassName = CD->getName(); - std::string MethodName = OMD->getSelector().getAsString(); + llvm::StringRef CategoryName = OCD ? OCD->getName() : ""; + llvm::StringRef ClassName = CD->getName(); + Selector MethodName = OMD->getSelector(); bool isClassMethod = !OMD->isInstanceMethod(); CodeGenTypes &Types = CGM.getTypes(); @@ -1833,121 +2193,31 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD, } llvm::Function *CGObjCGNU::GetPropertyGetFunction() { - std::vector Params; - Params.push_back(IdTy); - Params.push_back(SelectorTy); - Params.push_back(SizeTy); - Params.push_back(BoolTy); - // void objc_getProperty (id, SEL, ptrdiff_t, bool) - const llvm::FunctionType *FTy = - llvm::FunctionType::get(IdTy, Params, false); - return cast(CGM.CreateRuntimeFunction(FTy, - "objc_getProperty")); + return GetPropertyFn; } llvm::Function *CGObjCGNU::GetPropertySetFunction() { - std::vector Params; - Params.push_back(IdTy); - Params.push_back(SelectorTy); - Params.push_back(SizeTy); - Params.push_back(IdTy); - Params.push_back(BoolTy); - Params.push_back(BoolTy); - // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) - const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); - return cast(CGM.CreateRuntimeFunction(FTy, - "objc_setProperty")); + return SetPropertyFn; } llvm::Function *CGObjCGNU::GetGetStructFunction() { - std::vector Params; - Params.push_back(PtrTy); - Params.push_back(PtrTy); - Params.push_back(PtrDiffTy); - Params.push_back(BoolTy); - Params.push_back(BoolTy); - // objc_setPropertyStruct (void*, void*, ptrdiff_t, BOOL, BOOL) - const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); - return cast(CGM.CreateRuntimeFunction(FTy, - "objc_getPropertyStruct")); + return GetStructPropertyFn; } llvm::Function *CGObjCGNU::GetSetStructFunction() { - std::vector Params; - Params.push_back(PtrTy); - Params.push_back(PtrTy); - Params.push_back(PtrDiffTy); - Params.push_back(BoolTy); - Params.push_back(BoolTy); - // objc_setPropertyStruct (void*, void*, ptrdiff_t, BOOL, BOOL) - const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); - return cast(CGM.CreateRuntimeFunction(FTy, - "objc_setPropertyStruct")); + return SetStructPropertyFn; } llvm::Constant *CGObjCGNU::EnumerationMutationFunction() { - CodeGen::CodeGenTypes &Types = CGM.getTypes(); - ASTContext &Ctx = CGM.getContext(); - // void objc_enumerationMutation (id) - llvm::SmallVector Params; - Params.push_back(ASTIdTy); - const llvm::FunctionType *FTy = - Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params, - FunctionType::ExtInfo()), false); - return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); + return EnumerationMutationFn; } -namespace { - struct CallSyncExit : EHScopeStack::Cleanup { - llvm::Value *SyncExitFn; - llvm::Value *SyncArg; - CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg) - : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {} - - void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { - CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow(); - } - }; -} - -void CGObjCGNU::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, +void CGObjCGNU::EmitSynchronizedStmt(CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S) { - std::vector Args(1, IdTy); - llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); - - // Evaluate the lock operand. This should dominate the cleanup. - llvm::Value *SyncArg = - CGF.EmitScalarExpr(S.getSynchExpr()); - - // Acquire the lock. - llvm::Value *SyncEnter = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); - SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy); - CGF.Builder.CreateCall(SyncEnter, SyncArg); - - // Register an all-paths cleanup to release the lock. - llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); - CGF.EHStack.pushCleanup(NormalAndEHCleanup, SyncExit, SyncArg); - - // Emit the body of the statement. - CGF.EmitStmt(S.getSynchBody()); - - // Pop the lock-release cleanup. - CGF.PopCleanupBlock(); + EmitAtSynchronizedStmt(CGF, S, SyncEnterFn, SyncExitFn); } -namespace { - struct CatchHandler { - const VarDecl *Variable; - const Stmt *Body; - llvm::BasicBlock *Block; - llvm::Value *TypeInfo; - }; -} -void CGObjCGNU::EmitTryStmt(CodeGen::CodeGenFunction &CGF, +void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) { // Unlike the Apple non-fragile runtimes, which also uses // unwind-based zero cost exceptions, the GNU Objective C runtime's @@ -1957,127 +2227,17 @@ void CGObjCGNU::EmitTryStmt(CodeGen::CodeGenFunction &CGF, // catch handlers with calls to __blah_begin_catch/__blah_end_catch // (or even _Unwind_DeleteException), but probably doesn't // interoperate very well with foreign exceptions. - - // Jump destination for falling out of catch bodies. - CodeGenFunction::JumpDest Cont; - if (S.getNumCatchStmts()) - Cont = CGF.getJumpDestInCurrentScope("eh.cont"); - - // We handle @finally statements by pushing them as a cleanup - // before entering the catch. - CodeGenFunction::FinallyInfo FinallyInfo; - if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) { - std::vector Args(1, IdTy); - llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); - llvm::Constant *Rethrow = - CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); - - FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(), 0, 0, - Rethrow); - } - - llvm::SmallVector Handlers; - - // Enter the catch, if there is one. - if (S.getNumCatchStmts()) { - for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) { - const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I); - const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); - - Handlers.push_back(CatchHandler()); - CatchHandler &Handler = Handlers.back(); - Handler.Variable = CatchDecl; - Handler.Body = CatchStmt->getCatchBody(); - Handler.Block = CGF.createBasicBlock("catch"); - - // @catch() and @catch(id) both catch any ObjC exception. - // Treat them as catch-alls. - // FIXME: this is what this code was doing before, but should 'id' - // really be catching foreign exceptions? - if (!CatchDecl - || CatchDecl->getType()->isObjCIdType() - || CatchDecl->getType()->isObjCQualifiedIdType()) { - - Handler.TypeInfo = 0; // catch-all - - // Don't consider any other catches. - break; - } - - // All other types should be Objective-C interface pointer types. - const ObjCObjectPointerType *OPT = - CatchDecl->getType()->getAs(); - assert(OPT && "Invalid @catch type."); - const ObjCInterfaceDecl *IDecl = - OPT->getObjectType()->getInterface(); - assert(IDecl && "Invalid @catch type."); - Handler.TypeInfo = MakeConstantString(IDecl->getNameAsString()); - } - - EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size()); - for (unsigned I = 0, E = Handlers.size(); I != E; ++I) - Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block); - } - - // Emit the try body. - CGF.EmitStmt(S.getTryBody()); - - // Leave the try. - if (S.getNumCatchStmts()) - CGF.EHStack.popCatch(); - - // Remember where we were. - CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); - - // Emit the handlers. - for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { - CatchHandler &Handler = Handlers[I]; - CGF.EmitBlock(Handler.Block); - - llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot()); - - // Bind the catch parameter if it exists. - if (const VarDecl *CatchParam = Handler.Variable) { - const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType()); - Exn = CGF.Builder.CreateBitCast(Exn, CatchType); - - CGF.EmitAutoVarDecl(*CatchParam); - CGF.Builder.CreateStore(Exn, CGF.GetAddrOfLocalVar(CatchParam)); - } - - CGF.ObjCEHValueStack.push_back(Exn); - CGF.EmitStmt(Handler.Body); - CGF.ObjCEHValueStack.pop_back(); - - CGF.EmitBranchThroughCleanup(Cont); - } - - // Go back to the try-statement fallthrough. - CGF.Builder.restoreIP(SavedIP); - - // Pop out of the finally. - if (S.getFinallyStmt()) - CGF.ExitFinallyBlock(FinallyInfo); - - if (Cont.isValid()) { - if (Cont.getBlock()->use_empty()) - delete Cont.getBlock(); - else - CGF.EmitBlock(Cont.getBlock()); - } + // + // In Objective-C++ mode, we actually emit something equivalent to the C++ + // exception handler. + EmitTryCatchStmt(CGF, S, EnterCatchFn, ExitCatchFn, ExceptionReThrowFn); + return ; } -void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, +void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, const ObjCAtThrowStmt &S) { llvm::Value *ExceptionAsObject; - std::vector Args(1, IdTy); - llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); - llvm::Value *ThrowFn = - CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); - if (const Expr *ThrowExpr = S.getThrowExpr()) { llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr); ExceptionAsObject = Exception; @@ -2100,24 +2260,24 @@ void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, // as a result of stupidity. llvm::BasicBlock *UnwindBB = CGF.getInvokeDest(); if (!UnwindBB) { - CGF.Builder.CreateCall(ThrowFn, ExceptionAsObject); + CGF.Builder.CreateCall(ExceptionThrowFn, ExceptionAsObject); CGF.Builder.CreateUnreachable(); } else { - CGF.Builder.CreateInvoke(ThrowFn, UnwindBB, UnwindBB, &ExceptionAsObject, + CGF.Builder.CreateInvoke(ExceptionThrowFn, UnwindBB, UnwindBB, &ExceptionAsObject, &ExceptionAsObject+1); } // Clear the insertion point to indicate we are in unreachable code. CGF.Builder.ClearInsertionPoint(); } -llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, +llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF, llvm::Value *AddrWeakObj) { CGBuilderTy B = CGF.Builder; AddrWeakObj = EnforceType(B, AddrWeakObj, IdTy); return B.CreateCall(WeakReadFn, AddrWeakObj); } -void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, +void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst) { CGBuilderTy B = CGF.Builder; src = EnforceType(B, src, IdTy); @@ -2125,7 +2285,7 @@ void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, B.CreateCall2(WeakAssignFn, src, dst); } -void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, +void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst, bool threadlocal) { CGBuilderTy B = CGF.Builder; @@ -2138,7 +2298,7 @@ void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, assert(false && "EmitObjCGlobalAssign - Threal Local API NYI"); } -void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, +void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst, llvm::Value *ivarOffset) { CGBuilderTy B = CGF.Builder; @@ -2147,7 +2307,7 @@ void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, B.CreateCall3(IvarAssignFn, src, dst, ivarOffset); } -void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, +void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst) { CGBuilderTy B = CGF.Builder; src = EnforceType(B, src, IdTy); @@ -2155,7 +2315,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, B.CreateCall2(StrongCastAssignFn, src, dst); } -void CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, +void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF, llvm::Value *DestPtr, llvm::Value *SrcPtr, llvm::Value *Size) { @@ -2212,7 +2372,7 @@ llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable( return IvarOffsetPointer; } -LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, +LValue CGObjCGNU::EmitObjCValueForIvar(CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, @@ -2240,19 +2400,23 @@ static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, return 0; } -llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, +llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF, const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar) { if (CGM.getLangOptions().ObjCNonFragileABI) { Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar); - return CGF.Builder.CreateLoad(CGF.Builder.CreateLoad( - ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar")); + return CGF.Builder.CreateZExtOrBitCast( + CGF.Builder.CreateLoad(CGF.Builder.CreateLoad( + ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar")), + PtrDiffTy); } uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar); - return llvm::ConstantInt::get(LongTy, Offset, "ivar"); + return llvm::ConstantInt::get(PtrDiffTy, Offset, "ivar"); } -CodeGen::CGObjCRuntime * -CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM) { - return new CGObjCGNU(CGM); +CGObjCRuntime * +clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) { + if (CGM.getLangOptions().ObjCNonFragileABI) + return new CGObjCGNUstep(CGM); + return new CGObjCGCC(CGM); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp index 8dbd85f8b738..2b1cfe3da5bd 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This provides Objective-C code generation targetting the Apple runtime. +// This provides Objective-C code generation targeting the Apple runtime. // //===----------------------------------------------------------------------===// @@ -42,9 +42,6 @@ using namespace clang; using namespace CodeGen; -// Common CGObjCRuntime functions, these don't belong here, but they -// don't belong in CGObjCRuntime either so we will live with it for -// now. static void EmitNullReturnInitialization(CodeGenFunction &CGF, ReturnValueSlot &returnSlot, @@ -55,112 +52,6 @@ static void EmitNullReturnInitialization(CodeGenFunction &CGF, CGF.EmitNullInitialization(returnSlot.getValue(), resultType); } -static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, - const ObjCInterfaceDecl *OID, - const ObjCImplementationDecl *ID, - const ObjCIvarDecl *Ivar) { - const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); - - // FIXME: We should eliminate the need to have ObjCImplementationDecl passed - // in here; it should never be necessary because that should be the lexical - // decl context for the ivar. - - // If we know have an implementation (and the ivar is in it) then - // look up in the implementation layout. - const ASTRecordLayout *RL; - if (ID && ID->getClassInterface() == Container) - RL = &CGM.getContext().getASTObjCImplementationLayout(ID); - else - RL = &CGM.getContext().getASTObjCInterfaceLayout(Container); - - // Compute field index. - // - // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is - // implemented. This should be fixed to get the information from the layout - // directly. - unsigned Index = 0; - llvm::SmallVector Ivars; - CGM.getContext().ShallowCollectObjCIvars(Container, Ivars); - for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { - if (Ivar == Ivars[k]) - break; - ++Index; - } - assert(Index != Ivars.size() && "Ivar is not inside container!"); - assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!"); - - return RL->getFieldOffset(Index); -} - -uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, - const ObjCInterfaceDecl *OID, - const ObjCIvarDecl *Ivar) { - return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8; -} - -uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, - const ObjCImplementationDecl *OID, - const ObjCIvarDecl *Ivar) { - return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8; -} - -LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *OID, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers, - llvm::Value *Offset) { - // Compute (type*) ( (char *) BaseValue + Offset) - const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - QualType IvarTy = Ivar->getType(); - const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); - llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr); - V = CGF.Builder.CreateGEP(V, Offset, "add.ptr"); - V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); - - if (!Ivar->isBitField()) { - LValue LV = CGF.MakeAddrLValue(V, IvarTy); - LV.getQuals().addCVRQualifiers(CVRQualifiers); - return LV; - } - - // We need to compute an access strategy for this bit-field. We are given the - // offset to the first byte in the bit-field, the sub-byte offset is taken - // from the original layout. We reuse the normal bit-field access strategy by - // treating this as an access to a struct where the bit-field is in byte 0, - // and adjust the containing type size as appropriate. - // - // FIXME: Note that currently we make a very conservative estimate of the - // alignment of the bit-field, because (a) it is not clear what guarantees the - // runtime makes us, and (b) we don't have a way to specify that the struct is - // at an alignment plus offset. - // - // Note, there is a subtle invariant here: we can only call this routine on - // non-synthesized ivars but we may be called for synthesized ivars. However, - // a synthesized ivar can never be a bit-field, so this is safe. - const ASTRecordLayout &RL = - CGF.CGM.getContext().getASTObjCInterfaceLayout(OID); - uint64_t TypeSizeInBits = CGF.CGM.getContext().toBits(RL.getSize()); - uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar); - uint64_t BitOffset = FieldBitOffset % 8; - uint64_t ContainingTypeAlign = 8; - uint64_t ContainingTypeSize = TypeSizeInBits - (FieldBitOffset - BitOffset); - uint64_t BitFieldSize = - Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); - - // Allocate a new CGBitFieldInfo object to describe this access. - // - // FIXME: This is incredibly wasteful, these should be uniqued or part of some - // layout object. However, this is blocked on other cleanups to the - // Objective-C code, so for now we just live with allocating a bunch of these - // objects. - CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo( - CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize, - ContainingTypeSize, ContainingTypeAlign)); - - return LValue::MakeBitfield(V, *Info, - IvarTy.getCVRQualifiers() | CVRQualifiers); -} /// @@ -328,7 +219,7 @@ class ObjCCommonTypesHelper { CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); Params.push_back(IdType); Params.push_back(SelType); - Params.push_back(Ctx.LongTy); + Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified()); Params.push_back(Ctx.BoolTy); const llvm::FunctionType *FTy = Types.GetFunctionType(Types.getFunctionInfo(IdType, Params, @@ -346,7 +237,7 @@ class ObjCCommonTypesHelper { CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); Params.push_back(IdType); Params.push_back(SelType); - Params.push_back(Ctx.LongTy); + Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified()); Params.push_back(IdType); Params.push_back(Ctx.BoolTy); Params.push_back(Ctx.BoolTy); @@ -1294,7 +1185,8 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { llvm::Value *Receiver, QualType Arg0Ty, bool IsSuper, - const CallArgList &CallArgs); + const CallArgList &CallArgs, + const ObjCMethodDecl *Method); /// GetClassGlobal - Return the global variable for the Objective-C /// class of the given name. @@ -1555,7 +1447,7 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. llvm::Value *ObjCSuper = - CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); + CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateStore(ReceiverAsObject, @@ -1630,9 +1522,8 @@ CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, CallArgList ActualArgs; if (!IsSuper) Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); - ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty)); - ActualArgs.push_back(std::make_pair(RValue::get(Sel), - CGF.getContext().getObjCSelType())); + ActualArgs.add(RValue::get(Arg0), Arg0Ty); + ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType()); ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); CodeGenTypes &Types = CGM.getTypes(); @@ -2177,6 +2068,8 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 4, true); DefinedCategories.push_back(GV); DefinedCategoryNames.insert(ExtName.str()); + // method definition entries must be clear for next implementation. + MethodDefinitions.clear(); } // FIXME: Get from somewhere? @@ -2304,6 +2197,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { else GV = CreateMetadataVar(Name, Init, Section, 4, true); DefinedClasses.push_back(GV); + // method definition entries must be clear for next implementation. + MethodDefinitions.clear(); } llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, @@ -3596,7 +3491,9 @@ llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) { Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", llvm::ConstantArray::get(VMContext, Ident->getNameStart()), - "__TEXT,__cstring,cstring_literals", + ((ObjCABI == 2) ? + "__TEXT,__objc_classname,cstring_literals" : + "__TEXT,__cstring,cstring_literals"), 1, true); return getConstantGEP(VMContext, Entry, 0, 0); @@ -3668,7 +3565,7 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, // Note that 'i' here is actually the field index inside RD of Field, // although this dependency is hidden. const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - FieldOffset = RL.getFieldOffset(i) / 8; + FieldOffset = RL.getFieldOffset(i) / ByteSizeInBits; } else FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast(Field)); @@ -3920,7 +3817,9 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) { llvm::GlobalVariable * Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", llvm::ConstantArray::get(VMContext, BitMap.c_str()), - "__TEXT,__cstring,cstring_literals", + ((ObjCABI == 2) ? + "__TEXT,__objc_classname,cstring_literals" : + "__TEXT,__cstring,cstring_literals"), 1, true); return getConstantGEP(VMContext, Entry, 0, 0); } @@ -3999,7 +3898,9 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { if (!Entry) Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_", llvm::ConstantArray::get(VMContext, Sel.getAsString()), - "__TEXT,__cstring,cstring_literals", + ((ObjCABI == 2) ? + "__TEXT,__objc_methname,cstring_literals" : + "__TEXT,__cstring,cstring_literals"), 1, true); return getConstantGEP(VMContext, Entry, 0, 0); @@ -4019,7 +3920,9 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { if (!Entry) Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", llvm::ConstantArray::get(VMContext, TypeStr), - "__TEXT,__cstring,cstring_literals", + ((ObjCABI == 2) ? + "__TEXT,__objc_methtype,cstring_literals" : + "__TEXT,__cstring,cstring_literals"), 1, true); return getConstantGEP(VMContext, Entry, 0, 0); @@ -4035,7 +3938,9 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) { if (!Entry) Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", llvm::ConstantArray::get(VMContext, TypeStr), - "__TEXT,__cstring,cstring_literals", + ((ObjCABI == 2) ? + "__TEXT,__objc_methtype,cstring_literals" : + "__TEXT,__cstring,cstring_literals"), 1, true); return getConstantGEP(VMContext, Entry, 0, 0); @@ -4173,11 +4078,11 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) // } RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, Ctx.getTranslationUnitDecl(), - SourceLocation(), + SourceLocation(), SourceLocation(), &Ctx.Idents.get("_objc_super")); - RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, + RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0, Ctx.getObjCIdType(), 0, 0, false)); - RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, + RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0, Ctx.getObjCClassType(), 0, 0, false)); RD->completeDefinition(); @@ -4636,11 +4541,11 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // First the clang type for struct _message_ref_t RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, Ctx.getTranslationUnitDecl(), - SourceLocation(), + SourceLocation(), SourceLocation(), &Ctx.Idents.get("_message_ref_t")); - RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, + RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0, Ctx.VoidPtrTy, 0, 0, false)); - RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, + RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0, Ctx.getObjCSelType(), 0, 0, false)); RD->completeDefinition(); @@ -4966,7 +4871,7 @@ void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, if (!RL.getFieldCount()) InstanceStart = InstanceSize; else - InstanceStart = RL.getFieldOffset(0) / 8; + InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth(); } void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { @@ -5017,14 +4922,14 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) Root = Super; IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString()); - if (Root->hasAttr()) + if (Root->isWeakImported()) IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); // work on super class metadata symbol. std::string SuperClassName = ObjCMetaClassName + ID->getClassInterface()->getSuperClass()->getNameAsString(); SuperClassGV = GetClassGlobal(SuperClassName); - if (ID->getClassInterface()->getSuperClass()->hasAttr()) + if (ID->getClassInterface()->getSuperClass()->isWeakImported()) SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); } llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags, @@ -5054,7 +4959,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { std::string RootClassName = ID->getClassInterface()->getSuperClass()->getNameAsString(); SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName); - if (ID->getClassInterface()->getSuperClass()->hasAttr()) + if (ID->getClassInterface()->getSuperClass()->isWeakImported()) SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); } GetClassSizeInfo(ID, InstanceStart, InstanceSize); @@ -5076,6 +4981,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { // Force the definition of the EHType if necessary. if (flags & CLS_EXCEPTION) GetInterfaceEHType(ID->getClassInterface(), true); + // Make sure method definition entries are all clear for next implementation. + MethodDefinitions.clear(); } /// GenerateProtocolRef - This routine is called to generate code for @@ -5136,7 +5043,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { Values[0] = GetClassName(OCD->getIdentifier()); // meta-class entry symbol llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName); - if (Interface->hasAttr()) + if (Interface->isWeakImported()) ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); Values[1] = ClassGV; @@ -5204,6 +5111,8 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { // Determine if this category is also "non-lazy". if (ImplementationIsNonLazy(OCD)) DefinedNonLazyCategories.push_back(GCATV); + // method definition entries must be clear for next implementation. + MethodDefinitions.clear(); } /// GetMethodConstant - Return a struct objc_method constant for the @@ -5622,7 +5531,8 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( llvm::Value *Receiver, QualType Arg0Ty, bool IsSuper, - const CallArgList &CallArgs) { + const CallArgList &CallArgs, + const ObjCMethodDecl *Method) { // FIXME. Even though IsSuper is passes. This function doese not handle calls // to 'super' receivers. CodeGenTypes &Types = CGM.getTypes(); @@ -5685,15 +5595,15 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy); CallArgList ActualArgs; - ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty)); - ActualArgs.push_back(std::make_pair(RValue::get(Arg1), - ObjCTypes.MessageRefCPtrTy)); + ActualArgs.add(RValue::get(Arg0), Arg0Ty); + ActualArgs.add(RValue::get(Arg1), ObjCTypes.MessageRefCPtrTy); ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs, FunctionType::ExtInfo()); llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0); Callee = CGF.Builder.CreateLoad(Callee); - const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true); + const llvm::FunctionType *FTy = + Types.GetFunctionType(FnInfo1, Method ? Method->isVariadic() : false); Callee = CGF.Builder.CreateBitCast(Callee, llvm::PointerType::getUnqual(FTy)); return CGF.EmitCall(FnInfo1, Callee, Return, ActualArgs); @@ -5716,7 +5626,7 @@ CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, false, CallArgs, Method, ObjCTypes) : EmitMessageSend(CGF, Return, ResultType, Sel, Receiver, CGF.getContext().getObjCIdType(), - false, CallArgs); + false, CallArgs, Method); } llvm::GlobalVariable * @@ -5807,7 +5717,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder, /// decl. llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID) { - if (ID->hasAttr()) { + if (ID->isWeakImported()) { std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); @@ -5834,7 +5744,7 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. llvm::Value *ObjCSuper = - CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); + CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); @@ -5870,7 +5780,7 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, true, CallArgs, Method, ObjCTypes) : EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper, ObjCTypes.SuperPtrCTy, - true, CallArgs); + true, CallArgs, Method); } llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder, @@ -6008,65 +5918,12 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, return; } -namespace { - struct CallSyncExit : EHScopeStack::Cleanup { - llvm::Value *SyncExitFn; - llvm::Value *SyncArg; - CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg) - : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {} - - void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { - CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow(); - } - }; -} - void CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S) { - // Evaluate the lock operand. This should dominate the cleanup. - llvm::Value *SyncArg = CGF.EmitScalarExpr(S.getSynchExpr()); - - // Acquire the lock. - SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); - CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg) - ->setDoesNotThrow(); - - // Register an all-paths cleanup to release the lock. - CGF.EHStack.pushCleanup(NormalAndEHCleanup, - ObjCTypes.getSyncExitFn(), - SyncArg); - - // Emit the body of the statement. - CGF.EmitStmt(S.getSynchBody()); - - // Pop the lock-release cleanup. - CGF.PopCleanupBlock(); -} - -namespace { - struct CatchHandler { - const VarDecl *Variable; - const Stmt *Body; - llvm::BasicBlock *Block; - llvm::Value *TypeInfo; - }; - - struct CallObjCEndCatch : EHScopeStack::Cleanup { - CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) : - MightThrow(MightThrow), Fn(Fn) {} - bool MightThrow; - llvm::Value *Fn; - - void Emit(CodeGenFunction &CGF, bool IsForEH) { - if (!MightThrow) { - CGF.Builder.CreateCall(Fn)->setDoesNotThrow(); - return; - } - - CGF.EmitCallOrInvoke(Fn, 0, 0); - } - }; + EmitAtSynchronizedStmt(CGF, S, + cast(ObjCTypes.getSyncEnterFn()), + cast(ObjCTypes.getSyncExitFn())); } llvm::Constant * @@ -6096,104 +5953,10 @@ CGObjCNonFragileABIMac::GetEHType(QualType T) { void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtTryStmt &S) { - // Jump destination for falling out of catch bodies. - CodeGenFunction::JumpDest Cont; - if (S.getNumCatchStmts()) - Cont = CGF.getJumpDestInCurrentScope("eh.cont"); - - CodeGenFunction::FinallyInfo FinallyInfo; - if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) - FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(), - ObjCTypes.getObjCBeginCatchFn(), - ObjCTypes.getObjCEndCatchFn(), - ObjCTypes.getExceptionRethrowFn()); - - llvm::SmallVector Handlers; - - // Enter the catch, if there is one. - if (S.getNumCatchStmts()) { - for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) { - const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I); - const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); - - Handlers.push_back(CatchHandler()); - CatchHandler &Handler = Handlers.back(); - Handler.Variable = CatchDecl; - Handler.Body = CatchStmt->getCatchBody(); - Handler.Block = CGF.createBasicBlock("catch"); - - // @catch(...) always matches. - if (!CatchDecl) { - Handler.TypeInfo = 0; // catch-all - // Don't consider any other catches. - break; - } - - Handler.TypeInfo = GetEHType(CatchDecl->getType()); - } - - EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size()); - for (unsigned I = 0, E = Handlers.size(); I != E; ++I) - Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block); - } - - // Emit the try body. - CGF.EmitStmt(S.getTryBody()); - - // Leave the try. - if (S.getNumCatchStmts()) - CGF.EHStack.popCatch(); - - // Remember where we were. - CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); - - // Emit the handlers. - for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { - CatchHandler &Handler = Handlers[I]; - - CGF.EmitBlock(Handler.Block); - llvm::Value *RawExn = CGF.Builder.CreateLoad(CGF.getExceptionSlot()); - - // Enter the catch. - llvm::CallInst *Exn = - CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), RawExn, - "exn.adjusted"); - Exn->setDoesNotThrow(); - - // Add a cleanup to leave the catch. - bool EndCatchMightThrow = (Handler.Variable == 0); - CGF.EHStack.pushCleanup(NormalAndEHCleanup, - EndCatchMightThrow, - ObjCTypes.getObjCEndCatchFn()); - - // Bind the catch parameter if it exists. - if (const VarDecl *CatchParam = Handler.Variable) { - const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType()); - llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType); - - CGF.EmitAutoVarDecl(*CatchParam); - CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam)); - } - - CGF.ObjCEHValueStack.push_back(Exn); - CGF.EmitStmt(Handler.Body); - CGF.ObjCEHValueStack.pop_back(); - - // Leave the earlier cleanup. - CGF.PopCleanupBlock(); - - CGF.EmitBranchThroughCleanup(Cont); - } - - // Go back to the try-statement fallthrough. - CGF.Builder.restoreIP(SavedIP); - - // Pop out of the normal cleanup on the finally. - if (S.getFinallyStmt()) - CGF.ExitFinallyBlock(FinallyInfo); - - if (Cont.isValid()) - CGF.EmitBlock(Cont.getBlock()); + EmitTryCatchStmt(CGF, S, + cast(ObjCTypes.getObjCBeginCatchFn()), + cast(ObjCTypes.getObjCEndCatchFn()), + cast(ObjCTypes.getExceptionRethrowFn())); } /// EmitThrowStmt - Generate code for a throw statement. @@ -6290,10 +6053,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, CodeGen::CGObjCRuntime * CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) { + if (CGM.getLangOptions().ObjCNonFragileABI) + return new CGObjCNonFragileABIMac(CGM); return new CGObjCMac(CGM); } - -CodeGen::CGObjCRuntime * -CodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) { - return new CGObjCNonFragileABIMac(CGM); -} diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp new file mode 100644 index 000000000000..3d854d41acbe --- /dev/null +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -0,0 +1,310 @@ +//==- CGObjCRuntime.cpp - Interface to Shared Objective-C Runtime Features ==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This abstract class defines the interface for Objective-C runtime-specific +// code generation. It provides some concrete helper methods for functionality +// shared between all (or most) of the Objective-C runtimes supported by clang. +// +//===----------------------------------------------------------------------===// + +#include "CGObjCRuntime.h" + +#include "CGRecordLayout.h" +#include "CodeGenModule.h" +#include "CodeGenFunction.h" +#include "CGCleanup.h" + +#include "clang/AST/RecordLayout.h" +#include "clang/AST/StmtObjC.h" + +#include "llvm/Support/CallSite.h" + +using namespace clang; +using namespace CodeGen; + +static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, + const ObjCInterfaceDecl *OID, + const ObjCImplementationDecl *ID, + const ObjCIvarDecl *Ivar) { + const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); + + // FIXME: We should eliminate the need to have ObjCImplementationDecl passed + // in here; it should never be necessary because that should be the lexical + // decl context for the ivar. + + // If we know have an implementation (and the ivar is in it) then + // look up in the implementation layout. + const ASTRecordLayout *RL; + if (ID && ID->getClassInterface() == Container) + RL = &CGM.getContext().getASTObjCImplementationLayout(ID); + else + RL = &CGM.getContext().getASTObjCInterfaceLayout(Container); + + // Compute field index. + // + // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is + // implemented. This should be fixed to get the information from the layout + // directly. + unsigned Index = 0; + llvm::SmallVector Ivars; + CGM.getContext().ShallowCollectObjCIvars(Container, Ivars); + for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { + if (Ivar == Ivars[k]) + break; + ++Index; + } + assert(Index != Ivars.size() && "Ivar is not inside container!"); + assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!"); + + return RL->getFieldOffset(Index); +} + +uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, + const ObjCInterfaceDecl *OID, + const ObjCIvarDecl *Ivar) { + return LookupFieldBitOffset(CGM, OID, 0, Ivar) / + CGM.getContext().getCharWidth(); +} + +uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, + const ObjCImplementationDecl *OID, + const ObjCIvarDecl *Ivar) { + return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / + CGM.getContext().getCharWidth(); +} + +LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, + const ObjCInterfaceDecl *OID, + llvm::Value *BaseValue, + const ObjCIvarDecl *Ivar, + unsigned CVRQualifiers, + llvm::Value *Offset) { + // Compute (type*) ( (char *) BaseValue + Offset) + const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); + QualType IvarTy = Ivar->getType(); + const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); + llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr); + V = CGF.Builder.CreateInBoundsGEP(V, Offset, "add.ptr"); + V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); + + if (!Ivar->isBitField()) { + LValue LV = CGF.MakeAddrLValue(V, IvarTy); + LV.getQuals().addCVRQualifiers(CVRQualifiers); + return LV; + } + + // We need to compute an access strategy for this bit-field. We are given the + // offset to the first byte in the bit-field, the sub-byte offset is taken + // from the original layout. We reuse the normal bit-field access strategy by + // treating this as an access to a struct where the bit-field is in byte 0, + // and adjust the containing type size as appropriate. + // + // FIXME: Note that currently we make a very conservative estimate of the + // alignment of the bit-field, because (a) it is not clear what guarantees the + // runtime makes us, and (b) we don't have a way to specify that the struct is + // at an alignment plus offset. + // + // Note, there is a subtle invariant here: we can only call this routine on + // non-synthesized ivars but we may be called for synthesized ivars. However, + // a synthesized ivar can never be a bit-field, so this is safe. + const ASTRecordLayout &RL = + CGF.CGM.getContext().getASTObjCInterfaceLayout(OID); + uint64_t TypeSizeInBits = CGF.CGM.getContext().toBits(RL.getSize()); + uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar); + uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); + uint64_t ContainingTypeAlign = CGF.CGM.getContext().Target.getCharAlign(); + uint64_t ContainingTypeSize = TypeSizeInBits - (FieldBitOffset - BitOffset); + uint64_t BitFieldSize = + Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); + + // Allocate a new CGBitFieldInfo object to describe this access. + // + // FIXME: This is incredibly wasteful, these should be uniqued or part of some + // layout object. However, this is blocked on other cleanups to the + // Objective-C code, so for now we just live with allocating a bunch of these + // objects. + CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo( + CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize, + ContainingTypeSize, ContainingTypeAlign)); + + return LValue::MakeBitfield(V, *Info, + IvarTy.getCVRQualifiers() | CVRQualifiers); +} + +namespace { + struct CatchHandler { + const VarDecl *Variable; + const Stmt *Body; + llvm::BasicBlock *Block; + llvm::Value *TypeInfo; + }; + + struct CallObjCEndCatch : EHScopeStack::Cleanup { + CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) : + MightThrow(MightThrow), Fn(Fn) {} + bool MightThrow; + llvm::Value *Fn; + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + if (!MightThrow) { + CGF.Builder.CreateCall(Fn)->setDoesNotThrow(); + return; + } + + CGF.EmitCallOrInvoke(Fn, 0, 0); + } + }; +} + + +void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, + const ObjCAtTryStmt &S, + llvm::Function *beginCatchFn, + llvm::Function *endCatchFn, + llvm::Function *exceptionRethrowFn) { + // Jump destination for falling out of catch bodies. + CodeGenFunction::JumpDest Cont; + if (S.getNumCatchStmts()) + Cont = CGF.getJumpDestInCurrentScope("eh.cont"); + + CodeGenFunction::FinallyInfo FinallyInfo; + if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) + FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(), + beginCatchFn, + endCatchFn, + exceptionRethrowFn); + + llvm::SmallVector Handlers; + + // Enter the catch, if there is one. + if (S.getNumCatchStmts()) { + for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) { + const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I); + const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); + + Handlers.push_back(CatchHandler()); + CatchHandler &Handler = Handlers.back(); + Handler.Variable = CatchDecl; + Handler.Body = CatchStmt->getCatchBody(); + Handler.Block = CGF.createBasicBlock("catch"); + + // @catch(...) always matches. + if (!CatchDecl) { + Handler.TypeInfo = 0; // catch-all + // Don't consider any other catches. + break; + } + + Handler.TypeInfo = GetEHType(CatchDecl->getType()); + } + + EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size()); + for (unsigned I = 0, E = Handlers.size(); I != E; ++I) + Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block); + } + + // Emit the try body. + CGF.EmitStmt(S.getTryBody()); + + // Leave the try. + if (S.getNumCatchStmts()) + CGF.EHStack.popCatch(); + + // Remember where we were. + CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); + + // Emit the handlers. + for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { + CatchHandler &Handler = Handlers[I]; + + CGF.EmitBlock(Handler.Block); + llvm::Value *RawExn = CGF.Builder.CreateLoad(CGF.getExceptionSlot()); + + // Enter the catch. + llvm::Value *Exn = RawExn; + if (beginCatchFn) { + Exn = CGF.Builder.CreateCall(beginCatchFn, RawExn, "exn.adjusted"); + cast(Exn)->setDoesNotThrow(); + } + + if (endCatchFn) { + // Add a cleanup to leave the catch. + bool EndCatchMightThrow = (Handler.Variable == 0); + + CGF.EHStack.pushCleanup(NormalAndEHCleanup, + EndCatchMightThrow, + endCatchFn); + } + + // Bind the catch parameter if it exists. + if (const VarDecl *CatchParam = Handler.Variable) { + const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType()); + llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType); + + CGF.EmitAutoVarDecl(*CatchParam); + CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam)); + } + + CGF.ObjCEHValueStack.push_back(Exn); + CGF.EmitStmt(Handler.Body); + CGF.ObjCEHValueStack.pop_back(); + + // Leave the earlier cleanup. + if (endCatchFn) + CGF.PopCleanupBlock(); + + CGF.EmitBranchThroughCleanup(Cont); + } + + // Go back to the try-statement fallthrough. + CGF.Builder.restoreIP(SavedIP); + + // Pop out of the normal cleanup on the finally. + if (S.getFinallyStmt()) + CGF.ExitFinallyBlock(FinallyInfo); + + if (Cont.isValid()) + CGF.EmitBlock(Cont.getBlock()); +} + +namespace { + struct CallSyncExit : EHScopeStack::Cleanup { + llvm::Value *SyncExitFn; + llvm::Value *SyncArg; + CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg) + : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {} + + void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { + CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow(); + } + }; +} + +void CGObjCRuntime::EmitAtSynchronizedStmt(CodeGenFunction &CGF, + const ObjCAtSynchronizedStmt &S, + llvm::Function *syncEnterFn, + llvm::Function *syncExitFn) { + // Evaluate the lock operand. This should dominate the cleanup. + llvm::Value *SyncArg = + CGF.EmitScalarExpr(S.getSynchExpr()); + + // Acquire the lock. + SyncArg = CGF.Builder.CreateBitCast(SyncArg, syncEnterFn->getFunctionType()->getParamType(0)); + CGF.Builder.CreateCall(syncEnterFn, SyncArg); + + // Register an all-paths cleanup to release the lock. + CGF.EHStack.pushCleanup(NormalAndEHCleanup, syncExitFn, + SyncArg); + + // Emit the body of the statement. + CGF.EmitStmt(S.getSynchBody()); + + // Pop the lock-release cleanup. + CGF.PopCleanupBlock(); +} diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h index 5ad3a50adc3f..0cc2d824d401 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h @@ -17,7 +17,6 @@ #define CLANG_CODEGEN_OBCJRUNTIME_H #include "clang/Basic/IdentifierTable.h" // Selector #include "clang/AST/DeclObjC.h" -#include #include "CGBuilder.h" #include "CGCall.h" @@ -87,6 +86,26 @@ class CGObjCRuntime { const ObjCIvarDecl *Ivar, unsigned CVRQualifiers, llvm::Value *Offset); + /// Emits a try / catch statement. This function is intended to be called by + /// subclasses, and provides a generic mechanism for generating these, which + /// should be usable by all runtimes. The caller must provide the functions to + /// call when entering and exiting a @catch() block, and the function used to + /// rethrow exceptions. If the begin and end catch functions are NULL, then + /// the function assumes that the EH personality function provides the + /// thrown object directly. + void EmitTryCatchStmt(CodeGenFunction &CGF, + const ObjCAtTryStmt &S, + llvm::Function *beginCatchFn, + llvm::Function *endCatchFn, + llvm::Function *exceptionRethrowFn); + /// Emits an @synchronize() statement, using the syncEnterFn and syncExitFn + /// arguments as the functions called to lock and unlock the object. This + /// function can be called by subclasses that use zero-cost exception + /// handling. + void EmitAtSynchronizedStmt(CodeGenFunction &CGF, + const ObjCAtSynchronizedStmt &S, + llvm::Function *syncEnterFn, + llvm::Function *syncExitFn); public: virtual ~CGObjCRuntime(); @@ -118,7 +137,7 @@ class CGObjCRuntime { /// accompanying metadata) and a list of protocols. virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0; - /// Generate a class stucture for this class. + /// Generate a class structure for this class. virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0; /// Generate an Objective-C message send operation. @@ -230,7 +249,6 @@ class CGObjCRuntime { //TODO: This should include some way of selecting which runtime to target. CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM); CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM); -CGObjCRuntime *CreateMacNonFragileABIObjCRuntime(CodeGenModule &CGM); } } #endif diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRTTI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRTTI.cpp index 7ec0ee4b5cab..c73b199e31f7 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGRTTI.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRTTI.cpp @@ -16,6 +16,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" #include "clang/Frontend/CodeGenOptions.h" +#include "CGObjCRuntime.h" using namespace clang; using namespace CodeGen; @@ -195,7 +196,9 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { case BuiltinType::Overload: case BuiltinType::Dependent: - assert(false && "Should not see this type here!"); + case BuiltinType::BoundMember: + case BuiltinType::UnknownAny: + llvm_unreachable("asking for RRTI for a placeholder type!"); case BuiltinType::ObjCId: case BuiltinType::ObjCClass: @@ -875,14 +878,16 @@ void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { // For a non-virtual base, this is the offset in the object of the base // subobject. For a virtual base, this is the offset in the virtual table of // the virtual base offset for the virtual base referenced (negative). + CharUnits Offset; if (Base->isVirtual()) - OffsetFlags = CGM.getVTables().getVirtualBaseOffsetOffset(RD, BaseDecl); + Offset = + CGM.getVTables().getVirtualBaseOffsetOffset(RD, BaseDecl); else { const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - OffsetFlags = Layout.getBaseClassOffsetInBits(BaseDecl) / 8; + Offset = Layout.getBaseClassOffset(BaseDecl); }; - OffsetFlags <<= 8; + OffsetFlags = Offset.getQuantity() << 8; // The low-order byte of __offset_flags contains flags, as given by the // masks from the enumeration __offset_flags_masks. @@ -977,6 +982,10 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); return llvm::Constant::getNullValue(Int8PtrTy); } + + if (ForEH && Ty->isObjCObjectPointerType() && !Features.NeXTRuntime) { + return Runtime->GetEHType(Ty); + } return RTTIBuilder(*this).BuildTypeInfo(Ty); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h index 30da05f421fe..6d9fc0589e93 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h @@ -12,6 +12,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/DerivedTypes.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" namespace llvm { class raw_ostream; @@ -53,7 +54,7 @@ class CGBitFieldInfo { /// unused as the cleanest IR comes from having a well-constructed LLVM type /// with proper GEP instructions, but sometimes its use is required, for /// example if an access is intended to straddle an LLVM field boundary. - unsigned FieldByteOffset; + CharUnits FieldByteOffset; /// Bit offset in the accessed value to use. The width is implied by \see /// TargetBitWidth. @@ -68,7 +69,7 @@ class CGBitFieldInfo { // FIXME: Remove use of 0 to encode default, instead have IRgen do the right // thing when it generates the code, if avoiding align directives is // desired. - unsigned AccessAlignment; + CharUnits AccessAlignment; /// Offset for the target value. unsigned TargetBitOffset; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index ceae66f3849e..a4ac390dd98c 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -34,7 +34,7 @@ class CGRecordLayoutBuilder { public: /// FieldTypes - Holds the LLVM types that the struct is created from. /// - std::vector FieldTypes; + llvm::SmallVector FieldTypes; /// BaseSubobjectType - Holds the LLVM type for the non-virtual part /// of the struct. For example, consider: @@ -77,13 +77,26 @@ class CGRecordLayoutBuilder { /// Packed - Whether the resulting LLVM struct will be packed or not. bool Packed; + + /// IsMsStruct - Whether ms_struct is in effect or not + bool IsMsStruct; private: CodeGenTypes &Types; + /// LastLaidOutBaseInfo - Contains the offset and non-virtual size of the + /// last base laid out. Used so that we can replace the last laid out base + /// type with an i8 array if needed. + struct LastLaidOutBaseInfo { + CharUnits Offset; + CharUnits NonVirtualSize; + + bool isValid() const { return !NonVirtualSize.isZero(); } + void invalidate() { NonVirtualSize = CharUnits::Zero(); } + + } LastLaidOutBase; + /// Alignment - Contains the alignment of the RecordDecl. - // - // FIXME: This is not needed and should be removed. CharUnits Alignment; /// BitsAvailableInLastField - If a bit field spans only part of a LLVM field, @@ -143,6 +156,12 @@ class CGRecordLayoutBuilder { /// struct size is a multiple of the field alignment. void AppendPadding(CharUnits fieldOffset, CharUnits fieldAlignment); + /// ResizeLastBaseFieldIfNecessary - Fields and bases can be laid out in the + /// tail padding of a previous base. If this happens, the type of the previous + /// base needs to be changed to an array of i8. Returns true if the last + /// laid out base was resized. + bool ResizeLastBaseFieldIfNecessary(CharUnits offset); + /// getByteArrayType - Returns a byte array type with the given number of /// elements. const llvm::Type *getByteArrayType(CharUnits NumBytes); @@ -152,7 +171,7 @@ class CGRecordLayoutBuilder { /// AppendTailPadding - Append enough tail padding so that the type will have /// the passed size. - void AppendTailPadding(uint64_t RecordSize); + void AppendTailPadding(CharUnits RecordSize); CharUnits getTypeAlignment(const llvm::Type *Ty) const; @@ -168,7 +187,8 @@ class CGRecordLayoutBuilder { CGRecordLayoutBuilder(CodeGenTypes &Types) : BaseSubobjectType(0), IsZeroInitializable(true), IsZeroInitializableAsBase(true), - Packed(false), Types(Types), BitsAvailableInLastField(0) { } + Packed(false), IsMsStruct(false), + Types(Types), BitsAvailableInLastField(0) { } /// Layout - Will layout a RecordDecl. void Layout(const RecordDecl *D); @@ -179,6 +199,8 @@ class CGRecordLayoutBuilder { void CGRecordLayoutBuilder::Layout(const RecordDecl *D) { Alignment = Types.getContext().getASTRecordLayout(D).getAlignment(); Packed = D->hasAttr(); + + IsMsStruct = D->hasAttr(); if (D->isUnion()) { LayoutUnion(D); @@ -190,6 +212,7 @@ void CGRecordLayoutBuilder::Layout(const RecordDecl *D) { // We weren't able to layout the struct. Try again with a packed struct Packed = true; + LastLaidOutBase.invalidate(); NextFieldOffset = CharUnits::Zero(); FieldTypes.clear(); Fields.clear(); @@ -242,7 +265,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, assert(llvm::isPowerOf2_32(TypeSizeInBits) && "Unexpected type size!"); CGBitFieldInfo::AccessInfo Components[3]; unsigned NumComponents = 0; - unsigned AccessedTargetBits = 0; // The tumber of target bits accessed. + unsigned AccessedTargetBits = 0; // The number of target bits accessed. unsigned AccessWidth = TypeSizeInBits; // The current access width to attempt. // Round down from the field offset to find the first access position that is @@ -292,13 +315,15 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, // in higher bits. But this also reverts the bytes, so fix this here by reverting // the byte offset on big-endian machines. if (Types.getTargetData().isBigEndian()) { - AI.FieldByteOffset = (ContainingTypeSizeInBits - AccessStart - AccessWidth )/8; + AI.FieldByteOffset = Types.getContext().toCharUnitsFromBits( + ContainingTypeSizeInBits - AccessStart - AccessWidth); } else { - AI.FieldByteOffset = AccessStart / 8; + AI.FieldByteOffset = Types.getContext().toCharUnitsFromBits(AccessStart); } AI.FieldBitStart = AccessBitsInFieldStart - AccessStart; AI.AccessWidth = AccessWidth; - AI.AccessAlignment = llvm::MinAlign(ContainingTypeAlign, AccessStart) / 8; + AI.AccessAlignment = Types.getContext().toCharUnitsFromBits( + llvm::MinAlign(ContainingTypeAlign, AccessStart)); AI.TargetBitOffset = AccessedTargetBits; AI.TargetBitWidth = AccessBitsInFieldSize; @@ -332,34 +357,51 @@ void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D, return; uint64_t nextFieldOffsetInBits = Types.getContext().toBits(NextFieldOffset); - unsigned numBytesToAppend; + CharUnits numBytesToAppend; + unsigned charAlign = Types.getContext().Target.getCharAlign(); + + if (fieldOffset < nextFieldOffsetInBits && !BitsAvailableInLastField) { + assert(fieldOffset % charAlign == 0 && + "Field offset not aligned correctly"); + + CharUnits fieldOffsetInCharUnits = + Types.getContext().toCharUnitsFromBits(fieldOffset); + + // Try to resize the last base field. + if (ResizeLastBaseFieldIfNecessary(fieldOffsetInCharUnits)) + nextFieldOffsetInBits = Types.getContext().toBits(NextFieldOffset); + } if (fieldOffset < nextFieldOffsetInBits) { assert(BitsAvailableInLastField && "Bitfield size mismatch!"); assert(!NextFieldOffset.isZero() && "Must have laid out at least one byte"); // The bitfield begins in the previous bit-field. - numBytesToAppend = - llvm::RoundUpToAlignment(fieldSize - BitsAvailableInLastField, 8) / 8; + numBytesToAppend = Types.getContext().toCharUnitsFromBits( + llvm::RoundUpToAlignment(fieldSize - BitsAvailableInLastField, + charAlign)); } else { - assert(fieldOffset % 8 == 0 && "Field offset not aligned correctly"); + assert(fieldOffset % charAlign == 0 && + "Field offset not aligned correctly"); // Append padding if necessary. - AppendPadding(CharUnits::fromQuantity(fieldOffset / 8), CharUnits::One()); + AppendPadding(Types.getContext().toCharUnitsFromBits(fieldOffset), + CharUnits::One()); - numBytesToAppend = llvm::RoundUpToAlignment(fieldSize, 8) / 8; + numBytesToAppend = Types.getContext().toCharUnitsFromBits( + llvm::RoundUpToAlignment(fieldSize, charAlign)); - assert(numBytesToAppend && "No bytes to append!"); + assert(!numBytesToAppend.isZero() && "No bytes to append!"); } // Add the bit field info. BitFields.insert(std::make_pair(D, CGBitFieldInfo::MakeInfo(Types, D, fieldOffset, fieldSize))); - AppendBytes(CharUnits::fromQuantity(numBytesToAppend)); + AppendBytes(numBytesToAppend); BitsAvailableInLastField = - NextFieldOffset.getQuantity() * 8 - (fieldOffset + fieldSize); + Types.getContext().toBits(NextFieldOffset) - (fieldOffset + fieldSize); } bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, @@ -410,6 +452,14 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, CharUnits alignedNextFieldOffsetInBytes = NextFieldOffset.RoundUpToAlignment(typeAlignment); + if (fieldOffsetInBytes < alignedNextFieldOffsetInBytes) { + // Try to resize the last base field. + if (ResizeLastBaseFieldIfNecessary(fieldOffsetInBytes)) { + alignedNextFieldOffsetInBytes = + NextFieldOffset.RoundUpToAlignment(typeAlignment); + } + } + if (fieldOffsetInBytes < alignedNextFieldOffsetInBytes) { assert(!Packed && "Could not place field even with packed struct!"); return false; @@ -421,6 +471,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, Fields[D] = FieldTypes.size(); AppendField(fieldOffsetInBytes, Ty); + LastLaidOutBase.invalidate(); return true; } @@ -436,11 +487,12 @@ CGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field, return 0; const llvm::Type *FieldTy = llvm::Type::getInt8Ty(Types.getLLVMContext()); - unsigned NumBytesToAppend = - llvm::RoundUpToAlignment(FieldSize, 8) / 8; + CharUnits NumBytesToAppend = Types.getContext().toCharUnitsFromBits( + llvm::RoundUpToAlignment(FieldSize, + Types.getContext().Target.getCharAlign())); - if (NumBytesToAppend > 1) - FieldTy = llvm::ArrayType::get(FieldTy, NumBytesToAppend); + if (NumBytesToAppend > CharUnits::One()) + FieldTy = llvm::ArrayType::get(FieldTy, NumBytesToAppend.getQuantity()); // Add the bit field info. BitFields.insert(std::make_pair(Field, @@ -516,11 +568,16 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { void CGRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *base, const CGRecordLayout &baseLayout, CharUnits baseOffset) { + ResizeLastBaseFieldIfNecessary(baseOffset); + AppendPadding(baseOffset, CharUnits::One()); const ASTRecordLayout &baseASTLayout = Types.getContext().getASTRecordLayout(base); + LastLaidOutBase.Offset = NextFieldOffset; + LastLaidOutBase.NonVirtualSize = baseASTLayout.getNonVirtualSize(); + // Fields and bases can be laid out in the tail padding of previous // bases. If this happens, we need to allocate the base as an i8 // array; otherwise, we can use the subobject type. However, @@ -529,20 +586,10 @@ void CGRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *base, // approximation, which is to use the base subobject type if it // has the same LLVM storage size as the nvsize. - // The nvsize, i.e. the unpadded size of the base class. - CharUnits nvsize = baseASTLayout.getNonVirtualSize(); - -#if 0 const llvm::StructType *subobjectType = baseLayout.getBaseSubobjectLLVMType(); - const llvm::StructLayout *baseLLVMLayout = - Types.getTargetData().getStructLayout(subobjectType); - CharUnits stsize = CharUnits::fromQuantity(baseLLVMLayout->getSizeInBytes()); + AppendField(baseOffset, subobjectType); - if (nvsize == stsize) - AppendField(baseOffset, subobjectType); - else -#endif - AppendBytes(nvsize); + Types.addBaseSubobjectTypeName(base, baseLayout); } void CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *base, @@ -698,9 +745,22 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { LayoutNonVirtualBases(RD, Layout); unsigned FieldNo = 0; - + const FieldDecl *LastFD = 0; + for (RecordDecl::field_iterator Field = D->field_begin(), FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { + if (IsMsStruct) { + // Zero-length bitfields following non-bitfield members are + // ignored: + const FieldDecl *FD = (*Field); + if (Types.getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD) || + Types.getContext().ZeroBitfieldFollowsBitfield(FD, LastFD)) { + --FieldNo; + continue; + } + LastFD = FD; + } + if (!LayoutField(*Field, Layout.getFieldOffset(FieldNo))) { assert(!Packed && "Could not layout fields even with a packed LLVM struct!"); @@ -724,27 +784,25 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { } // Append tail padding if necessary. - AppendTailPadding(Types.getContext().toBits(Layout.getSize())); + AppendTailPadding(Layout.getSize()); return true; } -void CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) { - assert(RecordSize % 8 == 0 && "Invalid record size!"); +void CGRecordLayoutBuilder::AppendTailPadding(CharUnits RecordSize) { + ResizeLastBaseFieldIfNecessary(RecordSize); - CharUnits RecordSizeInBytes = - Types.getContext().toCharUnitsFromBits(RecordSize); - assert(NextFieldOffset <= RecordSizeInBytes && "Size mismatch!"); + assert(NextFieldOffset <= RecordSize && "Size mismatch!"); CharUnits AlignedNextFieldOffset = NextFieldOffset.RoundUpToAlignment(getAlignmentAsLLVMStruct()); - if (AlignedNextFieldOffset == RecordSizeInBytes) { + if (AlignedNextFieldOffset == RecordSize) { // We don't need any padding. return; } - CharUnits NumPadBytes = RecordSizeInBytes - NextFieldOffset; + CharUnits NumPadBytes = RecordSize - NextFieldOffset; AppendBytes(NumPadBytes); } @@ -777,6 +835,24 @@ void CGRecordLayoutBuilder::AppendPadding(CharUnits fieldOffset, } } +bool CGRecordLayoutBuilder::ResizeLastBaseFieldIfNecessary(CharUnits offset) { + // Check if we have a base to resize. + if (!LastLaidOutBase.isValid()) + return false; + + // This offset does not overlap with the tail padding. + if (offset >= NextFieldOffset) + return false; + + // Restore the field offset and append an i8 array instead. + FieldTypes.pop_back(); + NextFieldOffset = LastLaidOutBase.Offset; + AppendBytes(LastLaidOutBase.NonVirtualSize); + LastLaidOutBase.invalidate(); + + return true; +} + const llvm::Type *CGRecordLayoutBuilder::getByteArrayType(CharUnits numBytes) { assert(!numBytes.isZero() && "Empty byte arrays aren't allowed."); @@ -903,6 +979,8 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D); RecordDecl::field_iterator it = D->field_begin(); + const FieldDecl *LastFD = 0; + bool IsMsStruct = D->hasAttr(); for (unsigned i = 0, e = AST_RL.getFieldCount(); i != e; ++i, ++it) { const FieldDecl *FD = *it; @@ -912,13 +990,27 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { unsigned FieldNo = RL->getLLVMFieldNo(FD); assert(AST_RL.getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) && "Invalid field offset!"); + LastFD = FD; continue; } + if (IsMsStruct) { + // Zero-length bitfields following non-bitfield members are + // ignored: + if (getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD) || + getContext().ZeroBitfieldFollowsBitfield(FD, LastFD)) { + --i; + continue; + } + LastFD = FD; + } + // Ignore unnamed bit-fields. - if (!FD->getDeclName()) + if (!FD->getDeclName()) { + LastFD = FD; continue; - + } + const CGBitFieldInfo &Info = RL->getBitFieldInfo(FD); for (unsigned i = 0, e = Info.getNumComponents(); i != e; ++i) { const CGBitFieldInfo::AccessInfo &AI = Info.getComponent(i); @@ -926,7 +1018,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { // Verify that every component access is within the structure. uint64_t FieldOffset = SL->getElementOffsetInBits(AI.FieldIndex); uint64_t AccessBitOffset = FieldOffset + - getContext().toBits(CharUnits::fromQuantity(AI.FieldByteOffset)); + getContext().toBits(AI.FieldByteOffset); assert(AccessBitOffset + AI.AccessWidth <= TypeSizeInBits && "Invalid bit-field access (out of range)!"); } @@ -985,11 +1077,11 @@ void CGBitFieldInfo::print(llvm::raw_ostream &OS) const { OS.indent(8); OS << "\n"; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp index cd238112ed1d..99bc3f49ce92 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp @@ -72,6 +72,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { switch (S->getStmtClass()) { case Stmt::NoStmtClass: case Stmt::CXXCatchStmtClass: + case Stmt::SEHExceptStmtClass: + case Stmt::SEHFinallyStmtClass: llvm_unreachable("invalid statement class to emit generically"); case Stmt::NullStmtClass: case Stmt::CompoundStmtClass: @@ -153,6 +155,11 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::CXXTryStmtClass: EmitCXXTryStmt(cast(*S)); break; + case Stmt::CXXForRangeStmtClass: + EmitCXXForRangeStmt(cast(*S)); + case Stmt::SEHTryStmtClass: + // FIXME Not yet implemented + break; } } @@ -359,10 +366,12 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { // If the condition constant folds and can be elided, try to avoid emitting // the condition and the dead arm of the if/else. - if (int Cond = ConstantFoldsToSimpleInteger(S.getCond())) { + bool CondConstant; + if (ConstantFoldsToSimpleInteger(S.getCond(), CondConstant)) { // Figure out which block (then or else) is executed. - const Stmt *Executed = S.getThen(), *Skipped = S.getElse(); - if (Cond == -1) // Condition false? + const Stmt *Executed = S.getThen(); + const Stmt *Skipped = S.getElse(); + if (!CondConstant) // Condition false? std::swap(Executed, Skipped); // If the skipped block has no labels in it, just emit the executed block. @@ -395,11 +404,17 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { // Emit the 'else' code if present. if (const Stmt *Else = S.getElse()) { + // There is no need to emit line number for unconditional branch. + if (getDebugInfo()) + Builder.SetCurrentDebugLocation(llvm::DebugLoc()); EmitBlock(ElseBlock); { RunCleanupsScope ElseScope(*this); EmitStmt(Else); } + // There is no need to emit line number for unconditional branch. + if (getDebugInfo()) + Builder.SetCurrentDebugLocation(llvm::DebugLoc()); EmitBranch(ContBlock); } @@ -628,6 +643,80 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) { EmitBlock(LoopExit.getBlock(), true); } +void CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S) { + JumpDest LoopExit = getJumpDestInCurrentScope("for.end"); + + RunCleanupsScope ForScope(*this); + + CGDebugInfo *DI = getDebugInfo(); + if (DI) { + DI->setLocation(S.getSourceRange().getBegin()); + DI->EmitRegionStart(Builder); + } + + // Evaluate the first pieces before the loop. + EmitStmt(S.getRangeStmt()); + EmitStmt(S.getBeginEndStmt()); + + // Start the loop with a block that tests the condition. + // If there's an increment, the continue scope will be overwritten + // later. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + EmitBlock(CondBlock); + + // If there are any cleanups between here and the loop-exit scope, + // create a block to stage a loop exit along. + llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); + if (ForScope.requiresCleanups()) + ExitBlock = createBasicBlock("for.cond.cleanup"); + + // The loop body, consisting of the specified body and the loop variable. + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + + // The body is executed if the expression, contextually converted + // to bool, is true. + llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); + Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock); + + if (ExitBlock != LoopExit.getBlock()) { + EmitBlock(ExitBlock); + EmitBranchThroughCleanup(LoopExit); + } + + EmitBlock(ForBody); + + // Create a block for the increment. In case of a 'continue', we jump there. + JumpDest Continue = getJumpDestInCurrentScope("for.inc"); + + // Store the blocks to use for break and continue. + BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); + + { + // Create a separate cleanup scope for the loop variable and body. + RunCleanupsScope BodyScope(*this); + EmitStmt(S.getLoopVarStmt()); + EmitStmt(S.getBody()); + } + + // If there is an increment, emit it next. + EmitBlock(Continue.getBlock()); + EmitStmt(S.getInc()); + + BreakContinueStack.pop_back(); + + EmitBranch(CondBlock); + + ForScope.ForceCleanup(); + + if (DI) { + DI->setLocation(S.getSourceRange().getEnd()); + DI->EmitRegionEnd(Builder); + } + + // Emit the fall-through block. + EmitBlock(LoopExit.getBlock(), true); +} + void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) { if (RV.isScalar()) { Builder.CreateStore(RV.getScalarVal(), ReturnValue); @@ -745,8 +834,7 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) { if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) { // Range is small enough to add multiple switch instruction cases. for (unsigned i = 0, e = Range.getZExtValue() + 1; i != e; ++i) { - SwitchInsn->addCase(llvm::ConstantInt::get(getLLVMContext(), LHS), - CaseDest); + SwitchInsn->addCase(Builder.getInt(LHS), CaseDest); LHS++; } return; @@ -767,11 +855,9 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) { // Emit range check. llvm::Value *Diff = - Builder.CreateSub(SwitchInsn->getCondition(), - llvm::ConstantInt::get(getLLVMContext(), LHS), "tmp"); + Builder.CreateSub(SwitchInsn->getCondition(), Builder.getInt(LHS), "tmp"); llvm::Value *Cond = - Builder.CreateICmpULE(Diff, llvm::ConstantInt::get(getLLVMContext(), Range), - "inbounds"); + Builder.CreateICmpULE(Diff, Builder.getInt(Range), "inbounds"); Builder.CreateCondBr(Cond, CaseDest, FalseDest); // Restore the appropriate insertion point. @@ -782,16 +868,37 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) { } void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { + // Handle case ranges. if (S.getRHS()) { EmitCaseStmtRange(S); return; } + llvm::ConstantInt *CaseVal = + Builder.getInt(S.getLHS()->EvaluateAsInt(getContext())); + + // If the body of the case is just a 'break', and if there was no fallthrough, + // try to not emit an empty block. + if (isa(S.getSubStmt())) { + JumpDest Block = BreakContinueStack.back().BreakBlock; + + // Only do this optimization if there are no cleanups that need emitting. + if (isObviouslyBranchWithoutCleanups(Block)) { + SwitchInsn->addCase(CaseVal, Block.getBlock()); + + // If there was a fallthrough into this case, make sure to redirect it to + // the end of the switch as well. + if (Builder.GetInsertBlock()) { + Builder.CreateBr(Block.getBlock()); + Builder.ClearInsertionPoint(); + } + return; + } + } + EmitBlock(createBasicBlock("sw.bb")); llvm::BasicBlock *CaseDest = Builder.GetInsertBlock(); - llvm::APSInt CaseVal = S.getLHS()->EvaluateAsInt(getContext()); - SwitchInsn->addCase(llvm::ConstantInt::get(getLLVMContext(), CaseVal), - CaseDest); + SwitchInsn->addCase(CaseVal, CaseDest); // Recursively emitting the statement is acceptable, but is not wonderful for // code where we have many case statements nested together, i.e.: @@ -805,13 +912,12 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { const CaseStmt *CurCase = &S; const CaseStmt *NextCase = dyn_cast(S.getSubStmt()); - // Otherwise, iteratively add consequtive cases to this switch stmt. + // Otherwise, iteratively add consecutive cases to this switch stmt. while (NextCase && NextCase->getRHS() == 0) { CurCase = NextCase; - CaseVal = CurCase->getLHS()->EvaluateAsInt(getContext()); - SwitchInsn->addCase(llvm::ConstantInt::get(getLLVMContext(), CaseVal), - CaseDest); - + llvm::ConstantInt *CaseVal = + Builder.getInt(CurCase->getLHS()->EvaluateAsInt(getContext())); + SwitchInsn->addCase(CaseVal, CaseDest); NextCase = dyn_cast(CurCase->getSubStmt()); } @@ -827,6 +933,207 @@ void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) { EmitStmt(S.getSubStmt()); } +/// CollectStatementsForCase - Given the body of a 'switch' statement and a +/// constant value that is being switched on, see if we can dead code eliminate +/// the body of the switch to a simple series of statements to emit. Basically, +/// on a switch (5) we want to find these statements: +/// case 5: +/// printf(...); <-- +/// ++i; <-- +/// break; +/// +/// and add them to the ResultStmts vector. If it is unsafe to do this +/// transformation (for example, one of the elided statements contains a label +/// that might be jumped to), return CSFC_Failure. If we handled it and 'S' +/// should include statements after it (e.g. the printf() line is a substmt of +/// the case) then return CSFC_FallThrough. If we handled it and found a break +/// statement, then return CSFC_Success. +/// +/// If Case is non-null, then we are looking for the specified case, checking +/// that nothing we jump over contains labels. If Case is null, then we found +/// the case and are looking for the break. +/// +/// If the recursive walk actually finds our Case, then we set FoundCase to +/// true. +/// +enum CSFC_Result { CSFC_Failure, CSFC_FallThrough, CSFC_Success }; +static CSFC_Result CollectStatementsForCase(const Stmt *S, + const SwitchCase *Case, + bool &FoundCase, + llvm::SmallVectorImpl &ResultStmts) { + // If this is a null statement, just succeed. + if (S == 0) + return Case ? CSFC_Success : CSFC_FallThrough; + + // If this is the switchcase (case 4: or default) that we're looking for, then + // we're in business. Just add the substatement. + if (const SwitchCase *SC = dyn_cast(S)) { + if (S == Case) { + FoundCase = true; + return CollectStatementsForCase(SC->getSubStmt(), 0, FoundCase, + ResultStmts); + } + + // Otherwise, this is some other case or default statement, just ignore it. + return CollectStatementsForCase(SC->getSubStmt(), Case, FoundCase, + ResultStmts); + } + + // If we are in the live part of the code and we found our break statement, + // return a success! + if (Case == 0 && isa(S)) + return CSFC_Success; + + // If this is a switch statement, then it might contain the SwitchCase, the + // break, or neither. + if (const CompoundStmt *CS = dyn_cast(S)) { + // Handle this as two cases: we might be looking for the SwitchCase (if so + // the skipped statements must be skippable) or we might already have it. + CompoundStmt::const_body_iterator I = CS->body_begin(), E = CS->body_end(); + if (Case) { + // Keep track of whether we see a skipped declaration. The code could be + // using the declaration even if it is skipped, so we can't optimize out + // the decl if the kept statements might refer to it. + bool HadSkippedDecl = false; + + // If we're looking for the case, just see if we can skip each of the + // substatements. + for (; Case && I != E; ++I) { + HadSkippedDecl |= isa(I); + + switch (CollectStatementsForCase(*I, Case, FoundCase, ResultStmts)) { + case CSFC_Failure: return CSFC_Failure; + case CSFC_Success: + // A successful result means that either 1) that the statement doesn't + // have the case and is skippable, or 2) does contain the case value + // and also contains the break to exit the switch. In the later case, + // we just verify the rest of the statements are elidable. + if (FoundCase) { + // If we found the case and skipped declarations, we can't do the + // optimization. + if (HadSkippedDecl) + return CSFC_Failure; + + for (++I; I != E; ++I) + if (CodeGenFunction::ContainsLabel(*I, true)) + return CSFC_Failure; + return CSFC_Success; + } + break; + case CSFC_FallThrough: + // If we have a fallthrough condition, then we must have found the + // case started to include statements. Consider the rest of the + // statements in the compound statement as candidates for inclusion. + assert(FoundCase && "Didn't find case but returned fallthrough?"); + // We recursively found Case, so we're not looking for it anymore. + Case = 0; + + // If we found the case and skipped declarations, we can't do the + // optimization. + if (HadSkippedDecl) + return CSFC_Failure; + break; + } + } + } + + // If we have statements in our range, then we know that the statements are + // live and need to be added to the set of statements we're tracking. + for (; I != E; ++I) { + switch (CollectStatementsForCase(*I, 0, FoundCase, ResultStmts)) { + case CSFC_Failure: return CSFC_Failure; + case CSFC_FallThrough: + // A fallthrough result means that the statement was simple and just + // included in ResultStmt, keep adding them afterwards. + break; + case CSFC_Success: + // A successful result means that we found the break statement and + // stopped statement inclusion. We just ensure that any leftover stmts + // are skippable and return success ourselves. + for (++I; I != E; ++I) + if (CodeGenFunction::ContainsLabel(*I, true)) + return CSFC_Failure; + return CSFC_Success; + } + } + + return Case ? CSFC_Success : CSFC_FallThrough; + } + + // Okay, this is some other statement that we don't handle explicitly, like a + // for statement or increment etc. If we are skipping over this statement, + // just verify it doesn't have labels, which would make it invalid to elide. + if (Case) { + if (CodeGenFunction::ContainsLabel(S, true)) + return CSFC_Failure; + return CSFC_Success; + } + + // Otherwise, we want to include this statement. Everything is cool with that + // so long as it doesn't contain a break out of the switch we're in. + if (CodeGenFunction::containsBreak(S)) return CSFC_Failure; + + // Otherwise, everything is great. Include the statement and tell the caller + // that we fall through and include the next statement as well. + ResultStmts.push_back(S); + return CSFC_FallThrough; +} + +/// FindCaseStatementsForValue - Find the case statement being jumped to and +/// then invoke CollectStatementsForCase to find the list of statements to emit +/// for a switch on constant. See the comment above CollectStatementsForCase +/// for more details. +static bool FindCaseStatementsForValue(const SwitchStmt &S, + const llvm::APInt &ConstantCondValue, + llvm::SmallVectorImpl &ResultStmts, + ASTContext &C) { + // First step, find the switch case that is being branched to. We can do this + // efficiently by scanning the SwitchCase list. + const SwitchCase *Case = S.getSwitchCaseList(); + const DefaultStmt *DefaultCase = 0; + + for (; Case; Case = Case->getNextSwitchCase()) { + // It's either a default or case. Just remember the default statement in + // case we're not jumping to any numbered cases. + if (const DefaultStmt *DS = dyn_cast(Case)) { + DefaultCase = DS; + continue; + } + + // Check to see if this case is the one we're looking for. + const CaseStmt *CS = cast(Case); + // Don't handle case ranges yet. + if (CS->getRHS()) return false; + + // If we found our case, remember it as 'case'. + if (CS->getLHS()->EvaluateAsInt(C) == ConstantCondValue) + break; + } + + // If we didn't find a matching case, we use a default if it exists, or we + // elide the whole switch body! + if (Case == 0) { + // It is safe to elide the body of the switch if it doesn't contain labels + // etc. If it is safe, return successfully with an empty ResultStmts list. + if (DefaultCase == 0) + return !CodeGenFunction::ContainsLabel(&S); + Case = DefaultCase; + } + + // Ok, we know which case is being jumped to, try to collect all the + // statements that follow it. This can fail for a variety of reasons. Also, + // check to see that the recursive walk actually found our case statement. + // Insane cases like this can fail to find it in the recursive walk since we + // don't handle every stmt kind: + // switch (4) { + // while (1) { + // case 4: ... + bool FoundCase = false; + return CollectStatementsForCase(S.getBody(), Case, FoundCase, + ResultStmts) != CSFC_Failure && + FoundCase; +} + void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) { JumpDest SwitchExit = getJumpDestInCurrentScope("sw.epilog"); @@ -835,6 +1142,23 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) { if (S.getConditionVariable()) EmitAutoVarDecl(*S.getConditionVariable()); + // See if we can constant fold the condition of the switch and therefore only + // emit the live case statement (if any) of the switch. + llvm::APInt ConstantCondValue; + if (ConstantFoldsToSimpleInteger(S.getCond(), ConstantCondValue)) { + llvm::SmallVector CaseStmts; + if (FindCaseStatementsForValue(S, ConstantCondValue, CaseStmts, + getContext())) { + RunCleanupsScope ExecutedScope(*this); + + // Okay, we can dead code eliminate everything except this case. Emit the + // specified series of statements and we're good. + for (unsigned i = 0, e = CaseStmts.size(); i != e; ++i) + EmitStmt(CaseStmts[i]); + return; + } + } + llvm::Value *CondV = EmitScalarExpr(S.getCond()); // Handle nested switch statements. @@ -1031,7 +1355,7 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str, } } - return llvm::MDNode::get(CGF.getLLVMContext(), Locs.data(), Locs.size()); + return llvm::MDNode::get(CGF.getLLVMContext(), Locs); } void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp index 78b2dbe2ba22..a6849f8f3d21 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp @@ -53,6 +53,10 @@ class VTTBuilder { /// GenerateDefinition - Whether the VTT builder should generate LLVM IR for /// the VTT. bool GenerateDefinition; + + /// The linkage to use for any construction vtables required by this VTT. + /// Only required if we're building a definition. + llvm::GlobalVariable::LinkageTypes LinkageForConstructionVTables; /// GetAddrOfVTable - Returns the address of the vtable for the base class in /// the given vtable class. @@ -109,7 +113,9 @@ class VTTBuilder { public: VTTBuilder(CodeGenModule &CGM, const CXXRecordDecl *MostDerivedClass, - bool GenerateDefinition); + bool GenerateDefinition, + llvm::GlobalVariable::LinkageTypes LinkageForConstructionVTables + = (llvm::GlobalVariable::LinkageTypes) -1); // getVTTComponents - Returns a reference to the VTT components. const VTTComponentsVectorTy &getVTTComponents() const { @@ -132,13 +138,19 @@ class VTTBuilder { VTTBuilder::VTTBuilder(CodeGenModule &CGM, const CXXRecordDecl *MostDerivedClass, - bool GenerateDefinition) + bool GenerateDefinition, + llvm::GlobalVariable::LinkageTypes LinkageForConstructionVTables) : CGM(CGM), MostDerivedClass(MostDerivedClass), MostDerivedClassLayout(CGM.getContext().getASTRecordLayout(MostDerivedClass)), - GenerateDefinition(GenerateDefinition) { + GenerateDefinition(GenerateDefinition), + LinkageForConstructionVTables(LinkageForConstructionVTables) { + assert(!GenerateDefinition || + LinkageForConstructionVTables + != (llvm::GlobalVariable::LinkageTypes) -1); // Lay out this VTT. - LayoutVTT(BaseSubobject(MostDerivedClass, 0), /*BaseIsVirtual=*/false); + LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()), + /*BaseIsVirtual=*/false); } llvm::Constant * @@ -148,7 +160,7 @@ VTTBuilder::GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual, return 0; if (Base.getBase() == MostDerivedClass) { - assert(Base.getBaseOffset() == 0 && + assert(Base.getBaseOffset().isZero() && "Most derived class vtable must have a zero offset!"); // This is a regular vtable. return CGM.getVTables().GetAddrOfVTable(MostDerivedClass); @@ -156,6 +168,7 @@ VTTBuilder::GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual, return CGM.getVTables().GenerateConstructionVTable(MostDerivedClass, Base, BaseIsVirtual, + LinkageForConstructionVTables, AddressPoints); } @@ -217,8 +230,8 @@ void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { cast(I->getType()->getAs()->getDecl()); const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - uint64_t BaseOffset = Base.getBaseOffset() + - Layout.getBaseClassOffsetInBits(BaseDecl); + CharUnits BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); // Layout the VTT for this base. LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false); @@ -256,19 +269,19 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual; bool BaseDeclIsNonVirtualPrimaryBase = false; - uint64_t BaseOffset; + CharUnits BaseOffset; if (I->isVirtual()) { // Ignore virtual bases that we've already visited. if (!VBases.insert(BaseDecl)) continue; - BaseOffset = MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl); + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); BaseDeclIsMorallyVirtual = true; } else { const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - BaseOffset = - Base.getBaseOffset() + Layout.getBaseClassOffsetInBits(BaseDecl); + BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); if (!Layout.isPrimaryBaseVirtual() && Layout.getPrimaryBase() == BaseDecl) @@ -283,8 +296,8 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, if (!BaseDeclIsNonVirtualPrimaryBase && (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) { // Add the vtable pointer. - AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTable, VTableClass, - AddressPoints); + AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTable, + VTableClass, AddressPoints); } // And lay out the secondary virtual pointers for the base class. @@ -316,8 +329,8 @@ void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, if (!VBases.insert(BaseDecl)) continue; - uint64_t BaseOffset = - MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl); + CharUnits BaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true); } @@ -370,7 +383,7 @@ void CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl *RD) { - VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/true); + VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/true, Linkage); const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); const llvm::ArrayType *ArrayType = diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp index 891697f4cd09..581467c53751 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp @@ -43,15 +43,16 @@ struct BaseOffset { /// (Or the offset from the virtual base class to the base class, if the /// path from the derived class to the base class involves a virtual base /// class. - int64_t NonVirtualOffset; + CharUnits NonVirtualOffset; - BaseOffset() : DerivedClass(0), VirtualBase(0), NonVirtualOffset(0) { } + BaseOffset() : DerivedClass(0), VirtualBase(0), + NonVirtualOffset(CharUnits::Zero()) { } BaseOffset(const CXXRecordDecl *DerivedClass, - const CXXRecordDecl *VirtualBase, int64_t NonVirtualOffset) + const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset) : DerivedClass(DerivedClass), VirtualBase(VirtualBase), NonVirtualOffset(NonVirtualOffset) { } - bool isEmpty() const { return !NonVirtualOffset && !VirtualBase; } + bool isEmpty() const { return NonVirtualOffset.isZero() && !VirtualBase; } }; /// FinalOverriders - Contains the final overrider member functions for all @@ -64,9 +65,9 @@ class FinalOverriders { const CXXMethodDecl *Method; /// Offset - the base offset of the overrider in the layout class. - uint64_t Offset; + CharUnits Offset; - OverriderInfo() : Method(0), Offset(0) { } + OverriderInfo() : Method(0), Offset(CharUnits::Zero()) { } }; private: @@ -77,7 +78,7 @@ class FinalOverriders { /// MostDerivedClassOffset - If we're building final overriders for a /// construction vtable, this holds the offset from the layout class to the /// most derived class. - const uint64_t MostDerivedClassOffset; + const CharUnits MostDerivedClassOffset; /// LayoutClass - The class we're using for layout information. Will be /// different than the most derived class if the final overriders are for a @@ -91,7 +92,7 @@ class FinalOverriders { /// MethodBaseOffsetPairTy - Uniquely identifies a member function /// in a base subobject. - typedef std::pair MethodBaseOffsetPairTy; + typedef std::pair MethodBaseOffsetPairTy; typedef llvm::DenseMap OverridersMapTy; @@ -104,14 +105,14 @@ class FinalOverriders { /// as a record decl and a subobject number) and its offsets in the most /// derived class as well as the layout class. typedef llvm::DenseMap, - uint64_t> SubobjectOffsetMapTy; + CharUnits> SubobjectOffsetMapTy; typedef llvm::DenseMap SubobjectCountMapTy; /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the /// given base. void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, - uint64_t OffsetInLayoutClass, + CharUnits OffsetInLayoutClass, SubobjectOffsetMapTy &SubobjectOffsets, SubobjectOffsetMapTy &SubobjectLayoutClassOffsets, SubobjectCountMapTy &SubobjectCounts); @@ -125,13 +126,13 @@ class FinalOverriders { public: FinalOverriders(const CXXRecordDecl *MostDerivedClass, - uint64_t MostDerivedClassOffset, + CharUnits MostDerivedClassOffset, const CXXRecordDecl *LayoutClass); /// getOverrider - Get the final overrider for the given method declaration in /// the subobject with the given base offset. OverriderInfo getOverrider(const CXXMethodDecl *MD, - uint64_t BaseOffset) const { + CharUnits BaseOffset) const { assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) && "Did not find overrider!"); @@ -141,7 +142,8 @@ class FinalOverriders { /// dump - dump the final overriders. void dump() { VisitedVirtualBasesSetTy VisitedVirtualBases; - dump(llvm::errs(), BaseSubobject(MostDerivedClass, 0), VisitedVirtualBases); + dump(llvm::errs(), BaseSubobject(MostDerivedClass, CharUnits::Zero()), + VisitedVirtualBases); } }; @@ -149,7 +151,7 @@ class FinalOverriders { #define DUMP_OVERRIDERS 0 FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, - uint64_t MostDerivedClassOffset, + CharUnits MostDerivedClassOffset, const CXXRecordDecl *LayoutClass) : MostDerivedClass(MostDerivedClass), MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass), @@ -160,9 +162,11 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, SubobjectOffsetMapTy SubobjectOffsets; SubobjectOffsetMapTy SubobjectLayoutClassOffsets; SubobjectCountMapTy SubobjectCounts; - ComputeBaseOffsets(BaseSubobject(MostDerivedClass, 0), /*IsVirtual=*/false, - MostDerivedClassOffset, SubobjectOffsets, - SubobjectLayoutClassOffsets, SubobjectCounts); + ComputeBaseOffsets(BaseSubobject(MostDerivedClass, CharUnits::Zero()), + /*IsVirtual=*/false, + MostDerivedClassOffset, + SubobjectOffsets, SubobjectLayoutClassOffsets, + SubobjectCounts); // Get the the final overriders. CXXFinalOverriderMap FinalOverriders; @@ -180,7 +184,7 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, SubobjectNumber)) && "Did not find subobject offset!"); - uint64_t BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(), + CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(), SubobjectNumber)]; assert(I->second.size() == 1 && "Final overrider is not unique!"); @@ -190,7 +194,7 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, assert(SubobjectLayoutClassOffsets.count( std::make_pair(OverriderRD, Method.Subobject)) && "Did not find subobject offset!"); - uint64_t OverriderOffset = + CharUnits OverriderOffset = SubobjectLayoutClassOffsets[std::make_pair(OverriderRD, Method.Subobject)]; @@ -211,7 +215,7 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, static BaseOffset ComputeBaseOffset(ASTContext &Context, const CXXRecordDecl *DerivedRD, const CXXBasePath &Path) { - int64_t NonVirtualOffset = 0; + CharUnits NonVirtualOffset = CharUnits::Zero(); unsigned NonVirtualStart = 0; const CXXRecordDecl *VirtualBase = 0; @@ -240,13 +244,13 @@ static BaseOffset ComputeBaseOffset(ASTContext &Context, const RecordType *BaseType = Element.Base->getType()->getAs(); const CXXRecordDecl *Base = cast(BaseType->getDecl()); - NonVirtualOffset += Layout.getBaseClassOffsetInBits(Base); + NonVirtualOffset += Layout.getBaseClassOffset(Base); } // FIXME: This should probably use CharUnits or something. Maybe we should // even change the base offsets in ASTRecordLayout to be specified in // CharUnits. - return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset / 8); + return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset); } @@ -321,7 +325,7 @@ ComputeReturnAdjustmentBaseOffset(ASTContext &Context, void FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, - uint64_t OffsetInLayoutClass, + CharUnits OffsetInLayoutClass, SubobjectOffsetMapTy &SubobjectOffsets, SubobjectOffsetMapTy &SubobjectLayoutClassOffsets, SubobjectCountMapTy &SubobjectCounts) { @@ -337,8 +341,7 @@ FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber)) && "Subobject offset already exists!"); - SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = - Base.getBaseOffset(); + SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.getBaseOffset(); SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] = OffsetInLayoutClass; @@ -348,8 +351,8 @@ FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, const CXXRecordDecl *BaseDecl = cast(I->getType()->getAs()->getDecl()); - uint64_t BaseOffset; - uint64_t BaseOffsetInLayoutClass; + CharUnits BaseOffset; + CharUnits BaseOffsetInLayoutClass; if (I->isVirtual()) { // Check if we've visited this virtual base before. if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0))) @@ -358,20 +361,21 @@ FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, const ASTRecordLayout &LayoutClassLayout = Context.getASTRecordLayout(LayoutClass); - BaseOffset = MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl); + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); BaseOffsetInLayoutClass = - LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl); + LayoutClassLayout.getVBaseClassOffset(BaseDecl); } else { const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - uint64_t Offset = Layout.getBaseClassOffsetInBits(BaseDecl); + CharUnits Offset = Layout.getBaseClassOffset(BaseDecl); BaseOffset = Base.getBaseOffset() + Offset; BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset; } - ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset), I->isVirtual(), - BaseOffsetInLayoutClass, SubobjectOffsets, - SubobjectLayoutClassOffsets, SubobjectCounts); + ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset), + I->isVirtual(), BaseOffsetInLayoutClass, + SubobjectOffsets, SubobjectLayoutClassOffsets, + SubobjectCounts); } } @@ -389,24 +393,23 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base, if (!BaseDecl->isPolymorphic()) continue; - uint64_t BaseOffset; + CharUnits BaseOffset; if (I->isVirtual()) { if (!VisitedVirtualBases.insert(BaseDecl)) { // We've visited this base before. continue; } - BaseOffset = MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl); + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); } else { - BaseOffset = Layout.getBaseClassOffsetInBits(BaseDecl) + - Base.getBaseOffset(); + BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset(); } dump(Out, BaseSubobject(BaseDecl, BaseOffset), VisitedVirtualBases); } Out << "Final overriders for (" << RD->getQualifiedNameAsString() << ", "; - Out << Base.getBaseOffset() / 8 << ")\n"; + Out << Base.getBaseOffset().getQuantity() << ")\n"; // Now dump the overriders for this base subobject. for (CXXRecordDecl::method_iterator I = RD->method_begin(), @@ -420,7 +423,7 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base, Out << " " << MD->getQualifiedNameAsString() << " - ("; Out << Overrider.Method->getQualifiedNameAsString(); - Out << ", " << ", " << Overrider.Offset / 8 << ')'; + Out << ", " << ", " << Overrider.Offset.getQuantity() << ')'; BaseOffset Offset; if (!Overrider.Method->isPure()) @@ -431,7 +434,7 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base, if (Offset.VirtualBase) Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, "; - Out << Offset.NonVirtualOffset << " nv]"; + Out << Offset.NonVirtualOffset.getQuantity() << " nv]"; } Out << "\n"; @@ -460,15 +463,15 @@ class VTableComponent { CK_UnusedFunctionPointer }; - static VTableComponent MakeVCallOffset(int64_t Offset) { + static VTableComponent MakeVCallOffset(CharUnits Offset) { return VTableComponent(CK_VCallOffset, Offset); } - static VTableComponent MakeVBaseOffset(int64_t Offset) { + static VTableComponent MakeVBaseOffset(CharUnits Offset) { return VTableComponent(CK_VBaseOffset, Offset); } - static VTableComponent MakeOffsetToTop(int64_t Offset) { + static VTableComponent MakeOffsetToTop(CharUnits Offset) { return VTableComponent(CK_OffsetToTop, Offset); } @@ -510,19 +513,19 @@ class VTableComponent { return (Kind)(Value & 0x7); } - int64_t getVCallOffset() const { + CharUnits getVCallOffset() const { assert(getKind() == CK_VCallOffset && "Invalid component kind!"); return getOffset(); } - int64_t getVBaseOffset() const { + CharUnits getVBaseOffset() const { assert(getKind() == CK_VBaseOffset && "Invalid component kind!"); return getOffset(); } - int64_t getOffsetToTop() const { + CharUnits getOffsetToTop() const { assert(getKind() == CK_OffsetToTop && "Invalid component kind!"); return getOffset(); @@ -554,13 +557,13 @@ class VTableComponent { } private: - VTableComponent(Kind ComponentKind, int64_t Offset) { + VTableComponent(Kind ComponentKind, CharUnits Offset) { assert((ComponentKind == CK_VCallOffset || ComponentKind == CK_VBaseOffset || ComponentKind == CK_OffsetToTop) && "Invalid component kind!"); - assert(Offset <= ((1LL << 56) - 1) && "Offset is too big!"); + assert(Offset.getQuantity() <= ((1LL << 56) - 1) && "Offset is too big!"); - Value = ((Offset << 3) | ComponentKind); + Value = ((Offset.getQuantity() << 3) | ComponentKind); } VTableComponent(Kind ComponentKind, uintptr_t Ptr) { @@ -576,11 +579,11 @@ class VTableComponent { Value = Ptr | ComponentKind; } - int64_t getOffset() const { + CharUnits getOffset() const { assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset || getKind() == CK_OffsetToTop) && "Invalid component kind!"); - return Value >> 3; + return CharUnits::fromQuantity(Value >> 3); } uintptr_t getPointer() const { @@ -608,7 +611,7 @@ class VTableComponent { /// VCallOffsetMap - Keeps track of vcall offsets when building a vtable. struct VCallOffsetMap { - typedef std::pair MethodAndOffsetPairTy; + typedef std::pair MethodAndOffsetPairTy; /// Offsets - Keeps track of methods and their offsets. // FIXME: This should be a real map and not a vector. @@ -623,11 +626,11 @@ struct VCallOffsetMap { /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the /// add was successful, or false if there was already a member function with /// the same signature in the map. - bool AddVCallOffset(const CXXMethodDecl *MD, int64_t OffsetOffset); + bool AddVCallOffset(const CXXMethodDecl *MD, CharUnits OffsetOffset); /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the /// vtable address point) for the given virtual member function. - int64_t getVCallOffsetOffset(const CXXMethodDecl *MD); + CharUnits getVCallOffsetOffset(const CXXMethodDecl *MD); // empty - Return whether the offset map is empty or not. bool empty() const { return Offsets.empty(); } @@ -677,7 +680,7 @@ bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS, } bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD, - int64_t OffsetOffset) { + CharUnits OffsetOffset) { // Check if we can reuse an offset. for (unsigned I = 0, E = Offsets.size(); I != E; ++I) { if (MethodsCanShareVCallOffset(Offsets[I].first, MD)) @@ -689,7 +692,7 @@ bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD, return true; } -int64_t VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) { +CharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) { // Look for an offset. for (unsigned I = 0, E = Offsets.size(); I != E; ++I) { if (MethodsCanShareVCallOffset(Offsets[I].first, MD)) @@ -697,13 +700,13 @@ int64_t VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) { } assert(false && "Should always find a vcall offset offset!"); - return 0; + return CharUnits::Zero(); } /// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets. class VCallAndVBaseOffsetBuilder { public: - typedef llvm::DenseMap + typedef llvm::DenseMap VBaseOffsetOffsetsMapTy; private: @@ -741,24 +744,25 @@ class VCallAndVBaseOffsetBuilder { /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the /// given base subobject. void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual, - uint64_t RealBaseOffset); + CharUnits RealBaseOffset); /// AddVCallOffsets - Add vcall offsets for the given base subobject. - void AddVCallOffsets(BaseSubobject Base, uint64_t VBaseOffset); + void AddVCallOffsets(BaseSubobject Base, CharUnits VBaseOffset); /// AddVBaseOffsets - Add vbase offsets for the given class. - void AddVBaseOffsets(const CXXRecordDecl *Base, uint64_t OffsetInLayoutClass); + void AddVBaseOffsets(const CXXRecordDecl *Base, + CharUnits OffsetInLayoutClass); /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in - /// bytes, relative to the vtable address point. - int64_t getCurrentOffsetOffset() const; + /// chars, relative to the vtable address point. + CharUnits getCurrentOffsetOffset() const; public: VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass, const CXXRecordDecl *LayoutClass, const FinalOverriders *Overriders, BaseSubobject Base, bool BaseIsVirtual, - uint64_t OffsetInLayoutClass) + CharUnits OffsetInLayoutClass) : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()), Overriders(Overriders) { @@ -780,7 +784,7 @@ class VCallAndVBaseOffsetBuilder { void VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual, - uint64_t RealBaseOffset) { + CharUnits RealBaseOffset) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase()); // Itanium C++ ABI 2.5.2: @@ -795,7 +799,7 @@ VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base, if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) { bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual(); - uint64_t PrimaryBaseOffset; + CharUnits PrimaryBaseOffset; // Get the base offset of the primary base. if (PrimaryBaseIsVirtual) { @@ -806,7 +810,7 @@ VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base, Context.getASTRecordLayout(MostDerivedClass); PrimaryBaseOffset = - MostDerivedClassLayout.getVBaseClassOffsetInBits(PrimaryBase); + MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase); } else { assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 && "Primary base should have a zero offset!"); @@ -814,8 +818,9 @@ VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base, PrimaryBaseOffset = Base.getBaseOffset(); } - AddVCallAndVBaseOffsets(BaseSubobject(PrimaryBase, PrimaryBaseOffset), - PrimaryBaseIsVirtual, RealBaseOffset); + AddVCallAndVBaseOffsets( + BaseSubobject(PrimaryBase,PrimaryBaseOffset), + PrimaryBaseIsVirtual, RealBaseOffset); } AddVBaseOffsets(Base.getBase(), RealBaseOffset); @@ -825,22 +830,21 @@ VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base, AddVCallOffsets(Base, RealBaseOffset); } -int64_t VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const { +CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const { // OffsetIndex is the index of this vcall or vbase offset, relative to the // vtable address point. (We subtract 3 to account for the information just // above the address point, the RTTI info, the offset to top, and the // vcall offset itself). int64_t OffsetIndex = -(int64_t)(3 + Components.size()); - // FIXME: We shouldn't use / 8 here. - int64_t OffsetOffset = OffsetIndex * - (int64_t)Context.Target.getPointerWidth(0) / 8; - + CharUnits PointerWidth = + Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); + CharUnits OffsetOffset = PointerWidth * OffsetIndex; return OffsetOffset; } void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base, - uint64_t VBaseOffset) { + CharUnits VBaseOffset) { const CXXRecordDecl *RD = Base.getBase(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); @@ -866,14 +870,14 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base, if (!MD->isVirtual()) continue; - int64_t OffsetOffset = getCurrentOffsetOffset(); + CharUnits OffsetOffset = getCurrentOffsetOffset(); // Don't add a vcall offset if we already have one for this member function // signature. if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset)) continue; - int64_t Offset = 0; + CharUnits Offset = CharUnits::Zero(); if (Overriders) { // Get the final overrider. @@ -882,11 +886,11 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base, /// The vcall offset is the offset from the virtual base to the object /// where the function was overridden. - // FIXME: We should not use / 8 here. - Offset = (int64_t)(Overrider.Offset - VBaseOffset) / 8; + Offset = Overrider.Offset - VBaseOffset; } - Components.push_back(VTableComponent::MakeVCallOffset(Offset)); + Components.push_back( + VTableComponent::MakeVCallOffset(Offset)); } // And iterate over all non-virtual bases (ignoring the primary base). @@ -902,15 +906,17 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base, continue; // Get the base offset of this base. - uint64_t BaseOffset = Base.getBaseOffset() + - Layout.getBaseClassOffsetInBits(BaseDecl); + CharUnits BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); - AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset), VBaseOffset); + AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset), + VBaseOffset); } } -void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, - uint64_t OffsetInLayoutClass) { +void +VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, + CharUnits OffsetInLayoutClass) { const ASTRecordLayout &LayoutClassLayout = Context.getASTRecordLayout(LayoutClass); @@ -922,19 +928,19 @@ void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, // Check if this is a virtual base that we haven't visited before. if (I->isVirtual() && VisitedVirtualBases.insert(BaseDecl)) { - // FIXME: We shouldn't use / 8 here. - int64_t Offset = - (int64_t)(LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl) - - OffsetInLayoutClass) / 8; + CharUnits Offset = + LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass; // Add the vbase offset offset. assert(!VBaseOffsetOffsets.count(BaseDecl) && "vbase offset offset already exists!"); - int64_t VBaseOffsetOffset = getCurrentOffsetOffset(); - VBaseOffsetOffsets.insert(std::make_pair(BaseDecl, VBaseOffsetOffset)); + CharUnits VBaseOffsetOffset = getCurrentOffsetOffset(); + VBaseOffsetOffsets.insert( + std::make_pair(BaseDecl, VBaseOffsetOffset)); - Components.push_back(VTableComponent::MakeVBaseOffset(Offset)); + Components.push_back( + VTableComponent::MakeVBaseOffset(Offset)); } // Check the base class looking for more vbase offsets. @@ -950,7 +956,7 @@ class VTableBuilder { typedef llvm::SmallSetVector PrimaryBasesSetVectorTy; - typedef llvm::DenseMap + typedef llvm::DenseMap VBaseOffsetOffsetsMapTy; typedef llvm::DenseMap @@ -966,7 +972,7 @@ class VTableBuilder { /// MostDerivedClassOffset - If we're building a construction vtable, this /// holds the offset from the layout class to the most derived class. - const uint64_t MostDerivedClassOffset; + const CharUnits MostDerivedClassOffset; /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual /// base. (This only makes sense when building a construction vtable). @@ -1001,23 +1007,26 @@ class VTableBuilder { /// (Used for computing 'this' pointer adjustment thunks. struct MethodInfo { /// BaseOffset - The base offset of this method. - const uint64_t BaseOffset; + const CharUnits BaseOffset; /// BaseOffsetInLayoutClass - The base offset in the layout class of this /// method. - const uint64_t BaseOffsetInLayoutClass; + const CharUnits BaseOffsetInLayoutClass; /// VTableIndex - The index in the vtable that this method has. /// (For destructors, this is the index of the complete destructor). const uint64_t VTableIndex; - MethodInfo(uint64_t BaseOffset, uint64_t BaseOffsetInLayoutClass, + MethodInfo(CharUnits BaseOffset, CharUnits BaseOffsetInLayoutClass, uint64_t VTableIndex) : BaseOffset(BaseOffset), BaseOffsetInLayoutClass(BaseOffsetInLayoutClass), VTableIndex(VTableIndex) { } - MethodInfo() : BaseOffset(0), BaseOffsetInLayoutClass(0), VTableIndex(0) { } + MethodInfo() + : BaseOffset(CharUnits::Zero()), + BaseOffsetInLayoutClass(CharUnits::Zero()), + VTableIndex(0) { } }; typedef llvm::DenseMap MethodInfoMapTy; @@ -1066,7 +1075,7 @@ class VTableBuilder { /// final overrider. ThisAdjustment ComputeThisAdjustment(const CXXMethodDecl *MD, - uint64_t BaseOffsetInLayoutClass, + CharUnits BaseOffsetInLayoutClass, FinalOverriders::OverriderInfo Overrider); /// AddMethod - Add a single virtual member function to the vtable @@ -1093,16 +1102,16 @@ class VTableBuilder { /// C-in-D's copy of A's vtable is never referenced, so this is not /// necessary. bool IsOverriderUsed(const CXXMethodDecl *Overrider, - uint64_t BaseOffsetInLayoutClass, + CharUnits BaseOffsetInLayoutClass, const CXXRecordDecl *FirstBaseInPrimaryBaseChain, - uint64_t FirstBaseOffsetInLayoutClass) const; + CharUnits FirstBaseOffsetInLayoutClass) const; /// AddMethods - Add the methods of this base subobject and all its /// primary bases to the vtable components vector. - void AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, + void AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass, const CXXRecordDecl *FirstBaseInPrimaryBaseChain, - uint64_t FirstBaseOffsetInLayoutClass, + CharUnits FirstBaseOffsetInLayoutClass, PrimaryBasesSetVectorTy &PrimaryBases); // LayoutVTable - Layout the vtable for the given base class, including its @@ -1120,7 +1129,7 @@ class VTableBuilder { void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual, bool BaseIsVirtualInLayoutClass, - uint64_t OffsetInLayoutClass); + CharUnits OffsetInLayoutClass); /// LayoutSecondaryVTables - Layout the secondary vtables for the given base /// subobject. @@ -1128,12 +1137,12 @@ class VTableBuilder { /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base /// or a direct or indirect base of a virtual base. void LayoutSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual, - uint64_t OffsetInLayoutClass); + CharUnits OffsetInLayoutClass); /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this /// class hierarchy. void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, - uint64_t OffsetInLayoutClass, + CharUnits OffsetInLayoutClass, VisitedVirtualBasesSetTy &VBases); /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the @@ -1149,8 +1158,9 @@ class VTableBuilder { public: VTableBuilder(CodeGenVTables &VTables, const CXXRecordDecl *MostDerivedClass, - uint64_t MostDerivedClassOffset, bool MostDerivedClassIsVirtual, - const CXXRecordDecl *LayoutClass) + CharUnits MostDerivedClassOffset, + bool MostDerivedClassIsVirtual, const + CXXRecordDecl *LayoutClass) : VTables(VTables), MostDerivedClass(MostDerivedClass), MostDerivedClassOffset(MostDerivedClassOffset), MostDerivedClassIsVirtual(MostDerivedClassIsVirtual), @@ -1325,15 +1335,15 @@ ReturnAdjustment VTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) { if (Offset.DerivedClass == MostDerivedClass) { // We can get the offset offset directly from our map. Adjustment.VBaseOffsetOffset = - VBaseOffsetOffsets.lookup(Offset.VirtualBase); + VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity(); } else { Adjustment.VBaseOffsetOffset = VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass, - Offset.VirtualBase); + Offset.VirtualBase).getQuantity(); } } - Adjustment.NonVirtual = Offset.NonVirtualOffset; + Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity(); } return Adjustment; @@ -1360,8 +1370,7 @@ VTableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base, I != E; ++I) { BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I); - // FIXME: Should not use * 8 here. - uint64_t OffsetToBaseSubobject = Offset.NonVirtualOffset * 8; + CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset; if (Offset.VirtualBase) { // If we have a virtual base class, the non-virtual offset is relative @@ -1372,7 +1381,7 @@ VTableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base, /// Get the virtual base offset, relative to the most derived class /// layout. OffsetToBaseSubobject += - LayoutClassLayout.getVBaseClassOffsetInBits(Offset.VirtualBase); + LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase); } else { // Otherwise, the non-virtual offset is relative to the derived class // offset. @@ -1393,13 +1402,13 @@ VTableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base, ThisAdjustment VTableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD, - uint64_t BaseOffsetInLayoutClass, + CharUnits BaseOffsetInLayoutClass, FinalOverriders::OverriderInfo Overrider) { // Ignore adjustments for pure virtual member functions. if (Overrider.Method->isPure()) return ThisAdjustment(); - BaseSubobject OverriddenBaseSubobject(MD->getParent(), + BaseSubobject OverriddenBaseSubobject(MD->getParent(), BaseOffsetInLayoutClass); BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(), @@ -1422,18 +1431,21 @@ VTableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD, // build them. VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass, /*FinalOverriders=*/0, - BaseSubobject(Offset.VirtualBase, 0), + BaseSubobject(Offset.VirtualBase, + CharUnits::Zero()), /*BaseIsVirtual=*/true, - /*OffsetInLayoutClass=*/0); + /*OffsetInLayoutClass=*/ + CharUnits::Zero()); VCallOffsets = Builder.getVCallOffsets(); } - Adjustment.VCallOffsetOffset = VCallOffsets.getVCallOffsetOffset(MD); + Adjustment.VCallOffsetOffset = + VCallOffsets.getVCallOffsetOffset(MD).getQuantity(); } // Set the non-virtual part of the adjustment. - Adjustment.NonVirtual = Offset.NonVirtualOffset; + Adjustment.NonVirtual = Offset.NonVirtualOffset.getQuantity(); return Adjustment; } @@ -1489,9 +1501,9 @@ OverridesIndirectMethodInBases(const CXXMethodDecl *MD, bool VTableBuilder::IsOverriderUsed(const CXXMethodDecl *Overrider, - uint64_t BaseOffsetInLayoutClass, + CharUnits BaseOffsetInLayoutClass, const CXXRecordDecl *FirstBaseInPrimaryBaseChain, - uint64_t FirstBaseOffsetInLayoutClass) const { + CharUnits FirstBaseOffsetInLayoutClass) const { // If the base and the first base in the primary base chain have the same // offsets, then this overrider will be used. if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass) @@ -1529,7 +1541,7 @@ VTableBuilder::IsOverriderUsed(const CXXMethodDecl *Overrider, // Now check if this is the primary base that is not a primary base in the // most derived class. - if (LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase) != + if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) != FirstBaseOffsetInLayoutClass) { // We found it, stop walking the chain. break; @@ -1576,16 +1588,16 @@ FindNearestOverriddenMethod(const CXXMethodDecl *MD, } void -VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, +VTableBuilder::AddMethods(BaseSubobject Base, CharUnits BaseOffsetInLayoutClass, const CXXRecordDecl *FirstBaseInPrimaryBaseChain, - uint64_t FirstBaseOffsetInLayoutClass, + CharUnits FirstBaseOffsetInLayoutClass, PrimaryBasesSetVectorTy &PrimaryBases) { const CXXRecordDecl *RD = Base.getBase(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) { - uint64_t PrimaryBaseOffset; - uint64_t PrimaryBaseOffsetInLayoutClass; + CharUnits PrimaryBaseOffset; + CharUnits PrimaryBaseOffsetInLayoutClass; if (Layout.isPrimaryBaseVirtual()) { assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 && "Primary vbase should have a zero offset!"); @@ -1594,13 +1606,13 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, Context.getASTRecordLayout(MostDerivedClass); PrimaryBaseOffset = - MostDerivedClassLayout.getVBaseClassOffsetInBits(PrimaryBase); + MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase); const ASTRecordLayout &LayoutClassLayout = Context.getASTRecordLayout(LayoutClass); PrimaryBaseOffsetInLayoutClass = - LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase); + LayoutClassLayout.getVBaseClassOffset(PrimaryBase); } else { assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 && "Primary base should have a zero offset!"); @@ -1642,8 +1654,7 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, "Did not find the overridden method!"); MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD]; - MethodInfo MethodInfo(Base.getBaseOffset(), - BaseOffsetInLayoutClass, + MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass, OverriddenMethodInfo.VTableIndex); assert(!MethodInfoMap.count(MD) && @@ -1716,7 +1727,8 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, } void VTableBuilder::LayoutVTable() { - LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass, 0), + LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass, + CharUnits::Zero()), /*BaseIsMorallyVirtual=*/false, MostDerivedClassIsVirtual, MostDerivedClassOffset); @@ -1724,7 +1736,7 @@ void VTableBuilder::LayoutVTable() { VisitedVirtualBasesSetTy VBases; // Determine the primary virtual bases. - DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset, + DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset, VBases); VBases.clear(); @@ -1735,7 +1747,7 @@ void VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual, bool BaseIsVirtualInLayoutClass, - uint64_t OffsetInLayoutClass) { + CharUnits OffsetInLayoutClass) { assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!"); // Add vcall and vbase offsets for this vtable. @@ -1758,10 +1770,9 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets(); // Add the offset to top. - // FIXME: We should not use / 8 here. - int64_t OffsetToTop = -(int64_t)(OffsetInLayoutClass - - MostDerivedClassOffset) / 8; - Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop)); + CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass; + Components.push_back( + VTableComponent::MakeOffsetToTop(OffsetToTop)); // Next, add the RTTI. Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass)); @@ -1770,7 +1781,8 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, // Now go through all virtual member functions and add them. PrimaryBasesSetVectorTy PrimaryBases; - AddMethods(Base, OffsetInLayoutClass, Base.getBase(), OffsetInLayoutClass, + AddMethods(Base, OffsetInLayoutClass, + Base.getBase(), OffsetInLayoutClass, PrimaryBases); // Compute 'this' pointer adjustments. @@ -1779,8 +1791,9 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, // Add all address points. const CXXRecordDecl *RD = Base.getBase(); while (true) { - AddressPoints.insert(std::make_pair(BaseSubobject(RD, OffsetInLayoutClass), - AddressPoint)); + AddressPoints.insert(std::make_pair( + BaseSubobject(RD, OffsetInLayoutClass), + AddressPoint)); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); @@ -1794,7 +1807,7 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, const ASTRecordLayout &LayoutClassLayout = Context.getASTRecordLayout(LayoutClass); - if (LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase) != + if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) != OffsetInLayoutClass) { // We don't want to add this class (or any of its primary bases). break; @@ -1810,7 +1823,7 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, void VTableBuilder::LayoutSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual, - uint64_t OffsetInLayoutClass) { + CharUnits OffsetInLayoutClass) { // Itanium C++ ABI 2.5.2: // Following the primary virtual table of a derived class are secondary // virtual tables for each of its proper base classes, except any primary @@ -1844,10 +1857,11 @@ void VTableBuilder::LayoutSecondaryVTables(BaseSubobject Base, } // Get the base offset of this base. - uint64_t RelativeBaseOffset = Layout.getBaseClassOffsetInBits(BaseDecl); - uint64_t BaseOffset = Base.getBaseOffset() + RelativeBaseOffset; + CharUnits RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl); + CharUnits BaseOffset = Base.getBaseOffset() + RelativeBaseOffset; - uint64_t BaseOffsetInLayoutClass = OffsetInLayoutClass + RelativeBaseOffset; + CharUnits BaseOffsetInLayoutClass = + OffsetInLayoutClass + RelativeBaseOffset; // Don't emit a secondary vtable for a primary base. We might however want // to emit secondary vtables for other bases of this base. @@ -1858,16 +1872,17 @@ void VTableBuilder::LayoutSecondaryVTables(BaseSubobject Base, } // Layout the primary vtable (and any secondary vtables) for this base. - LayoutPrimaryAndSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset), - BaseIsMorallyVirtual, - /*BaseIsVirtualInLayoutClass=*/false, - BaseOffsetInLayoutClass); + LayoutPrimaryAndSecondaryVTables( + BaseSubobject(BaseDecl, BaseOffset), + BaseIsMorallyVirtual, + /*BaseIsVirtualInLayoutClass=*/false, + BaseOffsetInLayoutClass); } } void VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, - uint64_t OffsetInLayoutClass, + CharUnits OffsetInLayoutClass, VisitedVirtualBasesSetTy &VBases) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); @@ -1884,8 +1899,8 @@ VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &LayoutClassLayout = Context.getASTRecordLayout(LayoutClass); - uint64_t PrimaryBaseOffsetInLayoutClass = - LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase); + CharUnits PrimaryBaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(PrimaryBase); // We know that the base is not a primary base in the layout class if // the base offsets are different. @@ -1904,7 +1919,7 @@ VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *BaseDecl = cast(I->getType()->getAs()->getDecl()); - uint64_t BaseOffsetInLayoutClass; + CharUnits BaseOffsetInLayoutClass; if (I->isVirtual()) { if (!VBases.insert(BaseDecl)) @@ -1914,10 +1929,10 @@ VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD, Context.getASTRecordLayout(LayoutClass); BaseOffsetInLayoutClass = - LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl); + LayoutClassLayout.getVBaseClassOffset(BaseDecl); } else { BaseOffsetInLayoutClass = - OffsetInLayoutClass + Layout.getBaseClassOffsetInBits(BaseDecl); + OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl); } DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases); @@ -1942,18 +1957,19 @@ VTableBuilder::LayoutVTablesForVirtualBases(const CXXRecordDecl *RD, !PrimaryVirtualBases.count(BaseDecl) && VBases.insert(BaseDecl)) { const ASTRecordLayout &MostDerivedClassLayout = Context.getASTRecordLayout(MostDerivedClass); - uint64_t BaseOffset = - MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl); + CharUnits BaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); const ASTRecordLayout &LayoutClassLayout = Context.getASTRecordLayout(LayoutClass); - uint64_t BaseOffsetInLayoutClass = - LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl); + CharUnits BaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(BaseDecl); - LayoutPrimaryAndSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset), - /*BaseIsMorallyVirtual=*/true, - /*BaseIsVirtualInLayoutClass=*/true, - BaseOffsetInLayoutClass); + LayoutPrimaryAndSecondaryVTables( + BaseSubobject(BaseDecl, BaseOffset), + /*BaseIsMorallyVirtual=*/true, + /*BaseIsVirtualInLayoutClass=*/true, + BaseOffsetInLayoutClass); } // We only need to check the base for virtual base vtables if it actually @@ -1969,8 +1985,7 @@ void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) { if (isBuildingConstructorVTable()) { Out << "Construction vtable for ('"; Out << MostDerivedClass->getQualifiedNameAsString() << "', "; - // FIXME: Don't use / 8 . - Out << MostDerivedClassOffset / 8 << ") in '"; + Out << MostDerivedClassOffset.getQuantity() << ") in '"; Out << LayoutClass->getQualifiedNameAsString(); } else { Out << "Vtable for '"; @@ -2002,15 +2017,21 @@ void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) { switch (Component.getKind()) { case VTableComponent::CK_VCallOffset: - Out << "vcall_offset (" << Component.getVCallOffset() << ")"; + Out << "vcall_offset (" + << Component.getVCallOffset().getQuantity() + << ")"; break; case VTableComponent::CK_VBaseOffset: - Out << "vbase_offset (" << Component.getVBaseOffset() << ")"; + Out << "vbase_offset (" + << Component.getVBaseOffset().getQuantity() + << ")"; break; case VTableComponent::CK_OffsetToTop: - Out << "offset_to_top (" << Component.getOffsetToTop() << ")"; + Out << "offset_to_top (" + << Component.getOffsetToTop().getQuantity() + << ")"; break; case VTableComponent::CK_RTTI: @@ -2116,11 +2137,11 @@ void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) { const BaseSubobject &Base = AddressPointsByIndex.find(NextIndex)->second; - // FIXME: Instead of dividing by 8, we should be using CharUnits. Out << " -- (" << Base.getBase()->getQualifiedNameAsString(); - Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n"; + Out << ", " << Base.getBaseOffset().getQuantity(); + Out << ") vtable address --\n"; } else { - uint64_t BaseOffset = + CharUnits BaseOffset = AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset(); // We store the class names in a set to get a stable order. @@ -2136,9 +2157,8 @@ void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) { for (std::set::const_iterator I = ClassNames.begin(), E = ClassNames.end(); I != E; ++I) { - // FIXME: Instead of dividing by 8, we should be using CharUnits. Out << " -- (" << *I; - Out << ", " << BaseOffset / 8 << ") vtable address --\n"; + Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n"; } } } @@ -2153,12 +2173,13 @@ void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) { // We store the virtual base class names and their offsets in a map to get // a stable order. - std::map ClassNamesAndOffsets; + std::map ClassNamesAndOffsets; for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(), E = VBaseOffsetOffsets.end(); I != E; ++I) { std::string ClassName = I->first->getQualifiedNameAsString(); - int64_t OffsetOffset = I->second; - ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset)); + CharUnits OffsetOffset = I->second; + ClassNamesAndOffsets.insert( + std::make_pair(ClassName, OffsetOffset)); } Out << "Virtual base offset offsets for '"; @@ -2166,10 +2187,10 @@ void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) { Out << ClassNamesAndOffsets.size(); Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n"; - for (std::map::const_iterator I = + for (std::map::const_iterator I = ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end(); I != E; ++I) - Out << " " << I->first << " | " << I->second << '\n'; + Out << " " << I->first << " | " << I->second.getQuantity() << '\n'; Out << "\n"; } @@ -2233,9 +2254,51 @@ void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) { } Out << '\n'; - } } + + // Compute the vtable indices for all the member functions. + // Store them in a map keyed by the index so we'll get a sorted table. + std::map IndicesMap; + + for (CXXRecordDecl::method_iterator i = MostDerivedClass->method_begin(), + e = MostDerivedClass->method_end(); i != e; ++i) { + const CXXMethodDecl *MD = *i; + + // We only want virtual member functions. + if (!MD->isVirtual()) + continue; + + std::string MethodName = + PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual, + MD); + + if (const CXXDestructorDecl *DD = dyn_cast(MD)) { + IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))] = + MethodName + " [complete]"; + IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] = + MethodName + " [deleting]"; + } else { + IndicesMap[VTables.getMethodVTableIndex(MD)] = MethodName; + } + } + + // Print the vtable indices for all the member functions. + if (!IndicesMap.empty()) { + Out << "VTable indices for '"; + Out << MostDerivedClass->getQualifiedNameAsString(); + Out << "' (" << IndicesMap.size() << " entries).\n"; + + for (std::map::const_iterator I = IndicesMap.begin(), + E = IndicesMap.end(); I != E; ++I) { + uint64_t VTableIndex = I->first; + const std::string &MethodName = I->second; + + Out << llvm::format(" %4u | ", VTableIndex) << MethodName << '\n'; + } + } + + Out << '\n'; } } @@ -2243,14 +2306,16 @@ void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) { static void CollectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, VTableBuilder::PrimaryBasesSetVectorTy &PrimaryBases) { - while (RD) { - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - if (PrimaryBase) - PrimaryBases.insert(PrimaryBase); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - RD = PrimaryBase; - } + if (!PrimaryBase) + return; + + CollectPrimaryBases(PrimaryBase, Context, PrimaryBases); + + if (!PrimaryBases.insert(PrimaryBase)) + assert(false && "Found a duplicate primary base!"); } void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) { @@ -2410,8 +2475,9 @@ uint64_t CodeGenVTables::getMethodVTableIndex(GlobalDecl GD) { return I->second; } -int64_t CodeGenVTables::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, - const CXXRecordDecl *VBase) { +CharUnits +CodeGenVTables::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, + const CXXRecordDecl *VBase) { ClassPairTy ClassPair(RD, VBase); VirtualBaseClassOffsetOffsetsMapTy::iterator I = @@ -2420,9 +2486,9 @@ int64_t CodeGenVTables::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, return I->second; VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/0, - BaseSubobject(RD, 0), + BaseSubobject(RD, CharUnits::Zero()), /*BaseIsVirtual=*/false, - /*OffsetInLayoutClass=*/0); + /*OffsetInLayoutClass=*/CharUnits::Zero()); for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I = Builder.getVBaseOffsetOffsets().begin(), @@ -2430,7 +2496,8 @@ int64_t CodeGenVTables::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, // Insert all types. ClassPairTy ClassPair(RD, I->first); - VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second)); + VirtualBaseClassOffsetOffsets.insert( + std::make_pair(ClassPair, I->second)); } I = VirtualBaseClassOffsetOffsets.find(ClassPair); @@ -2531,7 +2598,7 @@ static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD, Fn->getVisibility() != llvm::GlobalVariable::DefaultVisibility) return; - if (MD->hasAttr()) + if (MD->getExplicitVisibility()) return; switch (MD->getTemplateSpecializationKind()) { @@ -2559,8 +2626,19 @@ static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD, Fn->setVisibility(llvm::GlobalValue::HiddenVisibility); } -void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, - const ThunkInfo &Thunk) { +#ifndef NDEBUG +static bool similar(const ABIArgInfo &infoL, CanQualType typeL, + const ABIArgInfo &infoR, CanQualType typeR) { + return (infoL.getKind() == infoR.getKind() && + (typeL == typeR || + (isa(typeL) && isa(typeR)) || + (isa(typeL) && isa(typeR)))); +} +#endif + +void CodeGenFunction::GenerateThunk(llvm::Function *Fn, + const CGFunctionInfo &FnInfo, + GlobalDecl GD, const ThunkInfo &Thunk) { const CXXMethodDecl *MD = cast(GD.getDecl()); const FunctionProtoType *FPT = MD->getType()->getAs(); QualType ResultType = FPT->getResultType(); @@ -2580,10 +2658,11 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, E = MD->param_end(); I != E; ++I) { ParmVarDecl *Param = *I; - FunctionArgs.push_back(std::make_pair(Param, Param->getType())); + FunctionArgs.push_back(Param); } - StartFunction(GlobalDecl(), ResultType, Fn, FunctionArgs, SourceLocation()); + StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, + SourceLocation()); CGM.getCXXABI().EmitInstanceFunctionProlog(*this); @@ -2596,16 +2675,13 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, CallArgList CallArgs; // Add our adjusted 'this' pointer. - CallArgs.push_back(std::make_pair(RValue::get(AdjustedThisPtr), ThisType)); + CallArgs.add(RValue::get(AdjustedThisPtr), ThisType); // Add the rest of the parameters. for (FunctionDecl::param_const_iterator I = MD->param_begin(), E = MD->param_end(); I != E; ++I) { - ParmVarDecl *Param = *I; - QualType ArgType = Param->getType(); - RValue Arg = EmitDelegateCallArg(Param); - - CallArgs.push_back(std::make_pair(Arg, ArgType)); + ParmVarDecl *param = *I; + EmitDelegateCallArg(CallArgs, param); } // Get our callee. @@ -2614,9 +2690,20 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, FPT->isVariadic()); llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); - const CGFunctionInfo &FnInfo = - CGM.getTypes().getFunctionInfo(ResultType, CallArgs, - FPT->getExtInfo()); +#ifndef NDEBUG + const CGFunctionInfo &CallFnInfo = + CGM.getTypes().getFunctionInfo(ResultType, CallArgs, FPT->getExtInfo()); + assert(CallFnInfo.getRegParm() == FnInfo.getRegParm() && + CallFnInfo.isNoReturn() == FnInfo.isNoReturn() && + CallFnInfo.getCallingConvention() == FnInfo.getCallingConvention()); + assert(similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), + FnInfo.getReturnInfo(), FnInfo.getReturnType())); + assert(CallFnInfo.arg_size() == FnInfo.arg_size()); + for (unsigned i = 0, e = FnInfo.arg_size(); i != e; ++i) + assert(similar(CallFnInfo.arg_begin()[i].info, + CallFnInfo.arg_begin()[i].type, + FnInfo.arg_begin()[i].info, FnInfo.arg_begin()[i].type)); +#endif // Determine whether we have a return value slot to use. ReturnValueSlot Slot; @@ -2658,8 +2745,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, Builder.CreateBr(AdjustEnd); EmitBlock(AdjustEnd); - llvm::PHINode *PHI = Builder.CreatePHI(ReturnValue->getType()); - PHI->reserveOperandSpace(2); + llvm::PHINode *PHI = Builder.CreatePHI(ReturnValue->getType(), 2); PHI->addIncoming(ReturnValue, AdjustNotNull); PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()), AdjustNull); @@ -2684,6 +2770,9 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk, bool UseAvailableExternallyLinkage) { + const CGFunctionInfo &FnInfo = CGM.getTypes().getFunctionInfo(GD); + + // FIXME: re-use FnInfo in this computation. llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk); // Strip off a bitcast if we got one back. @@ -2735,7 +2824,7 @@ void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk, } // Actually generate the thunk body. - CodeGenFunction(CGM).GenerateThunk(ThunkFn, GD, Thunk); + CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk); if (UseAvailableExternallyLinkage) ThunkFn->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); @@ -2796,7 +2885,8 @@ void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD, if (Entry.getPointer()) return; - VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD); + VTableBuilder Builder(*this, RD, CharUnits::Zero(), + /*MostDerivedClassIsVirtual=*/0, RD); // Add the VTable layout. uint64_t NumVTableComponents = Builder.getNumVTableComponents(); @@ -2864,7 +2954,8 @@ void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD, // Insert all types. ClassPairTy ClassPair(RD, I->first); - VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second)); + VirtualBaseClassOffsetOffsets.insert( + std::make_pair(ClassPair, I->second)); } } @@ -2895,15 +2986,18 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, switch (Component.getKind()) { case VTableComponent::CK_VCallOffset: - Init = llvm::ConstantInt::get(PtrDiffTy, Component.getVCallOffset()); + Init = llvm::ConstantInt::get(PtrDiffTy, + Component.getVCallOffset().getQuantity()); Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy); break; case VTableComponent::CK_VBaseOffset: - Init = llvm::ConstantInt::get(PtrDiffTy, Component.getVBaseOffset()); + Init = llvm::ConstantInt::get(PtrDiffTy, + Component.getVBaseOffset().getQuantity()); Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy); break; case VTableComponent::CK_OffsetToTop: - Init = llvm::ConstantInt::get(PtrDiffTy, Component.getOffsetToTop()); + Init = llvm::ConstantInt::get(PtrDiffTy, + Component.getOffsetToTop().getQuantity()); Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy); break; case VTableComponent::CK_RTTI: @@ -3001,7 +3095,8 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable, const CXXRecordDecl *RD) { // Dump the vtable layout if necessary. if (CGM.getLangOptions().DumpVTableLayouts) { - VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD); + VTableBuilder Builder(*this, RD, CharUnits::Zero(), + /*MostDerivedClassIsVirtual=*/0, RD); Builder.dumpLayout(llvm::errs()); } @@ -3028,8 +3123,10 @@ llvm::GlobalVariable * CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base, bool BaseIsVirtual, + llvm::GlobalVariable::LinkageTypes Linkage, VTableAddressPointsMapTy& AddressPoints) { - VTableBuilder Builder(*this, Base.getBase(), Base.getBaseOffset(), + VTableBuilder Builder(*this, Base.getBase(), + Base.getBaseOffset(), /*MostDerivedClassIsVirtual=*/BaseIsVirtual, RD); // Dump the vtable layout if necessary. @@ -3044,7 +3141,8 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); CGM.getCXXABI().getMangleContext(). - mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8, Base.getBase(), Out); + mangleCXXCtorVTable(RD, Base.getBaseOffset().getQuantity(), Base.getBase(), + Out); Out.flush(); llvm::StringRef Name = OutName.str(); @@ -3054,8 +3152,11 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, // Create the variable that will hold the construction vtable. llvm::GlobalVariable *VTable = - CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, - llvm::GlobalValue::InternalLinkage); + CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, Linkage); + CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForConstructionVTable); + + // V-tables are always unnamed_addr. + VTable->setUnnamedAddr(true); // Add the thunks. VTableThunksTy VTableThunks; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h index 7c119fa42241..e830e9a6fbcb 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h @@ -1,4 +1,4 @@ -//===--- CGVTables.h - Emit LLVM Code for C++ vtables ---------------------===// +//===--- CGVTables.h - Emit LLVM Code for C++ vtables -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/GlobalVariable.h" #include "clang/Basic/ABI.h" +#include "clang/AST/CharUnits.h" #include "GlobalDecl.h" namespace clang { @@ -33,17 +34,17 @@ class BaseSubobject { const CXXRecordDecl *Base; /// BaseOffset - The offset from the most derived class to the base class. - uint64_t BaseOffset; + CharUnits BaseOffset; public: - BaseSubobject(const CXXRecordDecl *Base, uint64_t BaseOffset) + BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset) : Base(Base), BaseOffset(BaseOffset) { } /// getBase - Returns the base class declaration. const CXXRecordDecl *getBase() const { return Base; } /// getBaseOffset - Returns the base class offset. - uint64_t getBaseOffset() const { return BaseOffset; } + CharUnits getBaseOffset() const { return BaseOffset; } friend bool operator==(const BaseSubobject &LHS, const BaseSubobject &RHS) { return LHS.Base == RHS.Base && LHS.BaseOffset == RHS.BaseOffset; @@ -59,19 +60,19 @@ template<> struct DenseMapInfo { static clang::CodeGen::BaseSubobject getEmptyKey() { return clang::CodeGen::BaseSubobject( DenseMapInfo::getEmptyKey(), - DenseMapInfo::getEmptyKey()); + clang::CharUnits::fromQuantity(DenseMapInfo::getEmptyKey())); } static clang::CodeGen::BaseSubobject getTombstoneKey() { return clang::CodeGen::BaseSubobject( DenseMapInfo::getTombstoneKey(), - DenseMapInfo::getTombstoneKey()); + clang::CharUnits::fromQuantity(DenseMapInfo::getTombstoneKey())); } static unsigned getHashValue(const clang::CodeGen::BaseSubobject &Base) { return DenseMapInfo::getHashValue(Base.getBase()) ^ - DenseMapInfo::getHashValue(Base.getBaseOffset()); + DenseMapInfo::getHashValue(Base.getBaseOffset().getQuantity()); } static bool isEqual(const clang::CodeGen::BaseSubobject &LHS, @@ -102,9 +103,9 @@ class CodeGenVTables { const CXXRecordDecl *> ClassPairTy; /// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to - /// the address point) in bytes where the offsets for virtual bases of a class + /// the address point) in chars where the offsets for virtual bases of a class /// are stored. - typedef llvm::DenseMap + typedef llvm::DenseMap VirtualBaseClassOffsetOffsetsMapTy; VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; @@ -234,13 +235,13 @@ class CodeGenVTables { /// stored. uint64_t getMethodVTableIndex(GlobalDecl GD); - /// getVirtualBaseOffsetOffset - Return the offset in bytes (relative to the + /// getVirtualBaseOffsetOffset - Return the offset in chars (relative to the /// vtable address point) where the offset of the virtual base that contains /// the given base is stored, otherwise, if no virtual base contains the given /// class, return 0. Base must be a virtual base class or an unambigious /// base. - int64_t getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, - const CXXRecordDecl *VBase); + CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, + const CXXRecordDecl *VBase); /// getAddressPoint - Get the address point of the given subobject in the /// class decl. @@ -259,6 +260,7 @@ class CodeGenVTables { llvm::GlobalVariable * GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base, bool BaseIsVirtual, + llvm::GlobalVariable::LinkageTypes Linkage, VTableAddressPointsMapTy& AddressPoints); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp index a24bbc480c19..62fa1f9843de 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp @@ -216,7 +216,7 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, return; } - // Otherwise, report the backend error as occuring in the generated .s file. + // Otherwise, report the backend error as occurring in the generated .s file. // If Loc is invalid, we still need to report the error, it just gets no // location info. Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp index f1b72863caca..626c2b09a032 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp @@ -33,7 +33,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) Target(CGM.getContext().Target), Builder(cgm.getModule().getContext()), BlockInfo(0), BlockPointer(0), NormalCleanupDest(0), EHCleanupDest(0), NextCleanupDestIndex(1), - ExceptionSlot(0), DebugInfo(0), IndirectBranch(0), + ExceptionSlot(0), DebugInfo(0), DisableDebugInfo(false), IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), DidCallStackSave(false), UnreachableBlock(0), CXXThisDecl(0), CXXThisValue(0), CXXVTTDecl(0), CXXVTTValue(0), @@ -210,6 +210,7 @@ void CodeGenFunction::EmitMCountInstrumentation() { void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, + const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation StartLoc) { const Decl *D = GD.getDecl(); @@ -218,6 +219,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, CurCodeDecl = CurFuncDecl = D; FnRetTy = RetTy; CurFn = Fn; + CurFnInfo = &FnInfo; assert(CurFn->isDeclaration() && "Function already has body?"); // Pass inline keyword to optimizer if it appears explicitly on any @@ -239,7 +241,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, CGM.getModule().getOrInsertNamedMetadata("opencl.kernels"); llvm::Value *Op = Fn; - OpenCLMetadata->addOperand(llvm::MDNode::get(Context, &Op, 1)); + OpenCLMetadata->addOperand(llvm::MDNode::get(Context, Op)); } } @@ -275,11 +277,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, if (CGM.getCodeGenOpts().InstrumentForProfiling) EmitMCountInstrumentation(); - // FIXME: Leaked. - // CC info is ignored, hopefully? - CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args, - FunctionType::ExtInfo()); - if (RetTy->isVoidType()) { // Void type; nothing to return. ReturnValue = 0; @@ -302,7 +299,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // emit the type size. for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; ++i) { - QualType Ty = i->second; + QualType Ty = (*i)->getType(); if (Ty->isVariablyModifiedType()) EmitVLASize(Ty); @@ -332,12 +329,13 @@ static void TryMarkNoThrow(llvm::Function *F) { F->setDoesNotThrow(true); } -void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) { +void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, + const CGFunctionInfo &FnInfo) { const FunctionDecl *FD = cast(GD.getDecl()); // Check if we should generate debug info for this function. - if (CGM.getDebugInfo() && !FD->hasAttr()) - DebugInfo = CGM.getDebugInfo(); + if (CGM.getModuleDebugInfo() && !FD->hasAttr()) + DebugInfo = CGM.getModuleDebugInfo(); FunctionArgList Args; QualType ResTy = FD->getResultType(); @@ -346,20 +344,15 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) { if (isa(FD) && cast(FD)->isInstance()) CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args); - if (FD->getNumParams()) { - const FunctionProtoType* FProto = FD->getType()->getAs(); - assert(FProto && "Function def must have prototype!"); - + if (FD->getNumParams()) for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) - Args.push_back(std::make_pair(FD->getParamDecl(i), - FProto->getArgType(i))); - } + Args.push_back(FD->getParamDecl(i)); SourceRange BodyRange; if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); // Emit the standard function prologue. - StartFunction(GD, ResTy, Fn, Args, BodyRange.getBegin()); + StartFunction(GD, ResTy, Fn, FnInfo, Args, BodyRange.getBegin()); // Generate the body of the function. if (isa(FD)) @@ -387,9 +380,12 @@ bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) { // If this is a label, we have to emit the code, consider something like: // if (0) { ... foo: bar(); } goto foo; + // + // TODO: If anyone cared, we could track __label__'s, since we know that you + // can't jump to one from outside their declared region. if (isa(S)) return true; - + // If this is a case/default statement, and we haven't seen a switch, we have // to emit the code. if (isa(S) && !IgnoreCaseStmts) @@ -407,26 +403,65 @@ bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) { return false; } +/// containsBreak - Return true if the statement contains a break out of it. +/// If the statement (recursively) contains a switch or loop with a break +/// inside of it, this is fine. +bool CodeGenFunction::containsBreak(const Stmt *S) { + // Null statement, not a label! + if (S == 0) return false; -/// ConstantFoldsToSimpleInteger - If the sepcified expression does not fold to -/// a constant, or if it does but contains a label, return 0. If it constant -/// folds to 'true' and does not contain a label, return 1, if it constant folds -/// to 'false' and does not contain a label, return -1. -int CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond) { + // If this is a switch or loop that defines its own break scope, then we can + // include it and anything inside of it. + if (isa(S) || isa(S) || isa(S) || + isa(S)) + return false; + + if (isa(S)) + return true; + + // Scan subexpressions for verboten breaks. + for (Stmt::const_child_range I = S->children(); I; ++I) + if (containsBreak(*I)) + return true; + + return false; +} + + +/// ConstantFoldsToSimpleInteger - If the specified expression does not fold +/// to a constant, or if it does but contains a label, return false. If it +/// constant folds return true and set the boolean result in Result. +bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond, + bool &ResultBool) { + llvm::APInt ResultInt; + if (!ConstantFoldsToSimpleInteger(Cond, ResultInt)) + return false; + + ResultBool = ResultInt.getBoolValue(); + return true; +} + +/// ConstantFoldsToSimpleInteger - If the specified expression does not fold +/// to a constant, or if it does but contains a label, return false. If it +/// constant folds return true and set the folded value. +bool CodeGenFunction:: +ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APInt &ResultInt) { // FIXME: Rename and handle conversion of other evaluatable things // to bool. Expr::EvalResult Result; if (!Cond->Evaluate(Result, getContext()) || !Result.Val.isInt() || Result.HasSideEffects) - return 0; // Not foldable, not integer or not fully evaluatable. - + return false; // Not foldable, not integer or not fully evaluatable. + if (CodeGenFunction::ContainsLabel(Cond)) - return 0; // Contains a label. - - return Result.Val.getInt().getBoolValue() ? 1 : -1; + return false; // Contains a label. + + ResultInt = Result.Val.getInt(); + return true; } + /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if /// statement) to the specified blocks. Based on the condition, this might try /// to simplify the codegen of the conditional based on the branch. @@ -434,22 +469,24 @@ int CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond) { void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock) { - if (const ParenExpr *PE = dyn_cast(Cond)) - return EmitBranchOnBoolExpr(PE->getSubExpr(), TrueBlock, FalseBlock); + Cond = Cond->IgnoreParens(); if (const BinaryOperator *CondBOp = dyn_cast(Cond)) { // Handle X && Y in a condition. if (CondBOp->getOpcode() == BO_LAnd) { // If we have "1 && X", simplify the code. "0 && X" would have constant // folded if the case was simple enough. - if (ConstantFoldsToSimpleInteger(CondBOp->getLHS()) == 1) { + bool ConstantBool = false; + if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) && + ConstantBool) { // br(1 && X) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); } // If we have "X && 1", simplify the code to use an uncond branch. // "X && 0" would have been constant folded to 0. - if (ConstantFoldsToSimpleInteger(CondBOp->getRHS()) == 1) { + if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) && + ConstantBool) { // br(X && 1) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock); } @@ -468,17 +505,22 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, eval.end(*this); return; - } else if (CondBOp->getOpcode() == BO_LOr) { + } + + if (CondBOp->getOpcode() == BO_LOr) { // If we have "0 || X", simplify the code. "1 || X" would have constant // folded if the case was simple enough. - if (ConstantFoldsToSimpleInteger(CondBOp->getLHS()) == -1) { + bool ConstantBool = false; + if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) && + !ConstantBool) { // br(0 || X) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); } // If we have "X || 0", simplify the code to use an uncond branch. // "X || 1" would have been constant folded to 1. - if (ConstantFoldsToSimpleInteger(CondBOp->getRHS()) == -1) { + if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) && + !ConstantBool) { // br(X || 0) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock); } @@ -575,8 +617,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, // count must be nonzero. CGF.EmitBlock(loopBB); - llvm::PHINode *cur = Builder.CreatePHI(i8p, "vla.cur"); - cur->reserveOperandSpace(2); + llvm::PHINode *cur = Builder.CreatePHI(i8p, 2, "vla.cur"); cur->addIncoming(begin, originBB); // memcpy the individual element bit-pattern. @@ -613,15 +654,16 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) { DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); // Get size and alignment info for this aggregate. - std::pair TypeInfo = getContext().getTypeInfo(Ty); - uint64_t Size = TypeInfo.first / 8; - unsigned Align = TypeInfo.second / 8; + std::pair TypeInfo = + getContext().getTypeInfoInChars(Ty); + CharUnits Size = TypeInfo.first; + CharUnits Align = TypeInfo.second; llvm::Value *SizeVal; const VariableArrayType *vla; // Don't bother emitting a zero-byte memset. - if (Size == 0) { + if (Size.isZero()) { // But note that getTypeInfo returns 0 for a VLA. if (const VariableArrayType *vlaType = dyn_cast_or_null( @@ -632,7 +674,7 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) { return; } } else { - SizeVal = llvm::ConstantInt::get(IntPtrTy, Size); + SizeVal = llvm::ConstantInt::get(IntPtrTy, Size.getQuantity()); vla = 0; } @@ -657,14 +699,15 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) { if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal); // Get and call the appropriate llvm.memcpy overload. - Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, Align, false); + Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, Align.getQuantity(), false); return; } // Otherwise, just memset the whole thing to zero. This is legal // because in LLVM, all default initializers (other than the ones we just // handled above) are guaranteed to have a bit pattern of all zeros. - Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, Align, false); + Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, + Align.getQuantity(), false); } llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) { @@ -686,7 +729,8 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() { CGBuilderTy TmpBuilder(createBasicBlock("indirectgoto")); // Create the PHI node that indirect gotos will add entries to. - llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, "indirect.goto.dest"); + llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, 0, + "indirect.goto.dest"); // Create the indirect branch instruction. IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h index be646fb29022..169c576f1a0e 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h @@ -25,7 +25,6 @@ #include "llvm/Support/ValueHandle.h" #include "CodeGenModule.h" #include "CGBuilder.h" -#include "CGCall.h" #include "CGValue.h" namespace llvm { @@ -43,6 +42,7 @@ namespace clang { class APValue; class ASTContext; class CXXDestructorDecl; + class CXXForRangeStmt; class CXXTryStmt; class Decl; class LabelDecl; @@ -769,6 +769,11 @@ class CodeGenFunction : public CodeGenTypeCache { /// block through the normal cleanup handling code (if any) and then /// on to \arg Dest. void EmitBranchThroughCleanup(JumpDest Dest); + + /// isObviouslyBranchWithoutCleanups - Return true if a branch to the + /// specified destination obviously has no cleanups to run. 'false' is always + /// a conservatively correct answer for this method. + bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const; /// EmitBranchThroughEHCleanup - Emit a branch from the current /// insert block through the EH cleanup handling code (if any) and @@ -944,6 +949,7 @@ class CodeGenFunction : public CodeGenTypeCache { const VarDecl *V); private: CGDebugInfo *DebugInfo; + bool DisableDebugInfo; /// IndirectBranch - The first time an indirect goto is seen we create a block /// with an indirect branch. Every time we see the address of a label taken, @@ -1030,7 +1036,14 @@ class CodeGenFunction : public CodeGenTypeCache { CodeGenTypes &getTypes() const { return CGM.getTypes(); } ASTContext &getContext() const; - CGDebugInfo *getDebugInfo() { return DebugInfo; } + CGDebugInfo *getDebugInfo() { + if (DisableDebugInfo) + return NULL; + return DebugInfo; + } + void disableDebugInfo() { DisableDebugInfo = true; } + void enableDebugInfo() { DisableDebugInfo = false; } + const LangOptions &getLangOptions() const { return CGM.getLangOptions(); } @@ -1100,15 +1113,13 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo); llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo); - llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, - BlockFieldFlags flags, - const VarDecl *BD); - llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, - BlockFieldFlags flags, - const VarDecl *BD); - void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags); + class AutoVarEmission; + + void emitByrefStructureInit(const AutoVarEmission &emission); + void enterByrefCleanup(const AutoVarEmission &emission); + llvm::Value *LoadBlockStruct() { assert(BlockPointer && "no block pointer set!"); return BlockPointer; @@ -1122,9 +1133,11 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *GetAddrOfBlockDecl(const VarDecl *var, bool ByRef); const llvm::Type *BuildByRefType(const VarDecl *var); - void GenerateCode(GlobalDecl GD, llvm::Function *Fn); + void GenerateCode(GlobalDecl GD, llvm::Function *Fn, + const CGFunctionInfo &FnInfo); void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, + const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation StartLoc); @@ -1141,7 +1154,8 @@ class CodeGenFunction : public CodeGenTypeCache { void FinishFunction(SourceLocation EndLoc=SourceLocation()); /// GenerateThunk - Generate a thunk for the given method. - void GenerateThunk(llvm::Function *Fn, GlobalDecl GD, const ThunkInfo &Thunk); + void GenerateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, + GlobalDecl GD, const ThunkInfo &Thunk); void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type, FunctionArgList &Args); @@ -1151,14 +1165,14 @@ class CodeGenFunction : public CodeGenTypeCache { /// void InitializeVTablePointer(BaseSubobject Base, const CXXRecordDecl *NearestVBase, - uint64_t OffsetFromNearestVBase, + CharUnits OffsetFromNearestVBase, llvm::Constant *VTable, const CXXRecordDecl *VTableClass); typedef llvm::SmallPtrSet VisitedVirtualBasesSetTy; void InitializeVTablePointers(BaseSubobject Base, const CXXRecordDecl *NearestVBase, - uint64_t OffsetFromNearestVBase, + CharUnits OffsetFromNearestVBase, bool BaseIsNonVirtualPrimaryBase, llvm::Constant *VTable, const CXXRecordDecl *VTableClass, @@ -1353,12 +1367,18 @@ class CodeGenFunction : public CodeGenTypeCache { /// always be accessible even if no aggregate location is provided. RValue EmitAnyExprToTemp(const Expr *E); - /// EmitsAnyExprToMem - Emits the code necessary to evaluate an + /// EmitAnyExprToMem - Emits the code necessary to evaluate an /// arbitrary expression into the given memory location. void EmitAnyExprToMem(const Expr *E, llvm::Value *Location, bool IsLocationVolatile, bool IsInitializer); + /// EmitExprAsInit - Emits the code necessary to initialize a + /// location in memory with the given initializer. + void EmitExprAsInit(const Expr *init, const VarDecl *var, + llvm::Value *loc, CharUnits alignment, + bool capturedByInit); + /// EmitAggregateCopy - Emit an aggrate copy. /// /// \param isVolatile - True iff either the source or the destination is @@ -1476,6 +1496,12 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, CXXCtorType CtorType, const FunctionArgList &Args); + // It's important not to confuse this and the previous function. Delegating + // constructors are the C++0x feature. The constructor delegate optimization + // is used to reduce duplication in the base and complete consturctors where + // they are substantially the same. + void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, + const FunctionArgList &Args); void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, @@ -1609,7 +1635,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::GlobalValue::LinkageTypes Linkage); /// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl. - void EmitParmDecl(const VarDecl &D, llvm::Value *Arg); + void EmitParmDecl(const VarDecl &D, llvm::Value *Arg, unsigned ArgNo); /// protectFromPeepholes - Protect a value that we're intending to /// store to the side, but which will probably be used later, from @@ -1680,6 +1706,7 @@ class CodeGenFunction : public CodeGenTypeCache { void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false); void EmitCXXTryStmt(const CXXTryStmt &S); + void EmitCXXForRangeStmt(const CXXForRangeStmt &S); //===--------------------------------------------------------------------===// // LValue Expression Emission @@ -1775,7 +1802,7 @@ class CodeGenFunction : public CodeGenTypeCache { LValue EmitComplexAssignmentLValue(const BinaryOperator *E); LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E); - // Note: only availabe for agg return types + // Note: only available for agg return types LValue EmitBinaryOperatorLValue(const BinaryOperator *E); LValue EmitCompoundAssignmentLValue(const CompoundAssignOperator *E); // Note: only available for agg return types @@ -2022,7 +2049,8 @@ class CodeGenFunction : public CodeGenTypeCache { const std::vector > &DtorsAndObjects); - void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D, + void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, + const VarDecl *D, llvm::GlobalVariable *Addr); void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest); @@ -2044,12 +2072,21 @@ class CodeGenFunction : public CodeGenTypeCache { /// that we can just remove the code. static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts = false); + /// containsBreak - Return true if the statement contains a break out of it. + /// If the statement (recursively) contains a switch or loop with a break + /// inside of it, this is fine. + static bool containsBreak(const Stmt *S); + /// ConstantFoldsToSimpleInteger - If the specified expression does not fold - /// to a constant, or if it does but contains a label, return 0. If it - /// constant folds to 'true' and does not contain a label, return 1, if it - /// constant folds to 'false' and does not contain a label, return -1. - int ConstantFoldsToSimpleInteger(const Expr *Cond); + /// to a constant, or if it does but contains a label, return false. If it + /// constant folds return true and set the boolean result in Result. + bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result); + /// ConstantFoldsToSimpleInteger - If the specified expression does not fold + /// to a constant, or if it does but contains a label, return false. If it + /// constant folds return true and set the folded value. + bool ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APInt &Result); + /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an /// if statement) to the specified blocks. Based on the condition, this might /// try to simplify the codegen of the conditional based on the branch. @@ -2061,12 +2098,12 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::BasicBlock *getTrapBB(); /// EmitCallArg - Emit a single call argument. - RValue EmitCallArg(const Expr *E, QualType ArgType); + void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType); /// EmitDelegateCallArg - We are performing a delegate call; that /// is, the current function is delegating to another one. Produce /// a r-value suitable for passing the given parameter. - RValue EmitDelegateCallArg(const VarDecl *Param); + void EmitDelegateCallArg(CallArgList &args, const VarDecl *param); private: void EmitReturnOfRValue(RValue RV, QualType Ty); @@ -2131,8 +2168,7 @@ class CodeGenFunction : public CodeGenTypeCache { getContext().getCanonicalType(ActualArgType).getTypePtr() && "type mismatch in call argument!"); #endif - Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType), - ArgType)); + EmitCallArg(Args, *Arg, ArgType); } // Either we've emitted all the call args, or we have a call to a @@ -2143,11 +2179,8 @@ class CodeGenFunction : public CodeGenTypeCache { } // If we still have any arguments, emit them using the type of the argument. - for (; Arg != ArgEnd; ++Arg) { - QualType ArgType = Arg->getType(); - Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType), - ArgType)); - } + for (; Arg != ArgEnd; ++Arg) + EmitCallArg(Args, *Arg, Arg->getType()); } const TargetCodeGenInfo &getTargetHooks() const { @@ -2155,6 +2188,10 @@ class CodeGenFunction : public CodeGenTypeCache { } void EmitDeclMetadata(); + + CodeGenModule::ByrefHelpers * + buildByrefHelpers(const llvm::StructType &byrefType, + const AutoVarEmission &emission); }; /// Helper class with most of the code for saving a value for a diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp index a8453c31d54e..83e927fcadbc 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp @@ -64,7 +64,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, ABI(createCXXABI(*this)), Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI), TBAA(0), - VTables(*this), Runtime(0), + VTables(*this), Runtime(0), DebugInfo(0), CFConstantStringClassRef(0), ConstantStringClassRef(0), VMContext(M.getContext()), NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0), @@ -72,22 +72,19 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, BlockObjectAssignDecl(0), BlockObjectDisposeDecl(0), BlockObjectAssign(0), BlockObjectDispose(0), BlockDescriptorType(0), GenericBlockLiteralType(0) { - if (!Features.ObjC1) - Runtime = 0; - else if (!Features.NeXTRuntime) - Runtime = CreateGNUObjCRuntime(*this); - else if (Features.ObjCNonFragileABI) - Runtime = CreateMacNonFragileABIObjCRuntime(*this); - else - Runtime = CreateMacObjCRuntime(*this); + if (Features.ObjC1) + createObjCRuntime(); // Enable TBAA unless it's suppressed. if (!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0) TBAA = new CodeGenTBAA(Context, VMContext, getLangOptions(), ABI.getMangleContext()); - // If debug info generation is enabled, create the CGDebugInfo object. - DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(*this) : 0; + // If debug info or coverage generation is enabled, create the CGDebugInfo + // object. + if (CodeGenOpts.DebugInfo || CodeGenOpts.EmitGcovArcs || + CodeGenOpts.EmitGcovNotes) + DebugInfo = new CGDebugInfo(*this); Block.GlobalUniqueCount = 0; @@ -115,8 +112,6 @@ CodeGenModule::~CodeGenModule() { void CodeGenModule::createObjCRuntime() { if (!Features.NeXTRuntime) Runtime = CreateGNUObjCRuntime(*this); - else if (Features.ObjCNonFragileABI) - Runtime = CreateMacNonFragileABIObjCRuntime(*this); else Runtime = CreateMacObjCRuntime(*this); } @@ -139,6 +134,13 @@ void CodeGenModule::Release() { EmitDeclMetadata(); } +void CodeGenModule::UpdateCompletedType(const TagDecl *TD) { + // Make sure that this type is translated. + Types.UpdateCompletedType(TD); + if (DebugInfo) + DebugInfo->UpdateCompletedType(TD); +} + llvm::MDNode *CodeGenModule::getTBAAInfo(QualType QTy) { if (!TBAA) return 0; @@ -151,7 +153,12 @@ void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst, } bool CodeGenModule::isTargetDarwin() const { - return getContext().Target.getTriple().getOS() == llvm::Triple::Darwin; + return getContext().Target.getTriple().isOSDarwin(); +} + +void CodeGenModule::Error(SourceLocation loc, llvm::StringRef error) { + unsigned diagID = getDiags().getCustomDiagID(Diagnostic::Error, error); + getDiags().Report(Context.getFullLoc(loc), diagID); } /// ErrorUnsupported - Print out an error that codegen doesn't support the @@ -220,7 +227,7 @@ void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV, return; // Don't override an explicit visibility attribute. - if (RD->hasAttr()) + if (RD->getExplicitVisibility()) return; switch (RD->getTemplateSpecializationKind()) { @@ -501,6 +508,13 @@ void CodeGenModule::SetInternalFunctionAttributes(const Decl *D, void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, bool IsIncompleteFunction) { + if (unsigned IID = F->getIntrinsicID()) { + // If this is an intrinsic function, set the function's attributes + // to the intrinsic's attributes. + F->setAttributes(llvm::Intrinsic::getAttributes((llvm::Intrinsic::ID)IID)); + return; + } + const FunctionDecl *FD = cast(GD.getDecl()); if (!IsIncompleteFunction) @@ -512,7 +526,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, if (FD->hasAttr()) { F->setLinkage(llvm::Function::DLLImportLinkage); } else if (FD->hasAttr() || - FD->hasAttr()) { + FD->isWeakImported()) { // "extern_weak" is overloaded in LLVM; we probably should have // separate linkage types for this. F->setLinkage(llvm::Function::ExternalWeakLinkage); @@ -989,7 +1003,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(llvm::StringRef MangledName, } else { if (D->hasAttr()) GV->setLinkage(llvm::GlobalValue::DLLImportLinkage); - else if (D->hasAttr() || D->hasAttr()) + else if (D->hasAttr() || D->isWeakImported()) GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); // Set visibility on a declaration only if it's explicit. @@ -1055,7 +1069,7 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, Ty = getTypes().ConvertTypeForMem(ASTTy); const llvm::PointerType *PTy = - llvm::PointerType::get(Ty, ASTTy.getAddressSpace()); + llvm::PointerType::get(Ty, getContext().getTargetAddressSpace(ASTTy)); llvm::StringRef MangledName = getMangledName(D); return GetOrCreateLLVMGlobal(MangledName, PTy, D); @@ -1066,7 +1080,7 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, llvm::Constant * CodeGenModule::CreateRuntimeVariable(const llvm::Type *Ty, llvm::StringRef Name) { - return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0, + return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0, true); } @@ -1234,7 +1248,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { // from the type of the global (this happens with unions). if (GV == 0 || GV->getType()->getElementType() != InitType || - GV->getType()->getAddressSpace() != ASTTy.getAddressSpace()) { + GV->getType()->getAddressSpace() != + getContext().getTargetAddressSpace(ASTTy)) { // Move the old entry aside so that we'll create a new one. Entry->setName(llvm::StringRef()); @@ -1281,7 +1296,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { EmitCXXGlobalVarDeclInitFunc(D, GV); // Emit global variable debug information. - if (CGDebugInfo *DI = getDebugInfo()) { + if (CGDebugInfo *DI = getModuleDebugInfo()) { DI->setLocation(D->getLocation()); DI->EmitGlobalVariable(GV, D); } @@ -1304,9 +1319,7 @@ CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, return llvm::GlobalVariable::WeakAnyLinkage; } else if (Linkage == GVA_TemplateInstantiation || Linkage == GVA_ExplicitTemplateInstantiation) - // FIXME: It seems like we can provide more specific linkage here - // (LinkOnceODR, WeakODR). - return llvm::GlobalVariable::WeakAnyLinkage; + return llvm::GlobalVariable::WeakODRLinkage; else if (!getLangOptions().CPlusPlus && ((!CodeGenOpts.NoCommon && !D->getAttr()) || D->getAttr()) && @@ -1391,7 +1404,14 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { const FunctionDecl *D = cast(GD.getDecl()); - const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD); + + // Compute the function info and LLVM type. + const CGFunctionInfo &FI = getTypes().getFunctionInfo(GD); + bool variadic = false; + if (const FunctionProtoType *fpt = D->getType()->getAs()) + variadic = fpt->isVariadic(); + const llvm::FunctionType *Ty = getTypes().GetFunctionType(FI, variadic, false); + // Get or create the prototype for the function. llvm::Constant *Entry = GetAddrOfFunction(GD, Ty); @@ -1451,7 +1471,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { // FIXME: this is redundant with part of SetFunctionDefinitionAttributes setGlobalVisibility(Fn, D); - CodeGenFunction(*this).GenerateCode(D, Fn); + CodeGenFunction(*this).GenerateCode(D, Fn, FI); SetFunctionDefinitionAttributes(D, Fn); SetLLVMFunctionAttributesForDefinition(D, Fn); @@ -1525,7 +1545,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { } } else if (D->hasAttr() || D->hasAttr() || - D->hasAttr()) { + D->isWeakImported()) { GA->setLinkage(llvm::Function::WeakAnyLinkage); } @@ -1662,7 +1682,10 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { // does make plain ascii ones writable. isConstant = true; } else { - Linkage = llvm::GlobalValue::PrivateLinkage; + // FIXME: With OS X ld 123.2 (xcode 4) and LTO we would get a linker error + // when using private linkage. It is not clear if this is a bug in ld + // or a reasonable new restriction. + Linkage = llvm::GlobalValue::LinkerPrivateLinkage; isConstant = !Features.WritableStrings; } @@ -1673,6 +1696,9 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { if (isUTF16) { CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy); GV->setAlignment(Align.getQuantity()); + } else { + CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy); + GV->setAlignment(Align.getQuantity()); } Fields[2] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2); @@ -1765,6 +1791,9 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) { if (isUTF16) { CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy); GV->setAlignment(Align.getQuantity()); + } else { + CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy); + GV->setAlignment(Align.getQuantity()); } Fields[1] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2); @@ -1835,7 +1864,7 @@ CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) { /// GenerateWritableString -- Creates storage for a string literal. -static llvm::Constant *GenerateStringLiteral(const std::string &str, +static llvm::Constant *GenerateStringLiteral(llvm::StringRef str, bool constant, CodeGenModule &CGM, const char *GlobalName) { @@ -1860,7 +1889,7 @@ static llvm::Constant *GenerateStringLiteral(const std::string &str, /// Feature.WriteableStrings. /// /// The result has pointer to array type. -llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str, +llvm::Constant *CodeGenModule::GetAddrOfConstantString(llvm::StringRef Str, const char *GlobalName) { bool IsConstant = !Features.WritableStrings; @@ -1870,26 +1899,27 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str, // Don't share any string literals if strings aren't constant. if (!IsConstant) - return GenerateStringLiteral(str, false, *this, GlobalName); + return GenerateStringLiteral(Str, false, *this, GlobalName); llvm::StringMapEntry &Entry = - ConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]); + ConstantStringMap.GetOrCreateValue(Str); if (Entry.getValue()) return Entry.getValue(); // Create a global variable for this. - llvm::Constant *C = GenerateStringLiteral(str, true, *this, GlobalName); + llvm::Constant *C = GenerateStringLiteral(Str, true, *this, GlobalName); Entry.setValue(C); return C; } /// GetAddrOfConstantCString - Returns a pointer to a character -/// array containing the literal and a terminating '\-' +/// array containing the literal and a terminating '\0' /// character. The result has pointer to array type. -llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &str, +llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &Str, const char *GlobalName){ - return GetAddrOfConstantString(str + '\0', GlobalName); + llvm::StringRef StrWithNull(Str.c_str(), Str.size() + 1); + return GetAddrOfConstantString(StrWithNull, GlobalName); } /// EmitObjCPropertyImplementations - Emit information for synthesized @@ -1920,37 +1950,48 @@ void CodeGenModule::EmitObjCPropertyImplementations(const } } +static bool needsDestructMethod(ObjCImplementationDecl *impl) { + ObjCInterfaceDecl *iface + = const_cast(impl->getClassInterface()); + for (ObjCIvarDecl *ivar = iface->all_declared_ivar_begin(); + ivar; ivar = ivar->getNextIvar()) + if (ivar->getType().isDestructedType()) + return true; + + return false; +} + /// EmitObjCIvarInitializations - Emit information for ivar initialization /// for an implementation. void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) { - if (!Features.NeXTRuntime || D->getNumIvarInitializers() == 0) + // We might need a .cxx_destruct even if we don't have any ivar initializers. + if (needsDestructMethod(D)) { + IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct"); + Selector cxxSelector = getContext().Selectors.getSelector(0, &II); + ObjCMethodDecl *DTORMethod = + ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(), + cxxSelector, getContext().VoidTy, 0, D, true, + false, true, false, ObjCMethodDecl::Required); + D->addInstanceMethod(DTORMethod); + CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false); + } + + // If the implementation doesn't have any ivar initializers, we don't need + // a .cxx_construct. + if (D->getNumIvarInitializers() == 0) return; - DeclContext* DC = const_cast(dyn_cast(D)); - assert(DC && "EmitObjCIvarInitializations - null DeclContext"); - IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct"); - Selector cxxSelector = getContext().Selectors.getSelector(0, &II); - ObjCMethodDecl *DTORMethod = ObjCMethodDecl::Create(getContext(), - D->getLocation(), - D->getLocation(), cxxSelector, - getContext().VoidTy, 0, - DC, true, false, true, false, - ObjCMethodDecl::Required); - D->addInstanceMethod(DTORMethod); - CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false); - II = &getContext().Idents.get(".cxx_construct"); - cxxSelector = getContext().Selectors.getSelector(0, &II); + IdentifierInfo *II = &getContext().Idents.get(".cxx_construct"); + Selector cxxSelector = getContext().Selectors.getSelector(0, &II); // The constructor returns 'self'. ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(), cxxSelector, getContext().getObjCIdType(), 0, - DC, true, false, true, false, + D, true, false, true, false, ObjCMethodDecl::Required); D->addInstanceMethod(CTORMethod); CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true); - - } /// EmitNamespace - Emit all declarations in a namespace. @@ -1990,7 +2031,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::CXXMethod: case Decl::Function: // Skip function templates - if (cast(D)->getDescribedFunctionTemplate()) + if (cast(D)->getDescribedFunctionTemplate() || + cast(D)->isLateTemplateParsed()) return; EmitGlobal(cast(D)); @@ -2000,6 +2042,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { EmitGlobal(cast(D)); break; + // Indirect fields from global anonymous structs and unions can be + // ignored; only the actual variable requires IR gen support. + case Decl::IndirectField: + break; + // C++ Decls case Decl::Namespace: EmitNamespace(cast(D)); @@ -2014,12 +2061,15 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { break; case Decl::CXXConstructor: // Skip function templates - if (cast(D)->getDescribedFunctionTemplate()) + if (cast(D)->getDescribedFunctionTemplate() || + cast(D)->isLateTemplateParsed()) return; EmitCXXConstructors(cast(D)); break; case Decl::CXXDestructor: + if (cast(D)->isLateTemplateParsed()) + return; EmitCXXDestructors(cast(D)); break; @@ -2035,13 +2085,12 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::ObjCInterface: break; - case Decl::ObjCCategory: { - ObjCCategoryDecl *CD = cast(D); - if (CD->IsClassExtension() && CD->hasSynthBitfield()) - Context.ResetObjCLayout(CD->getClassInterface()); - break; - } - + case Decl::ObjCCategory: { + ObjCCategoryDecl *CD = cast(D); + if (CD->IsClassExtension() && CD->hasSynthBitfield()) + Context.ResetObjCLayout(CD->getClassInterface()); + break; + } case Decl::ObjCProtocol: Runtime->GenerateProtocol(cast(D)); @@ -2118,7 +2167,7 @@ static void EmitGlobalDeclMetadata(CodeGenModule &CGM, Addr, GetPointerConstant(CGM.getLLVMContext(), D.getDecl()) }; - GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops, 2)); + GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops)); } /// Emits metadata nodes associating all the global values in the @@ -2159,7 +2208,7 @@ void CodeGenFunction::EmitDeclMetadata() { if (llvm::AllocaInst *Alloca = dyn_cast(Addr)) { llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D); - Alloca->setMetadata(DeclPtrKind, llvm::MDNode::get(Context, &DAddr, 1)); + Alloca->setMetadata(DeclPtrKind, llvm::MDNode::get(Context, DAddr)); } else if (llvm::GlobalValue *GV = dyn_cast(Addr)) { GlobalDecl GD = GlobalDecl(cast(D)); EmitGlobalDeclMetadata(CGM, GlobalMetadata, GD, GV); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h index 73e6ece14732..99c973cce628 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h @@ -20,7 +20,6 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Mangle.h" -#include "CGCall.h" #include "CGVTables.h" #include "CodeGenTypes.h" #include "GlobalDecl.h" @@ -69,12 +68,14 @@ namespace clang { namespace CodeGen { + class CallArgList; class CodeGenFunction; class CodeGenTBAA; class CGCXXABI; class CGDebugInfo; class CGObjCRuntime; class BlockFieldFlags; + class FunctionArgList; struct OrderGlobalInits { unsigned int priority; @@ -246,9 +247,6 @@ class CodeGenModule : public CodeGenTypeCache { int GlobalUniqueCount; } Block; - llvm::DenseMap AssignCache; - llvm::DenseMap DestroyCache; - /// @} public: CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts, @@ -281,7 +279,8 @@ class CodeGenModule : public CodeGenTypeCache { StaticLocalDeclMap[D] = GV; } - CGDebugInfo *getDebugInfo() { return DebugInfo; } + CGDebugInfo *getModuleDebugInfo() { return DebugInfo; } + ASTContext &getContext() const { return Context; } const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } const LangOptions &getLangOptions() const { return Features; } @@ -311,6 +310,7 @@ class CodeGenModule : public CodeGenTypeCache { enum TypeVisibilityKind { TVK_ForVTT, TVK_ForVTable, + TVK_ForConstructionVTable, TVK_ForRTTI, TVK_ForRTTIName }; @@ -358,6 +358,7 @@ class CodeGenModule : public CodeGenTypeCache { llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D, const llvm::Type *Ty = 0); + /// GetAddrOfFunction - Return the address of the given function. If Ty is /// non-null, then this function will use the specified type if it has to /// create it. @@ -382,14 +383,35 @@ class CodeGenModule : public CodeGenTypeCache { CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd); - llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, - BlockFieldFlags flags, - unsigned Align, - const VarDecl *variable); - llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, - BlockFieldFlags flags, - unsigned Align, - const VarDecl *variable); + /// A pair of helper functions for a __block variable. + class ByrefHelpers : public llvm::FoldingSetNode { + public: + llvm::Constant *CopyHelper; + llvm::Constant *DisposeHelper; + + /// The alignment of the field. This is important because + /// different offsets to the field within the byref struct need to + /// have different helper functions. + CharUnits Alignment; + + ByrefHelpers(CharUnits alignment) : Alignment(alignment) {} + virtual ~ByrefHelpers(); + + void Profile(llvm::FoldingSetNodeID &id) const { + id.AddInteger(Alignment.getQuantity()); + profileImpl(id); + } + virtual void profileImpl(llvm::FoldingSetNodeID &id) const = 0; + + virtual bool needsCopy() const { return true; } + virtual void emitCopy(CodeGenFunction &CGF, + llvm::Value *dest, llvm::Value *src) = 0; + + virtual bool needsDispose() const { return true; } + virtual void emitDispose(CodeGenFunction &CGF, llvm::Value *field) = 0; + }; + + llvm::FoldingSet ByrefHelpersCache; /// getUniqueBlockCount - Fetches the global unique block count. int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; } @@ -437,7 +459,7 @@ class CodeGenModule : public CodeGenTypeCache { /// /// \param GlobalName If provided, the name to use for the global /// (if one is created). - llvm::Constant *GetAddrOfConstantString(const std::string& str, + llvm::Constant *GetAddrOfConstantString(llvm::StringRef Str, const char *GlobalName=0); /// GetAddrOfConstantCString - Returns a pointer to a character array @@ -451,13 +473,15 @@ class CodeGenModule : public CodeGenTypeCache { /// GetAddrOfCXXConstructor - Return the address of the constructor of the /// given type. - llvm::GlobalValue *GetAddrOfCXXConstructor(const CXXConstructorDecl *D, - CXXCtorType Type); + llvm::GlobalValue *GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor, + CXXCtorType ctorType, + const CGFunctionInfo *fnInfo = 0); /// GetAddrOfCXXDestructor - Return the address of the constructor of the /// given type. - llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *D, - CXXDtorType Type); + llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor, + CXXDtorType dtorType, + const CGFunctionInfo *fnInfo = 0); /// getBuiltinLibFunction - Given a builtin id for a function like /// "__builtin_fabsf", return a Function* for "fabsf". @@ -502,10 +526,8 @@ class CodeGenModule : public CodeGenTypeCache { ///@} - void UpdateCompletedType(const TagDecl *TD) { - // Make sure that this type is translated. - Types.UpdateCompletedType(TD); - } + // UpdateCompleteType - Make sure that this type is translated. + void UpdateCompletedType(const TagDecl *TD); llvm::Constant *getMemberPointerConstant(const UnaryOperator *e); @@ -523,6 +545,9 @@ class CodeGenModule : public CodeGenTypeCache { llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV, const AnnotateAttr *AA, unsigned LineNo); + /// Error - Emit a general error that something can't be done. + void Error(SourceLocation loc, llvm::StringRef error); + /// ErrorUnsupported - Print out an error that codegen doesn't support the /// specified stmt yet. /// \param OmitOnError - If true, then this error should only be emitted if no diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp index 3f2c6cabf2ae..53e40b2238b3 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -74,7 +74,8 @@ llvm::MDNode *CodeGenTBAA::getTBAAInfoForNamedType(llvm::StringRef NameStr, }; // Create the mdnode. - return llvm::MDNode::get(VMContext, Ops, llvm::array_lengthof(Ops) - !Flags); + unsigned Len = llvm::array_lengthof(Ops) - !Flags; + return llvm::MDNode::get(VMContext, llvm::ArrayRef(Ops, Len)); } static bool TypeHasMayAlias(QualType QTy) { @@ -155,7 +156,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) { // theoretically implement this by combining information about all the // members into a single identifying MDNode. if (!Features.CPlusPlus && - ETy->getDecl()->getTypedefForAnonDecl()) + ETy->getDecl()->getTypedefNameForAnonDecl()) return MetadataCache[Ty] = getChar(); // In C++ mode, types have linkage, so we can rely on the ODR and diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp index 5254922f13a1..8db6fe518684 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp @@ -65,6 +65,36 @@ void CodeGenTypes::HandleLateResolvedPointers() { } } +void CodeGenTypes::addRecordTypeName(const RecordDecl *RD, const llvm::Type *Ty, + llvm::StringRef suffix) { + llvm::SmallString<256> TypeName; + llvm::raw_svector_ostream OS(TypeName); + OS << RD->getKindName() << '.'; + + // Name the codegen type after the typedef name + // if there is no tag type name available + if (RD->getIdentifier()) { + // FIXME: We should not have to check for a null decl context here. + // Right now we do it because the implicit Obj-C decls don't have one. + if (RD->getDeclContext()) + OS << RD->getQualifiedNameAsString(); + else + RD->printName(OS); + } else if (const TypedefNameDecl *TDD = RD->getTypedefNameForAnonDecl()) { + // FIXME: We should not have to check for a null decl context here. + // Right now we do it because the implicit Obj-C decls don't have one. + if (TDD->getDeclContext()) + OS << TDD->getQualifiedNameAsString(); + else + TDD->printName(OS); + } else + OS << "anon"; + + if (!suffix.empty()) + OS << suffix; + + TheModule.addTypeName(OS.str(), Ty); +} /// ConvertType - Convert the specified type to its LLVM form. const llvm::Type *CodeGenTypes::ConvertType(QualType T, bool IsRecursive) { @@ -199,7 +229,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { #define DEPENDENT_TYPE(Class, Base) case Type::Class: #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" - assert(false && "Non-canonical or dependent types aren't possible."); + llvm_unreachable("Non-canonical or dependent types aren't possible."); break; case Type::Builtin: { @@ -253,10 +283,12 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case BuiltinType::Overload: case BuiltinType::Dependent: - assert(0 && "Unexpected builtin type!"); + case BuiltinType::BoundMember: + case BuiltinType::UnknownAny: + llvm_unreachable("Unexpected placeholder builtin type!"); break; } - assert(0 && "Unknown builtin type!"); + llvm_unreachable("Unknown builtin type!"); break; } case Type::Complex: { @@ -270,14 +302,16 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { QualType ETy = RTy.getPointeeType(); llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext()); PointersToResolve.push_back(std::make_pair(ETy, PointeeType)); - return llvm::PointerType::get(PointeeType, ETy.getAddressSpace()); + unsigned AS = Context.getTargetAddressSpace(ETy); + return llvm::PointerType::get(PointeeType, AS); } case Type::Pointer: { const PointerType &PTy = cast(Ty); QualType ETy = PTy.getPointeeType(); llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext()); PointersToResolve.push_back(std::make_pair(ETy, PointeeType)); - return llvm::PointerType::get(PointeeType, ETy.getAddressSpace()); + unsigned AS = Context.getTargetAddressSpace(ETy); + return llvm::PointerType::get(PointeeType, AS); } case Type::VariableArray: { @@ -371,30 +405,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { const TagDecl *TD = cast(Ty).getDecl(); const llvm::Type *Res = ConvertTagDeclType(TD); - llvm::SmallString<256> TypeName; - llvm::raw_svector_ostream OS(TypeName); - OS << TD->getKindName() << '.'; - - // Name the codegen type after the typedef name - // if there is no tag type name available - if (TD->getIdentifier()) { - // FIXME: We should not have to check for a null decl context here. - // Right now we do it because the implicit Obj-C decls don't have one. - if (TD->getDeclContext()) - OS << TD->getQualifiedNameAsString(); - else - TD->printName(OS); - } else if (const TypedefDecl *TDD = TD->getTypedefForAnonDecl()) { - // FIXME: We should not have to check for a null decl context here. - // Right now we do it because the implicit Obj-C decls don't have one. - if (TDD->getDeclContext()) - OS << TDD->getQualifiedNameAsString(); - else - TDD->printName(OS); - } else - OS << "anon"; - - TheModule.addTypeName(OS.str(), Res); + if (const RecordDecl *RD = dyn_cast(TD)) + addRecordTypeName(RD, Res, llvm::StringRef()); return Res; } @@ -402,7 +414,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { const QualType FTy = cast(Ty).getPointeeType(); llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext()); PointersToResolve.push_back(std::make_pair(FTy, PointeeType)); - return llvm::PointerType::get(PointeeType, FTy.getAddressSpace()); + unsigned AS = Context.getTargetAddressSpace(FTy); + return llvm::PointerType::get(PointeeType, AS); } case Type::MemberPointer: { @@ -500,6 +513,15 @@ CodeGenTypes::getCGRecordLayout(const RecordDecl *RD) { return *Layout; } +void CodeGenTypes::addBaseSubobjectTypeName(const CXXRecordDecl *RD, + const CGRecordLayout &layout) { + llvm::StringRef suffix; + if (layout.getBaseSubobjectLLVMType() != layout.getLLVMType()) + suffix = ".base"; + + addRecordTypeName(RD, layout.getBaseSubobjectLLVMType(), suffix); +} + bool CodeGenTypes::isZeroInitializable(QualType T) { // No need to check for member pointers when not compiling C++. if (!Context.getLangOptions().CPlusPlus) diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h index 41513daf17ca..dc383cb4db5d 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h @@ -101,6 +101,11 @@ class CodeGenTypes { /// used to handle cyclic structures properly. void HandleLateResolvedPointers(); + /// addRecordTypeName - Compute a name from the given record decl with an + /// optional suffix and name the given LLVM type using it. + void addRecordTypeName(const RecordDecl *RD, const llvm::Type *Ty, + llvm::StringRef suffix); + public: CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD, const ABIInfo &Info, CGCXXABI &CXXABI); @@ -145,10 +150,19 @@ class CodeGenTypes { const CGRecordLayout &getCGRecordLayout(const RecordDecl*); + /// addBaseSubobjectTypeName - Add a type name for the base subobject of the + /// given record layout. + void addBaseSubobjectTypeName(const CXXRecordDecl *RD, + const CGRecordLayout &layout); + /// UpdateCompletedType - When we find the full definition for a TagDecl, /// replace the 'opaque' type we previously made for it if applicable. void UpdateCompletedType(const TagDecl *TD); + /// getNullaryFunctionInfo - Get the function info for a void() + /// function with standard CC. + const CGFunctionInfo &getNullaryFunctionInfo(); + /// getFunctionInfo - Get the function info for the specified function decl. const CGFunctionInfo &getFunctionInfo(GlobalDecl GD); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp index 95654a33a125..33abf3a4aaf7 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This provides C++ code generation targetting the Itanium C++ ABI. The class +// This provides C++ code generation targeting the Itanium C++ ABI. The class // in this file generates structures that follow the Itanium C++ ABI, which is // documented at: // http://www.codesourcery.com/public/cxx-abi/abi.html @@ -282,8 +282,7 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, // We're done. CGF.EmitBlock(FnEnd); - llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo()); - Callee->reserveOperandSpace(2); + llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo(), 2); Callee->addIncoming(VirtualFn, FnVirtual); Callee->addIncoming(NonVirtualFn, FnNonVirtual); return Callee; @@ -515,10 +514,10 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { if (MD->isVirtual()) { uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD); - // FIXME: We shouldn't use / 8 here. - uint64_t PointerWidthInBytes = - getContext().Target.getPointerWidth(0) / 8; - uint64_t VTableOffset = (Index * PointerWidthInBytes); + const ASTContext &Context = getContext(); + CharUnits PointerWidth = + Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); + uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); if (IsARM) { // ARM C++ ABI 3.2.1: @@ -538,20 +537,21 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); } } else { - const FunctionProtoType *FPT = MD->getType()->getAs(); + const FunctionProtoType *FPT = MD->getType()->castAs(); const llvm::Type *Ty; // Check whether the function has a computable LLVM signature. if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) { // The function has a computable LLVM signature; use the correct type. - Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic()); + Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), + FPT->isVariadic()); } else { // Use an arbitrary non-function type to tell GetAddrOfFunction that the // function type is incomplete. Ty = ptrdiff_t; } + llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); - llvm::Constant *Addr = CGM.GetAddrOfFunction(MD, Ty); - MemPtr[0] = llvm::ConstantExpr::getPtrToInt(Addr, ptrdiff_t); + MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t); MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); } @@ -651,20 +651,21 @@ ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); } - // In Itanium, a member function pointer is null if 'ptr' is null. + // In Itanium, a member function pointer is not null if 'ptr' is not null. llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); - // In ARM, it's that, plus the low bit of 'adj' must be zero. + // On ARM, a member function pointer is also non-null if the low bit of 'adj' + // (the virtual bit) is set. if (IsARM) { llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj"); llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); - llvm::Value *IsNotVirtual = Builder.CreateICmpEQ(VirtualBit, Zero, - "memptr.notvirtual"); - Result = Builder.CreateAnd(Result, IsNotVirtual); + llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero, + "memptr.isvirtual"); + Result = Builder.CreateOr(Result, IsVirtual); } return Result; @@ -745,7 +746,7 @@ void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, ImplicitParamDecl *VTTDecl = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), &Context.Idents.get("vtt"), T); - Params.push_back(std::make_pair(VTTDecl, VTTDecl->getType())); + Params.push_back(VTTDecl); getVTTDecl(CGF) = VTTDecl; } } @@ -757,7 +758,7 @@ void ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, // Return 'this' from certain constructors and destructors. if (HasThisReturn(CGF.CurGD)) - ResTy = Params[0].second; + ResTy = Params[0]->getType(); } void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { @@ -1064,10 +1065,18 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // global initialization is always single-threaded. bool ThreadsafeStatics = (getContext().getLangOptions().ThreadsafeStatics && D.isLocalVarDecl()); - - // Guard variables are 64 bits in the generic ABI and 32 bits on ARM. - const llvm::IntegerType *GuardTy - = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty()); + + const llvm::IntegerType *GuardTy; + + // If we have a global variable with internal linkage and thread-safe statics + // are disabled, we can just let the guard variable be of type i8. + bool UseInt8GuardVariable = !ThreadsafeStatics && GV->hasInternalLinkage(); + if (UseInt8GuardVariable) + GuardTy = Builder.getInt8Ty(); + else { + // Guard variables are 64 bits in the generic ABI and 32 bits on ARM. + GuardTy = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty()); + } const llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo(); // Create the guard variable. @@ -1098,7 +1107,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // if (__cxa_guard_acquire(&obj_guard)) // ... // } - if (IsARM) { + if (IsARM && !UseInt8GuardVariable) { llvm::Value *V = Builder.CreateLoad(GuardVariable); V = Builder.CreateAnd(V, Builder.getInt32(1)); IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 3a63eba39741..747e5e3222c2 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This provides C++ code generation targetting the Microsoft Visual C++ ABI. +// This provides C++ code generation targeting the Microsoft Visual C++ ABI. // The class in this file generates structures that follow the Microsoft // Visual C++ ABI, which is actually not very well documented at all outside // of Microsoft. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp index 2ffc840b9f92..bc2472cebbeb 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp @@ -16,6 +16,7 @@ #include "ABIInfo.h" #include "CodeGenFunction.h" #include "clang/AST/RecordLayout.h" +#include "clang/Frontend/CodeGenOptions.h" #include "llvm/Type.h" #include "llvm/Target/TargetData.h" #include "llvm/ADT/Triple.h" @@ -358,7 +359,7 @@ bool UseX86_MMXType(const llvm::Type *IRType) { static const llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF, llvm::StringRef Constraint, const llvm::Type* Ty) { - if (Constraint=="y" && Ty->isVectorTy()) + if ((Constraint == "y" || Constraint == "&y") && Ty->isVectorTy()) return llvm::Type::getX86_MMXTy(CGF.getLLVMContext()); return Ty; } @@ -864,6 +865,15 @@ class X86_64ABIInfo : public ABIInfo { unsigned &neededInt, unsigned &neededSSE) const; + /// The 0.98 ABI revision clarified a lot of ambiguities, + /// unfortunately in ways that were not always consistent with + /// certain previous compilers. In particular, platforms which + /// required strict binary compatibility with older versions of GCC + /// may need to exempt themselves. + bool honorsRevision0_98() const { + return !getContext().Target.getTriple().isOSDarwin(); + } + public: X86_64ABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {} @@ -1252,15 +1262,24 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, // (a) If one of the classes is MEMORY, the whole argument is // passed in memory. // - // (b) If SSEUP is not preceeded by SSE, it is converted to SSE. - - // The first of these conditions is guaranteed by how we implement - // the merge (just bail). + // (b) If X87UP is not preceded by X87, the whole argument is + // passed in memory. + // + // (c) If the size of the aggregate exceeds two eightbytes and the first + // eight-byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole + // argument is passed in memory. + // + // (d) If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE. // - // The second condition occurs in the case of unions; for example - // union { _Complex double; unsigned; }. + // Some of these are enforced by the merging logic. Others can arise + // only with unions; for example: + // union { _Complex double; unsigned; } + // + // Note that clauses (b) and (c) were added in 0.98. if (Hi == Memory) Lo = Memory; + if (Hi == X87Up && Lo != X87 && honorsRevision0_98()) + Lo = Memory; if (Hi == SSEUp && Lo != SSE) Hi = SSE; } @@ -1689,7 +1708,7 @@ classifyReturnType(QualType RetTy) const { // AMD64-ABI 3.2.3p4: Rule 5. If the class is SSEUP, the eightbyte // is passed in the upper half of the last used SSE register. // - // SSEUP should always be preceeded by SSE, just widen. + // SSEUP should always be preceded by SSE, just widen. case SSEUp: assert(Lo == SSE && "Unexpected SSEUp classification."); ResType = Get16ByteVectorType(RetTy); @@ -1698,9 +1717,9 @@ classifyReturnType(QualType RetTy) const { // AMD64-ABI 3.2.3p4: Rule 7. If the class is X87UP, the value is // returned together with the previous X87 value in %st0. case X87Up: - // If X87Up is preceeded by X87, we don't need to do + // If X87Up is preceded by X87, we don't need to do // anything. However, in some cases with unions it may not be - // preceeded by X87. In such situations we follow gcc and pass the + // preceded by X87. In such situations we follow gcc and pass the // extra bits in an SSE reg. if (Lo != X87) { HighPart = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), @@ -1799,7 +1818,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt, const llvm::Type *HighPart = 0; switch (Hi) { // Memory was handled previously, ComplexX87 and X87 should - // never occur as hi classes, and X87Up must be preceed by X87, + // never occur as hi classes, and X87Up must be preceded by X87, // which is passed in memory. case Memory: case X87: @@ -2082,9 +2101,8 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, // Return the appropriate result. CGF.EmitBlock(ContBlock); - llvm::PHINode *ResAddr = CGF.Builder.CreatePHI(RegAddr->getType(), + llvm::PHINode *ResAddr = CGF.Builder.CreatePHI(RegAddr->getType(), 2, "vaarg.addr"); - ResAddr->reserveOperandSpace(2); ResAddr->addIncoming(RegAddr, InRegBlock); ResAddr->addIncoming(MemAddr, InMemBlock); return ResAddr; @@ -2271,27 +2289,33 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { it != ie; ++it) it->info = classifyArgumentType(it->type); - const llvm::Triple &Triple(getContext().Target.getTriple()); + // Always honor user-specified calling convention. + if (FI.getCallingConvention() != llvm::CallingConv::C) + return; + + // Calling convention as default by an ABI. llvm::CallingConv::ID DefaultCC; - if (Triple.getEnvironmentName() == "gnueabi" || - Triple.getEnvironmentName() == "eabi") + llvm::StringRef Env = getContext().Target.getTriple().getEnvironmentName(); + if (Env == "gnueabi" || Env == "eabi") DefaultCC = llvm::CallingConv::ARM_AAPCS; else DefaultCC = llvm::CallingConv::ARM_APCS; + // If user did not ask for specific calling convention explicitly (e.g. via + // pcs attribute), set effective calling convention if it's different than ABI + // default. switch (getABIKind()) { case APCS: if (DefaultCC != llvm::CallingConv::ARM_APCS) FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_APCS); break; - case AAPCS: if (DefaultCC != llvm::CallingConv::ARM_AAPCS) FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS); break; - case AAPCS_VFP: - FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS_VFP); + if (DefaultCC != llvm::CallingConv::ARM_AAPCS_VFP) + FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS_VFP); break; } } @@ -2317,22 +2341,26 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const { // Otherwise, pass by coercing to a structure of the appropriate size. // - // FIXME: This is kind of nasty... but there isn't much choice because the ARM - // backend doesn't support byval. // FIXME: This doesn't handle alignment > 64 bits. const llvm::Type* ElemTy; unsigned SizeRegs; - if (getContext().getTypeAlign(Ty) > 32) { - ElemTy = llvm::Type::getInt64Ty(getVMContext()); - SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64; - } else { + if (getContext().getTypeSizeInChars(Ty) <= CharUnits::fromQuantity(64)) { ElemTy = llvm::Type::getInt32Ty(getVMContext()); SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32; + } else if (getABIKind() == ARMABIInfo::APCS) { + // Initial ARM ByVal support is APCS-only. + return ABIArgInfo::getIndirect(0, /*ByVal=*/true); + } else { + // FIXME: This is kind of nasty... but there isn't much choice + // because most of the ARM calling conventions don't yet support + // byval. + ElemTy = llvm::Type::getInt64Ty(getVMContext()); + SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64; } - std::vector LLVMFields; - LLVMFields.push_back(llvm::ArrayType::get(ElemTy, SizeRegs)); - const llvm::Type* STy = llvm::StructType::get(getVMContext(), LLVMFields, - true); + + const llvm::Type *STy = + llvm::StructType::get(getVMContext(), + llvm::ArrayType::get(ElemTy, SizeRegs), NULL, NULL); return ABIArgInfo::getDirect(STy); } @@ -2515,6 +2543,74 @@ llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, return AddrTyped; } +//===----------------------------------------------------------------------===// +// PTX ABI Implementation +//===----------------------------------------------------------------------===// + +namespace { + +class PTXABIInfo : public ABIInfo { +public: + PTXABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} + + ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType Ty) const; + + virtual void computeInfo(CGFunctionInfo &FI) const; + virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, + CodeGenFunction &CFG) const; +}; + +class PTXTargetCodeGenInfo : public TargetCodeGenInfo { +public: + PTXTargetCodeGenInfo(CodeGenTypes &CGT) + : TargetCodeGenInfo(new PTXABIInfo(CGT)) {} +}; + +ABIArgInfo PTXABIInfo::classifyReturnType(QualType RetTy) const { + if (RetTy->isVoidType()) + return ABIArgInfo::getIgnore(); + if (isAggregateTypeForABI(RetTy)) + return ABIArgInfo::getIndirect(0); + return ABIArgInfo::getDirect(); +} + +ABIArgInfo PTXABIInfo::classifyArgumentType(QualType Ty) const { + if (isAggregateTypeForABI(Ty)) + return ABIArgInfo::getIndirect(0); + + return ABIArgInfo::getDirect(); +} + +void PTXABIInfo::computeInfo(CGFunctionInfo &FI) const { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); + it != ie; ++it) + it->info = classifyArgumentType(it->type); + + // Always honor user-specified calling convention. + if (FI.getCallingConvention() != llvm::CallingConv::C) + return; + + // Calling convention as default by an ABI. + llvm::CallingConv::ID DefaultCC; + llvm::StringRef Env = getContext().Target.getTriple().getEnvironmentName(); + if (Env == "device") + DefaultCC = llvm::CallingConv::PTX_Device; + else + DefaultCC = llvm::CallingConv::PTX_Kernel; + + FI.setEffectiveCallingConvention(DefaultCC); +} + +llvm::Value *PTXABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, + CodeGenFunction &CFG) const { + llvm_unreachable("PTX does not support varargs"); + return 0; +} + +} + //===----------------------------------------------------------------------===// // SystemZ ABI Implementation //===----------------------------------------------------------------------===// @@ -2815,17 +2911,24 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::arm: case llvm::Triple::thumb: - // FIXME: We want to know the float calling convention as well. - if (strcmp(getContext().Target.getABI(), "apcs-gnu") == 0) - return *(TheTargetCodeGenInfo = - new ARMTargetCodeGenInfo(Types, ARMABIInfo::APCS)); + { + ARMABIInfo::ABIKind Kind = ARMABIInfo::AAPCS; - return *(TheTargetCodeGenInfo = - new ARMTargetCodeGenInfo(Types, ARMABIInfo::AAPCS)); + if (strcmp(getContext().Target.getABI(), "apcs-gnu") == 0) + Kind = ARMABIInfo::APCS; + else if (CodeGenOpts.FloatABI == "hard") + Kind = ARMABIInfo::AAPCS_VFP; + + return *(TheTargetCodeGenInfo = new ARMTargetCodeGenInfo(Types, Kind)); + } case llvm::Triple::ppc: return *(TheTargetCodeGenInfo = new PPC32TargetCodeGenInfo(Types)); + case llvm::Triple::ptx32: + case llvm::Triple::ptx64: + return *(TheTargetCodeGenInfo = new PTXTargetCodeGenInfo(Types)); + case llvm::Triple::systemz: return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo(Types)); @@ -2836,10 +2939,11 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo(Types)); case llvm::Triple::x86: - switch (Triple.getOS()) { - case llvm::Triple::Darwin: + if (Triple.isOSDarwin()) return *(TheTargetCodeGenInfo = new X86_32TargetCodeGenInfo(Types, true, true)); + + switch (Triple.getOS()) { case llvm::Triple::Cygwin: case llvm::Triple::MinGW32: case llvm::Triple::AuroraUX: diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp index 5619212d38bb..2657faa0d3a7 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp @@ -101,6 +101,12 @@ bool Compilation::CleanupFileList(const ArgStringList &Files, llvm::sys::Path P(*it); std::string Error; + // Don't try to remove files which we don't have write access to (but may be + // able to remove). Underlying tools may have intentionally not overwritten + // them. + if (!P.canWrite()) + continue; + if (P.eraseFromDisk(false, &Error)) { // Failure is only failure if the file exists and is "regular". There is // a race condition here due to the limited interface of diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index 4b6aef6f4bf8..302779b97929 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -30,6 +30,7 @@ #include "clang/Basic/Version.h" #include "llvm/Config/config.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/PrettyStackTrace.h" @@ -42,13 +43,6 @@ #include -#ifdef __CYGWIN__ -#include -#if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 -#define IS_CYGWIN15 1 -#endif -#endif - using namespace clang::driver; using namespace clang; @@ -58,15 +52,17 @@ Driver::Driver(llvm::StringRef _ClangExecutable, bool IsProduction, bool CXXIsProduction, Diagnostic &_Diags) : Opts(createDriverOptTable()), Diags(_Diags), - ClangExecutable(_ClangExecutable), DefaultHostTriple(_DefaultHostTriple), - DefaultImageName(_DefaultImageName), + ClangExecutable(_ClangExecutable), UseStdLib(true), + DefaultHostTriple(_DefaultHostTriple), DefaultImageName(_DefaultImageName), DriverTitle("clang \"gcc-compatible\" driver"), Host(0), - CCPrintOptionsFilename(0), CCPrintHeadersFilename(0), CCCIsCXX(false), - CCCEcho(false), CCCPrintBindings(false), CCPrintOptions(false), - CCPrintHeaders(false), CCCGenericGCCName("gcc"), - CheckInputsExist(true), CCCUseClang(true), CCCUseClangCXX(true), - CCCUseClangCPP(true), CCCUsePCH(true), SuppressMissingInputWarning(false) { + CCPrintOptionsFilename(0), CCPrintHeadersFilename(0), + CCLogDiagnosticsFilename(0), CCCIsCXX(false), + CCCIsCPP(false),CCCEcho(false), CCCPrintBindings(false), + CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), + CCCGenericGCCName(""), CheckInputsExist(true), CCCUseClang(true), + CCCUseClangCXX(true), CCCUseClangCPP(true), CCCUsePCH(true), + SuppressMissingInputWarning(false) { if (IsProduction) { // In a "production" build, only use clang on architectures we expect to // work, and don't use clang C++. @@ -100,11 +96,10 @@ Driver::~Driver() { delete Host; } -InputArgList *Driver::ParseArgStrings(const char **ArgBegin, - const char **ArgEnd) { +InputArgList *Driver::ParseArgStrings(llvm::ArrayRef ArgList) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); unsigned MissingArgIndex, MissingArgCount; - InputArgList *Args = getOpts().ParseArgs(ArgBegin, ArgEnd, + InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(), MissingArgIndex, MissingArgCount); // Check for missing argument error. @@ -206,7 +201,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { return DAL; } -Compilation *Driver::BuildCompilation(int argc, const char **argv) { +Compilation *Driver::BuildCompilation(llvm::ArrayRef ArgList) { llvm::PrettyStackTraceString CrashInfo("Compilation construction"); // FIXME: Handle environment options which effect driver behavior, somewhere @@ -218,9 +213,7 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) { // FIXME: This stuff needs to go into the Compilation, not the driver. bool CCCPrintOptions = false, CCCPrintActions = false; - const char **Start = argv + 1, **End = argv + argc; - - InputArgList *Args = ParseArgStrings(Start, End); + InputArgList *Args = ParseArgStrings(ArgList.slice(1)); // -no-canonical-prefixes is used very early in main. Args->ClaimAllArgs(options::OPT_no_canonical_prefixes); @@ -238,13 +231,6 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) { CCCPrintActions = Args->hasArg(options::OPT_ccc_print_phases); CCCPrintBindings = Args->hasArg(options::OPT_ccc_print_bindings); CCCIsCXX = Args->hasArg(options::OPT_ccc_cxx) || CCCIsCXX; - if (CCCIsCXX) { -#ifdef IS_CYGWIN15 - CCCGenericGCCName = "g++-4"; -#else - CCCGenericGCCName = "g++"; -#endif - } CCCEcho = Args->hasArg(options::OPT_ccc_echo); if (const Arg *A = Args->getLastArg(options::OPT_ccc_gcc_name)) CCCGenericGCCName = A->getValue(*Args); @@ -287,6 +273,10 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) { A->claim(); PrefixDirs.push_back(A->getValue(*Args, 0)); } + if (const Arg *A = Args->getLastArg(options::OPT__sysroot_EQ)) + SysRoot = A->getValue(*Args); + if (Args->hasArg(options::OPT_nostdlib)) + UseStdLib = false; Host = GetHostInfo(DefaultHostTriple.c_str()); @@ -593,7 +583,7 @@ static bool ContainsCompileAction(const Action *A) { } void Driver::BuildUniversalActions(const ToolChain &TC, - const ArgList &Args, + const DerivedArgList &Args, ActionList &Actions) const { llvm::PrettyStackTraceString CrashInfo("Building universal build actions"); // Collect the list of architectures. Duplicates are allowed, but should only @@ -688,7 +678,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, } } -void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, +void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, ActionList &Actions) const { llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); // Start by constructing the list of inputs and their types. @@ -721,18 +711,23 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, // // Otherwise emit an error but still use a valid type to avoid // spurious errors (e.g., no inputs). - if (!Args.hasArgNoClaim(options::OPT_E)) + if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP) Diag(clang::diag::err_drv_unknown_stdin_type); Ty = types::TY_C; } else { - // Otherwise lookup by extension, and fallback to ObjectType if not - // found. We use a host hook here because Darwin at least has its own + // Otherwise lookup by extension. + // Fallback is C if invoked as C preprocessor or Object otherwise. + // We use a host hook here because Darwin at least has its own // idea of what .s is. if (const char *Ext = strrchr(Value, '.')) Ty = TC.LookupTypeForExtension(Ext + 1); - if (Ty == types::TY_INVALID) - Ty = types::TY_Object; + if (Ty == types::TY_INVALID) { + if (CCCIsCPP) + Ty = types::TY_C; + else + Ty = types::TY_Object; + } // If the driver is invoked as C++ compiler (like clang++ or c++) it // should autodetect some input files as C++ for g++ compatibility. @@ -799,6 +794,15 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, } } + if (CCCIsCPP && Inputs.empty()) { + // If called as standalone preprocessor, stdin is processed + // if no other input is present. + unsigned Index = Args.getBaseArgs().MakeIndex("-"); + Arg *A = Opts->ParseOneArg(Args, Index); + A->claim(); + Inputs.push_back(std::make_pair(types::TY_C, A)); + } + if (!SuppressMissingInputWarning && Inputs.empty()) { Diag(clang::diag::err_drv_no_input_files); return; @@ -811,7 +815,8 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, phases::ID FinalPhase; // -{E,M,MM} only run the preprocessor. - if ((FinalPhaseArg = Args.getLastArg(options::OPT_E)) || + if (CCCIsCPP || + (FinalPhaseArg = Args.getLastArg(options::OPT_E)) || (FinalPhaseArg = Args.getLastArg(options::OPT_M, options::OPT_MM))) { FinalPhase = phases::Preprocess; @@ -853,6 +858,10 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, // Claim here to avoid the more general unused warning. InputArg->claim(); + // Suppress all unused style warnings with -Qunused-arguments + if (Args.hasArg(options::OPT_Qunused_arguments)) + continue; + // Special case '-E' warning on a previously preprocessed file to make // more sense. if (InitialPhase == phases::Compile && FinalPhase == phases::Preprocess && @@ -945,7 +954,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, } else if (Args.hasArg(options::OPT_emit_ast)) { return new CompileJobAction(Input, types::TY_AST); } else if (Args.hasArg(options::OPT_emit_llvm) || - Args.hasArg(options::OPT_flto) || HasO4) { + Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false) || + HasO4) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; return new CompileJobAction(Input, Output); @@ -1064,14 +1074,17 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC, bool HasStatic = (C.getArgs().hasArg(options::OPT_mkernel) || C.getArgs().hasArg(options::OPT_static) || C.getArgs().hasArg(options::OPT_fapple_kext)); - bool IsIADefault = (TC->IsIntegratedAssemblerDefault() && !HasStatic); + bool IsDarwin = TC->getTriple().getOS() == llvm::Triple::Darwin; + bool IsIADefault = TC->IsIntegratedAssemblerDefault() && + !(HasStatic && IsDarwin); if (C.getArgs().hasFlag(options::OPT_integrated_as, options::OPT_no_integrated_as, IsIADefault) && !C.getArgs().hasArg(options::OPT_save_temps) && isa(JA) && Inputs->size() == 1 && isa(*Inputs->begin())) { - const Tool &Compiler = TC->SelectTool(C,cast(**Inputs->begin())); + const Tool &Compiler = TC->SelectTool( + C, cast(**Inputs->begin()), (*Inputs)[0]->getInputs()); if (Compiler.hasIntegratedAssembler()) { Inputs = &(*Inputs)[0]->getInputs(); ToolForJob = &Compiler; @@ -1080,7 +1093,7 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC, // Otherwise use the tool for the current job. if (!ToolForJob) - ToolForJob = &TC->SelectTool(C, *JA); + ToolForJob = &TC->SelectTool(C, *JA, *Inputs); // See if we should use an integrated preprocessor. We do so when we have // exactly one input, since this is the only use case we care about @@ -1206,7 +1219,13 @@ const char *Driver::GetNamedOutputPath(Compilation &C, } llvm::SmallString<128> BasePath(BaseInput); - llvm::StringRef BaseName = llvm::sys::path::filename(BasePath); + llvm::StringRef BaseName; + + // Dsymutil actions should use the full path. + if (isa(JA)) + BaseName = BasePath; + else + BaseName = llvm::sys::path::filename(BasePath); // Determine what the derived output name should be. const char *NamedOutput; @@ -1243,7 +1262,12 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { // attempting to use this prefix when lokup up program paths. for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(), ie = PrefixDirs.end(); it != ie; ++it) { - llvm::sys::Path P(*it); + std::string Dir(*it); + if (Dir.empty()) + continue; + if (Dir[0] == '=') + Dir = SysRoot + Dir.substr(1); + llvm::sys::Path P(Dir); P.appendComponent(Name); bool Exists; if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) @@ -1253,7 +1277,12 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { const ToolChain::path_list &List = TC.getFilePaths(); for (ToolChain::path_list::const_iterator it = List.begin(), ie = List.end(); it != ie; ++it) { - llvm::sys::Path P(*it); + std::string Dir(*it); + if (Dir.empty()) + continue; + if (Dir[0] == '=') + Dir = SysRoot + Dir.substr(1); + llvm::sys::Path P(Dir); P.appendComponent(Name); bool Exists; if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) @@ -1323,7 +1352,7 @@ std::string Driver::GetTemporaryPath(const char *Suffix) const { const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { llvm::PrettyStackTraceString CrashInfo("Constructing host"); - llvm::Triple Triple(TripleStr); + llvm::Triple Triple(llvm::Triple::normalize(TripleStr).c_str()); // TCE is an osless target if (Triple.getArchName() == "tce") diff --git a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp index cd413180f77b..198af54c035a 100644 --- a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp @@ -113,14 +113,9 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, TCTriple.setArch(Arch); // If we recognized the arch, match it to the toolchains we support. - const char *UseNewToolChain = ::getenv("CCC_ENABLE_NEW_DARWIN_TOOLCHAIN"); - if (UseNewToolChain || - Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64 || + if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { TC = new toolchains::DarwinClang(*this, TCTriple); - } else if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) { - // We still use the legacy DarwinGCC toolchain on X86. - TC = new toolchains::DarwinGCC(*this, TCTriple); } else TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple); } diff --git a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp index c3d3048c12fe..0252b3e5cac5 100644 --- a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp @@ -20,9 +20,9 @@ using namespace clang::driver::options; // Ordering on Info. The ordering is *almost* lexicographic, with two // exceptions. First, '\0' comes at the end of the alphabet instead of -// the beginning (thus options preceed any other options which prefix +// the beginning (thus options precede any other options which prefix // them). Second, for options with the same name, the less permissive -// version should come first; a Flag option should preceed a Joined +// version should come first; a Flag option should precede a Joined // option, for example. static int StrCmpOptionName(const char *A, const char *B) { diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index e305683930cf..d9199154104a 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -47,7 +47,7 @@ bool ToolChain::HasNativeLLVMSupport() const { return false; } -/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting. +/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. // // FIXME: tblgen this. static const char *getARMTargetCPU(const ArgList &Args, @@ -101,6 +101,8 @@ static const char *getARMTargetCPU(const ArgList &Args, return "iwmmxt"; if (MArch == "xscale") return "xscale"; + if (MArch == "armv6m" || MArch == "armv6-m") + return "cortex-m0"; // If all else failed, return the most base CPU LLVM supports. return "arm7tdmi"; @@ -137,6 +139,12 @@ static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) { if (CPU == "cortex-a8" || CPU == "cortex-a9") return "v7"; + if (CPU == "cortex-m3") + return "v7m"; + + if (CPU == "cortex-m0") + return "v6m"; + return ""; } @@ -168,10 +176,10 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const { } std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args) const { - // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on - // non-Darwin. + // Diagnose use of Darwin OS deployment target arguments on non-Darwin. if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ, - options::OPT_miphoneos_version_min_EQ)) + options::OPT_miphoneos_version_min_EQ, + options::OPT_mios_simulator_version_min_EQ)) getDriver().Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index 422c5720f5ff..499587a10cff 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -105,7 +105,8 @@ static const char *GetArmArchForMCpu(llvm::StringRef Value) { return "xscale"; if (Value == "arm1136j-s" || Value == "arm1136jf-s" || - Value == "arm1176jz-s" || Value == "arm1176jzf-s") + Value == "arm1176jz-s" || Value == "arm1176jzf-s" || + Value == "cortex-m0" ) return "armv6"; if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3") @@ -118,7 +119,8 @@ llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const { switch (getTriple().getArch()) { default: return getArchName(); - + + case llvm::Triple::thumb: case llvm::Triple::arm: { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) if (const char *Arch = GetArmArchForMArch(A->getValue(Args))) @@ -133,82 +135,6 @@ llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const { } } -DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple) - : Darwin(Host, Triple) -{ - // We can only work with 4.2.1 currently. - GCCVersion[0] = 4; - GCCVersion[1] = 2; - GCCVersion[2] = 1; - - // Set up the tool chain paths to match gcc. - ToolChainDir = "i686-apple-darwin"; - ToolChainDir += llvm::utostr(DarwinVersion[0]); - ToolChainDir += "/"; - ToolChainDir += llvm::utostr(GCCVersion[0]); - ToolChainDir += '.'; - ToolChainDir += llvm::utostr(GCCVersion[1]); - ToolChainDir += '.'; - ToolChainDir += llvm::utostr(GCCVersion[2]); - - // Try the next major version if that tool chain dir is invalid. - std::string Tmp = "/usr/lib/gcc/" + ToolChainDir; - bool Exists; - if (llvm::sys::fs::exists(Tmp, Exists) || Exists) { - std::string Next = "i686-apple-darwin"; - Next += llvm::utostr(DarwinVersion[0] + 1); - Next += "/"; - Next += llvm::utostr(GCCVersion[0]); - Next += '.'; - Next += llvm::utostr(GCCVersion[1]); - Next += '.'; - Next += llvm::utostr(GCCVersion[2]); - - // Use that if it exists, otherwise hope the user isn't linking. - // - // FIXME: Drop dependency on gcc's tool chain. - Tmp = "/usr/lib/gcc/" + Next; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - ToolChainDir = Next; - } - - std::string Path; - if (getArchName() == "x86_64") { - Path = getDriver().Dir; - Path += "/../lib/gcc/"; - Path += ToolChainDir; - Path += "/x86_64"; - getFilePaths().push_back(Path); - - Path = "/usr/lib/gcc/"; - Path += ToolChainDir; - Path += "/x86_64"; - getFilePaths().push_back(Path); - } - - Path = getDriver().Dir; - Path += "/../lib/gcc/"; - Path += ToolChainDir; - getFilePaths().push_back(Path); - - Path = "/usr/lib/gcc/"; - Path += ToolChainDir; - getFilePaths().push_back(Path); - - Path = getDriver().Dir; - Path += "/../libexec/gcc/"; - Path += ToolChainDir; - getProgramPaths().push_back(Path); - - Path = "/usr/libexec/gcc/"; - Path += ToolChainDir; - getProgramPaths().push_back(Path); - - getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir) - getProgramPaths().push_back(getDriver().Dir); -} - Darwin::~Darwin() { // Free tool implementations. for (llvm::DenseMap::iterator @@ -226,33 +152,31 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args) const { unsigned Version[3]; getTargetVersion(Version); - - // Mangle the target version into the OS triple component. For historical - // reasons that make little sense, the version passed here is the "darwin" - // version, which drops the 10 and offsets by 4. See inverse code when - // setting the OS version preprocessor define. - if (!isTargetIPhoneOS()) { - Version[0] = Version[1] + 4; - Version[1] = Version[2]; - Version[2] = 0; - } else { - // Use the environment to communicate that we are targetting iPhoneOS. - Triple.setEnvironmentName("iphoneos"); - } - + llvm::SmallString<16> Str; - llvm::raw_svector_ostream(Str) << "darwin" << Version[0] - << "." << Version[1] << "." << Version[2]; + llvm::raw_svector_ostream(Str) + << (isTargetIPhoneOS() ? "ios" : "macosx") + << Version[0] << "." << Version[1] << "." << Version[2]; Triple.setOSName(Str.str()); return Triple.getTriple(); } -Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; - if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) - Key = Action::AnalyzeJobClass; - else + + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) { + // Fallback to llvm-gcc for i386 kext compiles, we don't support that ABI. + if (Inputs.size() == 1 && + types::isCXX(Inputs[0]->getType()) && + getTriple().getOS() == llvm::Triple::Darwin && + getTriple().getArch() == llvm::Triple::x86 && + C.getArgs().getLastArg(options::OPT_fapple_kext)) + Key = JA.getKind(); + else + Key = Action::AnalyzeJobClass; + } else Key = JA.getKind(); // FIXME: This doesn't belong here, but ideally we will support static soon @@ -297,91 +221,12 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const { return *T; } -void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - std::string Tmp; - - // FIXME: Derive these correctly. - if (getArchName() == "x86_64") { - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir + - "/x86_64")); - // Intentionally duplicated for (temporary) gcc bug compatibility. - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir + - "/x86_64")); - } - - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir)); - - Tmp = getDriver().Dir + "/../lib/gcc/" + ToolChainDir; - bool Exists; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - CmdArgs.push_back(Args.MakeArgString("-L" + Tmp)); - Tmp = getDriver().Dir + "/../lib/gcc"; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - CmdArgs.push_back(Args.MakeArgString("-L" + Tmp)); - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir)); - // Intentionally duplicated for (temporary) gcc bug compatibility. - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir)); - Tmp = getDriver().Dir + "/../lib/" + ToolChainDir; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - CmdArgs.push_back(Args.MakeArgString("-L" + Tmp)); - Tmp = getDriver().Dir + "/../lib"; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - CmdArgs.push_back(Args.MakeArgString("-L" + Tmp)); - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir + - "/../../../" + ToolChainDir)); - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir + - "/../../..")); -} - -void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - // Note that this routine is only used for targetting OS X. - - // Derived from libgcc and lib specs but refactored. - if (Args.hasArg(options::OPT_static)) { - CmdArgs.push_back("-lgcc_static"); - } else { - if (Args.hasArg(options::OPT_static_libgcc)) { - CmdArgs.push_back("-lgcc_eh"); - } else if (Args.hasArg(options::OPT_miphoneos_version_min_EQ)) { - // Derived from darwin_iphoneos_libgcc spec. - if (isTargetIPhoneOS()) { - CmdArgs.push_back("-lgcc_s.1"); - } else { - CmdArgs.push_back("-lgcc_s.10.5"); - } - } else if (Args.hasArg(options::OPT_shared_libgcc) || - Args.hasFlag(options::OPT_fexceptions, - options::OPT_fno_exceptions) || - Args.hasArg(options::OPT_fgnu_runtime)) { - // FIXME: This is probably broken on 10.3? - if (isMacosxVersionLT(10, 5)) - CmdArgs.push_back("-lgcc_s.10.4"); - else if (isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-lgcc_s.10.5"); - } else { - if (isMacosxVersionLT(10, 3, 9)) - ; // Do nothing. - else if (isMacosxVersionLT(10, 5)) - CmdArgs.push_back("-lgcc_s.10.4"); - else if (isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-lgcc_s.10.5"); - } - - if (isTargetIPhoneOS() || isMacosxVersionLT(10, 6)) { - CmdArgs.push_back("-lgcc"); - CmdArgs.push_back("-lSystem"); - } else { - CmdArgs.push_back("-lSystem"); - CmdArgs.push_back("-lgcc"); - } - } -} DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple) : Darwin(Host, Triple) { + std::string UsrPrefix = "llvm-gcc-4.2/"; + getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); @@ -392,18 +237,18 @@ DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple) getProgramPaths().push_back(getDriver().Dir); // For fallback, we need to know how to find the GCC cc1 executables, so we - // also add the GCC libexec paths. This is legiy code that can be removed once - // fallback is no longer useful. + // also add the GCC libexec paths. This is legacy code that can be removed + // once fallback is no longer useful. std::string ToolChainDir = "i686-apple-darwin"; ToolChainDir += llvm::utostr(DarwinVersion[0]); ToolChainDir += "/4.2.1"; std::string Path = getDriver().Dir; - Path += "/../libexec/gcc/"; + Path += "/../" + UsrPrefix + "libexec/gcc/"; Path += ToolChainDir; getProgramPaths().push_back(Path); - Path = "/usr/libexec/gcc/"; + Path = "/usr/" + UsrPrefix + "libexec/gcc/"; Path += ToolChainDir; getProgramPaths().push_back(Path); } @@ -498,12 +343,13 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, // Select the dynamic runtime library and the target specific static library. const char *DarwinStaticLib = 0; if (isTargetIPhoneOS()) { - CmdArgs.push_back("-lgcc_s.1"); + // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1, + // it never went into the SDK. + if (!isTargetIOSSimulator()) + CmdArgs.push_back("-lgcc_s.1"); - // We may need some static functions for armv6/thumb which are required to - // be in the same linkage unit as their caller. - if (getDarwinArchName(Args) == "armv6") - DarwinStaticLib = "libclang_rt.armv6.a"; + // We currently always need a static runtime library for iOS. + DarwinStaticLib = "libclang_rt.ios.a"; } else { // The dynamic runtime library was merged with libSystem for 10.6 and // beyond; only 10.4 and 10.5 need an additional runtime library. @@ -513,7 +359,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, CmdArgs.push_back("-lgcc_s.10.5"); // For OS X, we thought we would only need a static runtime library when - // targetting 10.4, to provide versions of the static functions which were + // targeting 10.4, to provide versions of the static functions which were // omitted from 10.4.dylib. // // Unfortunately, that turned out to not be true, because Darwin system @@ -547,46 +393,69 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { const OptTable &Opts = getDriver().getOpts(); Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ); - Arg *iPhoneVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ); - if (OSXVersion && iPhoneVersion) { + Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ); + Arg *iOSSimVersion = Args.getLastArg( + options::OPT_mios_simulator_version_min_EQ); + if (OSXVersion && (iOSVersion || iOSSimVersion)) { getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) << OSXVersion->getAsString(Args) - << iPhoneVersion->getAsString(Args); - iPhoneVersion = 0; - } else if (!OSXVersion && !iPhoneVersion) { - // If neither OS X nor iPhoneOS targets were specified, check for + << (iOSVersion ? iOSVersion : iOSSimVersion)->getAsString(Args); + iOSVersion = iOSSimVersion = 0; + } else if (iOSVersion && iOSSimVersion) { + getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) + << iOSVersion->getAsString(Args) + << iOSSimVersion->getAsString(Args); + iOSSimVersion = 0; + } else if (!OSXVersion && !iOSVersion && !iOSSimVersion) { + // If not deployment target was specified on the command line, check for // environment defines. const char *OSXTarget = ::getenv("MACOSX_DEPLOYMENT_TARGET"); - const char *iPhoneOSTarget = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"); + const char *iOSTarget = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"); + const char *iOSSimTarget = ::getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET"); // Ignore empty strings. if (OSXTarget && OSXTarget[0] == '\0') OSXTarget = 0; - if (iPhoneOSTarget && iPhoneOSTarget[0] == '\0') - iPhoneOSTarget = 0; + if (iOSTarget && iOSTarget[0] == '\0') + iOSTarget = 0; + if (iOSSimTarget && iOSSimTarget[0] == '\0') + iOSSimTarget = 0; - // Diagnose conflicting deployment targets, and choose default platform - // based on the tool chain. + // Handle conflicting deployment targets // // FIXME: Don't hardcode default here. - if (OSXTarget && iPhoneOSTarget) { - // FIXME: We should see if we can get away with warning or erroring on - // this. Perhaps put under -pedantic? + + // Do not allow conflicts with the iOS simulator target. + if (iOSSimTarget && (OSXTarget || iOSTarget)) { + getDriver().Diag(clang::diag::err_drv_conflicting_deployment_targets) + << "IOS_SIMULATOR_DEPLOYMENT_TARGET" + << (OSXTarget ? "MACOSX_DEPLOYMENT_TARGET" : + "IPHONEOS_DEPLOYMENT_TARGET"); + } + + // Allow conflicts among OSX and iOS for historical reasons, but choose the + // default platform. + if (OSXTarget && iOSTarget) { if (getTriple().getArch() == llvm::Triple::arm || getTriple().getArch() == llvm::Triple::thumb) OSXTarget = 0; else - iPhoneOSTarget = 0; + iOSTarget = 0; } if (OSXTarget) { const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget); Args.append(OSXVersion); - } else if (iPhoneOSTarget) { + } else if (iOSTarget) { const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ); - iPhoneVersion = Args.MakeJoinedArg(0, O, iPhoneOSTarget); - Args.append(iPhoneVersion); + iOSVersion = Args.MakeJoinedArg(0, O, iOSTarget); + Args.append(iOSVersion); + } else if (iOSSimTarget) { + const Option *O = Opts.getOption( + options::OPT_mios_simulator_version_min_EQ); + iOSSimVersion = Args.MakeJoinedArg(0, O, iOSSimTarget); + Args.append(iOSSimVersion); } else { // Otherwise, assume we are targeting OS X. const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); @@ -595,25 +464,44 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } } + // Reject invalid architecture combinations. + if (iOSSimVersion && (getTriple().getArch() != llvm::Triple::x86 && + getTriple().getArch() != llvm::Triple::x86_64)) { + getDriver().Diag(clang::diag::err_drv_invalid_arch_for_deployment_target) + << getTriple().getArchName() << iOSSimVersion->getAsString(Args); + } + // Set the tool chain target information. unsigned Major, Minor, Micro; bool HadExtra; if (OSXVersion) { - assert(!iPhoneVersion && "Unknown target platform!"); + assert((!iOSVersion && !iOSSimVersion) && "Unknown target platform!"); if (!Driver::GetReleaseVersion(OSXVersion->getValue(Args), Major, Minor, Micro, HadExtra) || HadExtra || - Major != 10 || Minor >= 10 || Micro >= 10) + Major != 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(clang::diag::err_drv_invalid_version_number) << OSXVersion->getAsString(Args); } else { - assert(iPhoneVersion && "Unknown target platform!"); - if (!Driver::GetReleaseVersion(iPhoneVersion->getValue(Args), Major, Minor, + const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion; + assert(Version && "Unknown target platform!"); + if (!Driver::GetReleaseVersion(Version->getValue(Args), Major, Minor, Micro, HadExtra) || HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(clang::diag::err_drv_invalid_version_number) - << iPhoneVersion->getAsString(Args); + << Version->getAsString(Args); } - setTarget(iPhoneVersion, Major, Minor, Micro); + + bool IsIOSSim = bool(iOSSimVersion); + + // In GCC, the simulator historically was treated as being OS X in some + // contexts, like determining the link logic, despite generally being called + // with an iOS deployment target. For compatibility, we detect the + // simulator as iOS + x86, and treat it differently in a few contexts. + if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 || + getTriple().getArch() == llvm::Triple::x86_64)) + IsIOSSim = true; + + setTarget(/*IsIPhoneOS=*/ !OSXVersion, Major, Minor, Micro, IsIOSSim); } void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, @@ -716,9 +604,12 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // driver behavior; that isn't going to work in our model. We // use isDriverOption() as an approximation, although things // like -O4 are going to slip through. - if (!XarchArg || Index > Prev + 1 || - XarchArg->getOption().isDriverOption()) { - getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument) + if (!XarchArg || Index > Prev + 1) { + getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument_with_args) + << A->getAsString(Args); + continue; + } else if (XarchArg->getOption().isDriverOption()) { + getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument_isdriver) << A->getAsString(Args); continue; } @@ -922,6 +813,11 @@ const char *Darwin::GetForcedPicModel() const { return 0; } +bool Darwin::SupportsProfiling() const { + // Profiling instrumentation is only supported on x86. + return getArchName() == "i386" || getArchName() == "x86_64"; +} + bool Darwin::SupportsObjCGC() const { // Garbage collection is supported everywhere except on iPhone OS. return !isTargetIPhoneOS(); @@ -939,7 +835,7 @@ Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args) const { Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple) : ToolChain(Host, Triple) { getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir.c_str()) + if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); } @@ -951,7 +847,8 @@ Generic_GCC::~Generic_GCC() { } Tool &Generic_GCC::SelectTool(const Compilation &C, - const JobAction &JA) const { + const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1039,7 +936,8 @@ const char *TCEToolChain::GetForcedPicModel() const { } Tool &TCEToolChain::SelectTool(const Compilation &C, - const JobAction &JA) const { + const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; Key = Action::AnalyzeJobClass; @@ -1065,7 +963,8 @@ OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple) getFilePaths().push_back("/usr/lib"); } -Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1089,7 +988,7 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::openbsd::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1115,7 +1014,8 @@ FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple) } } -Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1138,7 +1038,7 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::freebsd::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1157,16 +1057,16 @@ NetBSD::NetBSD(const HostInfo &Host, const llvm::Triple& Triple) llvm::Triple::x86_64) Lib32 = true; - getProgramPaths().push_back(getDriver().Dir + "/../libexec"); - getProgramPaths().push_back("/usr/libexec"); - if (Lib32) { - getFilePaths().push_back("/usr/lib/i386"); - } else { - getFilePaths().push_back("/usr/lib"); + if (getDriver().UseStdLib) { + if (Lib32) + getFilePaths().push_back("=/usr/lib/i386"); + else + getFilePaths().push_back("=/usr/lib"); } } -Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1189,7 +1089,7 @@ Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::netbsd::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1206,7 +1106,8 @@ Minix::Minix(const HostInfo &Host, const llvm::Triple& Triple) getFilePaths().push_back("/usr/gnu/lib/gcc/i686-pc-minix/4.4.3"); } -Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1221,7 +1122,7 @@ Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::minix::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1234,7 +1135,7 @@ AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple) : Generic_GCC(Host, Triple) { getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir.c_str()) + if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); getFilePaths().push_back(getDriver().Dir + "/../lib"); @@ -1245,7 +1146,8 @@ AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple) } -Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1260,7 +1162,7 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::auroraux::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1277,16 +1179,22 @@ enum LinuxDistro { Exherbo, Fedora13, Fedora14, + Fedora15, + FedoraRawhide, OpenSuse11_3, + UbuntuHardy, + UbuntuIntrepid, UbuntuJaunty, UbuntuKarmic, UbuntuLucid, UbuntuMaverick, + UbuntuNatty, UnknownDistro }; static bool IsFedora(enum LinuxDistro Distro) { - return Distro == Fedora13 || Distro == Fedora14; + return Distro == Fedora13 || Distro == Fedora14 || + Distro == Fedora15 || Distro == FedoraRawhide; } static bool IsOpenSuse(enum LinuxDistro Distro) { @@ -1298,8 +1206,10 @@ static bool IsDebian(enum LinuxDistro Distro) { } static bool IsUbuntu(enum LinuxDistro Distro) { - return Distro == UbuntuLucid || Distro == UbuntuMaverick || - Distro == UbuntuJaunty || Distro == UbuntuKarmic; + return Distro == UbuntuHardy || Distro == UbuntuIntrepid || + Distro == UbuntuLucid || Distro == UbuntuMaverick || + Distro == UbuntuJaunty || Distro == UbuntuKarmic || + Distro == UbuntuNatty; } static bool IsDebianBased(enum LinuxDistro Distro) { @@ -1315,7 +1225,9 @@ static bool HasMultilib(llvm::Triple::ArchType Arch, enum LinuxDistro Distro) { return true; } - if (Arch == llvm::Triple::x86 && IsDebianBased(Distro)) + if (Arch == llvm::Triple::ppc64) + return true; + if ((Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) && IsDebianBased(Distro)) return true; return false; } @@ -1327,24 +1239,35 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { llvm::SmallVector Lines; Data.split(Lines, "\n"); for (unsigned int i = 0, s = Lines.size(); i < s; ++ i) { - if (Lines[i] == "DISTRIB_CODENAME=maverick") - return UbuntuMaverick; - else if (Lines[i] == "DISTRIB_CODENAME=lucid") - return UbuntuLucid; + if (Lines[i] == "DISTRIB_CODENAME=hardy") + return UbuntuHardy; + else if (Lines[i] == "DISTRIB_CODENAME=intrepid") + return UbuntuIntrepid; else if (Lines[i] == "DISTRIB_CODENAME=jaunty") return UbuntuJaunty; else if (Lines[i] == "DISTRIB_CODENAME=karmic") return UbuntuKarmic; + else if (Lines[i] == "DISTRIB_CODENAME=lucid") + return UbuntuLucid; + else if (Lines[i] == "DISTRIB_CODENAME=maverick") + return UbuntuMaverick; + else if (Lines[i] == "DISTRIB_CODENAME=natty") + return UbuntuNatty; } return UnknownDistro; } if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) { llvm::StringRef Data = File.get()->getBuffer(); - if (Data.startswith("Fedora release 14 (Laughlin)")) + if (Data.startswith("Fedora release 15")) + return Fedora15; + else if (Data.startswith("Fedora release 14")) return Fedora14; - else if (Data.startswith("Fedora release 13 (Goddard)")) + else if (Data.startswith("Fedora release 13")) return Fedora13; + else if (Data.startswith("Fedora release") && + Data.find("Rawhide") != llvm::StringRef::npos) + return FedoraRawhide; return UnknownDistro; } @@ -1384,7 +1307,7 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) Suffix32 = "/32"; std::string Suffix64 = ""; - if (Arch == llvm::Triple::x86) + if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) Suffix64 = "/64"; std::string Lib32 = "lib"; @@ -1400,7 +1323,7 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) Lib64 = "lib64"; std::string GccTriple = ""; - if (Arch == llvm::Triple::arm) { + if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { if (!llvm::sys::fs::exists("/usr/lib/gcc/arm-linux-gnueabi", Exists) && Exists) GccTriple = "arm-linux-gnueabi"; @@ -1423,6 +1346,9 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-manbo-linux-gnu", Exists) && Exists) GccTriple = "x86_64-manbo-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib/x86_64-linux-gnu/gcc", + Exists) && Exists) + GccTriple = "x86_64-linux-gnu"; } else if (Arch == llvm::Triple::x86) { if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-linux-gnu", Exists) && Exists) GccTriple = "i686-linux-gnu"; @@ -1438,11 +1364,26 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) else if (!llvm::sys::fs::exists("/usr/lib/gcc/i586-suse-linux", Exists) && Exists) GccTriple = "i586-suse-linux"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/i486-slackware-linux", Exists) + && Exists) + GccTriple = "i486-slackware-linux"; + } else if (Arch == llvm::Triple::ppc) { + if (!llvm::sys::fs::exists("/usr/lib/powerpc-linux-gnu", Exists) && Exists) + GccTriple = "powerpc-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/powerpc-unknown-linux-gnu", Exists) && Exists) + GccTriple = "powerpc-unknown-linux-gnu"; + } else if (Arch == llvm::Triple::ppc64) { + if (!llvm::sys::fs::exists("/usr/lib/gcc/powerpc64-unknown-linux-gnu", Exists) && Exists) + GccTriple = "powerpc64-unknown-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib64/gcc/powerpc64-unknown-linux-gnu", Exists) && Exists) + GccTriple = "powerpc64-unknown-linux-gnu"; } - const char* GccVersions[] = {"4.5.2", "4.5.1", "4.5", "4.4.5", "4.4.4", - "4.4.3", "4.4", "4.3.4", "4.3.3", "4.3.2", - "4.3"}; + const char* GccVersions[] = {"4.6.0", + "4.5.2", "4.5.1", "4.5", + "4.4.5", "4.4.4", "4.4.3", "4.4", + "4.3.4", "4.3.3", "4.3.2", "4.3", + "4.2.4", "4.2.3", "4.2.2", "4.2.1", "4.2"}; std::string Base = ""; for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) { std::string Suffix = GccTriple + "/" + GccVersions[i]; @@ -1456,10 +1397,15 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) Base = t2; break; } + std::string t3 = "/usr/lib/" + GccTriple + "/gcc/" + Suffix; + if (!llvm::sys::fs::exists(t3 + "/crtbegin.o", Exists) && Exists) { + Base = t3; + break; + } } path_list &Paths = getFilePaths(); - bool Is32Bits = getArch() == llvm::Triple::x86; + bool Is32Bits = (getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::ppc); std::string Suffix; std::string Lib; @@ -1485,10 +1431,10 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) ExtraOpts.push_back("relro"); } - if (Arch == llvm::Triple::arm) + if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) ExtraOpts.push_back("-X"); - if (IsFedora(Distro) || Distro == UbuntuMaverick) + if (IsFedora(Distro) || Distro == UbuntuMaverick || Distro == UbuntuNatty) ExtraOpts.push_back("--hash-style=gnu"); if (IsDebian(Distro) || Distro == UbuntuLucid || Distro == UbuntuJaunty || @@ -1500,7 +1446,7 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) if (Distro == DebianSqueeze || IsOpenSuse(Distro) || IsFedora(Distro) || Distro == UbuntuLucid || Distro == UbuntuMaverick || - Distro == UbuntuKarmic) + Distro == UbuntuKarmic || Distro == UbuntuNatty) ExtraOpts.push_back("--build-id"); if (Distro == ArchLinux) @@ -1527,7 +1473,8 @@ bool Linux::HasNativeLLVMSupport() const { return true; } -Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1550,7 +1497,7 @@ Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::linuxtools::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1564,7 +1511,7 @@ DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple) // Path mangling to find libexec getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir.c_str()) + if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); getFilePaths().push_back(getDriver().Dir + "/../lib"); @@ -1572,7 +1519,8 @@ DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple) getFilePaths().push_back("/usr/lib/gcc41"); } -Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1587,7 +1535,7 @@ Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::dragonfly::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1598,7 +1546,8 @@ Windows::Windows(const HostInfo &Host, const llvm::Triple& Triple) : ToolChain(Host, Triple) { } -Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h index 0e3645cb8f7e..7a1a05025296 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h @@ -33,7 +33,8 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain { Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple); ~Generic_GCC(); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; virtual bool IsUnwindTablesDefault() const; virtual const char *GetDefaultRelocationModel() const; @@ -56,10 +57,13 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { // the argument translation business. mutable bool TargetInitialized; - /// Whether we are targetting iPhoneOS target. + /// Whether we are targeting iPhoneOS target. mutable bool TargetIsIPhoneOS; - /// The OS version we are targetting. + /// Whether we are targeting the iPhoneOS simulator target. + mutable bool TargetIsIPhoneOSSimulator; + + /// The OS version we are targeting. mutable unsigned TargetVersion[3]; /// The default macosx-version-min of this tool chain; empty until @@ -80,18 +84,22 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { // FIXME: Eliminate these ...Target functions and derive separate tool chains // for these targets and put version in constructor. - void setTarget(bool isIPhoneOS, unsigned Major, unsigned Minor, - unsigned Micro) const { + void setTarget(bool IsIPhoneOS, unsigned Major, unsigned Minor, + unsigned Micro, bool IsIOSSim) const { + assert((!IsIOSSim || IsIPhoneOS) && "Unexpected deployment target!"); + // FIXME: For now, allow reinitialization as long as values don't // change. This will go away when we move away from argument translation. - if (TargetInitialized && TargetIsIPhoneOS == isIPhoneOS && + if (TargetInitialized && TargetIsIPhoneOS == IsIPhoneOS && + TargetIsIPhoneOSSimulator == IsIOSSim && TargetVersion[0] == Major && TargetVersion[1] == Minor && TargetVersion[2] == Micro) return; assert(!TargetInitialized && "Target already initialized!"); TargetInitialized = true; - TargetIsIPhoneOS = isIPhoneOS; + TargetIsIPhoneOS = IsIPhoneOS; + TargetIsIPhoneOSSimulator = IsIOSSim; TargetVersion[0] = Major; TargetVersion[1] = Minor; TargetVersion[2] = Micro; @@ -102,6 +110,11 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { return TargetIsIPhoneOS; } + bool isTargetIOSSimulator() const { + assert(TargetInitialized && "Target not initialized!"); + return TargetIsIPhoneOSSimulator; + } + bool isTargetInitialized() const { return TargetInitialized; } void getTargetVersion(unsigned (&Res)[3]) const { @@ -160,7 +173,8 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args, const char *BoundArch) const; - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; virtual bool IsBlocksDefault() const { // Always allow blocks on Darwin; users interested in versioning are @@ -212,6 +226,8 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { virtual const char *GetDefaultRelocationModel() const; virtual const char *GetForcedPicModel() const; + virtual bool SupportsProfiling() const; + virtual bool SupportsObjCGC() const; virtual bool UseDwarfDebugFlags() const; @@ -244,29 +260,6 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin { /// } }; -/// DarwinGCC - The Darwin toolchain used by GCC. -class LLVM_LIBRARY_VISIBILITY DarwinGCC : public Darwin { - /// GCC version to use. - unsigned GCCVersion[3]; - - /// The directory suffix for this tool chain. - std::string ToolChainDir; - -public: - DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple); - - /// @name Darwin ToolChain Implementation - /// { - - virtual void AddLinkSearchPathArgs(const ArgList &Args, - ArgStringList &CmdArgs) const; - - virtual void AddLinkRuntimeLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const; - - /// } -}; - /// Darwin_Generic_GCC - Generic Darwin tool chain using gcc. class LLVM_LIBRARY_VISIBILITY Darwin_Generic_GCC : public Generic_GCC { public: @@ -294,42 +287,48 @@ class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC { public: AuroraUX(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF { public: OpenBSD(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF { public: FreeBSD(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF { public: NetBSD(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY Minix : public Generic_GCC { public: Minix(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF { public: DragonFly(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF { @@ -338,7 +337,8 @@ class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF { virtual bool HasNativeLLVMSupport() const; - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; std::string Linker; std::vector ExtraOpts; @@ -352,7 +352,8 @@ class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain { TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple); ~TCEToolChain(); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; bool IsMathErrnoDefault() const; bool IsUnwindTablesDefault() const; const char* GetDefaultRelocationModel() const; @@ -369,7 +370,8 @@ class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain { public: Windows(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; virtual bool IsIntegratedAssemblerDefault() const; virtual bool IsUnwindTablesDefault() const; diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index a2c95fc3b952..7b78cd5d9d4b 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -34,14 +34,32 @@ #include "InputInfo.h" #include "ToolChains.h" +#ifdef __CYGWIN__ +#include +#if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 +#define IS_CYGWIN15 1 +#endif +#endif + using namespace clang::driver; using namespace clang::driver::tools; +/// FindTargetProgramPath - Return path of the target specific version of +/// ProgName. If it doesn't exist, return path of ProgName itself. +static std::string FindTargetProgramPath(const ToolChain &TheToolChain, + const char *ProgName) { + std::string Executable(TheToolChain.getTripleString() + "-" + ProgName); + std::string Path(TheToolChain.GetProgramPath(Executable.c_str())); + if (Path != Executable) + return Path; + return TheToolChain.GetProgramPath(ProgName); +} + /// CheckPreprocessingOptions - Perform some validation of preprocessing /// arguments that is shared with gcc. static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) - if (!Args.hasArg(options::OPT_E)) + if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP) D.Diag(clang::diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-E"; } @@ -309,7 +327,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, } } -/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting. +/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. // // FIXME: tblgen this. static const char *getARMTargetCPU(const ArgList &Args, @@ -363,6 +381,8 @@ static const char *getARMTargetCPU(const ArgList &Args, return "iwmmxt"; if (MArch == "xscale") return "xscale"; + if (MArch == "armv6m" || MArch == "armv6-m") + return "cortex-m0"; // If all else failed, return the most base CPU LLVM supports. return "arm7tdmi"; @@ -420,10 +440,17 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { } void Clang::AddARMTargetArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { + ArgStringList &CmdArgs, + bool KernelOrKext) const { const Driver &D = getToolChain().getDriver(); llvm::Triple Triple = getToolChain().getTriple(); + // Disable movt generation, if requested. +#ifdef DISABLE_ARM_DARWIN_USE_MOVT + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-darwin-use-movt=0"); +#endif + // Select the ABI to use. // // FIXME: Support -meabi. @@ -577,6 +604,28 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } else D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); } + + // Setting -msoft-float effectively disables NEON because of the GCC + // implementation, although the same isn't true of VFP or VFP3. + if (FloatABI == "soft") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } + + // Kernel code has more strict alignment requirements. + if (KernelOrKext) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-long-calls"); + + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-strict-align"); + + // The kext linker doesn't know how to deal with movw/movt. +#ifndef DISABLE_ARM_DARWIN_USE_MOVT + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-darwin-use-movt=0"); +#endif + } } void Clang::AddMIPSTargetArgs(const ArgList &Args, @@ -726,12 +775,12 @@ void Clang::AddX86TargetArgs(const ArgList &Args, CPUName = "x86-64"; else if (getToolChain().getArchName() == "i386") CPUName = "i486"; - } else if (getToolChain().getOS().startswith("netbsd")) { + } else if (getToolChain().getOS().startswith("freebsd")) { if (getToolChain().getArchName() == "x86_64") CPUName = "x86-64"; else if (getToolChain().getArchName() == "i386") CPUName = "i486"; - } else if (getToolChain().getOS().startswith("freebsd")) { + } else if (getToolChain().getOS().startswith("netbsd")) { if (getToolChain().getArchName() == "x86_64") CPUName = "x86-64"; else if (getToolChain().getArchName() == "i386") @@ -767,34 +816,112 @@ void Clang::AddX86TargetArgs(const ArgList &Args, } } -static bool needsExceptions(const ArgList &Args, types::ID InputType, - const llvm::Triple &Triple) { - // Handle -fno-exceptions. +static bool +shouldUseExceptionTablesForObjCExceptions(const ArgList &Args, + const llvm::Triple &Triple) { + // We use the zero-cost exception tables for Objective-C if the non-fragile + // ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and + // later. + + if (Args.hasArg(options::OPT_fobjc_nonfragile_abi)) + return true; + + if (Triple.getOS() != llvm::Triple::Darwin) + return false; + + return (Triple.getDarwinMajorNumber() >= 9 && + (Triple.getArch() == llvm::Triple::x86_64 || + Triple.getArch() == llvm::Triple::arm)); +} + +/// addExceptionArgs - Adds exception related arguments to the driver command +/// arguments. There's a master flag, -fexceptions and also language specific +/// flags to enable/disable C++ and Objective-C exceptions. +/// This makes it possible to for example disable C++ exceptions but enable +/// Objective-C exceptions. +static void addExceptionArgs(const ArgList &Args, types::ID InputType, + const llvm::Triple &Triple, + bool KernelOrKext, bool IsRewriter, + ArgStringList &CmdArgs) { + if (KernelOrKext) + return; + + // Exceptions are enabled by default. + bool ExceptionsEnabled = true; + + // This keeps track of whether exceptions were explicitly turned on or off. + bool DidHaveExplicitExceptionFlag = false; + if (Arg *A = Args.getLastArg(options::OPT_fexceptions, options::OPT_fno_exceptions)) { if (A->getOption().matches(options::OPT_fexceptions)) - return true; - else - return false; + ExceptionsEnabled = true; + else + ExceptionsEnabled = false; + + DidHaveExplicitExceptionFlag = true; } - // Otherwise, C++ inputs use exceptions. - if (types::isCXX(InputType)) - return true; + bool ShouldUseExceptionTables = false; - // As do Objective-C non-fragile ABI inputs and all Objective-C inputs on - // x86_64 and ARM after SnowLeopard. - if (types::isObjC(InputType)) { - if (Args.hasArg(options::OPT_fobjc_nonfragile_abi)) - return true; - if (Triple.getOS() != llvm::Triple::Darwin) - return false; - return (Triple.getDarwinMajorNumber() >= 9 && - (Triple.getArch() == llvm::Triple::x86_64 || - Triple.getArch() == llvm::Triple::arm)); + // Exception tables and cleanups can be enabled with -fexceptions even if the + // language itself doesn't support exceptions. + if (ExceptionsEnabled && DidHaveExplicitExceptionFlag) + ShouldUseExceptionTables = true; + + // Obj-C exceptions are enabled by default, regardless of -fexceptions. This + // is not necessarily sensible, but follows GCC. + if (types::isObjC(InputType) && + Args.hasFlag(options::OPT_fobjc_exceptions, + options::OPT_fno_objc_exceptions, + true)) { + CmdArgs.push_back("-fobjc-exceptions"); + + ShouldUseExceptionTables |= + shouldUseExceptionTablesForObjCExceptions(Args, Triple); } - return false; + if (types::isCXX(InputType)) { + bool CXXExceptionsEnabled = ExceptionsEnabled; + + if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, + options::OPT_fno_cxx_exceptions, + options::OPT_fexceptions, + options::OPT_fno_exceptions)) { + if (A->getOption().matches(options::OPT_fcxx_exceptions)) + CXXExceptionsEnabled = true; + else if (A->getOption().matches(options::OPT_fno_cxx_exceptions)) + CXXExceptionsEnabled = false; + } + + if (CXXExceptionsEnabled) { + CmdArgs.push_back("-fcxx-exceptions"); + + ShouldUseExceptionTables = true; + } + } + + if (ShouldUseExceptionTables) + CmdArgs.push_back("-fexceptions"); +} + +static bool ShouldDisableCFI(const ArgList &Args, + const ToolChain &TC) { + + // FIXME: Duplicated code with ToolChains.cpp + // FIXME: This doesn't belong here, but ideally we will support static soon + // anyway. + bool HasStatic = (Args.hasArg(options::OPT_mkernel) || + Args.hasArg(options::OPT_static) || + Args.hasArg(options::OPT_fapple_kext)); + bool IsIADefault = TC.IsIntegratedAssemblerDefault() && !HasStatic; + bool UseIntegratedAs = Args.hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + IsIADefault); + bool UseCFI = Args.hasFlag(options::OPT_fdwarf2_cfi_asm, + options::OPT_fno_dwarf2_cfi_asm, + UseIntegratedAs); + return !UseCFI; } void Clang::ConstructJob(Compilation &C, const JobAction &JA, @@ -837,8 +964,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_O_Group)) IsOpt = !A->getOption().matches(options::OPT_O0); if (Args.hasFlag(options::OPT_mrelax_all, - options::OPT_mno_relax_all, - !IsOpt)) + options::OPT_mno_relax_all, + !IsOpt)) CmdArgs.push_back("-mrelax-all"); // When using an integrated assembler, translate -Wa, and -Xassembler @@ -855,10 +982,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Value == "-force_cpusubtype_ALL") { // Do nothing, this is the default and we don't support anything else. } else if (Value == "-L") { - // We don't support -L yet, but it isn't important enough to error - // on. No one should really be using it for a semantic change. - D.Diag(clang::diag::warn_drv_unsupported_option_argument) - << A->getOption().getName() << Value; + CmdArgs.push_back("-msave-temp-labels"); } else { D.Diag(clang::diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; @@ -925,29 +1049,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Treat blocks as analysis entry points. CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks"); + CmdArgs.push_back("-analyzer-eagerly-assume"); + // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { - types::ID InputType = Inputs[0].getType(); - - // Checks to perform for all language types. - CmdArgs.push_back("-analyzer-checker=core"); + CmdArgs.push_back("-analyzer-checker=deadcode"); + CmdArgs.push_back("-analyzer-checker=security"); + if (getToolChain().getTriple().getOS() != llvm::Triple::Win32) CmdArgs.push_back("-analyzer-checker=unix"); + if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple) - CmdArgs.push_back("-analyzer-checker=macosx"); - - // Checks to perform for Objective-C/Objective-C++. - if (types::isObjC(InputType)) { - // Enable all checkers in 'cocoa' package. - CmdArgs.push_back("-analyzer-checker=cocoa"); - } - - // NOTE: Leaving -analyzer-check-objc-mem here is intentional. - // It also checks C code. - CmdArgs.push_back("-analyzer-check-objc-mem"); - - CmdArgs.push_back("-analyzer-eagerly-assume"); + CmdArgs.push_back("-analyzer-checker=osx"); } // Set the output format. The default is plist, for (lame) historical @@ -1011,7 +1125,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants)) - CmdArgs.push_back("-no-merge-all-constants"); + CmdArgs.push_back("-fno-merge-all-constants"); // LLVM Code Generator Options. @@ -1020,6 +1134,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } + if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) + CmdArgs.push_back("-mrtd"); + // FIXME: Set --enable-unsafe-fp-math. if (Args.hasFlag(options::OPT_fno_omit_frame_pointer, options::OPT_fomit_frame_pointer)) @@ -1054,6 +1171,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getTriple().getOS() != llvm::Triple::Darwin) CmdArgs.push_back("-mconstructor-aliases"); + // Darwin's kernel doesn't support guard variables; just die if we + // try to use them. + if (KernelOrKext && + getToolChain().getTriple().getOS() == llvm::Triple::Darwin) + CmdArgs.push_back("-fforbid-guard-variables"); + if (Args.hasArg(options::OPT_mms_bitfields)) { CmdArgs.push_back("-mms-bitfields"); } @@ -1090,7 +1213,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::arm: case llvm::Triple::thumb: - AddARMTargetArgs(Args, CmdArgs); + AddARMTargetArgs(Args, CmdArgs, KernelOrKext); break; case llvm::Triple::mips: @@ -1155,6 +1278,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_P); Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout); + if (D.CCLogDiagnostics) { + CmdArgs.push_back("-diagnostic-log-file"); + CmdArgs.push_back(D.CCLogDiagnosticsFilename ? + D.CCLogDiagnosticsFilename : "-"); + } + // Special case debug options to only pass -g to clang. This is // wrong. Args.ClaimAllArgs(options::OPT_g_Group); @@ -1167,6 +1296,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions); + if (Args.hasArg(options::OPT_ftest_coverage) || + Args.hasArg(options::OPT_coverage)) + CmdArgs.push_back("-femit-coverage-notes"); + if (Args.hasArg(options::OPT_fprofile_arcs) || + Args.hasArg(options::OPT_coverage)) + CmdArgs.push_back("-femit-coverage-data"); + Args.AddLastArg(CmdArgs, options::OPT_nostdinc); Args.AddLastArg(CmdArgs, options::OPT_nostdincxx); Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc); @@ -1192,10 +1328,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else if (A->getOption().matches(options::OPT_O) && A->getValue(Args)[0] == '\0') CmdArgs.push_back("-O2"); - else if (A->getOption().matches(options::OPT_O) && - A->getValue(Args)[0] == 'z' && - A->getValue(Args)[1] == '\0') - CmdArgs.push_back("-Os"); else A->render(Args, CmdArgs); } @@ -1236,6 +1368,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_trigraphs); } + // Map the bizarre '-Wwrite-strings' flag to a more sensible + // '-fconst-strings'; this better indicates its actual behavior. + if (Args.hasFlag(options::OPT_Wwrite_strings, options::OPT_Wno_write_strings, + false)) { + // For perfect compatibility with GCC, we do this even in the presence of + // '-w'. This flag names something other than a warning for GCC. + CmdArgs.push_back("-fconst-strings"); + } + + // GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active + // during C++ compilation, which it is by default. GCC keeps this define even + // in the presence of '-w', match this behavior bug-for-bug. + if (types::isCXX(InputType) && + Args.hasFlag(options::OPT_Wdeprecated, options::OPT_Wno_deprecated, + true)) { + CmdArgs.push_back("-fdeprecated-macro"); + } + // Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'. if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) { if (Asm->getOption().matches(options::OPT_fasm)) @@ -1244,6 +1394,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-gnu-keywords"); } + if (ShouldDisableCFI(Args, getToolChain())) + CmdArgs.push_back("-fno-dwarf2-cfi-asm"); + if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_)) { CmdArgs.push_back("-ftemplate-depth"); CmdArgs.push_back(A->getValue(Args)); @@ -1317,7 +1470,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions); Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info); - Args.AddLastArg(CmdArgs, options::OPT_pg); + if (getToolChain().SupportsProfiling()) + Args.AddLastArg(CmdArgs, options::OPT_pg); // -flax-vector-conversions is default. if (!Args.hasFlag(options::OPT_flax_vector_conversions, @@ -1354,7 +1508,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } - Args.AddLastArg(CmdArgs, options::OPT_fwrapv); + // Forward -ftrap_function= options to the backend. + if (Arg *A = Args.getLastArg(options::OPT_ftrap_function_EQ)) { + llvm::StringRef FuncName = A->getValue(Args); + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back(Args.MakeArgString("-trap-func=" + FuncName)); + } + + // -fno-strict-overflow implies -fwrapv if it isn't disabled, but + // -fstrict-overflow won't turn off an explicitly enabled -fwrapv. + if (Arg *A = Args.getLastArg(options::OPT_fwrapv, + options::OPT_fno_wrapv)) { + if (A->getOption().matches(options::OPT_fwrapv)) + CmdArgs.push_back("-fwrapv"); + } else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow, + options::OPT_fno_strict_overflow)) { + if (A->getOption().matches(options::OPT_fno_strict_overflow)) + CmdArgs.push_back("-fwrapv"); + } Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings); Args.AddLastArg(CmdArgs, options::OPT_funroll_loops); @@ -1395,7 +1566,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fblocks=0 is default. if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks, - getToolChain().IsBlocksDefault())) { + getToolChain().IsBlocksDefault()) || + (Args.hasArg(options::OPT_fgnu_runtime) && + Args.hasArg(options::OPT_fobjc_nonfragile_abi) && + !Args.hasArg(options::OPT_fno_blocks))) { CmdArgs.push_back("-fblocks"); } @@ -1411,10 +1585,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fno-elide-constructors"); - // -fexceptions=0 is default. - if (!KernelOrKext && - needsExceptions(Args, InputType, getToolChain().getTriple())) - CmdArgs.push_back("-fexceptions"); + // Add exception args. + addExceptionArgs(Args, InputType, getToolChain().getTriple(), + KernelOrKext, IsRewriter, CmdArgs); if (getToolChain().UseSjLjExceptions()) CmdArgs.push_back("-fsjlj-exceptions"); @@ -1469,6 +1642,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_borland_extensions, false)) CmdArgs.push_back("-fborland-extensions"); + // -fno-delayed-template-parsing is default. + if (Args.hasFlag(options::OPT_fdelayed_template_parsing, + options::OPT_fno_delayed_template_parsing, + false)) + CmdArgs.push_back("-fdelayed-template-parsing"); + // -fgnu-keywords default varies depending on language; only pass if // specified. if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords, @@ -1545,17 +1724,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } + // FIXME: Don't expose -fobjc-default-synthesize-properties as a top-level + // driver flag yet. This feature is still under active development + // and shouldn't be exposed as a user visible feature (which may change). + // Clang still supports this as a -cc1 option for development and testing. +#if 0 // -fobjc-default-synthesize-properties=0 is default. if (Args.hasFlag(options::OPT_fobjc_default_synthesize_properties, options::OPT_fno_objc_default_synthesize_properties, getToolChain().IsObjCDefaultSynthPropertiesDefault())) { CmdArgs.push_back("-fobjc-default-synthesize-properties"); } - - // -fno-objc-exceptions is default. - if (IsRewriter || Args.hasFlag(options::OPT_fobjc_exceptions, - options::OPT_fno_objc_exceptions)) - CmdArgs.push_back("-fobjc-exceptions"); +#endif } if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, @@ -1619,6 +1799,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info, options::OPT_fno_diagnostics_fixit_info)) CmdArgs.push_back("-fno-diagnostics-fixit-info"); + + // Enable -fdiagnostics-show-name by default. + if (Args.hasFlag(options::OPT_fdiagnostics_show_name, + options::OPT_fno_diagnostics_show_name, false)) + CmdArgs.push_back("-fdiagnostics-show-name"); // Enable -fdiagnostics-show-option by default. if (Args.hasFlag(options::OPT_fdiagnostics_show_option, @@ -1631,6 +1816,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } + if (Arg *A = Args.getLastArg( + options::OPT_fdiagnostics_show_note_include_stack, + options::OPT_fno_diagnostics_show_note_include_stack)) { + if (A->getOption().matches( + options::OPT_fdiagnostics_show_note_include_stack)) + CmdArgs.push_back("-fdiagnostics-show-note-include-stack"); + else + CmdArgs.push_back("-fno-diagnostics-show-note-include-stack"); + } + // Color diagnostics are the default, unless the terminal doesn't support // them. if (Args.hasFlag(options::OPT_fcolor_diagnostics, @@ -1686,9 +1881,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } #endif + // Only allow -traditional or -traditional-cpp outside in preprocessing modes. if (Arg *A = Args.getLastArg(options::OPT_traditional, - options::OPT_traditional_cpp)) - D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); + options::OPT_traditional_cpp)) { + if (isa(JA)) + CmdArgs.push_back("-traditional-cpp"); + else + D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); + } Args.AddLastArg(CmdArgs, options::OPT_dM); Args.AddLastArg(CmdArgs, options::OPT_dD); @@ -1768,6 +1968,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // care to warn the user about. Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group); Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group); + + // Disable warnings for clang -E -use-gold-plugin -emit-llvm foo.c + Args.ClaimAllArgs(options::OPT_use_gold_plugin); + Args.ClaimAllArgs(options::OPT_emit_llvm); } void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, @@ -1782,6 +1986,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // Don't warn about "clang -w -c foo.s" Args.ClaimAllArgs(options::OPT_w); + // and "clang -emit-llvm -c foo.s" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and "clang -use-gold-plugin -c foo.s" + Args.ClaimAllArgs(options::OPT_use_gold_plugin); // Invoke ourselves in -cc1as mode. // @@ -1807,7 +2015,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, !IsOpt)) CmdArgs.push_back("-relax-all"); - // FIXME: Add -force_cpusubtype_ALL support, once we have it. + // Ignore explicit -force_cpusubtype_ALL option. + (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); // FIXME: Add -g support, once we have it. @@ -1815,6 +2024,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); + Args.AddAllArgs(CmdArgs, options::OPT_mllvm); assert(Output.isFilename() && "Unexpected lipo output."); CmdArgs.push_back("-o"); @@ -1930,7 +2140,20 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, } } - const char *GCCName = getToolChain().getDriver().getCCCGenericGCCName().c_str(); + const std::string customGCCName = D.getCCCGenericGCCName(); + const char *GCCName; + if (!customGCCName.empty()) + GCCName = customGCCName.c_str(); + else if (D.CCCIsCXX) { +#ifdef IS_CYGWIN15 + // FIXME: Detect the version of Cygwin at runtime? + GCCName = "g++-4"; +#else + GCCName = "g++"; +#endif + } else + GCCName = "gcc"; + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); @@ -2044,10 +2267,6 @@ void darwin::CC1::AddCC1Args(const ArgList &Args, CmdArgs.push_back("-fno-builtin-strcpy"); } - // gcc has some code here to deal with when no -mmacosx-version-min - // and no -miphoneos-version-min is present, but this never happens - // due to tool chain specific argument translation. - if (Args.hasArg(options::OPT_g_Flag) && !Args.hasArg(options::OPT_fno_eliminate_unused_debug_symbols)) CmdArgs.push_back("-feliminate-unused-debug-symbols"); @@ -2111,7 +2330,8 @@ void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, if (Args.hasArg(options::OPT_v)) CmdArgs.push_back("-version"); - if (Args.hasArg(options::OPT_pg)) + if (Args.hasArg(options::OPT_pg) && + getToolChain().SupportsProfiling()) CmdArgs.push_back("-p"); Args.AddLastArg(CmdArgs, options::OPT_p); @@ -2134,6 +2354,9 @@ void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, } else Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only); + // Claim Clang only -f options, they aren't worth warning about. + Args.ClaimAllArgs(options::OPT_f_clang_Group); + Args.AddAllArgs(CmdArgs, options::OPT_undef); if (Args.hasArg(options::OPT_Qn)) CmdArgs.push_back("-fno-ident"); @@ -2191,6 +2414,9 @@ void darwin::CC1::AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, // The driver treats -fsyntax-only specially. Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only); + // Claim Clang only -f options, they aren't worth warning about. + Args.ClaimAllArgs(options::OPT_f_clang_Group); + if (Args.hasArg(options::OPT_g_Group) && !Args.hasArg(options::OPT_g0) && !Args.hasArg(options::OPT_fno_working_directory)) CmdArgs.push_back("-fworking-directory"); @@ -2322,7 +2548,7 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA, OutputArgs.push_back("-o"); OutputArgs.push_back(Output.getFilename()); - if (Args.hasArg(options::OPT_E)) { + if (Args.hasArg(options::OPT_E) || getToolChain().getDriver().CCCIsCPP) { AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs); } else { AddCPPOptionsArgs(Args, CmdArgs, Inputs, ArgStringList()); @@ -2442,11 +2668,16 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, assert(Inputs.size() == 1 && "Unexpected number of inputs."); const InputInfo &Input = Inputs[0]; - // Bit of a hack, this is only used for original inputs. - // - // FIXME: This is broken for preprocessed .s inputs. - if (Input.isFilename() && - strcmp(Input.getFilename(), Input.getBaseInput()) == 0) { + // Determine the original source input. + const Action *SourceAction = &JA; + while (SourceAction->getKind() != Action::InputClass) { + assert(!SourceAction->getInputs().empty() && "unexpected root action!"); + SourceAction = SourceAction->getInputs()[0]; + } + + // Forward -g, assuming we are dealing with an actual assembly file. + if (SourceAction->getType() == types::TY_Asm || + SourceAction->getType() == types::TY_PP_Asm) { if (Args.hasArg(options::OPT_gstabs)) CmdArgs.push_back("--gstabs"); else if (Args.hasArg(options::OPT_g_Group)) @@ -2502,6 +2733,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); + const toolchains::Darwin &DarwinTC = getDarwinToolChain(); unsigned Version[3] = { 0, 0, 0 }; if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { @@ -2521,7 +2753,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, // will match the linker version detected at configure time. We need the // universal driver. if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle) && - !getDarwinToolChain().isTargetIPhoneOS()) { + !DarwinTC.isTargetIPhoneOS()) { // Don't pass -demangle to ld_classic. // // FIXME: This is a temporary workaround, ld should be handling this. @@ -2596,7 +2828,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddLastArg(CmdArgs, options::OPT_all__load); Args.AddAllArgs(CmdArgs, options::OPT_allowable__client); Args.AddLastArg(CmdArgs, options::OPT_bind__at__load); - if (getDarwinToolChain().isTargetIPhoneOS()) + if (DarwinTC.isTargetIPhoneOS()) Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal); Args.AddLastArg(CmdArgs, options::OPT_dead__strip); Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms); @@ -2608,15 +2840,27 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddAllArgs(CmdArgs, options::OPT_image__base); Args.AddAllArgs(CmdArgs, options::OPT_init); - // Adding all arguments doesn't make sense here but this is what gcc does. One - // of this should always be present thanks to argument translation. - assert((Args.hasArg(options::OPT_mmacosx_version_min_EQ) || - Args.hasArg(options::OPT_miphoneos_version_min_EQ)) && - "Missing version argument (lost in translation)?"); - Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ, - "-macosx_version_min"); - Args.AddAllArgsTranslated(CmdArgs, options::OPT_miphoneos_version_min_EQ, - "-iphoneos_version_min"); + // Add the deployment target. + unsigned TargetVersion[3]; + DarwinTC.getTargetVersion(TargetVersion); + + // If we had an explicit -mios-simulator-version-min argument, honor that, + // otherwise use the traditional deployment targets. We can't just check the + // is-sim attribute because existing code follows this path, and the linker + // may not handle the argument. + // + // FIXME: We may be able to remove this, once we can verify no one depends on + // it. + if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ)) + CmdArgs.push_back("-ios_simulator_version_min"); + else if (DarwinTC.isTargetIPhoneOS()) + CmdArgs.push_back("-iphoneos_version_min"); + else + CmdArgs.push_back("-macosx_version_min"); + CmdArgs.push_back(Args.MakeArgString(llvm::Twine(TargetVersion[0]) + "." + + llvm::Twine(TargetVersion[1]) + "." + + llvm::Twine(TargetVersion[2]))); + Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); Args.AddLastArg(CmdArgs, options::OPT_multi__module); Args.AddLastArg(CmdArgs, options::OPT_single__module); @@ -2722,7 +2966,10 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // Derived from startfile spec. if (Args.hasArg(options::OPT_dynamiclib)) { // Derived from darwin_dylib1 spec. - if (getDarwinToolChain().isTargetIPhoneOS()) { + if (getDarwinToolChain().isTargetIOSSimulator()) { + // The simulator doesn't have a versioned crt1 file. + CmdArgs.push_back("-ldylib1.o"); + } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-ldylib1.o"); } else { @@ -2735,7 +2982,10 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_bundle)) { if (!Args.hasArg(options::OPT_static)) { // Derived from darwin_bundle1 spec. - if (getDarwinToolChain().isTargetIPhoneOS()) { + if (getDarwinToolChain().isTargetIOSSimulator()) { + // The simulator doesn't have a versioned crt1 file. + CmdArgs.push_back("-lbundle1.o"); + } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-lbundle1.o"); } else { @@ -2744,7 +2994,8 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, } } } else { - if (Args.hasArg(options::OPT_pg)) { + if (Args.hasArg(options::OPT_pg) && + getToolChain().SupportsProfiling()) { if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) || Args.hasArg(options::OPT_preload)) { @@ -2761,7 +3012,10 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lcrt0.o"); } else { // Derived from darwin_crt1 spec. - if (getDarwinToolChain().isTargetIPhoneOS()) { + if (getDarwinToolChain().isTargetIOSSimulator()) { + // The simulator doesn't have a versioned crt1 file. + CmdArgs.push_back("-lcrt1.o"); + } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-lcrt1.o"); else @@ -3156,6 +3410,9 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { @@ -3206,12 +3463,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddAllArgs(CmdArgs, options::OPT_L); - const ToolChain::path_list Paths = getToolChain().getFilePaths(); for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); i != e; ++i) CmdArgs.push_back(Args.MakeArgString(llvm::StringRef("-L") + *i)); - Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); @@ -3323,8 +3578,8 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(FindTargetProgramPath(getToolChain(), + "as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -3336,6 +3591,9 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { @@ -3434,8 +3692,8 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, "crtn.o"))); } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + const char *Exec = Args.MakeArgString(FindTargetProgramPath(getToolChain(), + "ld")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -3487,14 +3745,14 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -g foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); - if (Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) { - CmdArgs.push_back("--sysroot"); - CmdArgs.push_back(A->getValue(Args)); - } + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); if (Args.hasArg(options::OPT_pie)) CmdArgs.push_back("-pie"); @@ -3517,13 +3775,19 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-m"); if (ToolChain.getArch() == llvm::Triple::x86) CmdArgs.push_back("elf_i386"); - else if (ToolChain.getArch() == llvm::Triple::arm) + else if (ToolChain.getArch() == llvm::Triple::arm + || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("armelf_linux_eabi"); + else if (ToolChain.getArch() == llvm::Triple::ppc) + CmdArgs.push_back("elf32ppclinux"); + else if (ToolChain.getArch() == llvm::Triple::ppc64) + CmdArgs.push_back("elf64ppc"); else CmdArgs.push_back("elf_x86_64"); if (Args.hasArg(options::OPT_static)) { - if (ToolChain.getArch() == llvm::Triple::arm) + if (ToolChain.getArch() == llvm::Triple::arm + || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("-Bstatic"); else CmdArgs.push_back("-static"); @@ -3532,13 +3796,19 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, } if (ToolChain.getArch() == llvm::Triple::arm || + ToolChain.getArch() == llvm::Triple::thumb || (!Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-dynamic-linker"); if (ToolChain.getArch() == llvm::Triple::x86) CmdArgs.push_back("/lib/ld-linux.so.2"); - else if (ToolChain.getArch() == llvm::Triple::arm) + else if (ToolChain.getArch() == llvm::Triple::arm || + ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("/lib/ld-linux.so.3"); + else if (ToolChain.getArch() == llvm::Triple::ppc) + CmdArgs.push_back("/lib/ld.so.1"); + else if (ToolChain.getArch() == llvm::Triple::ppc64) + CmdArgs.push_back("/lib64/ld64.so.1"); else CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2"); } @@ -3573,6 +3843,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); const ToolChain::path_list Paths = ToolChain.getFilePaths(); + for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); i != e; ++i) CmdArgs.push_back(Args.MakeArgString(llvm::StringRef("-L") + *i)); @@ -3770,6 +4041,9 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h index 10c883900933..93abf75722eb 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.h +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h @@ -34,7 +34,8 @@ namespace tools { const InputInfo &Output, const InputInfoList &Inputs) const; - void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; + void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs, + bool KernelOrKext) const; void AddMIPSTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; void AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp index 92fb1e8cbeb0..ecd6ef442aea 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/ASTConsumers.h" -#include "clang/Frontend/DocumentXML.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" @@ -51,39 +50,6 @@ ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) { return new ASTPrinter(out); } -//===----------------------------------------------------------------------===// -/// ASTPrinterXML - XML-printer of ASTs - -namespace { - class ASTPrinterXML : public ASTConsumer { - DocumentXML Doc; - - public: - ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {} - - void Initialize(ASTContext &Context) { - Doc.initialize(Context); - } - - virtual void HandleTranslationUnit(ASTContext &Ctx) { - Doc.addSubNode("TranslationUnit"); - for (DeclContext::decl_iterator - D = Ctx.getTranslationUnitDecl()->decls_begin(), - DEnd = Ctx.getTranslationUnitDecl()->decls_end(); - D != DEnd; - ++D) - Doc.PrintDecl(*D); - Doc.toParent(); - Doc.finalize(); - } - }; -} // end anonymous namespace - - -ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) { - return new ASTPrinterXML(out ? *out : llvm::outs()); -} - ASTConsumer *clang::CreateASTDumper() { return new ASTPrinter(0, true); } @@ -369,8 +335,9 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << " " << FD << '\n'; break; } - case Decl::Typedef: { - TypedefDecl* TD = cast(*I); + case Decl::Typedef: + case Decl::TypeAlias: { + TypedefNameDecl* TD = cast(*I); Out << " " << TD << '\n'; break; } diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp index a7942e6090c8..2a1244841e3b 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp @@ -20,6 +20,8 @@ #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/Job.h" +#include "clang/Driver/ArgList.h" +#include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" @@ -34,6 +36,7 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Atomic.h" @@ -42,6 +45,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/CrashRecoveryContext.h" #include #include #include @@ -90,8 +94,10 @@ const unsigned DefaultPreambleRebuildInterval = 5; static llvm::sys::cas_flag ActiveASTUnitObjects; ASTUnit::ASTUnit(bool _MainFileIsAST) - : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST), + : OnlyLocalDecls(false), CaptureDiagnostics(false), + MainFileIsAST(_MainFileIsAST), CompleteTranslationUnit(true), WantTiming(getenv("LIBCLANG_TIMING")), + OwnsRemappedFileBuffers(true), NumStoredDiagnosticsFromDriver(0), ConcurrencyCheckValue(CheckUnlocked), PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0), @@ -116,7 +122,7 @@ ASTUnit::~ASTUnit() { // perform this operation here because we explicitly request that the // compiler instance *not* free these buffers for each invocation of the // parser. - if (Invocation.get()) { + if (Invocation.getPtr() && OwnsRemappedFileBuffers) { PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); for (PreprocessorOptions::remapped_file_buffer_iterator FB = PPOpts.remapped_file_buffer_begin(), @@ -496,33 +502,69 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, unsigned NumRemappedFiles, bool CaptureDiagnostics) { llvm::OwningPtr AST(new ASTUnit(true)); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + ASTUnitCleanup(AST.get()); + llvm::CrashRecoveryContextCleanupRegistrar > + DiagCleanup(Diags.getPtr()); + ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics); AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; AST->Diagnostics = Diags; - AST->FileMgr.reset(new FileManager(FileSystemOpts)); - AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics(), - AST->getFileManager())); + AST->FileMgr = new FileManager(FileSystemOpts); + AST->SourceMgr = new SourceManager(AST->getDiagnostics(), + AST->getFileManager()); AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager())); for (unsigned I = 0; I != NumRemappedFiles; ++I) { - // Create the file entry for the file that we're mapping from. - const FileEntry *FromFile - = AST->getFileManager().getVirtualFile(RemappedFiles[I].first, - RemappedFiles[I].second->getBufferSize(), - 0); - if (!FromFile) { - AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file) - << RemappedFiles[I].first; - delete RemappedFiles[I].second; - continue; + FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second; + if (const llvm::MemoryBuffer * + memBuf = fileOrBuf.dyn_cast()) { + // Create the file entry for the file that we're mapping from. + const FileEntry *FromFile + = AST->getFileManager().getVirtualFile(RemappedFiles[I].first, + memBuf->getBufferSize(), + 0); + if (!FromFile) { + AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file) + << RemappedFiles[I].first; + delete memBuf; + continue; + } + + // Override the contents of the "from" file with the contents of + // the "to" file. + AST->getSourceManager().overrideFileContents(FromFile, memBuf); + + } else { + const char *fname = fileOrBuf.get(); + const FileEntry *ToFile = AST->FileMgr->getFile(fname); + if (!ToFile) { + AST->getDiagnostics().Report(diag::err_fe_remap_missing_to_file) + << RemappedFiles[I].first << fname; + continue; + } + + // Create the file entry for the file that we're mapping from. + const FileEntry *FromFile + = AST->getFileManager().getVirtualFile(RemappedFiles[I].first, + ToFile->getSize(), + 0); + if (!FromFile) { + AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file) + << RemappedFiles[I].first; + delete memBuf; + continue; + } + + // Override the contents of the "from" file with the contents of + // the "to" file. + AST->getSourceManager().overrideFileContents(FromFile, ToFile); } - - // Override the contents of the "from" file with the contents of - // the "to" file. - AST->getSourceManager().overrideFileContents(FromFile, - RemappedFiles[I].second); } // Gather Info for preprocessor construction later on. @@ -563,12 +605,11 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, TargetOpts.CPU = ""; TargetOpts.Features.clear(); TargetOpts.Triple = TargetTriple; - AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(), - TargetOpts)); - AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo, - *AST->Target.get(), - AST->getSourceManager(), HeaderInfo)); - Preprocessor &PP = *AST->PP.get(); + AST->Target = TargetInfo::CreateTargetInfo(AST->getDiagnostics(), + TargetOpts); + AST->PP = new Preprocessor(AST->getDiagnostics(), LangInfo, *AST->Target, + AST->getSourceManager(), HeaderInfo); + Preprocessor &PP = *AST->PP; PP.setPredefines(Reader->getSuggestedPredefines()); PP.setCounterValue(Counter); @@ -576,14 +617,14 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, // Create and initialize the ASTContext. - AST->Ctx.reset(new ASTContext(LangInfo, - AST->getSourceManager(), - *AST->Target.get(), - PP.getIdentifierTable(), - PP.getSelectorTable(), - PP.getBuiltinInfo(), - /* size_reserve = */0)); - ASTContext &Context = *AST->Ctx.get(); + AST->Ctx = new ASTContext(LangInfo, + AST->getSourceManager(), + *AST->Target, + PP.getIdentifierTable(), + PP.getSelectorTable(), + PP.getBuiltinInfo(), + /* size_reserve = */0); + ASTContext &Context = *AST->Ctx; Reader->InitializeContext(Context); @@ -803,25 +844,30 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { delete SavedMainFileBuffer; SavedMainFileBuffer = 0; - if (!Invocation.get()) { + if (!Invocation) { delete OverrideMainBuffer; return true; } // Create the compiler instance to use for building the AST. - CompilerInstance Clang; - Clang.setInvocation(Invocation.take()); - OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; + llvm::OwningPtr Clang(new CompilerInstance()); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + CICleanup(Clang.get()); + + Clang->setInvocation(&*Invocation); + OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second; // Set up diagnostics, capturing any diagnostics that would // otherwise be dropped. - Clang.setDiagnostics(&getDiagnostics()); + Clang->setDiagnostics(&getDiagnostics()); // Create the target instance. - Clang.getTargetOpts().Features = TargetFeatures; - Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), - Clang.getTargetOpts())); - if (!Clang.hasTarget()) { + Clang->getTargetOpts().Features = TargetFeatures; + Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), + Clang->getTargetOpts())); + if (!Clang->hasTarget()) { delete OverrideMainBuffer; return true; } @@ -830,23 +876,23 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { // // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. - Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); + Clang->getTarget().setForcedLangOptions(Clang->getLangOpts()); - assert(Clang.getFrontendOpts().Inputs.size() == 1 && + assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); - assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST && + assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST && "FIXME: AST inputs not yet supported here!"); - assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR && + assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR && "IR inputs not support here!"); // Configure the various subsystems. // FIXME: Should we retain the previous file manager? - FileSystemOpts = Clang.getFileSystemOpts(); - FileMgr.reset(new FileManager(Clang.getFileSystemOpts())); - SourceMgr.reset(new SourceManager(getDiagnostics(), *FileMgr)); + FileSystemOpts = Clang->getFileSystemOpts(); + FileMgr = new FileManager(FileSystemOpts); + SourceMgr = new SourceManager(getDiagnostics(), *FileMgr); TheSema.reset(); - Ctx.reset(); - PP.reset(); + Ctx = 0; + PP = 0; // Clear out old caches and data. TopLevelDecls.clear(); @@ -863,14 +909,14 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { } // Create a file manager object to provide access to and cache the filesystem. - Clang.setFileManager(&getFileManager()); + Clang->setFileManager(&getFileManager()); // Create the source manager. - Clang.setSourceManager(&getSourceManager()); + Clang->setSourceManager(&getSourceManager()); // If the main file has been overridden due to the use of a preamble, // make that override happen and introduce the preamble. - PreprocessorOptions &PreprocessorOpts = Clang.getPreprocessorOpts(); + PreprocessorOptions &PreprocessorOpts = Clang->getPreprocessorOpts(); std::string PriorImplicitPCHInclude; if (OverrideMainBuffer) { PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer); @@ -901,23 +947,27 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { PreprocessorOpts.PrecompiledPreambleBytes.second = false; } - llvm::OwningPtr Act; - Act.reset(new TopLevelDeclTrackerAction(*this)); - if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second, - Clang.getFrontendOpts().Inputs[0].first)) + llvm::OwningPtr Act( + new TopLevelDeclTrackerAction(*this)); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + ActCleanup(Act.get()); + + if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second, + Clang->getFrontendOpts().Inputs[0].first)) goto error; Act->Execute(); - // Steal the created target, context, and preprocessor, and take back the - // source and file managers. - TheSema.reset(Clang.takeSema()); - Consumer.reset(Clang.takeASTConsumer()); - Ctx.reset(Clang.takeASTContext()); - PP.reset(Clang.takePreprocessor()); - Clang.takeSourceManager(); - Clang.takeFileManager(); - Target.reset(Clang.takeTarget()); + // Steal the created target, context, and preprocessor. + TheSema.reset(Clang->takeSema()); + Consumer.reset(Clang->takeASTConsumer()); + Ctx = &Clang->getASTContext(); + PP = &Clang->getPreprocessor(); + Clang->setSourceManager(0); + Clang->setFileManager(0); + Target = &Clang->getTarget(); Act->EndSourceFile(); @@ -928,9 +978,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude; } - Invocation.reset(Clang.takeInvocation()); return false; - + error: // Remove the overridden buffer we used for the preamble. if (OverrideMainBuffer) { @@ -942,9 +991,6 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { } StoredDiagnostics.clear(); - Clang.takeSourceManager(); - Clang.takeFileManager(); - Invocation.reset(Clang.takeInvocation()); return true; } @@ -1146,7 +1192,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( !AnyFileChanged && R != REnd; ++R) { struct stat StatBuf; - if (stat(R->second.c_str(), &StatBuf)) { + if (FileMgr->getNoncachedStatValue(R->second, StatBuf)) { // If we can't stat the file we're remapping to, assume that something // horrible happened. AnyFileChanged = true; @@ -1184,7 +1230,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // The file was not remapped; check whether it has changed on disk. struct stat StatBuf; - if (stat(F->first(), &StatBuf)) { + if (FileMgr->getNoncachedStatValue(F->first(), StatBuf)) { // If we can't stat the file, assume that something horrible happened. AnyFileChanged = true; } else if (StatBuf.st_size != F->second.first || @@ -1292,18 +1338,23 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( PreprocessorOpts.PrecompiledPreambleBytes.second = false; // Create the compiler instance to use for building the precompiled preamble. - CompilerInstance Clang; - Clang.setInvocation(&PreambleInvocation); - OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; + llvm::OwningPtr Clang(new CompilerInstance()); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + CICleanup(Clang.get()); + + Clang->setInvocation(&PreambleInvocation); + OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second; // Set up diagnostics, capturing all of the diagnostics produced. - Clang.setDiagnostics(&getDiagnostics()); + Clang->setDiagnostics(&getDiagnostics()); // Create the target instance. - Clang.getTargetOpts().Features = TargetFeatures; - Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), - Clang.getTargetOpts())); - if (!Clang.hasTarget()) { + Clang->getTargetOpts().Features = TargetFeatures; + Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), + Clang->getTargetOpts())); + if (!Clang->hasTarget()) { llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); Preamble.clear(); PreambleRebuildCounter = DefaultPreambleRebuildInterval; @@ -1316,18 +1367,18 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. - Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); + Clang->getTarget().setForcedLangOptions(Clang->getLangOpts()); - assert(Clang.getFrontendOpts().Inputs.size() == 1 && + assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); - assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST && + assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST && "FIXME: AST inputs not yet supported here!"); - assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR && + assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR && "IR inputs not support here!"); // Clear out old caches and data. getDiagnostics().Reset(); - ProcessWarningOptions(getDiagnostics(), Clang.getDiagnosticOpts()); + ProcessWarningOptions(getDiagnostics(), Clang->getDiagnosticOpts()); StoredDiagnostics.erase( StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver, StoredDiagnostics.end()); @@ -1337,17 +1388,16 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( PreprocessedEntitiesInPreamble.clear(); // Create a file manager object to provide access to and cache the filesystem. - Clang.setFileManager(new FileManager(Clang.getFileSystemOpts())); + Clang->setFileManager(new FileManager(Clang->getFileSystemOpts())); // Create the source manager. - Clang.setSourceManager(new SourceManager(getDiagnostics(), - Clang.getFileManager())); + Clang->setSourceManager(new SourceManager(getDiagnostics(), + Clang->getFileManager())); llvm::OwningPtr Act; Act.reset(new PrecompilePreambleAction(*this)); - if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second, - Clang.getFrontendOpts().Inputs[0].first)) { - Clang.takeInvocation(); + if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second, + Clang->getFrontendOpts().Inputs[0].first)) { llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); Preamble.clear(); PreambleRebuildCounter = DefaultPreambleRebuildInterval; @@ -1358,8 +1408,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( Act->Execute(); Act->EndSourceFile(); - Clang.takeInvocation(); - + if (Diagnostics->hasErrorOccurred()) { // There were errors parsing the preamble, so no precompiled header was // generated. Forget that we even tried. @@ -1383,14 +1432,14 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // Keep track of all of the files that the source manager knows about, // so we can verify whether they have changed or not. FilesInPreamble.clear(); - SourceManager &SourceMgr = Clang.getSourceManager(); + SourceManager &SourceMgr = Clang->getSourceManager(); const llvm::MemoryBuffer *MainFileBuffer = SourceMgr.getBuffer(SourceMgr.getMainFileID()); for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(), FEnd = SourceMgr.fileinfo_end(); F != FEnd; ++F) { - const FileEntry *File = F->second->Entry; + const FileEntry *File = F->second->OrigEntry; if (!File || F->second->getRawBuffer() == MainFileBuffer) continue; @@ -1491,6 +1540,20 @@ llvm::StringRef ASTUnit::getMainFileName() const { return Invocation->getFrontendOpts().Inputs[0].second; } +ASTUnit *ASTUnit::create(CompilerInvocation *CI, + llvm::IntrusiveRefCntPtr Diags) { + llvm::OwningPtr AST; + AST.reset(new ASTUnit(false)); + ConfigureDiags(Diags, 0, 0, *AST, /*CaptureDiagnostics=*/false); + AST->Diagnostics = Diags; + AST->Invocation = CI; + AST->FileSystemOpts = CI->getFileSystemOpts(); + AST->FileMgr = new FileManager(AST->FileSystemOpts); + AST->SourceMgr = new SourceManager(*Diags, *AST->FileMgr); + + return AST.take(); +} + bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { if (!Invocation) return true; @@ -1513,6 +1576,10 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { SimpleTimer ParsingTimer(WantTiming); ParsingTimer.setOutput("Parsing " + getMainFileName()); + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + MemBufferCleanup(OverrideMainBuffer); + return Parse(OverrideMainBuffer); } @@ -1532,8 +1599,15 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, AST->CaptureDiagnostics = CaptureDiagnostics; AST->CompleteTranslationUnit = CompleteTranslationUnit; AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; - AST->Invocation.reset(CI); + AST->Invocation = CI; + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + ASTUnitCleanup(AST.get()); + llvm::CrashRecoveryContextCleanupRegistrar > + DiagCleanup(Diags.getPtr()); + return AST->LoadFromCompilerInvocation(PrecompilePreamble)? 0 : AST.take(); } @@ -1545,6 +1619,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, bool CaptureDiagnostics, RemappedFile *RemappedFiles, unsigned NumRemappedFiles, + bool RemappedFilesKeepOriginalName, bool PrecompilePreamble, bool CompleteTranslationUnit, bool CacheCodeCompletionResults, @@ -1557,63 +1632,35 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd - ArgBegin, ArgBegin); } - - llvm::SmallVector Args; - Args.push_back(""); // FIXME: Remove dummy argument. - Args.insert(Args.end(), ArgBegin, ArgEnd); - - // FIXME: Find a cleaner way to force the driver into restricted modes. We - // also want to force it to use clang. - Args.push_back("-fsyntax-only"); llvm::SmallVector StoredDiagnostics; - llvm::OwningPtr CI; + llvm::IntrusiveRefCntPtr CI; { CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags, StoredDiagnostics); - // FIXME: We shouldn't have to pass in the path info. - driver::Driver TheDriver("clang", llvm::sys::getHostTriple(), - "a.out", false, false, *Diags); - - // Don't check that inputs exist, they have been remapped. - TheDriver.setCheckInputsExist(false); - - llvm::OwningPtr C( - TheDriver.BuildCompilation(Args.size(), Args.data())); - - // We expect to get back exactly one command job, if we didn't something - // failed. - const driver::JobList &Jobs = C->getJobs(); - if (Jobs.size() != 1 || !isa(Jobs.begin())) { - llvm::SmallString<256> Msg; - llvm::raw_svector_ostream OS(Msg); - C->PrintJob(OS, C->getJobs(), "; ", true); - Diags->Report(diag::err_fe_expected_compiler_job) << OS.str(); + CI = clang::createInvocationFromCommandLine( + llvm::ArrayRef(ArgBegin, ArgEnd-ArgBegin), + Diags); + if (!CI) return 0; - } - - const driver::Command *Cmd = cast(*Jobs.begin()); - if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { - Diags->Report(diag::err_fe_expected_clang_command); - return 0; - } - - const driver::ArgStringList &CCArgs = Cmd->getArguments(); - CI.reset(new CompilerInvocation); - CompilerInvocation::CreateFromArgs(*CI, - const_cast(CCArgs.data()), - const_cast(CCArgs.data()) + - CCArgs.size(), - *Diags); } // Override any files that need remapping - for (unsigned I = 0; I != NumRemappedFiles; ++I) - CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, - RemappedFiles[I].second); + for (unsigned I = 0; I != NumRemappedFiles; ++I) { + FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second; + if (const llvm::MemoryBuffer * + memBuf = fileOrBuf.dyn_cast()) { + CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, memBuf); + } else { + const char *fname = fileOrBuf.get(); + CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, fname); + } + } + CI->getPreprocessorOpts().RemappedFilesKeepOriginalName = + RemappedFilesKeepOriginalName; // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; @@ -1633,8 +1680,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, AST.reset(new ASTUnit(false)); ConfigureDiags(Diags, ArgBegin, ArgEnd, *AST, CaptureDiagnostics); AST->Diagnostics = Diags; - - AST->FileMgr.reset(new FileManager(FileSystemOptions())); + + AST->FileSystemOpts = CI->getFileSystemOpts(); + AST->FileMgr = new FileManager(AST->FileSystemOpts); AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; AST->CompleteTranslationUnit = CompleteTranslationUnit; @@ -1642,12 +1690,23 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size(); AST->NumStoredDiagnosticsInPreamble = StoredDiagnostics.size(); AST->StoredDiagnostics.swap(StoredDiagnostics); - AST->Invocation.reset(CI.take()); + AST->Invocation = CI; + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + ASTUnitCleanup(AST.get()); + llvm::CrashRecoveryContextCleanupRegistrar > + CICleanup(CI.getPtr()); + llvm::CrashRecoveryContextCleanupRegistrar > + DiagCleanup(Diags.getPtr()); + return AST->LoadFromCompilerInvocation(PrecompilePreamble) ? 0 : AST.take(); } bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) { - if (!Invocation.get()) + if (!Invocation) return true; SimpleTimer ParsingTimer(WantTiming); @@ -1664,9 +1723,18 @@ bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) { delete R->second; } Invocation->getPreprocessorOpts().clearRemappedFiles(); - for (unsigned I = 0; I != NumRemappedFiles; ++I) - Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, - RemappedFiles[I].second); + for (unsigned I = 0; I != NumRemappedFiles; ++I) { + FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second; + if (const llvm::MemoryBuffer * + memBuf = fileOrBuf.dyn_cast()) { + Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, + memBuf); + } else { + const char *fname = fileOrBuf.get(); + Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, + fname); + } + } // If we have a preamble file lying around, or if we might try to // build a precompiled preamble, do so now. @@ -1934,16 +2002,18 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, SourceManager &SourceMgr, FileManager &FileMgr, llvm::SmallVectorImpl &StoredDiagnostics, llvm::SmallVectorImpl &OwnedBuffers) { - if (!Invocation.get()) + if (!Invocation) return; SimpleTimer CompletionTimer(WantTiming); CompletionTimer.setOutput("Code completion @ " + File + ":" + llvm::Twine(Line) + ":" + llvm::Twine(Column)); - CompilerInvocation CCInvocation(*Invocation); - FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts(); - PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts(); + llvm::IntrusiveRefCntPtr + CCInvocation(new CompilerInvocation(*Invocation)); + + FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts(); + PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts(); FrontendOpts.ShowMacrosInCodeCompletion = IncludeMacros && CachedCompletionResults.empty(); @@ -1955,25 +2025,30 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, FrontendOpts.CodeCompletionAt.Column = Column; // Set the language options appropriately. - LangOpts = CCInvocation.getLangOpts(); + LangOpts = CCInvocation->getLangOpts(); - CompilerInstance Clang; - Clang.setInvocation(&CCInvocation); - OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; + llvm::OwningPtr Clang(new CompilerInstance()); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + CICleanup(Clang.get()); + + Clang->setInvocation(&*CCInvocation); + OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second; // Set up diagnostics, capturing any diagnostics produced. - Clang.setDiagnostics(&Diag); - ProcessWarningOptions(Diag, CCInvocation.getDiagnosticOpts()); + Clang->setDiagnostics(&Diag); + ProcessWarningOptions(Diag, CCInvocation->getDiagnosticOpts()); CaptureDroppedDiagnostics Capture(true, - Clang.getDiagnostics(), + Clang->getDiagnostics(), StoredDiagnostics); // Create the target instance. - Clang.getTargetOpts().Features = TargetFeatures; - Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), - Clang.getTargetOpts())); - if (!Clang.hasTarget()) { - Clang.takeInvocation(); + Clang->getTargetOpts().Features = TargetFeatures; + Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), + Clang->getTargetOpts())); + if (!Clang->hasTarget()) { + Clang->setInvocation(0); return; } @@ -1981,27 +2056,33 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, // // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. - Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); + Clang->getTarget().setForcedLangOptions(Clang->getLangOpts()); - assert(Clang.getFrontendOpts().Inputs.size() == 1 && + assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); - assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST && + assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST && "FIXME: AST inputs not yet supported here!"); - assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR && + assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR && "IR inputs not support here!"); // Use the source and file managers that we were given. - Clang.setFileManager(&FileMgr); - Clang.setSourceManager(&SourceMgr); + Clang->setFileManager(&FileMgr); + Clang->setSourceManager(&SourceMgr); // Remap files. PreprocessorOpts.clearRemappedFiles(); PreprocessorOpts.RetainRemappedFileBuffers = true; for (unsigned I = 0; I != NumRemappedFiles; ++I) { - PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, - RemappedFiles[I].second); - OwnedBuffers.push_back(RemappedFiles[I].second); + FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second; + if (const llvm::MemoryBuffer * + memBuf = fileOrBuf.dyn_cast()) { + PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, memBuf); + OwnedBuffers.push_back(memBuf); + } else { + const char *fname = fileOrBuf.get(); + PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, fname); + } } // Use the code completion consumer we were given, but adding any cached @@ -2011,7 +2092,7 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, FrontendOpts.ShowMacrosInCodeCompletion, FrontendOpts.ShowCodePatternsInCodeCompletion, FrontendOpts.ShowGlobalSymbolsInCodeCompletion); - Clang.setCodeCompletionConsumer(AugmentedConsumer); + Clang->setCodeCompletionConsumer(AugmentedConsumer); // If we have a precompiled preamble, try to use it. We only allow // the use of the precompiled preamble if we're if the completion @@ -2026,7 +2107,7 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, if (const FileStatus *MainStatus = MainPath.getFileStatus()) if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID()) OverrideMainBuffer - = getMainBufferWithPrecompiledPreamble(CCInvocation, false, + = getMainBufferWithPrecompiledPreamble(*CCInvocation, false, Line - 1); } @@ -2063,16 +2144,11 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, llvm::OwningPtr Act; Act.reset(new SyntaxOnlyAction); - if (Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second, - Clang.getFrontendOpts().Inputs[0].first)) { + if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second, + Clang->getFrontendOpts().Inputs[0].first)) { Act->Execute(); Act->EndSourceFile(); } - - // Steal back our resources. - Clang.takeFileManager(); - Clang.takeSourceManager(); - Clang.takeInvocation(); } bool ASTUnit::Save(llvm::StringRef File) { @@ -2086,7 +2162,16 @@ bool ASTUnit::Save(llvm::StringRef File) { llvm::raw_fd_ostream::F_Binary); if (!ErrorInfo.empty() || Out.has_error()) return true; - + + serialize(Out); + Out.close(); + return Out.has_error(); +} + +bool ASTUnit::serialize(llvm::raw_ostream &OS) { + if (getDiagnostics().hasErrorOccurred()) + return true; + std::vector Buffer; llvm::BitstreamWriter Stream(Buffer); ASTWriter Writer(Stream); @@ -2094,7 +2179,7 @@ bool ASTUnit::Save(llvm::StringRef File) { // Write the generated bitstream to "Out". if (!Buffer.empty()) - Out.write((char *)&Buffer.front(), Buffer.size()); - Out.close(); - return Out.has_error(); + OS.write((char *)&Buffer.front(), Buffer.size()); + + return false; } diff --git a/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp index ee3fdd834334..06a1fd29838b 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp @@ -288,12 +288,12 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) && ParsingPreprocessorDirective) { - // Insert an eom token into the token cache. It has the same + // Insert an eod token into the token cache. It has the same // position as the next token that is not on the same line as the // preprocessor directive. Observe that we continue processing // 'Tok' when we exit this branch. Token Tmp = Tok; - Tmp.setKind(tok::eom); + Tmp.setKind(tok::eod); Tmp.clearFlag(Token::StartOfLine); Tmp.setIdentifierInfo(0); EmitToken(Tmp); @@ -473,7 +473,7 @@ void PTHWriter::GeneratePTH(const std::string &MainFile) { for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(), E = SM.fileinfo_end(); I != E; ++I) { const SrcMgr::ContentCache &C = *I->second; - const FileEntry *FE = C.Entry; + const FileEntry *FE = C.OrigEntry; // FIXME: Handle files with non-absolute paths. if (llvm::sys::path::is_relative(FE->getName())) diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp index fd593de560c0..ace3c5adb100 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp @@ -22,6 +22,7 @@ #include "clang/Frontend/ChainedDiagnosticClient.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/LogDiagnosticPrinter.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/VerifyDiagnosticsClient.h" #include "clang/Frontend/Utils.h" @@ -47,7 +48,7 @@ CompilerInstance::~CompilerInstance() { } void CompilerInstance::setInvocation(CompilerInvocation *Value) { - Invocation.reset(Value); + Invocation = Value; } void CompilerInstance::setDiagnostics(Diagnostic *Value) { @@ -55,24 +56,20 @@ void CompilerInstance::setDiagnostics(Diagnostic *Value) { } void CompilerInstance::setTarget(TargetInfo *Value) { - Target.reset(Value); + Target = Value; } void CompilerInstance::setFileManager(FileManager *Value) { - FileMgr.reset(Value); + FileMgr = Value; } -void CompilerInstance::setSourceManager(SourceManager *Value) { - SourceMgr.reset(Value); +void CompilerInstance::setSourceManager(SourceManager *Value) { + SourceMgr = Value; } -void CompilerInstance::setPreprocessor(Preprocessor *Value) { - PP.reset(Value); -} +void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; } -void CompilerInstance::setASTContext(ASTContext *Value) { - Context.reset(Value); -} +void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; } void CompilerInstance::setSema(Sema *S) { TheSema.reset(S); @@ -110,15 +107,47 @@ static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger)); } +static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts, + const CodeGenOptions *CodeGenOpts, + Diagnostic &Diags) { + std::string ErrorInfo; + bool OwnsStream = false; + llvm::raw_ostream *OS = &llvm::errs(); + if (DiagOpts.DiagnosticLogFile != "-") { + // Create the output stream. + llvm::raw_fd_ostream *FileOS( + new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(), + ErrorInfo, llvm::raw_fd_ostream::F_Append)); + if (!ErrorInfo.empty()) { + Diags.Report(diag::warn_fe_cc_log_diagnostics_failure) + << DiagOpts.DumpBuildInformation << ErrorInfo; + } else { + FileOS->SetUnbuffered(); + FileOS->SetUseAtomicWrites(true); + OS = FileOS; + OwnsStream = true; + } + } + + // Chain in the diagnostic client which will log the diagnostics. + LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts, + OwnsStream); + if (CodeGenOpts) + Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags); + Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger)); +} + void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv, DiagnosticClient *Client) { - Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client); + Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client, + &getCodeGenOpts()); } llvm::IntrusiveRefCntPtr CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, int Argc, const char* const *Argv, - DiagnosticClient *Client) { + DiagnosticClient *Client, + const CodeGenOptions *CodeGenOpts) { llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); llvm::IntrusiveRefCntPtr Diags(new Diagnostic(DiagID)); @@ -133,6 +162,10 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, if (Opts.VerifyDiagnostics) Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient())); + // Chain in -diagnostic-log-file dumper, if requested. + if (!Opts.DiagnosticLogFile.empty()) + SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags); + if (!Opts.DumpBuildInformation.empty()) SetUpBuildDumpLog(Opts, Argc, Argv, *Diags); @@ -145,23 +178,23 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, // File Manager void CompilerInstance::createFileManager() { - FileMgr.reset(new FileManager(getFileSystemOpts())); + FileMgr = new FileManager(getFileSystemOpts()); } // Source Manager void CompilerInstance::createSourceManager(FileManager &FileMgr) { - SourceMgr.reset(new SourceManager(getDiagnostics(), FileMgr)); + SourceMgr = new SourceManager(getDiagnostics(), FileMgr); } // Preprocessor void CompilerInstance::createPreprocessor() { - PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), - getPreprocessorOpts(), getHeaderSearchOpts(), - getDependencyOutputOpts(), getTarget(), - getFrontendOpts(), getSourceManager(), - getFileManager())); + PP = createPreprocessor(getDiagnostics(), getLangOpts(), + getPreprocessorOpts(), getHeaderSearchOpts(), + getDependencyOutputOpts(), getTarget(), + getFrontendOpts(), getSourceManager(), + getFileManager()); } Preprocessor * @@ -209,7 +242,8 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags, llvm::StringRef OutputPath = DepOpts.HeaderIncludeOutputFile; if (OutputPath == "-") OutputPath = ""; - AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath); + AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath, + /*ShowDepth=*/false); } return PP; @@ -219,10 +253,10 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags, void CompilerInstance::createASTContext() { Preprocessor &PP = getPreprocessor(); - Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(), - getTarget(), PP.getIdentifierTable(), - PP.getSelectorTable(), PP.getBuiltinInfo(), - /*size_reserve=*/ 0)); + Context = new ASTContext(getLangOpts(), PP.getSourceManager(), + getTarget(), PP.getIdentifierTable(), + PP.getSelectorTable(), PP.getBuiltinInfo(), + /*size_reserve=*/ 0); } // ExternalASTSource @@ -362,19 +396,22 @@ void CompilerInstance::clearOutputFiles(bool EraseFiles) { it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { delete it->OS; if (!it->TempFilename.empty()) { - llvm::sys::Path TempPath(it->TempFilename); - if (EraseFiles) - TempPath.eraseFromDisk(); - else { - std::string Error; - llvm::sys::Path NewOutFile(it->Filename); + if (EraseFiles) { + bool existed; + llvm::sys::fs::remove(it->TempFilename, existed); + } else { + llvm::SmallString<128> NewOutFile(it->Filename); + // If '-working-directory' was passed, the output filename should be // relative to that. - FileManager::FixupRelativePath(NewOutFile, getFileSystemOpts()); - if (TempPath.renamePathOnDisk(NewOutFile, &Error)) { + FileMgr->FixupRelativePath(NewOutFile); + if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename, + NewOutFile.str())) { getDiagnostics().Report(diag::err_fe_unable_to_rename_temp) - << it->TempFilename << it->Filename << Error; - TempPath.eraseFromDisk(); + << it->TempFilename << it->Filename << ec.message(); + + bool existed; + llvm::sys::fs::remove(it->TempFilename, existed); } } } else if (!it->Filename.empty() && EraseFiles) diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp index 4b44c488f8a8..495c6a8956df 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp @@ -30,16 +30,6 @@ #include "llvm/Support/Path.h" using namespace clang; -static const char *getAnalysisName(Analyses Kind) { - switch (Kind) { - default: - llvm_unreachable("Unknown analysis kind!"); -#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\ - case NAME: return "-" CMDFLAG; -#include "clang/Frontend/Analyses.def" - } -} - static const char *getAnalysisStoreName(AnalysisStores Kind) { switch (Kind) { default: @@ -76,8 +66,6 @@ static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) { static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, std::vector &Res) { - for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i) - Res.push_back(getAnalysisName(Opts.AnalysisList[i])); if (Opts.ShowCheckerHelp) Res.push_back("-analyzer-checker-help"); if (Opts.AnalysisStoreOpt != BasicStoreModel) { @@ -102,8 +90,6 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, Res.push_back("-analyzer-display-progress"); if (Opts.AnalyzeNestedBlocks) Res.push_back("-analyzer-opt-analyze-nested-blocks"); - if (Opts.AnalyzerStats) - Res.push_back("-analyzer-stats"); if (Opts.EagerlyAssume) Res.push_back("-analyzer-eagerly-assume"); if (!Opts.PurgeDead) @@ -112,12 +98,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, Res.push_back("-trim-egraph"); if (Opts.VisualizeEGDot) Res.push_back("-analyzer-viz-egraph-graphviz"); - if (Opts.VisualizeEGDot) + if (Opts.VisualizeEGUbi) Res.push_back("-analyzer-viz-egraph-ubigraph"); - if (Opts.EnableExperimentalChecks) - Res.push_back("-analyzer-experimental-checks"); - if (Opts.BufferOverflows) - Res.push_back("-analyzer-check-buffer-overflows"); for (unsigned i = 0, e = Opts.CheckersControlList.size(); i != e; ++i) { const std::pair &opt = Opts.CheckersControlList[i]; @@ -141,17 +123,23 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, Res.push_back("-dwarf-debug-flags"); Res.push_back(Opts.DwarfDebugFlags); } + if (Opts.EmitGcovArcs) + Res.push_back("-femit-coverage-data"); + if (Opts.EmitGcovNotes) + Res.push_back("-femit-coverage-notes"); if (!Opts.MergeAllConstants) Res.push_back("-fno-merge-all-constants"); if (Opts.NoCommon) Res.push_back("-fno-common"); + if (Opts.ForbidGuardVariables) + Res.push_back("-fforbid-guard-variables"); if (Opts.NoImplicitFloat) Res.push_back("-no-implicit-float"); if (Opts.OmitLeafFramePointer) Res.push_back("-momit-leaf-frame-pointer"); if (Opts.OptimizeSize) { assert(Opts.OptimizationLevel == 2 && "Invalid options!"); - Res.push_back("-Os"); + Opts.OptimizeSize == 1 ? Res.push_back("-Os") : Res.push_back("-Oz"); } else if (Opts.OptimizationLevel != 0) Res.push_back("-O" + llvm::utostr(Opts.OptimizationLevel)); if (!Opts.MainFileName.empty()) { @@ -213,6 +201,10 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, } if (Opts.RelaxAll) Res.push_back("-mrelax-all"); + if (Opts.SaveTempLabels) + Res.push_back("-msave-temp-labels"); + if (Opts.NoDwarf2CFIAsm) + Res.push_back("-fno-dwarf2-cfi-asm"); if (Opts.SoftFloat) Res.push_back("-msoft-float"); if (Opts.UnwindTables) @@ -223,6 +215,10 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, } if (!Opts.VerifyModule) Res.push_back("-disable-llvm-verifier"); + for (unsigned i = 0, e = Opts.BackendOptions.size(); i != e; ++i) { + Res.push_back("-backend-option"); + Res.push_back(Opts.BackendOptions[i]); + } } static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts, @@ -273,6 +269,8 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts, Res.push_back("-fcolor-diagnostics"); if (Opts.VerifyDiagnostics) Res.push_back("-verify"); + if (Opts.ShowNames) + Res.push_back("-fdiagnostics-show-name"); if (Opts.ShowOptionNames) Res.push_back("-fdiagnostics-show-option"); if (Opts.ShowCategories == 1) @@ -283,6 +281,10 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts, Res.push_back("-ferror-limit"); Res.push_back(llvm::utostr(Opts.ErrorLimit)); } + if (!Opts.DiagnosticLogFile.empty()) { + Res.push_back("-diagnostic-log-file"); + Res.push_back(Opts.DiagnosticLogFile); + } if (Opts.MacroBacktraceLimit != DiagnosticOptions::DefaultMacroBacktraceLimit) { Res.push_back("-fmacro-backtrace-limit"); @@ -340,7 +342,6 @@ static const char *getActionName(frontend::ActionKind Kind) { case frontend::ASTDump: return "-ast-dump"; case frontend::ASTDumpXML: return "-ast-dump-xml"; case frontend::ASTPrint: return "-ast-print"; - case frontend::ASTPrintXML: return "-ast-print-xml"; case frontend::ASTView: return "-ast-view"; case frontend::BoostCon: return "-boostcon"; case frontend::CreateModule: return "-create-module"; @@ -578,7 +579,7 @@ static void LangOptsToArgs(const LangOptions &Opts, if (Opts.WritableStrings) Res.push_back("-fwritable-strings"); if (Opts.ConstStrings) - Res.push_back("-Wwrite-strings"); + Res.push_back("-fconst-strings"); if (!Opts.LaxVectorConversions) Res.push_back("-fno-lax-vector-conversions"); if (Opts.AltiVec) @@ -591,6 +592,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fcxx-exceptions"); if (Opts.SjLjExceptions) Res.push_back("-fsjlj-exceptions"); + if (Opts.TraditionalCPP) + Res.push_back("-traditional-cpp"); if (!Opts.RTTI) Res.push_back("-fno-rtti"); if (Opts.MSBitfields) @@ -689,6 +692,14 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fconstant-string-class"); Res.push_back(Opts.ObjCConstantStringClass); } + if (Opts.FakeAddressSpaceMap) + Res.push_back("-ffake-address-space-map"); + if (Opts.ParseUnknownAnytype) + Res.push_back("-funknown-anytype"); + if (Opts.DelayedTemplateParsing) + Res.push_back("-fdelayed-template-parsing"); + if (Opts.Deprecated) + Res.push_back("-fdeprecated-macro"); } static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts, @@ -725,6 +736,10 @@ static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts, assert(Opts.ImplicitPTHInclude == Opts.TokenCache && "Unsupported option combination!"); } + for (unsigned i = 0, e = Opts.ChainedIncludes.size(); i != e; ++i) { + Res.push_back("-chain-include"); + Res.push_back(Opts.ChainedIncludes[i]); + } for (unsigned i = 0, e = Opts.RemappedFiles.size(); i != e; ++i) { Res.push_back("-remap-file"); Res.push_back(Opts.RemappedFiles[i].first + ";" + @@ -804,8 +819,8 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, unsigned DefaultOpt = 0; if (IK == IK_OpenCL && !Args.hasArg(OPT_cl_opt_disable)) DefaultOpt = 2; - // -Os implies -O2 - return Args.hasArg(OPT_Os) ? 2 : + // -Os/-Oz implies -O2 + return (Args.hasArg(OPT_Os) || Args.hasArg (OPT_Oz)) ? 2 : Args.getLastArgIntValue(OPT_O, DefaultOpt, Diags); } @@ -813,11 +828,6 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Diagnostic &Diags) { using namespace cc1options; - Opts.AnalysisList.clear(); -#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) \ - if (Args.hasArg(OPT_analysis_##NAME)) Opts.AnalysisList.push_back(NAME); -#include "clang/Frontend/Analyses.def" - if (Arg *A = Args.getLastArg(OPT_analyzer_store)) { llvm::StringRef Name = A->getValue(Args); AnalysisStores Value = llvm::StringSwitch(Name) @@ -870,20 +880,17 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress); Opts.AnalyzeNestedBlocks = Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks); - Opts.AnalyzerStats = Args.hasArg(OPT_analysis_AnalyzerStats); Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead); Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume); Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function); Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG); Opts.CFGAddImplicitDtors = Args.hasArg(OPT_analysis_CFGAddImplicitDtors); Opts.CFGAddInitializers = Args.hasArg(OPT_analysis_CFGAddInitializers); - Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks); Opts.TrimGraph = Args.hasArg(OPT_trim_egraph); Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags); Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags); Opts.EagerlyTrimEGraph = !Args.hasArg(OPT_analyzer_no_eagerly_trim_egraph); Opts.InlineCall = Args.hasArg(OPT_analyzer_inline_call); - Opts.BufferOverflows = Args.hasArg(OPT_analysis_WarnBufferOverflows); Opts.CheckersControlList.clear(); for (arg_iterator it = Args.filtered_begin(OPT_analyzer_checker, @@ -921,12 +928,14 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.LimitDebugInfo = Args.hasArg(OPT_flimit_debug_info); Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns); Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone); + Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float); Opts.OptimizeSize = Args.hasArg(OPT_Os); + Opts.OptimizeSize = Args.hasArg(OPT_Oz) ? 2 : Opts.OptimizeSize; Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) || Args.hasArg(OPT_ffreestanding)); Opts.UnrollLoops = Args.hasArg(OPT_funroll_loops) || @@ -945,9 +954,12 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.NoInfsFPMath = Opts.NoNaNsFPMath = Args.hasArg(OPT_cl_finite_math_only)|| Args.hasArg(OPT_cl_fast_relaxed_math); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); + Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option); Opts.NumRegisterParameters = Args.getLastArgIntValue(OPT_mregparm, 0, Diags); Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer); + Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels); + Opts.NoDwarf2CFIAsm = Args.hasArg(OPT_fno_dwarf2_cfi_asm); Opts.SoftFloat = Args.hasArg(OPT_msoft_float); Opts.UnsafeFPMath = Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); @@ -962,6 +974,8 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions); Opts.InstrumentForProfiling = Args.hasArg(OPT_pg); + Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data); + Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes); if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) { llvm::StringRef Name = A->getValue(Args); @@ -991,6 +1005,7 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Diagnostic &Diags) { using namespace cc1options; + Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file); Opts.IgnoreWarnings = Args.hasArg(OPT_w); Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros); Opts.Pedantic = Args.hasArg(OPT_pedantic); @@ -1000,8 +1015,16 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.ShowColumn = !Args.hasArg(OPT_fno_show_column); Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info); Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location); + Opts.ShowNames = Args.hasArg(OPT_fdiagnostics_show_name); Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option); + // Default behavior is to not to show note include stacks. + Opts.ShowNoteIncludeStack = false; + if (Arg *A = Args.getLastArg(OPT_fdiagnostics_show_note_include_stack, + OPT_fno_diagnostics_show_note_include_stack)) + if (A->getOption().matches(OPT_fdiagnostics_show_note_include_stack)) + Opts.ShowNoteIncludeStack = true; + llvm::StringRef ShowOverloads = Args.getLastArgValue(OPT_fshow_overloads_EQ, "all"); if (ShowOverloads == "best") @@ -1067,8 +1090,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::ASTDumpXML; break; case OPT_ast_print: Opts.ProgramAction = frontend::ASTPrint; break; - case OPT_ast_print_xml: - Opts.ProgramAction = frontend::ASTPrintXML; break; case OPT_ast_view: Opts.ProgramAction = frontend::ASTView; break; case OPT_boostcon: @@ -1177,8 +1198,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, InputKind DashX = IK_None; if (const Arg *A = Args.getLastArg(OPT_x)) { DashX = llvm::StringSwitch(A->getValue(Args)) - .Case("c", IK_C) - .Case("cl", IK_OpenCL) .Case("c", IK_C) .Case("cl", IK_OpenCL) .Case("cuda", IK_CUDA) @@ -1189,6 +1208,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, .Case("assembler-with-cpp", IK_Asm) .Case("c++-cpp-output", IK_PreprocessedCXX) .Case("objective-c-cpp-output", IK_PreprocessedObjC) + .Case("objc-cpp-output", IK_PreprocessedObjC) .Case("objective-c++-cpp-output", IK_PreprocessedObjCXX) .Case("c-header", IK_C) .Case("objective-c-header", IK_ObjC) @@ -1288,7 +1308,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, LangStandard::Kind LangStd) { - // Set some properties which depend soley on the input kind; it would be nice + // Set some properties which depend solely on the input kind; it would be nice // to move these to the language standard, and have the driver resolve the // input kind + language standard. if (IK == IK_Asm) { @@ -1332,6 +1352,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); Opts.BCPLComment = Std.hasBCPLComments(); Opts.C99 = Std.isC99(); + Opts.C1X = Std.isC1X(); Opts.CPlusPlus = Std.isCPlusPlus(); Opts.CPlusPlus0x = Std.isCPlusPlus0x(); Opts.Digraphs = Std.hasDigraphs(); @@ -1423,6 +1444,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_pthread)) Opts.POSIXThreads = 1; + if (Args.hasArg(OPT_fdelayed_template_parsing)) + Opts.DelayedTemplateParsing = 1; + llvm::StringRef Vis = Args.getLastArgValue(OPT_fvisibility, "default"); if (Vis == "default") Opts.setVisibilityMode(DefaultVisibility); @@ -1457,7 +1481,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.MSCVersion = Args.getLastArgIntValue(OPT_fmsc_version, 0, Diags); Opts.Borland = Args.hasArg(OPT_fborland_extensions); Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); - Opts.ConstStrings = Args.hasArg(OPT_Wwrite_strings); + Opts.ConstStrings = Args.hasFlag(OPT_fconst_strings, OPT_fno_const_strings, + Opts.ConstStrings); if (Args.hasArg(OPT_fno_lax_vector_conversions)) Opts.LaxVectorConversions = 0; if (Args.hasArg(OPT_fno_threadsafe_statics)) @@ -1466,6 +1491,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); + Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp); Opts.RTTI = !Args.hasArg(OPT_fno_rtti); Opts.Blocks = Args.hasArg(OPT_fblocks); @@ -1482,6 +1508,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.MathErrno = Args.hasArg(OPT_fmath_errno); Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 1024, Diags); + Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing); Opts.NumLargeByValueCopy = Args.getLastArgIntValue(OPT_Wlarge_by_value_copy, 0, Diags); Opts.MSBitfields = Args.hasArg(OPT_mms_bitfields); @@ -1504,6 +1531,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.SinglePrecisionConstants = Args.hasArg(OPT_cl_single_precision_constant); Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math); Opts.OptimizeSize = 0; + Opts.MRTD = Args.hasArg(OPT_mrtd); + Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map); + Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype); + + // Record whether the __DEPRECATED define was requested. + Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro, + OPT_fno_deprecated_macro, + Opts.Deprecated); // FIXME: Eliminate this dependency. unsigned Opt = getOptimizationLevel(Args, IK, Diags); @@ -1593,6 +1628,12 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.Includes.push_back(A->getValue(Args)); } + for (arg_iterator it = Args.filtered_begin(OPT_chain_include), + ie = Args.filtered_end(); it != ie; ++it) { + const Arg *A = *it; + Opts.ChainedIncludes.push_back(A->getValue(Args)); + } + // Include 'altivec.h' if -faltivec option present if (Args.hasArg(OPT_faltivec)) Opts.Includes.push_back("altivec.h"); diff --git a/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp b/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp new file mode 100644 index 000000000000..0005f910d214 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -0,0 +1,90 @@ +//===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Construct a compiler invocation object for command line driver arguments +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/Utils.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/DiagnosticOptions.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/ArgList.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/Tool.h" +#include "llvm/Support/Host.h" +using namespace clang; + +/// createInvocationFromCommandLine - Construct a compiler invocation object for +/// a command line argument vector. +/// +/// \return A CompilerInvocation, or 0 if none was built for the given +/// argument vector. +CompilerInvocation * +clang::createInvocationFromCommandLine(llvm::ArrayRef ArgList, + llvm::IntrusiveRefCntPtr Diags) { + if (!Diags.getPtr()) { + // No diagnostics engine was provided, so create our own diagnostics object + // with the default options. + DiagnosticOptions DiagOpts; + Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgList.size(), + ArgList.begin()); + } + + llvm::SmallVector Args; + Args.push_back(""); // FIXME: Remove dummy argument. + Args.insert(Args.end(), ArgList.begin(), ArgList.end()); + + // FIXME: Find a cleaner way to force the driver into restricted modes. We + // also want to force it to use clang. + Args.push_back("-fsyntax-only"); + + // FIXME: We shouldn't have to pass in the path info. + driver::Driver TheDriver("clang", llvm::sys::getHostTriple(), + "a.out", false, false, *Diags); + + // Don't check that inputs exist, they may have been remapped. + TheDriver.setCheckInputsExist(false); + + llvm::OwningPtr C(TheDriver.BuildCompilation(Args)); + + // Just print the cc1 options if -### was present. + if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) { + C->PrintJob(llvm::errs(), C->getJobs(), "\n", true); + return 0; + } + + // We expect to get back exactly one command job, if we didn't something + // failed. + const driver::JobList &Jobs = C->getJobs(); + if (Jobs.size() != 1 || !isa(Jobs.begin())) { + llvm::SmallString<256> Msg; + llvm::raw_svector_ostream OS(Msg); + C->PrintJob(OS, C->getJobs(), "; ", true); + Diags->Report(diag::err_fe_expected_compiler_job) << OS.str(); + return 0; + } + + const driver::Command *Cmd = cast(*Jobs.begin()); + if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { + Diags->Report(diag::err_fe_expected_clang_command); + return 0; + } + + const driver::ArgStringList &CCArgs = Cmd->getArguments(); + CompilerInvocation *CI = new CompilerInvocation(); + CompilerInvocation::CreateFromArgs(*CI, + const_cast(CCArgs.data()), + const_cast(CCArgs.data()) + + CCArgs.size(), + *Diags); + return CI; +} diff --git a/contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp deleted file mode 100644 index 8d3d225a4b38..000000000000 --- a/contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp +++ /dev/null @@ -1,183 +0,0 @@ -//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the XML document class, which provides the means to -// dump out the AST in a XML form that exposes type details and other fields. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/DocumentXML.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/Expr.h" - -namespace clang { - -//--------------------------------------------------------- -class DocumentXML::DeclPrinter : public DeclVisitor { - DocumentXML& Doc; - - void addSubNodes(FunctionDecl* FD) { - for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) { - Visit(FD->getParamDecl(i)); - Doc.toParent(); - } - } - - void addFunctionBody(FunctionDecl* FD) { - if (FD->isThisDeclarationADefinition()) { - Doc.addSubNode("Body"); - Doc.PrintStmt(FD->getBody()); - Doc.toParent(); - } - } - - void addSubNodes(RecordDecl* RD) { - for (RecordDecl::decl_iterator i = RD->decls_begin(), - e = RD->decls_end(); i != e; ++i) { - if (!(*i)->isImplicit()) { - Visit(*i); - Doc.toParent(); - } - } - } - - void addSubNodes(CXXRecordDecl* RD) { - addSubNodes(cast(RD)); - - if (RD->isDefinition()) { - // FIXME: This breaks XML generation - //Doc.addAttribute("num_bases", RD->getNumBases()); - - for (CXXRecordDecl::base_class_iterator - base = RD->bases_begin(), - bend = RD->bases_end(); - base != bend; - ++base) { - Doc.addSubNode("Base"); - Doc.addAttribute("id", base->getType()); - AccessSpecifier as = base->getAccessSpecifierAsWritten(); - const char* as_name = ""; - switch(as) { - case AS_none: as_name = ""; break; - case AS_public: as_name = "public"; break; - case AS_protected: as_name = "protected"; break; - case AS_private: as_name = "private"; break; - } - Doc.addAttributeOptional("access", as_name); - Doc.addAttribute("is_virtual", base->isVirtual()); - Doc.toParent(); - } - } - } - - void addSubNodes(EnumDecl* ED) { - for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(), - e = ED->enumerator_end(); i != e; ++i) { - Visit(*i); - Doc.toParent(); - } - } - - void addSubNodes(EnumConstantDecl* ECD) { - if (ECD->getInitExpr()) - Doc.PrintStmt(ECD->getInitExpr()); - } - - void addSubNodes(FieldDecl* FdD) { - if (FdD->isBitField()) - Doc.PrintStmt(FdD->getBitWidth()); - } - - void addSubNodes(VarDecl* V) { - if (V->getInit()) - Doc.PrintStmt(V->getInit()); - } - - void addSubNodes(ParmVarDecl* argDecl) { - if (argDecl->getDefaultArg()) - Doc.PrintStmt(argDecl->getDefaultArg()); - } - - void addSubNodes(DeclContext* ns) { - - for (DeclContext::decl_iterator - d = ns->decls_begin(), - dend = ns->decls_end(); - d != dend; - ++d) { - Visit(*d); - Doc.toParent(); - } - } - - void addSpecialAttribute(const char* pName, EnumDecl* ED) { - const QualType& enumType = ED->getIntegerType(); - if (!enumType.isNull()) - Doc.addAttribute(pName, enumType); - } - - void addIdAttribute(LinkageSpecDecl* ED) { - Doc.addAttribute("id", ED); - } - - void addIdAttribute(NamedDecl* ND) { - Doc.addAttribute("id", ND); - } - -public: - DeclPrinter(DocumentXML& doc) : Doc(doc) {} - -#define NODE_XML( CLASS, NAME ) \ - void Visit##CLASS(CLASS* T) \ - { \ - Doc.addSubNode(NAME); - -#define ID_ATTRIBUTE_XML addIdAttribute(T); -#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); -#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); -#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation()); -#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T); - -#define ATTRIBUTE_ENUM_XML( FN, NAME ) \ - { \ - const char* pAttributeName = NAME; \ - const bool optional = false; \ - switch (T->FN) { \ - default: assert(0 && "unknown enum value"); - -#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ - { \ - const char* pAttributeName = NAME; \ - const bool optional = true; \ - switch (T->FN) { \ - default: assert(0 && "unknown enum value"); - -#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; -#define END_ENUM_XML } } -#define END_NODE_XML } - -#define SUB_NODE_XML( CLASS ) addSubNodes(T); -#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T); -#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T); - -#define SUB_NODE_FN_BODY_XML addFunctionBody(T); - -#include "clang/Frontend/DeclXML.def" -}; - - -//--------------------------------------------------------- -void DocumentXML::writeDeclToXML(Decl *D) { - DeclPrinter(*this).Visit(D); - toParent(); -} - -//--------------------------------------------------------- -} // NS clang - diff --git a/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp index bc5a55df0860..5c3a23128a14 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp @@ -171,7 +171,7 @@ void DependencyFileCallback::OutputDependencyFile() { *OS << '\n'; // Create phony targets if requested. - if (PhonyTarget) { + if (PhonyTarget && !Files.empty()) { // Skip the first entry, this is always the input file itself. for (std::vector::iterator I = Files.begin() + 1, E = Files.end(); I != E; ++I) { diff --git a/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp deleted file mode 100644 index a09db0be473e..000000000000 --- a/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp +++ /dev/null @@ -1,381 +0,0 @@ -//===--- DocumentXML.cpp - XML document for ASTs --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the XML document class, which provides the means to -// dump out the AST in a XML form that exposes type details and other fields. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/DocumentXML.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/ASTContext.h" -#include "clang/Basic/SourceManager.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Config/config.h" -#include - -namespace clang { - -//--------------------------------------------------------- -DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) : - Out(out), - Ctx(0), - HasCurrentNodeSubNodes(false) { - NodeStack.push(rootName); - Out << "\n<" << rootName; -} - -//--------------------------------------------------------- -DocumentXML& DocumentXML::addSubNode(const std::string& name) { - if (!HasCurrentNodeSubNodes) - Out << ">\n"; - NodeStack.push(name); - HasCurrentNodeSubNodes = false; - Indent(); - Out << "<" << NodeStack.top(); - return *this; -} - -//--------------------------------------------------------- -void DocumentXML::Indent() { - for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i) - Out << ' '; -} - -//--------------------------------------------------------- -DocumentXML& DocumentXML::toParent() { - assert(NodeStack.size() > 1 && "too much backtracking"); - - if (HasCurrentNodeSubNodes) { - Indent(); - Out << "\n"; - } else - Out << "/>\n"; - NodeStack.pop(); - HasCurrentNodeSubNodes = true; - return *this; -} - -//--------------------------------------------------------- -namespace { - -enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST }; - -unsigned getNewId(tIdType idType) { - static unsigned int idCounts[ID_LAST] = { 0 }; - return ++idCounts[idType]; -} - -//--------------------------------------------------------- -inline std::string getPrefixedId(unsigned uId, tIdType idType) { - static const char idPrefix[ID_LAST] = { '_', 'f', 'l' }; - char buffer[20]; - char* BufPtr = llvm::utohex_buffer(uId, buffer + 20); - *--BufPtr = idPrefix[idType]; - return BufPtr; -} - -//--------------------------------------------------------- -template -bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) { - typename T::iterator i = idMap.find(value); - bool toAdd = i == idMap.end(); - if (toAdd) - idMap.insert(typename T::value_type(value, getNewId(idType))); - return toAdd; -} - -} // anon NS - - -//--------------------------------------------------------- -std::string DocumentXML::escapeString(const char* pStr, - std::string::size_type len) { - std::string value; - value.reserve(len + 1); - char buffer[16]; - for (unsigned i = 0; i < len; ++i) { - switch (char C = pStr[i]) { - default: - if (isprint(C)) - value += C; - else { -#ifdef LLVM_ON_WIN32 - sprintf(buffer, "\\%03o", C); -#else - snprintf(buffer, sizeof(buffer), "\\%03o", C); -#endif - value += buffer; - } - break; - - case '\n': value += "\\n"; break; - case '\t': value += "\\t"; break; - case '\a': value += "\\a"; break; - case '\b': value += "\\b"; break; - case '\r': value += "\\r"; break; - - case '&': value += "&"; break; - case '<': value += "<"; break; - case '>': value += ">"; break; - case '"': value += """; break; - case '\'': value += "'"; break; - - } - } - return value; -} - -//--------------------------------------------------------- -void DocumentXML::finalize() { - assert(NodeStack.size() == 1 && "not completely backtracked"); - - addSubNode("ReferenceSection"); - addSubNode("Types"); - - for (XML::IdMap::iterator i = Types.begin(), e = Types.end(); - i != e; ++i) { - if (i->first.hasLocalQualifiers()) { - writeTypeToXML(i->first); - addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); - toParent(); - } - } - - for (XML::IdMap::iterator i = BasicTypes.begin(), - e = BasicTypes.end(); i != e; ++i) { - writeTypeToXML(i->first); - addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); - toParent(); - } - - - toParent().addSubNode("Contexts"); - - for (XML::IdMap::iterator i = Contexts.begin(), - e = Contexts.end(); i != e; ++i) { - addSubNode(i->first->getDeclKindName()); - addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); - if (const NamedDecl *ND = dyn_cast(i->first)) - addAttribute("name", ND->getNameAsString()); - if (const TagDecl *TD = dyn_cast(i->first)) - addAttribute("type", getPrefixedId(BasicTypes[TD->getTypeForDecl()], ID_NORMAL)); - else if (const FunctionDecl *FD = dyn_cast(i->first)) - addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAs()], ID_NORMAL)); - - if (const DeclContext* parent = i->first->getParent()) - addAttribute("context", parent); - toParent(); - } - - toParent().addSubNode("Files"); - - for (XML::IdMap::iterator i = SourceFiles.begin(), - e = SourceFiles.end(); i != e; ++i) { - addSubNode("File"); - addAttribute("id", getPrefixedId(i->second, ID_FILE)); - addAttribute("name", escapeString(i->first.c_str(), i->first.size())); - toParent(); - } - - toParent().toParent(); - - // write the root closing node (which has always subnodes) - Out << "\n"; -} - -//--------------------------------------------------------- -void DocumentXML::addAttribute(const char* pAttributeName, - const QualType& pType) { - addTypeRecursively(pType); - addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL)); -} - -//--------------------------------------------------------- -void DocumentXML::addPtrAttribute(const char* pAttributeName, - const Type* pType) { - addTypeRecursively(pType); - addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL)); -} - -//--------------------------------------------------------- -void DocumentXML::addPtrAttribute(const char* pAttributeName, - const NestedNameSpecifier* pNNS) { - switch (pNNS->getKind()) { - case NestedNameSpecifier::Identifier: { - IdentifierInfo *ii = pNNS->getAsIdentifier(); - // FIXME how should we handle those ? - addPtrAttribute(pAttributeName, ii->getName().data()); - break; - } - case NestedNameSpecifier::Namespace: { - addPtrAttribute(pAttributeName, pNNS->getAsNamespace()); - break; - } - case NestedNameSpecifier::NamespaceAlias: { - addPtrAttribute(pAttributeName, pNNS->getAsNamespaceAlias()); - break; - } - case NestedNameSpecifier::TypeSpec: { - addPtrAttribute(pAttributeName, pNNS->getAsType()); - break; - } - case NestedNameSpecifier::TypeSpecWithTemplate: { - addPtrAttribute(pAttributeName, pNNS->getAsType()); - break; - } - case NestedNameSpecifier::Global: { - addPtrAttribute(pAttributeName, "::"); - break; - } - } -} - -//--------------------------------------------------------- -void DocumentXML::addTypeRecursively(const QualType& pType) -{ - if (addToMap(Types, pType)) - { - addTypeRecursively(pType.getTypePtr()); - // beautifier: a non-qualified type shall be transparent - if (!pType.hasLocalQualifiers()) - { - Types[pType] = BasicTypes[pType.getTypePtr()]; - } - } -} - -//--------------------------------------------------------- -void DocumentXML::addTypeRecursively(const Type* pType) -{ - if (addToMap(BasicTypes, pType)) - { - addParentTypes(pType); -/* - // FIXME: doesn't work in the immediate streaming approach - if (const VariableArrayType *VAT = dyn_cast(pType)) - { - addSubNode("VariableArraySizeExpression"); - PrintStmt(VAT->getSizeExpr()); - toParent(); - } -*/ - } -} - -//--------------------------------------------------------- -void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC) -{ - addContextsRecursively(DC); - addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL)); -} - -//--------------------------------------------------------- -void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D) -{ - if (const DeclContext* DC = dyn_cast(D)) - { - addContextsRecursively(DC); - addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL)); - } - else - { - addToMap(Decls, D); - addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL)); - } -} - -//--------------------------------------------------------- -void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D) -{ - addPtrAttribute(pName, static_cast(D)); -} - -//--------------------------------------------------------- -void DocumentXML::addContextsRecursively(const DeclContext *DC) -{ - if (DC != 0 && addToMap(Contexts, DC)) - { - addContextsRecursively(DC->getParent()); - } -} - -//--------------------------------------------------------- -void DocumentXML::addSourceFileAttribute(const std::string& fileName) -{ - addToMap(SourceFiles, fileName, ID_FILE); - addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE)); -} - - -//--------------------------------------------------------- -void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L) -{ - addToMap(Labels, L, ID_LABEL); - addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL)); -} - - -//--------------------------------------------------------- -PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc) -{ - SourceManager& SM = Ctx->getSourceManager(); - SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); - PresumedLoc PLoc; - if (!SpellingLoc.isInvalid()) - { - PLoc = SM.getPresumedLoc(SpellingLoc); - if (PLoc.isValid()) { - addSourceFileAttribute(PLoc.getFilename()); - addAttribute("line", PLoc.getLine()); - addAttribute("col", PLoc.getColumn()); - } - } - // else there is no error in some cases (eg. CXXThisExpr) - return PLoc; -} - -//--------------------------------------------------------- -void DocumentXML::addLocationRange(const SourceRange& R) -{ - PresumedLoc PStartLoc = addLocation(R.getBegin()); - if (R.getBegin() != R.getEnd()) - { - SourceManager& SM = Ctx->getSourceManager(); - SourceLocation SpellingLoc = SM.getSpellingLoc(R.getEnd()); - if (!SpellingLoc.isInvalid()) - { - PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc); - if (PLoc.isInvalid()) { - } else if (PStartLoc.isInvalid() || - strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) { - addToMap(SourceFiles, PLoc.getFilename(), ID_FILE); - addAttribute("endfile", PLoc.getFilename()); - addAttribute("endline", PLoc.getLine()); - addAttribute("endcol", PLoc.getColumn()); - } else if (PLoc.getLine() != PStartLoc.getLine()) { - addAttribute("endline", PLoc.getLine()); - addAttribute("endcol", PLoc.getColumn()); - } else { - addAttribute("endcol", PLoc.getColumn()); - } - } - } -} - -//--------------------------------------------------------- -void DocumentXML::PrintDecl(Decl *D) -{ - writeDeclToXML(D); -} - -//--------------------------------------------------------- -} // NS clang - diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp index e3d8b8594190..42da44c2c720 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp @@ -20,6 +20,7 @@ #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Parse/ParseAST.h" #include "clang/Serialization/ASTDeserializationListener.h" +#include "clang/Serialization/ChainedIncludesSource.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Timer.h" #include "llvm/Support/ErrorHandling.h" @@ -209,8 +210,16 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); - /// Use PCH? - if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { + if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { + // Convert headers to PCH and chain them. + llvm::OwningPtr source; + source.reset(ChainedIncludesSource::create(CI)); + if (!source) + goto failure; + CI.getASTContext().setExternalSource(source); + + } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { + // Use PCH. assert(hasPCHSupport() && "This action does not have PCH support!"); ASTDeserializationListener *DeserialListener = CI.getInvocation().getFrontendOpts().ChainedPCH ? @@ -249,10 +258,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // matching EndSourceFile(). failure: if (isCurrentFileAST()) { - CI.takeASTContext(); - CI.takePreprocessor(); - CI.takeSourceManager(); - CI.takeFileManager(); + CI.setASTContext(0); + CI.setPreprocessor(0); + CI.setSourceManager(0); + CI.setFileManager(0); } CI.getDiagnosticClient().EndSourceFile(); @@ -304,7 +313,7 @@ void FrontendAction::EndSourceFile() { CI.takeASTConsumer(); if (!isCurrentFileAST()) { CI.takeSema(); - CI.takeASTContext(); + CI.resetAndLeakASTContext(); } } else { if (!isCurrentFileAST()) { @@ -333,10 +342,10 @@ void FrontendAction::EndSourceFile() { if (isCurrentFileAST()) { CI.takeSema(); - CI.takeASTContext(); - CI.takePreprocessor(); - CI.takeSourceManager(); - CI.takeFileManager(); + CI.resetAndLeakASTContext(); + CI.resetAndLeakPreprocessor(); + CI.resetAndLeakSourceManager(); + CI.resetAndLeakFileManager(); } setCompilerInstance(0); diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp index d8e7d2904500..7b06c7e49acf 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp @@ -47,13 +47,6 @@ ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, return 0; } -ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile) { - if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml")) - return CreateASTPrinterXML(OS); - return 0; -} - ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) { return CreateASTDumper(); diff --git a/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp index 45ff1d2e412f..51dec967cd6b 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp @@ -22,13 +22,16 @@ class HeaderIncludesCallback : public PPCallbacks { bool HasProcessedPredefines; bool OwnsOutputFile; bool ShowAllHeaders; + bool ShowDepth; public: HeaderIncludesCallback(const Preprocessor *PP, bool ShowAllHeaders_, - llvm::raw_ostream *OutputFile_, bool OwnsOutputFile_) + llvm::raw_ostream *OutputFile_, bool OwnsOutputFile_, + bool ShowDepth_) : SM(PP->getSourceManager()), OutputFile(OutputFile_), CurrentIncludeDepth(0), HasProcessedPredefines(false), - OwnsOutputFile(OwnsOutputFile_), ShowAllHeaders(ShowAllHeaders_) {} + OwnsOutputFile(OwnsOutputFile_), ShowAllHeaders(ShowAllHeaders_), + ShowDepth(ShowDepth_) {} ~HeaderIncludesCallback() { if (OwnsOutputFile) @@ -41,7 +44,7 @@ class HeaderIncludesCallback : public PPCallbacks { } void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders, - llvm::StringRef OutputPath) { + llvm::StringRef OutputPath, bool ShowDepth) { llvm::raw_ostream *OutputFile = &llvm::errs(); bool OwnsOutputFile = false; @@ -63,7 +66,8 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders, } PP.addPPCallbacks(new HeaderIncludesCallback(&PP, ShowAllHeaders, - OutputFile, OwnsOutputFile)); + OutputFile, OwnsOutputFile, + ShowDepth)); } void HeaderIncludesCallback::FileChanged(SourceLocation Loc, @@ -78,15 +82,18 @@ void HeaderIncludesCallback::FileChanged(SourceLocation Loc, // Adjust the current include depth. if (Reason == PPCallbacks::EnterFile) { ++CurrentIncludeDepth; - } else { + } else if (Reason == PPCallbacks::ExitFile) { if (CurrentIncludeDepth) --CurrentIncludeDepth; // We track when we are done with the predefines by watching for the first - // place where we drop back to a nesting depth of 0. - if (CurrentIncludeDepth == 0 && !HasProcessedPredefines) + // place where we drop back to a nesting depth of 1. + if (CurrentIncludeDepth == 1 && !HasProcessedPredefines) HasProcessedPredefines = true; - } + + return; + } else + return; // Show the header if we are (a) past the predefines, or (b) showing all // headers and in the predefines at a depth past the initial file and command @@ -102,9 +109,12 @@ void HeaderIncludesCallback::FileChanged(SourceLocation Loc, Lexer::Stringify(Filename); llvm::SmallString<256> Msg; - for (unsigned i = 0; i != CurrentIncludeDepth; ++i) - Msg += '.'; - Msg += ' '; + if (ShowDepth) { + // The main source file is at depth 1, so skip one dot. + for (unsigned i = 1; i != CurrentIncludeDepth; ++i) + Msg += '.'; + Msg += ' '; + } Msg += Filename; Msg += '\n'; diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp index 566b96cd790d..3795c657096a 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp @@ -80,6 +80,10 @@ class InitHeaderSearch { llvm::StringRef Arch, llvm::StringRef Version); + /// AddMinGW64CXXPaths - Add the necessary paths to support + /// libstdc++ of x86_64-w64-mingw32 aka mingw-w64. + void AddMinGW64CXXPaths(llvm::StringRef Base); + /// AddDelimitedPaths - Add a list of paths delimited by the system PATH /// separator. The processing follows that of the CPATH variable for gcc. void AddDelimitedPaths(llvm::StringRef String); @@ -117,8 +121,13 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path, llvm::StringRef MappedPathStr = Path.toStringRef(MappedPathStorage); // Handle isysroot. - if (Group == System && !IgnoreSysRoot && + if ((Group == System || Group == CXXSystem) && !IgnoreSysRoot && +#if defined(_WIN32) + !MappedPathStr.empty() && + llvm::sys::path::is_separator(MappedPathStr[0]) && +#else llvm::sys::path::is_absolute(MappedPathStr) && +#endif IsNotEmptyOrRoot) { MappedPathStorage.clear(); MappedPathStr = @@ -211,6 +220,15 @@ void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base, CXXSystem, true, false, false); } +void InitHeaderSearch::AddMinGW64CXXPaths(llvm::StringRef Base) { + AddPath(Base, + CXXSystem, true, false, false); + AddPath(Base + "/x86_64-w64-mingw32", + CXXSystem, true, false, false); + AddPath(Base + "/backward", + CXXSystem, true, false, false); +} + // FIXME: This probably should goto to some platform utils place. #ifdef _MSC_VER @@ -538,6 +556,11 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, AddPath("/usr/include/w32api", System, true, false, false); break; case llvm::Triple::MinGW32: + // FIXME: We should be aware of i686-w64-mingw32. + if (triple.getArch() == llvm::Triple::x86_64) + AddPath("c:/mingw/x86_64-w64-mingw32/include", + System, true, false, false); + AddPath("/mingw/include", System, true, false, false); AddPath("c:/mingw/include", System, true, false, false); break; case llvm::Triple::FreeBSD: @@ -568,36 +591,8 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { return; } // FIXME: temporary hack: hard-coded paths. - switch (os) { - case llvm::Triple::Cygwin: - // Cygwin-1.7 - AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4"); - // g++-4 / Cygwin-1.5 - AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2"); - // FIXME: Do we support g++-3.4.4? - AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "3.4.4"); - break; - case llvm::Triple::MinGW32: - // mingw-w64-20110207 - AddPath("c:/MinGW/include/c++/4.5.3", CXXSystem, true, false, false); - AddPath("c:/MinGW/include/c++/4.5.3/x86_64-w64-mingw32", CXXSystem, true, - false, false); - AddPath("c:/MinGW/include/c++/4.5.3/backward", CXXSystem, true, false, - false); - // mingw-w64-20101129 - AddPath("c:/MinGW/include/c++/4.5.2", CXXSystem, true, false, false); - AddPath("c:/MinGW/include/c++/4.5.2/x86_64-w64-mingw32", CXXSystem, true, - false, false); - AddPath("c:/MinGW/include/c++/4.5.2/backward", CXXSystem, true, false, - false); - // Try gcc 4.5.0 - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0"); - // Try gcc 4.4.0 - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0"); - // Try gcc 4.3.0 - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0"); - break; - case llvm::Triple::Darwin: + + if (triple.isOSDarwin()) { switch (triple.getArch()) { default: break; @@ -627,6 +622,34 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { "arm-apple-darwin10", "v6", "", triple); break; } + return; + } + + switch (os) { + case llvm::Triple::Cygwin: + // Cygwin-1.7 + AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4"); + // g++-4 / Cygwin-1.5 + AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2"); + // FIXME: Do we support g++-3.4.4? + AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "3.4.4"); + break; + case llvm::Triple::MinGW32: + // FIXME: We should be aware of i686-w64-mingw32. + if (triple.getArch() == llvm::Triple::x86_64) { + // mingw-w64-20110207 + AddMinGW64CXXPaths("c:/mingw/x86_64-w64-mingw32/include/c++/4.5.3"); + // mingw-w64-20101129 + AddMinGW64CXXPaths("c:/mingw/x86_64-w64-mingw32/include/c++/4.5.2"); + } + // Try gcc 4.5.2 (MSYS) + AddMinGWCPlusPlusIncludePaths("/mingw/lib/gcc", "mingw32", "4.5.2"); + // Try gcc 4.5.0 + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0"); + // Try gcc 4.4.0 + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0"); + // Try gcc 4.3.0 + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0"); break; case llvm::Triple::DragonFly: AddPath("/usr/include/c++/4.1", CXXSystem, true, false, false); @@ -674,6 +697,11 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { //===------------------------------------------------------------------===// // Redhat based distros. //===------------------------------------------------------------------===// + // Fedora 15 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0", + "x86_64-redhat-linux", "32", "", triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0", + "i686-redhat-linux", "", "", triple); // Fedora 14 AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.1", "x86_64-redhat-linux", "32", "", triple); @@ -746,7 +774,26 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { "i686-pc-linux-gnu", "", "", triple); AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1", "x86_64-unknown-linux-gnu", "", "", triple); - // Gentoo x86 2010.0 stable + + // Arch Linux gcc 4.6 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0", + "i686-pc-linux-gnu", "", "", triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0", + "x86_64-unknown-linux-gnu", "", "", triple); + + // Gentoo x86 gcc 4.5.2 + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/i686-pc-linux-gnu/4.5.2/include/g++-v4", + "i686-pc-linux-gnu", "", "", triple); + // Gentoo x86 gcc 4.4.5 + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/i686-pc-linux-gnu/4.4.5/include/g++-v4", + "i686-pc-linux-gnu", "", "", triple); + // Gentoo x86 gcc 4.4.4 + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/i686-pc-linux-gnu/4.4.4/include/g++-v4", + "i686-pc-linux-gnu", "", "", triple); + // Gentoo x86 2010.0 stable AddGnuCPlusPlusIncludePaths( "/usr/lib/gcc/i686-pc-linux-gnu/4.4.3/include/g++-v4", "i686-pc-linux-gnu", "", "", triple); @@ -762,7 +809,15 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { AddGnuCPlusPlusIncludePaths( "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4", "i686-pc-linux-gnu", "", "", triple); + // Gentoo x86 llvm-gcc trunk + AddGnuCPlusPlusIncludePaths( + "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1", + "i686-pc-linux-gnu", "", "", triple); + // Gentoo amd64 gcc 4.5.2 + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.2/include/g++-v4", + "x86_64-pc-linux-gnu", "32", "", triple); // Gentoo amd64 gcc 4.4.5 AddGnuCPlusPlusIncludePaths( "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/include/g++-v4", @@ -782,7 +837,7 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { // Gentoo amd64 stable AddGnuCPlusPlusIncludePaths( "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4", - "i686-pc-linux-gnu", "", "", triple); + "x86_64-pc-linux-gnu", "", "", triple); // Gentoo amd64 llvm-gcc trunk AddGnuCPlusPlusIncludePaths( @@ -834,7 +889,7 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang, AddDefaultCIncludePaths(triple, HSOpts); // Add the default framework include paths on Darwin. - if (triple.getOS() == llvm::Triple::Darwin) { + if (triple.isOSDarwin()) { AddPath("/System/Library/Frameworks", System, true, false, true); AddPath("/Library/Frameworks", System, true, false, true); } diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp index 91b5280a87ef..abe251d67df2 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp @@ -247,13 +247,18 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__GNUC_PATCHLEVEL__", "1"); Builder.defineMacro("__GNUC__", "4"); Builder.defineMacro("__GXX_ABI_VERSION", "1002"); - Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible Clang Compiler\""); + + // As sad as it is, enough software depends on the __VERSION__ for version + // checks that it is necessary to report 4.2.1 (the base GCC version we claim + // compatibility with) first. + Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible " + + llvm::Twine(getClangFullCPPVersion()) + "\""); // Initialize language-specific preprocessor defines. // These should all be defined in the preprocessor according to the // current language configuration. - if (!LangOpts.Microsoft) + if (!LangOpts.Microsoft && !LangOpts.TraditionalCPP) Builder.defineMacro("__STDC__"); if (LangOpts.AsmPreprocessor) Builder.defineMacro("__ASSEMBLER__"); @@ -313,8 +318,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.SjLjExceptions) Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__"); - if (LangOpts.CPlusPlus) { + if (LangOpts.Deprecated) Builder.defineMacro("__DEPRECATED"); + + if (LangOpts.CPlusPlus) { Builder.defineMacro("__GNUG__", "4"); Builder.defineMacro("__GXX_WEAK__"); if (LangOpts.GNUMode) @@ -328,12 +335,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI, } if (LangOpts.Microsoft) { - // Filter out some microsoft extensions when trying to parse in ms-compat - // mode. - Builder.defineMacro("__int8", "__INT8_TYPE__"); - Builder.defineMacro("__int16", "__INT16_TYPE__"); - Builder.defineMacro("__int32", "__INT32_TYPE__"); - Builder.defineMacro("__int64", "__INT64_TYPE__"); // Both __PRETTY_FUNCTION__ and __FUNCTION__ are GCC extensions, however // VC++ appears to only like __FUNCTION__. Builder.defineMacro("__PRETTY_FUNCTION__", "__FUNCTION__"); @@ -414,6 +415,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (!LangOpts.CharIsSigned) Builder.defineMacro("__CHAR_UNSIGNED__"); + if (!TargetInfo::isTypeSigned(TI.getWIntType())) + Builder.defineMacro("__WINT_UNSIGNED__"); + // Define exact-width integer types for stdint.h Builder.defineMacro("__INT" + llvm::Twine(TI.getCharWidth()) + "_TYPE__", "char"); @@ -531,20 +535,13 @@ static void InitializeFileRemapping(Diagnostic &Diags, continue; } - // Load the contents of the file we're mapping to. - std::string ErrorStr; - const llvm::MemoryBuffer *Buffer - = FileMgr.getBufferForFile(ToFile->getName(), &ErrorStr); - if (!Buffer) { - Diags.Report(diag::err_fe_error_opening) - << Remap->second << ErrorStr; - continue; - } - // Override the contents of the "from" file with the contents of // the "to" file. - SourceMgr.overrideFileContents(FromFile, Buffer); + SourceMgr.overrideFileContents(FromFile, ToFile); } + + SourceMgr.setOverridenFilesKeepOriginalName( + InitOpts.RemappedFilesKeepOriginalName); } /// InitializePreprocessor - Initialize the preprocessor getting it and the diff --git a/contrib/llvm/tools/clang/lib/Frontend/LogDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/LogDiagnosticPrinter.cpp new file mode 100644 index 000000000000..954bad4e7c54 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Frontend/LogDiagnosticPrinter.cpp @@ -0,0 +1,146 @@ +//===--- LogDiagnosticPrinter.cpp - Log Diagnostic Printer ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/LogDiagnosticPrinter.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; + +LogDiagnosticPrinter::LogDiagnosticPrinter(llvm::raw_ostream &os, + const DiagnosticOptions &diags, + bool _OwnsOutputStream) + : OS(os), LangOpts(0), DiagOpts(&diags), + OwnsOutputStream(_OwnsOutputStream) { +} + +LogDiagnosticPrinter::~LogDiagnosticPrinter() { + if (OwnsOutputStream) + delete &OS; +} + +static llvm::StringRef getLevelName(Diagnostic::Level Level) { + switch (Level) { + default: + return ""; + case Diagnostic::Ignored: return "ignored"; + case Diagnostic::Note: return "note"; + case Diagnostic::Warning: return "warning"; + case Diagnostic::Error: return "error"; + case Diagnostic::Fatal: return "fatal error"; + } +} + +void LogDiagnosticPrinter::EndSourceFile() { + // We emit all the diagnostics in EndSourceFile. However, we don't emit any + // entry if no diagnostics were present. + // + // Note that DiagnosticClient has no "end-of-compilation" callback, so we will + // miss any diagnostics which are emitted after and outside the translation + // unit processing. + if (Entries.empty()) + return; + + // Write to a temporary string to ensure atomic write of diagnostic object. + llvm::SmallString<512> Msg; + llvm::raw_svector_ostream OS(Msg); + + OS << "\n"; + if (!MainFilename.empty()) { + OS << " main-file\n" + << " " << MainFilename << "\n"; + } + if (!DwarfDebugFlags.empty()) { + OS << " dwarf-debug-flags\n" + << " " << DwarfDebugFlags << "\n"; + } + OS << " diagnostics\n"; + OS << " \n"; + for (unsigned i = 0, e = Entries.size(); i != e; ++i) { + DiagEntry &DE = Entries[i]; + + OS << " \n"; + OS << " level\n" + << " " << getLevelName(DE.DiagnosticLevel) << "\n"; + if (!DE.Filename.empty()) { + OS << " filename\n" + << " " << DE.Filename << "\n"; + } + if (DE.Line != 0) { + OS << " line\n" + << " " << DE.Line << "\n"; + } + if (DE.Column != 0) { + OS << " column\n" + << " " << DE.Column << "\n"; + } + if (!DE.Message.empty()) { + OS << " message\n" + << " " << DE.Message << "\n"; + } + OS << " \n"; + } + OS << " \n"; + OS << "\n"; + + this->OS << OS.str(); +} + +void LogDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, + const DiagnosticInfo &Info) { + // Default implementation (Warnings/errors count). + DiagnosticClient::HandleDiagnostic(Level, Info); + + // Initialize the main file name, if we haven't already fetched it. + if (MainFilename.empty()) { + const SourceManager &SM = Info.getSourceManager(); + FileID FID = SM.getMainFileID(); + if (!FID.isInvalid()) { + const FileEntry *FE = SM.getFileEntryForID(FID); + if (FE && FE->getName()) + MainFilename = FE->getName(); + } + } + + // Create the diag entry. + DiagEntry DE; + DE.DiagnosticID = Info.getID(); + DE.DiagnosticLevel = Level; + + // Format the message. + llvm::SmallString<100> MessageStr; + Info.FormatDiagnostic(MessageStr); + DE.Message = MessageStr.str(); + + // Set the location information. + DE.Filename = ""; + DE.Line = DE.Column = 0; + if (Info.getLocation().isValid()) { + const SourceManager &SM = Info.getSourceManager(); + PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation()); + + if (PLoc.isInvalid()) { + // At least print the file name if available: + FileID FID = SM.getFileID(Info.getLocation()); + if (!FID.isInvalid()) { + const FileEntry *FE = SM.getFileEntryForID(FID); + if (FE && FE->getName()) + DE.Filename = FE->getName(); + } + } else { + DE.Filename = PLoc.getFilename(); + DE.Line = PLoc.getLine(); + DE.Column = PLoc.getColumn(); + } + } + + // Record the diagnostic entry. + Entries.push_back(DE); +} diff --git a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp index 3649c3c99728..5aa65d7a60aa 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp @@ -95,6 +95,10 @@ class MultiplexASTMutationListener : public ASTMutationListener { virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D); virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D); + virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D); + virtual void CompletedImplicitDefinition(const FunctionDecl *D); + virtual void StaticDataMemberInstantiated(const VarDecl *D); private: std::vector Listeners; }; @@ -125,6 +129,21 @@ void MultiplexASTMutationListener::AddedCXXTemplateSpecialization( for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->AddedCXXTemplateSpecialization(TD, D); } +void MultiplexASTMutationListener::AddedCXXTemplateSpecialization( + const FunctionTemplateDecl *TD, const FunctionDecl *D) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->AddedCXXTemplateSpecialization(TD, D); +} +void MultiplexASTMutationListener::CompletedImplicitDefinition( + const FunctionDecl *D) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->CompletedImplicitDefinition(D); +} +void MultiplexASTMutationListener::StaticDataMemberInstantiated( + const VarDecl *D) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->StaticDataMemberInstantiated(D); +} } // end namespace clang diff --git a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp index 922d743adf4e..b46e04749ba3 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp @@ -432,7 +432,7 @@ struct UnknownPragmaHandler : public PragmaHandler { Callbacks->OS.write(Prefix, strlen(Prefix)); Callbacks->SetEmittedTokensOnThisLine(); // Read and print all of the pragma tokens. - while (PragmaTok.isNot(tok::eom)) { + while (PragmaTok.isNot(tok::eod)) { if (PragmaTok.hasLeadingSpace()) Callbacks->OS << ' '; std::string TokSpell = PP.getSpelling(PragmaTok); diff --git a/contrib/llvm/tools/clang/lib/Frontend/StmtXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/StmtXML.cpp deleted file mode 100644 index c113cc18dc1c..000000000000 --- a/contrib/llvm/tools/clang/lib/Frontend/StmtXML.cpp +++ /dev/null @@ -1,439 +0,0 @@ -//===--- StmtXML.cpp - XML implementation for Stmt ASTs ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the Stmt::dumpXML methods, which dump out the -// AST to an XML document. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/DocumentXML.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclCXX.h" -#include "clang/Basic/SourceManager.h" -using namespace clang; - -//===----------------------------------------------------------------------===// -// StmtXML Visitor -//===----------------------------------------------------------------------===// - -namespace { - class StmtXML : public StmtVisitor { - DocumentXML& Doc; - - //static const char *getOpcodeStr(UnaryOperator::Opcode Op); - //static const char *getOpcodeStr(BinaryOperator::Opcode Op); - - - void addSpecialAttribute(const char* pName, StringLiteral* Str) { - Doc.addAttribute(pName, Doc.escapeString(Str->getString().data(), - Str->getString().size())); - } - - void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) { - if (S->isArgumentType()) - Doc.addAttribute(pName, S->getArgumentType()); - } - - void addSpecialAttribute(const char* pName, CXXTypeidExpr* S) { - if (S->isTypeOperand()) - Doc.addAttribute(pName, S->getTypeOperand()); - } - - - public: - StmtXML(DocumentXML& doc) - : Doc(doc) { - } - - void DumpSubTree(Stmt *S) { - if (S) { - Visit(S); - if (DeclStmt* DS = dyn_cast(S)) { - for (DeclStmt::decl_iterator DI = DS->decl_begin(), - DE = DS->decl_end(); DI != DE; ++DI) { - Doc.PrintDecl(*DI); - } - } else { - for (Stmt::child_range i = S->children(); i; ++i) - DumpSubTree(*i); - } - Doc.toParent(); - } else { - Doc.addSubNode("NULL").toParent(); - } - } - - -#define NODE_XML( CLASS, NAME ) \ - void Visit##CLASS(CLASS* S) \ - { \ - typedef CLASS tStmtType; \ - Doc.addSubNode(NAME); - -#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN); -#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN); -#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S); -#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange()); - - -#define ATTRIBUTE_ENUM_XML( FN, NAME ) \ - { \ - const char* pAttributeName = NAME; \ - const bool optional = false; \ - switch (S->FN) { \ - default: assert(0 && "unknown enum value"); - -#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ - { \ - const char* pAttributeName = NAME; \ - const bool optional = true; \ - switch (S->FN) { \ - default: assert(0 && "unknown enum value"); - -#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; -#define END_ENUM_XML } } -#define END_NODE_XML } - -#define ID_ATTRIBUTE_XML Doc.addAttribute("id", S); -#define SUB_NODE_XML( CLASS ) -#define SUB_NODE_SEQUENCE_XML( CLASS ) -#define SUB_NODE_OPT_XML( CLASS ) - -#include "clang/Frontend/StmtXML.def" - -#if (0) - // Stmts. - void VisitStmt(Stmt *Node); - void VisitDeclStmt(DeclStmt *Node); - void VisitLabelStmt(LabelStmt *Node); - void VisitGotoStmt(GotoStmt *Node); - - // Exprs - void VisitExpr(Expr *Node); - void VisitDeclRefExpr(DeclRefExpr *Node); - void VisitPredefinedExpr(PredefinedExpr *Node); - void VisitCharacterLiteral(CharacterLiteral *Node); - void VisitIntegerLiteral(IntegerLiteral *Node); - void VisitFloatingLiteral(FloatingLiteral *Node); - void VisitStringLiteral(StringLiteral *Str); - void VisitUnaryOperator(UnaryOperator *Node); - void VisitOffsetOfExpr(OffsetOfExpr *Node); - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node); - void VisitMemberExpr(MemberExpr *Node); - void VisitExtVectorElementExpr(ExtVectorElementExpr *Node); - void VisitBinaryOperator(BinaryOperator *Node); - void VisitCompoundAssignOperator(CompoundAssignOperator *Node); - void VisitAddrLabelExpr(AddrLabelExpr *Node); - - // C++ - void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node); - void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node); - void VisitCXXThisExpr(CXXThisExpr *Node); - void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node); - - // ObjC - void VisitObjCEncodeExpr(ObjCEncodeExpr *Node); - void VisitObjCMessageExpr(ObjCMessageExpr* Node); - void VisitObjCSelectorExpr(ObjCSelectorExpr *Node); - void VisitObjCProtocolExpr(ObjCProtocolExpr *Node); - void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node); - void VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *Node); - void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); -#endif - }; -} - -//===----------------------------------------------------------------------===// -// Stmt printing methods. -//===----------------------------------------------------------------------===// -#if (0) -void StmtXML::VisitStmt(Stmt *Node) { - // nothing special to do -} - -void StmtXML::VisitDeclStmt(DeclStmt *Node) { - for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end(); - DI != DE; ++DI) { - Doc.PrintDecl(*DI); - } -} - -void StmtXML::VisitLabelStmt(LabelStmt *Node) { - Doc.addAttribute("name", Node->getName()); -} - -void StmtXML::VisitGotoStmt(GotoStmt *Node) { - Doc.addAttribute("name", Node->getLabel()->getName()); -} - -//===----------------------------------------------------------------------===// -// Expr printing methods. -//===----------------------------------------------------------------------===// - -void StmtXML::VisitExpr(Expr *Node) { - DumpExpr(Node); -} - -void StmtXML::VisitDeclRefExpr(DeclRefExpr *Node) { - DumpExpr(Node); - - const char* pKind; - switch (Node->getDecl()->getKind()) { - case Decl::Function: pKind = "FunctionDecl"; break; - case Decl::Var: pKind = "Var"; break; - case Decl::ParmVar: pKind = "ParmVar"; break; - case Decl::EnumConstant: pKind = "EnumConstant"; break; - case Decl::Typedef: pKind = "Typedef"; break; - case Decl::Record: pKind = "Record"; break; - case Decl::Enum: pKind = "Enum"; break; - case Decl::CXXRecord: pKind = "CXXRecord"; break; - case Decl::ObjCInterface: pKind = "ObjCInterface"; break; - case Decl::ObjCClass: pKind = "ObjCClass"; break; - default: pKind = "Decl"; break; - } - - Doc.addAttribute("kind", pKind); - Doc.addAttribute("name", Node->getDecl()->getNameAsString()); - Doc.addRefAttribute(Node->getDecl()); -} - -void StmtXML::VisitPredefinedExpr(PredefinedExpr *Node) { - DumpExpr(Node); - switch (Node->getIdentType()) { - default: assert(0 && "unknown case"); - case PredefinedExpr::Func: Doc.addAttribute("predefined", " __func__"); break; - case PredefinedExpr::Function: Doc.addAttribute("predefined", " __FUNCTION__"); break; - case PredefinedExpr::PrettyFunction: Doc.addAttribute("predefined", " __PRETTY_FUNCTION__");break; - } -} - -void StmtXML::VisitCharacterLiteral(CharacterLiteral *Node) { - DumpExpr(Node); - Doc.addAttribute("value", Node->getValue()); -} - -void StmtXML::VisitIntegerLiteral(IntegerLiteral *Node) { - DumpExpr(Node); - bool isSigned = Node->getType()->isSignedIntegerType(); - Doc.addAttribute("value", Node->getValue().toString(10, isSigned)); -} - -void StmtXML::VisitFloatingLiteral(FloatingLiteral *Node) { - DumpExpr(Node); - // FIXME: output float as written in source (no approximation or the like) - //Doc.addAttribute("value", Node->getValueAsApproximateDouble())); - Doc.addAttribute("value", "FIXME"); -} - -void StmtXML::VisitStringLiteral(StringLiteral *Str) { - DumpExpr(Str); - if (Str->isWide()) - Doc.addAttribute("is_wide", "1"); - - Doc.addAttribute("value", Doc.escapeString(Str->getStrData(), Str->getByteLength())); -} - - -const char *StmtXML::getOpcodeStr(UnaryOperator::Opcode Op) { - switch (Op) { - default: assert(0 && "Unknown unary operator"); - case UnaryOperator::PostInc: return "postinc"; - case UnaryOperator::PostDec: return "postdec"; - case UnaryOperator::PreInc: return "preinc"; - case UnaryOperator::PreDec: return "predec"; - case UnaryOperator::AddrOf: return "addrof"; - case UnaryOperator::Deref: return "deref"; - case UnaryOperator::Plus: return "plus"; - case UnaryOperator::Minus: return "minus"; - case UnaryOperator::Not: return "not"; - case UnaryOperator::LNot: return "lnot"; - case UnaryOperator::Real: return "__real"; - case UnaryOperator::Imag: return "__imag"; - case UnaryOperator::Extension: return "__extension__"; - } -} - - -const char *StmtXML::getOpcodeStr(BinaryOperator::Opcode Op) { - switch (Op) { - default: assert(0 && "Unknown binary operator"); - case BinaryOperator::PtrMemD: return "ptrmemd"; - case BinaryOperator::PtrMemI: return "ptrmemi"; - case BinaryOperator::Mul: return "mul"; - case BinaryOperator::Div: return "div"; - case BinaryOperator::Rem: return "rem"; - case BinaryOperator::Add: return "add"; - case BinaryOperator::Sub: return "sub"; - case BinaryOperator::Shl: return "shl"; - case BinaryOperator::Shr: return "shr"; - case BinaryOperator::LT: return "lt"; - case BinaryOperator::GT: return "gt"; - case BinaryOperator::LE: return "le"; - case BinaryOperator::GE: return "ge"; - case BinaryOperator::EQ: return "eq"; - case BinaryOperator::NE: return "ne"; - case BinaryOperator::And: return "and"; - case BinaryOperator::Xor: return "xor"; - case BinaryOperator::Or: return "or"; - case BinaryOperator::LAnd: return "land"; - case BinaryOperator::LOr: return "lor"; - case BinaryOperator::Assign: return "assign"; - case BinaryOperator::MulAssign: return "mulassign"; - case BinaryOperator::DivAssign: return "divassign"; - case BinaryOperator::RemAssign: return "remassign"; - case BinaryOperator::AddAssign: return "addassign"; - case BinaryOperator::SubAssign: return "subassign"; - case BinaryOperator::ShlAssign: return "shlassign"; - case BinaryOperator::ShrAssign: return "shrassign"; - case BinaryOperator::AndAssign: return "andassign"; - case BinaryOperator::XorAssign: return "xorassign"; - case BinaryOperator::OrAssign: return "orassign"; - case BinaryOperator::Comma: return "comma"; - } -} - -void StmtXML::VisitUnaryOperator(UnaryOperator *Node) { - DumpExpr(Node); - Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode())); -} - -void StmtXML::OffsetOfExpr(OffsetOfExpr *Node) { - DumpExpr(Node); -} - -void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof"); - Doc.addAttribute("is_type", Node->isArgumentType() ? "1" : "0"); - if (Node->isArgumentType()) - DumpTypeExpr(Node->getArgumentType()); -} - -void StmtXML::VisitMemberExpr(MemberExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("is_deref", Node->isArrow() ? "1" : "0"); - Doc.addAttribute("name", Node->getMemberDecl()->getNameAsString()); - Doc.addRefAttribute(Node->getMemberDecl()); -} - -void StmtXML::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("name", Node->getAccessor().getName()); -} - -void StmtXML::VisitBinaryOperator(BinaryOperator *Node) { - DumpExpr(Node); - Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode())); -} - -void StmtXML::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { - VisitBinaryOperator(Node); -/* FIXME: is this needed in the AST? - DumpExpr(Node); - CurrentNode = CurrentNode->addSubNode("ComputeLHSTy"); - DumpType(Node->getComputationLHSType()); - CurrentNode = CurrentNode->Parent->addSubNode("ComputeResultTy"); - DumpType(Node->getComputationResultType()); - Doc.toParent(); -*/ -} - -// GNU extensions. - -void StmtXML::VisitAddrLabelExpr(AddrLabelExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("name", Node->getLabel()->getName()); -} - -//===----------------------------------------------------------------------===// -// C++ Expressions -//===----------------------------------------------------------------------===// - -void StmtXML::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("kind", Node->getCastName()); - DumpTypeExpr(Node->getTypeAsWritten()); -} - -void StmtXML::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("value", Node->getValue() ? "true" : "false"); -} - -void StmtXML::VisitCXXThisExpr(CXXThisExpr *Node) { - DumpExpr(Node); -} - -void StmtXML::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { - DumpExpr(Node); - DumpTypeExpr(Node->getTypeAsWritten()); -} - -//===----------------------------------------------------------------------===// -// Obj-C Expressions -//===----------------------------------------------------------------------===// - -void StmtXML::VisitObjCMessageExpr(ObjCMessageExpr* Node) { - DumpExpr(Node); - Doc.addAttribute("selector", Node->getSelector().getAsString()); - IdentifierInfo* clsName = Node->getClassName(); - if (clsName) - Doc.addAttribute("class", clsName->getName()); -} - -void StmtXML::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { - DumpExpr(Node); - DumpTypeExpr(Node->getEncodedType()); -} - -void StmtXML::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("selector", Node->getSelector().getAsString()); -} - -void StmtXML::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("protocol", Node->getProtocol()->getNameAsString()); -} - -void StmtXML::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("property", Node->getProperty()->getNameAsString()); -} - -void StmtXML::VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *Node) { - DumpExpr(Node); - ObjCMethodDecl *Getter = Node->getGetterMethod(); - ObjCMethodDecl *Setter = Node->getSetterMethod(); - Doc.addAttribute("Getter", Getter->getSelector().getAsString()); - Doc.addAttribute("Setter", Setter ? Setter->getSelector().getAsString().c_str() : "(null)"); -} - -void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { - DumpExpr(Node); - Doc.addAttribute("kind", Node->getDecl()->getDeclKindName()); - Doc.addAttribute("decl", Node->getDecl()->getNameAsString()); - if (Node->isFreeIvar()) - Doc.addAttribute("isFreeIvar", "1"); -} -#endif -//===----------------------------------------------------------------------===// -// Stmt method implementations -//===----------------------------------------------------------------------===// - -/// dumpAll - This does a dump of the specified AST fragment and all subtrees. -void DocumentXML::PrintStmt(const Stmt *S) { - StmtXML P(*this); - P.DumpSubTree(const_cast(S)); -} - diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp index 084915311dcc..47c942ca8dfa 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp @@ -53,8 +53,11 @@ TextDiagnosticPrinter::~TextDiagnosticPrinter() { delete &OS; } -void TextDiagnosticPrinter:: -PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) { +void TextDiagnosticPrinter::PrintIncludeStack(Diagnostic::Level Level, + SourceLocation Loc, + const SourceManager &SM) { + if (!DiagOpts->ShowNoteIncludeStack && Level == Diagnostic::Note) return; + if (Loc.isInvalid()) return; PresumedLoc PLoc = SM.getPresumedLoc(Loc); @@ -62,7 +65,7 @@ PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) { return; // Print out the other include frames first. - PrintIncludeStack(PLoc.getIncludeLoc(), SM); + PrintIncludeStack(Level, PLoc.getIncludeLoc(), SM); if (DiagOpts->ShowLocation) OS << "In file included from " << PLoc.getFilename() @@ -289,7 +292,8 @@ static void SelectInterestingSourceRegion(std::string &SourceLine, } } -void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, +void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level, + SourceLocation Loc, CharSourceRange *Ranges, unsigned NumRanges, const SourceManager &SM, @@ -313,7 +317,7 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first; // FIXME: Map ranges? - EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns, + EmitCaretDiagnostic(Level, OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns, OnMacroInst + 1, MacroSkipStart, MacroSkipEnd); // Map the location. @@ -339,7 +343,7 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, // "included from" lines. if (LastWarningLoc != PLoc.getIncludeLoc()) { LastWarningLoc = PLoc.getIncludeLoc(); - PrintIncludeStack(LastWarningLoc, SM); + PrintIncludeStack(Level, LastWarningLoc, SM); } if (DiagOpts->ShowLocation) { @@ -351,8 +355,9 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, } OS << "note: instantiated from:\n"; - EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns, - OnMacroInst + 1, MacroSkipStart, MacroSkipEnd); + EmitCaretDiagnostic(Level, Loc, Ranges, NumRanges, SM, Hints, NumHints, + Columns, OnMacroInst + 1, MacroSkipStart, + MacroSkipEnd); return; } @@ -805,12 +810,12 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, // "included from" lines. if (LastWarningLoc != PLoc.getIncludeLoc()) { LastWarningLoc = PLoc.getIncludeLoc(); - PrintIncludeStack(LastWarningLoc, SM); + PrintIncludeStack(Level, LastWarningLoc, SM); StartOfLocationInfo = OS.tell(); } // Compute the column number. - if (DiagOpts->ShowLocation && PLoc.isValid()) { + if (DiagOpts->ShowLocation) { if (DiagOpts->ShowColors) OS.changeColor(savedColor, true); @@ -903,6 +908,13 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, llvm::SmallString<100> OutStr; Info.FormatDiagnostic(OutStr); + if (DiagOpts->ShowNames && + !DiagnosticIDs::isBuiltinNote(Info.getID())) { + OutStr += " ["; + OutStr += DiagnosticIDs::getName(Info.getID()); + OutStr += "]"; + } + std::string OptionName; if (DiagOpts->ShowOptionNames) { // Was this a warning mapped to an error using -Werror or pragma? @@ -1034,7 +1046,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, } } - EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(), + EmitCaretDiagnostic(Level, LastLoc, Ranges, NumRanges, LastLoc.getManager(), Info.getFixItHints(), Info.getNumFixItHints(), DiagOpts->MessageLength, diff --git a/contrib/llvm/tools/clang/lib/Frontend/TypeXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/TypeXML.cpp deleted file mode 100644 index a8c8f75d4b7f..000000000000 --- a/contrib/llvm/tools/clang/lib/Frontend/TypeXML.cpp +++ /dev/null @@ -1,119 +0,0 @@ -//===--- DocumentXML.cpp - XML document for ASTs --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the XML document class, which provides the means to -// dump out the AST in a XML form that exposes type details and other fields. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/DocumentXML.h" -#include "clang/AST/TypeVisitor.h" -#include "clang/AST/Type.h" -#include "clang/AST/Decl.h" - -namespace clang { - namespace XML { - namespace { - -//--------------------------------------------------------- -class TypeWriter : public TypeVisitor { - DocumentXML& Doc; - -public: - TypeWriter(DocumentXML& doc) : Doc(doc) {} - -#define NODE_XML( CLASS, NAME ) \ - void Visit##CLASS(const CLASS* T) { \ - Doc.addSubNode(NAME); - -#define ID_ATTRIBUTE_XML // done by the Document class itself -#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); -#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); - -#define ATTRIBUTE_ENUM_XML( FN, NAME ) \ - { \ - const char* pAttributeName = NAME; \ - const bool optional = false; \ - switch (T->FN) { \ - default: assert(0 && "unknown enum value"); - -#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ - { \ - const char* pAttributeName = NAME; \ - const bool optional = true; \ - switch (T->FN) { \ - default: assert(0 && "unknown enum value"); - -#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; -#define END_ENUM_XML } } -#define END_NODE_XML } - -#include "clang/Frontend/TypeXML.def" - -}; - -//--------------------------------------------------------- - } // anon clang - } // NS XML - -//--------------------------------------------------------- -class DocumentXML::TypeAdder : public TypeVisitor { - DocumentXML& Doc; - - void addIfType(const Type* pType) { - Doc.addTypeRecursively(pType); - } - - void addIfType(const QualType& pType) { - Doc.addTypeRecursively(pType); - } - - template void addIfType(T) {} - -public: - TypeAdder(DocumentXML& doc) : Doc(doc) {} - -#define NODE_XML( CLASS, NAME ) \ - void Visit##CLASS(const CLASS* T) \ - { - -#define ID_ATTRIBUTE_XML -#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN); -#define CONTEXT_ATTRIBUTE_XML( FN ) -#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN); -#define ATTRIBUTE_OPT_XML( FN, NAME ) -#define ATTRIBUTE_ENUM_XML( FN, NAME ) -#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) -#define ENUM_XML( VALUE, NAME ) -#define END_ENUM_XML -#define END_NODE_XML } - -#include "clang/Frontend/TypeXML.def" -}; - -//--------------------------------------------------------- -void DocumentXML::addParentTypes(const Type* pType) { - TypeAdder(*this).Visit(pType); -} - -//--------------------------------------------------------- -void DocumentXML::writeTypeToXML(const Type* pType) { - XML::TypeWriter(*this).Visit(const_cast(pType)); -} - -//--------------------------------------------------------- -void DocumentXML::writeTypeToXML(const QualType& pType) { - XML::TypeWriter(*this).VisitQualType(const_cast(&pType)); -} - -//--------------------------------------------------------- -} // NS clang - diff --git a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 65fad6da51fa..664b53351dc1 100644 --- a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -37,7 +37,6 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) { case ASTDump: return new ASTDumpAction(); case ASTDumpXML: return new ASTDumpXMLAction(); case ASTPrint: return new ASTPrintAction(); - case ASTPrintXML: return new ASTPrintXMLAction(); case ASTView: return new ASTViewAction(); case BoostCon: return new BoostConAction(); case CreateModule: return 0; diff --git a/contrib/llvm/tools/clang/lib/Headers/avxintrin.h b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h index 884d31cb8917..2eb2f8562256 100644 --- a/contrib/llvm/tools/clang/lib/Headers/avxintrin.h +++ b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h @@ -385,41 +385,23 @@ _mm256_dp_ps(__m256 a, __m256 b, const int c) #define _CMP_GT_OQ 0x1e /* Greater-than (ordered, non-signaling) */ #define _CMP_TRUE_US 0x1f /* True (unordered, signaling) */ -static __inline __m128d __attribute__((__always_inline__, __nodebug__)) -_mm_cmp_pd(__m128d a, __m128d b, const int c) -{ - return (__m128d)__builtin_ia32_cmppd((__v2df)a, (__v2df)b, c); -} +#define _mm_cmp_pd(a, b, c) \ + (__m128d)__builtin_ia32_cmppd((__v2df)(a), (__v2df)(b), (c)) -static __inline __m128 __attribute__((__always_inline__, __nodebug__)) -_mm_cmp_ps(__m128 a, __m128 b, const int c) -{ - return (__m128)__builtin_ia32_cmpps((__v4sf)a, (__v4sf)b, c); -} +#define _mm_cmp_ps(a, b, c) \ + (__m128)__builtin_ia32_cmpps((__v4sf)(a), (__v4sf)(b), (c)) -static __inline __m256d __attribute__((__always_inline__, __nodebug__)) -_mm256_cmp_pd(__m256d a, __m256d b, const int c) -{ - return (__m256d)__builtin_ia32_cmppd256((__v4df)a, (__v4df)b, c); -} +#define _mm256_cmp_pd(a, b, c) \ + (__m256d)__builtin_ia32_cmppd256((__v4df)(a), (__v4df)(b), (c)) -static __inline __m256 __attribute__((__always_inline__, __nodebug__)) -_mm256_cmp_ps(__m256 a, __m256 b, const int c) -{ - return (__m256)__builtin_ia32_cmpps256((__v8sf)a, (__v8sf)b, c); -} +#define _mm256_cmp_ps(a, b, c) \ + (__m256)__builtin_ia32_cmpps256((__v8sf)(a), (__v8sf)(b), (c)) -static __inline __m128d __attribute__((__always_inline__, __nodebug__)) -_mm_cmp_sd(__m128d a, __m128d b, const int c) -{ - return (__m128d)__builtin_ia32_cmpsd((__v2df)a, (__v2df)b, c); -} +#define _mm_cmp_sd(a, b, c) \ + (__m128d)__builtin_ia32_cmpsd((__v2df)(a), (__v2df)(b), (c)) -static __inline __m128 __attribute__((__always_inline__, __nodebug__)) -_mm_cmp_ss(__m128 a, __m128 b, const int c) -{ - return (__m128)__builtin_ia32_cmpss((__v4sf)a, (__v4sf)b, c); -} +#define _mm_cmp_ss(a, b, c) \ + (__m128)__builtin_ia32_cmpss((__v4sf)(a), (__v4sf)(b), (c)) /* Vector extract */ static __inline __m128d __attribute__((__always_inline__, __nodebug__)) diff --git a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h index 11b258178103..0c1d730f015d 100644 --- a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h +++ b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h @@ -466,7 +466,7 @@ _mm_loadr_pd(double const *dp) static __inline__ __m128d __attribute__((__always_inline__, __nodebug__)) _mm_loadu_pd(double const *dp) { - return __builtin_ia32_loadupd(dp); + return (__m128d){ dp[0], dp[1] }; } static __inline__ __m128d __attribute__((__always_inline__, __nodebug__)) @@ -1210,16 +1210,18 @@ _mm_movemask_epi8(__m128i a) } #define _mm_shuffle_epi32(a, imm) \ - ((__m128i)__builtin_shufflevector((__v4si)(a), (__v4si) {0}, \ + ((__m128i)__builtin_shufflevector((__v4si)(a), (__v4si) _mm_set1_epi32(0), \ (imm) & 0x3, ((imm) & 0xc) >> 2, \ ((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6)) + + #define _mm_shufflelo_epi16(a, imm) \ - ((__m128i)__builtin_shufflevector((__v8hi)(a), (__v8hi) {0}, \ + ((__m128i)__builtin_shufflevector((__v8hi)(a), (__v8hi) _mm_set1_epi16(0), \ (imm) & 0x3, ((imm) & 0xc) >> 2, \ ((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6, \ 4, 5, 6, 7)) #define _mm_shufflehi_epi16(a, imm) \ - ((__m128i)__builtin_shufflevector((__v8hi)(a), (__v8hi) {0}, 0, 1, 2, 3, \ + ((__m128i)__builtin_shufflevector((__v8hi)(a), (__v8hi) _mm_set1_epi16(0), 0, 1, 2, 3, \ 4 + (((imm) & 0x03) >> 0), \ 4 + (((imm) & 0x0c) >> 2), \ 4 + (((imm) & 0x30) >> 4), \ diff --git a/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h b/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h new file mode 100644 index 000000000000..2f456ad940eb --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h @@ -0,0 +1,161 @@ +/*===---- mm3dnow.h - 3DNow! intrinsics ------------------------------------=== + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef _MM3DNOW_H_INCLUDED +#define _MM3DNOW_H_INCLUDED + +#include + +typedef float __v2sf __attribute__((__vector_size__(8))); + +static __inline__ void __attribute__((__always_inline__, __nodebug__)) +_m_femms() { + __builtin_ia32_femms(); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pavgusb(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pavgusb((__v8qi)__m1, (__v8qi)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pf2id(__m64 __m) { + return (__m64)__builtin_ia32_pf2id((__v2sf)__m); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfacc(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfacc((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfadd(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfadd((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfcmpeq(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfcmpeq((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfcmpge(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfcmpge((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfcmpgt(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfcmpgt((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfmax(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfmax((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfmin(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfmin((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfmul(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfmul((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfrcp(__m64 __m) { + return (__m64)__builtin_ia32_pfrcp((__v2sf)__m); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfrcpit1(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfrcpit1((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfrcpit2(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfrcpit2((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfrsqrt(__m64 __m) { + return (__m64)__builtin_ia32_pfrsqrt((__v2sf)__m); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfrsqrtit1(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfrsqrtit1((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfsub(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfsub((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfsubr(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfsubr((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pi2fd(__m64 __m) { + return (__m64)__builtin_ia32_pi2fd((__v2si)__m); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pmulhrw(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pmulhrw((__v4hi)__m1, (__v4hi)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pf2iw(__m64 __m) { + return (__m64)__builtin_ia32_pf2iw((__v2sf)__m); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfnacc(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfnacc((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pfpnacc(__m64 __m1, __m64 __m2) { + return (__m64)__builtin_ia32_pfpnacc((__v2sf)__m1, (__v2sf)__m2); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pi2fw(__m64 __m) { + return (__m64)__builtin_ia32_pi2fw((__v2si)__m); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pswapdsf(__m64 __m) { + return (__m64)__builtin_ia32_pswapdsf((__v2sf)__m); +} + +static __inline__ __m64 __attribute__((__always_inline__, __nodebug__)) +_m_pswapdsi(__m64 __m) { + return (__m64)__builtin_ia32_pswapdsi((__v2si)__m); +} + +#endif diff --git a/contrib/llvm/tools/clang/lib/Headers/mm_malloc.h b/contrib/llvm/tools/clang/lib/Headers/mm_malloc.h index e7da5434587a..ec9236204bb9 100644 --- a/contrib/llvm/tools/clang/lib/Headers/mm_malloc.h +++ b/contrib/llvm/tools/clang/lib/Headers/mm_malloc.h @@ -40,6 +40,7 @@ extern "C" int posix_memalign(void **memptr, size_t alignment, size_t size); #endif #endif +#if !(defined(_WIN32) && defined(_mm_malloc)) static __inline__ void *__attribute__((__always_inline__, __nodebug__, __malloc__)) _mm_malloc(size_t size, size_t align) @@ -67,5 +68,6 @@ _mm_free(void *p) { free(p); } +#endif #endif /* __MM_MALLOC_H */ diff --git a/contrib/llvm/tools/clang/lib/Headers/stddef.h b/contrib/llvm/tools/clang/lib/Headers/stddef.h index 7cc0bc1a75fd..9e87ee89b3b9 100644 --- a/contrib/llvm/tools/clang/lib/Headers/stddef.h +++ b/contrib/llvm/tools/clang/lib/Headers/stddef.h @@ -26,7 +26,10 @@ #ifndef __STDDEF_H #define __STDDEF_H +#ifndef _PTRDIFF_T +#define _PTRDIFF_T typedef __typeof__(((int*)0)-((int*)0)) ptrdiff_t; +#endif #ifndef _SIZE_T #define _SIZE_T typedef __typeof__(sizeof(int)) size_t; @@ -51,7 +54,7 @@ typedef __WCHAR_TYPE__ wchar_t; #endif /* __STDDEF_H */ /* Some C libraries expect to see a wint_t here. Others (notably MinGW) will use -__WINT_TYPE__ directly; accomodate both by requiring __need_wint_t */ +__WINT_TYPE__ directly; accommodate both by requiring __need_wint_t */ #if defined(__need_wint_t) #if !defined(_WINT_T) #define _WINT_T diff --git a/contrib/llvm/tools/clang/lib/Headers/stdint.h b/contrib/llvm/tools/clang/lib/Headers/stdint.h index 9498ed5f52d9..6f1a8761e1c8 100644 --- a/contrib/llvm/tools/clang/lib/Headers/stdint.h +++ b/contrib/llvm/tools/clang/lib/Headers/stdint.h @@ -46,7 +46,7 @@ * and 64-bit widths regardless of whether there are corresponding exact-width * types. * - * To accomodate targets that are missing types that are exactly 8, 16, 32, or + * To accommodate targets that are missing types that are exactly 8, 16, 32, or * 64 bits wide, this implementation takes an approach of cascading * redefintions, redefining __int_leastN_t to successively smaller exact-width * types. It is therefore important that the types are defined in order of @@ -58,7 +58,7 @@ * * In violation of the standard, some targets do not implement a type that is * wide enough to represent all of the required widths (8-, 16-, 32-, 64-bit). - * To accomodate these targets, a required minimum-width type is only + * To accommodate these targets, a required minimum-width type is only * defined if there exists an exact-width type of equal or greater width. */ @@ -609,11 +609,15 @@ typedef __UINTMAX_TYPE__ uintmax_t; # define UINT_FAST8_MAX __UINT_LEAST8_MAX #endif /* __INT_LEAST8_MIN */ +/* Some utility macros */ +#define __INTN_MIN(n) __stdint_join3( INT, n, _MIN) +#define __INTN_MAX(n) __stdint_join3( INT, n, _MAX) +#define __UINTN_MAX(n) __stdint_join3(UINT, n, _MAX) +#define __INTN_C(n, v) __stdint_join3( INT, n, _C(v)) +#define __UINTN_C(n, v) __stdint_join3(UINT, n, _C(v)) + /* C99 7.18.2.4 Limits of integer types capable of holding object pointers. */ /* C99 7.18.3 Limits of other integer types. */ -#define __INTN_MIN(n) __stdint_join3( INT, n, _MIN) -#define __INTN_MAX(n) __stdint_join3( INT, n, _MAX) -#define __UINTN_MAX(n) __stdint_join3(UINT, n, _MAX) #define INTPTR_MIN __INTN_MIN(__INTPTR_WIDTH__) #define INTPTR_MAX __INTN_MAX(__INTPTR_WIDTH__) @@ -630,23 +634,26 @@ typedef __UINTMAX_TYPE__ uintmax_t; /* C99 7.18.3 Limits of other integer types. */ #define SIG_ATOMIC_MIN __INTN_MIN(__SIG_ATOMIC_WIDTH__) #define SIG_ATOMIC_MAX __INTN_MAX(__SIG_ATOMIC_WIDTH__) -#define WINT_MIN __INTN_MIN(__WINT_WIDTH__) -#define WINT_MAX __INTN_MAX(__WINT_WIDTH__) +#ifdef __WINT_UNSIGNED__ +# define WINT_MIN __UINTN_C(__WINT_WIDTH__, 0) +# define WINT_MAX __UINTN_MAX(__WINT_WIDTH__) +#else +# define WINT_MIN __INTN_MIN(__WINT_WIDTH__) +# define WINT_MAX __INTN_MAX(__WINT_WIDTH__) +#endif -/* FIXME: if we ever support a target with unsigned wchar_t, this should be - * 0 .. Max. - */ #ifndef WCHAR_MAX -#define WCHAR_MAX __INTN_MAX(__WCHAR_WIDTH__) +# define WCHAR_MAX __WCHAR_MAX__ #endif #ifndef WCHAR_MIN -#define WCHAR_MIN __INTN_MIN(__WCHAR_WIDTH__) +# if __WCHAR_MAX__ == __INTN_MAX(__WCHAR_WIDTH__) +# define WCHAR_MIN __INTN_MIN(__WCHAR_WIDTH__) +# else +# define WCHAR_MIN __UINTN_C(__WCHAR_WIDTH__, 0) +# endif #endif /* 7.18.4.2 Macros for greatest-width integer constants. */ -#define __INTN_C(n, v) __stdint_join3( INT, n, _C(v)) -#define __UINTN_C(n, v) __stdint_join3(UINT, n, _C(v)) - #define INTMAX_C(v) __INTN_C(__INTMAX_WIDTH__, v) #define UINTMAX_C(v) __UINTN_C(__INTMAX_WIDTH__, v) diff --git a/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h index 42dd3e8d3b87..00760ed6d1ef 100644 --- a/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h +++ b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h @@ -539,7 +539,7 @@ _mm_load_ps(const float *p) static __inline__ __m128 __attribute__((__always_inline__, __nodebug__)) _mm_loadu_ps(const float *p) { - return __builtin_ia32_loadups(p); + return (__m128){ p[0], p[1], p[2], p[3] }; } static __inline__ __m128 __attribute__((__always_inline__, __nodebug__)) diff --git a/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp b/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp index d6e30ab39658..3fd4336230e2 100644 --- a/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp +++ b/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp @@ -55,7 +55,7 @@ void RefMapper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { } void RefMapper::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - NamedDecl *ND = TL.getTypedefDecl(); + NamedDecl *ND = TL.getTypedefNameDecl(); Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc()))); } diff --git a/contrib/llvm/tools/clang/lib/Index/Entity.cpp b/contrib/llvm/tools/clang/lib/Index/Entity.cpp index 749dcc899322..afac05c41377 100644 --- a/contrib/llvm/tools/clang/lib/Index/Entity.cpp +++ b/contrib/llvm/tools/clang/lib/Index/Entity.cpp @@ -141,7 +141,7 @@ Entity EntityGetter::VisitVarDecl(VarDecl *D) { } Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) { - // If it's static it cannot be refered to by another translation unit. + // If it's static it cannot be referred to by another translation unit. if (D->getStorageClass() == SC_Static) return Entity(D); diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp index e424f9165515..e102a6da608c 100644 --- a/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp @@ -199,8 +199,8 @@ void HeaderMap::dump() const { /// LookupFile - Check to see if the specified relative filename is located in /// this HeaderMap. If so, open it and return its FileEntry. -const FileEntry *HeaderMap::LookupFile(llvm::StringRef Filename, - FileManager &FM) const { +const FileEntry *HeaderMap::LookupFile( + llvm::StringRef Filename, FileManager &FM) const { const HMapHeader &Hdr = getHeader(); unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets); diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp index b028e339ae91..372078c60d20 100644 --- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp @@ -114,8 +114,11 @@ const char *DirectoryLookup::getName() const { /// LookupFile - Lookup the specified file in this search path, returning it /// if it exists or returning null if not. -const FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename, - HeaderSearch &HS) const { +const FileEntry *DirectoryLookup::LookupFile( + llvm::StringRef Filename, + HeaderSearch &HS, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) const { llvm::SmallString<1024> TmpDir; if (isNormalDir()) { // Concatenate the requested file onto the directory. @@ -123,21 +126,46 @@ const FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename, TmpDir += getDir()->getName(); TmpDir.push_back('/'); TmpDir.append(Filename.begin(), Filename.end()); - return HS.getFileMgr().getFile(TmpDir.str()); + if (SearchPath != NULL) { + llvm::StringRef SearchPathRef(getDir()->getName()); + SearchPath->clear(); + SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); + } + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin(), Filename.end()); + } + return HS.getFileMgr().getFile(TmpDir.str(), /*openFile=*/true); } if (isFramework()) - return DoFrameworkLookup(Filename, HS); + return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath); assert(isHeaderMap() && "Unknown directory lookup"); - return getHeaderMap()->LookupFile(Filename, HS.getFileMgr()); + const FileEntry * const Result = getHeaderMap()->LookupFile( + Filename, HS.getFileMgr()); + if (Result) { + if (SearchPath != NULL) { + llvm::StringRef SearchPathRef(getName()); + SearchPath->clear(); + SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); + } + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin(), Filename.end()); + } + } + return Result; } /// DoFrameworkLookup - Do a lookup of the specified file in the current /// DirectoryLookup, which is a framework directory. -const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename, - HeaderSearch &HS) const { +const FileEntry *DirectoryLookup::DoFrameworkLookup( + llvm::StringRef Filename, + HeaderSearch &HS, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) const { FileManager &FileMgr = HS.getFileMgr(); // Framework names must have a '/' in the filename. @@ -183,19 +211,37 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename, FrameworkDirCache = getFrameworkDir(); } + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); + } + // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" unsigned OrigSize = FrameworkName.size(); FrameworkName += "Headers/"; + + if (SearchPath != NULL) { + SearchPath->clear(); + // Without trailing '/'. + SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); + } + FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); - if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str())) + if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), + /*openFile=*/true)) { return FE; + } // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" const char *Private = "Private"; FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, Private+strlen(Private)); - return FileMgr.getFile(FrameworkName.str()); + if (SearchPath != NULL) + SearchPath->insert(SearchPath->begin()+OrigSize, Private, + Private+strlen(Private)); + + return FileMgr.getFile(FrameworkName.str(), /*openFile=*/true); } @@ -209,11 +255,14 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename, /// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if /// non-null, indicates where the #including file is, in case a relative search /// is needed. -const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename, - bool isAngled, - const DirectoryLookup *FromDir, - const DirectoryLookup *&CurDir, - const FileEntry *CurFileEnt) { +const FileEntry *HeaderSearch::LookupFile( + llvm::StringRef Filename, + bool isAngled, + const DirectoryLookup *FromDir, + const DirectoryLookup *&CurDir, + const FileEntry *CurFileEnt, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) { // If 'Filename' is absolute, check to see if it exists and no searching. if (llvm::sys::path::is_absolute(Filename)) { CurDir = 0; @@ -221,8 +270,14 @@ const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename, // If this was an #include_next "/absolute/file", fail. if (FromDir) return 0; + if (SearchPath != NULL) + SearchPath->clear(); + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin(), Filename.end()); + } // Otherwise, just return the file. - return FileMgr.getFile(Filename); + return FileMgr.getFile(Filename, /*openFile=*/true); } // Step #0, unless disabled, check to see if the file is in the #includer's @@ -237,7 +292,7 @@ const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename, TmpDir += CurFileEnt->getDir()->getName(); TmpDir.push_back('/'); TmpDir.append(Filename.begin(), Filename.end()); - if (const FileEntry *FE = FileMgr.getFile(TmpDir.str())) { + if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(),/*openFile=*/true)) { // Leave CurDir unset. // This file is a system header or C++ unfriendly if the old file is. // @@ -246,6 +301,15 @@ const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename, // of evaluation. unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo; getFileInfo(FE).DirInfo = DirInfo; + if (SearchPath != NULL) { + llvm::StringRef SearchPathRef(CurFileEnt->getDir()->getName()); + SearchPath->clear(); + SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); + } + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin(), Filename.end()); + } return FE; } } @@ -283,7 +347,7 @@ const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename, // Check each directory in sequence to see if it contains this file. for (; i != SearchDirs.size(); ++i) { const FileEntry *FE = - SearchDirs[i].LookupFile(Filename, *this); + SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath); if (!FE) continue; CurDir = &SearchDirs[i]; @@ -308,7 +372,9 @@ const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename, /// for the designated file, otherwise return null. const FileEntry *HeaderSearch:: LookupSubframeworkHeader(llvm::StringRef Filename, - const FileEntry *ContextFileEnt) { + const FileEntry *ContextFileEnt, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) { assert(ContextFileEnt && "No context file?"); // Framework names must have a '/' in the filename. Find it. @@ -356,17 +422,34 @@ LookupSubframeworkHeader(llvm::StringRef Filename, const FileEntry *FE = 0; + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); + } + // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" llvm::SmallString<1024> HeadersFilename(FrameworkName); HeadersFilename += "Headers/"; + if (SearchPath != NULL) { + SearchPath->clear(); + // Without trailing '/'. + SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); + } + HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - if (!(FE = FileMgr.getFile(HeadersFilename.str()))) { + if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) { // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" HeadersFilename = FrameworkName; HeadersFilename += "PrivateHeaders/"; + if (SearchPath != NULL) { + SearchPath->clear(); + // Without trailing '/'. + SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); + } + HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - if (!(FE = FileMgr.getFile(HeadersFilename.str()))) + if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) return 0; } diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp index b17198b21983..16cc4f8fd54f 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp @@ -71,9 +71,22 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr, "We assume that the input buffer has a null character at the end" " to simplify lexing!"); + // Check whether we have a BOM in the beginning of the buffer. If yes - act + // accordingly. Right now we support only UTF-8 with and without BOM, so, just + // skip the UTF-8 BOM if it's present. + if (BufferStart == BufferPtr) { + // Determine the size of the BOM. + size_t BOMLength = llvm::StringSwitch(BufferStart) + .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM + .Default(0); + + // Skip the BOM. + BufferPtr += BOMLength; + } + Is_PragmaLexer = false; IsInConflictMarker = false; - + // Start of the file is a start of line. IsAtStartOfLine = true; @@ -178,7 +191,7 @@ Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc, InstantiationLocEnd, TokLen); // Ensure that the lexer thinks it is inside a directive, so that end \n will - // return an EOM token. + // return an EOD token. L->ParsingPreprocessorDirective = true; // This lexer really is for _Pragma. @@ -216,6 +229,54 @@ void Lexer::Stringify(llvm::SmallVectorImpl &Str) { // Token Spelling //===----------------------------------------------------------------------===// +/// getSpelling() - Return the 'spelling' of this token. The spelling of a +/// token are the characters used to represent the token in the source file +/// after trigraph expansion and escaped-newline folding. In particular, this +/// wants to get the true, uncanonicalized, spelling of things like digraphs +/// UCNs, etc. +llvm::StringRef Lexer::getSpelling(SourceLocation loc, + llvm::SmallVectorImpl &buffer, + const SourceManager &SM, + const LangOptions &options, + bool *invalid) { + // Break down the source location. + std::pair locInfo = SM.getDecomposedLoc(loc); + + // Try to the load the file buffer. + bool invalidTemp = false; + llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); + if (invalidTemp) { + if (invalid) *invalid = true; + return llvm::StringRef(); + } + + const char *tokenBegin = file.data() + locInfo.second; + + // Lex from the start of the given location. + Lexer lexer(SM.getLocForStartOfFile(locInfo.first), options, + file.begin(), tokenBegin, file.end()); + Token token; + lexer.LexFromRawLexer(token); + + unsigned length = token.getLength(); + + // Common case: no need for cleaning. + if (!token.needsCleaning()) + return llvm::StringRef(tokenBegin, length); + + // Hard case, we need to relex the characters into the string. + buffer.clear(); + buffer.reserve(length); + + for (const char *ti = tokenBegin, *te = ti + length; ti != te; ) { + unsigned charSize; + buffer.push_back(Lexer::getCharAndSizeNoWarn(ti, charSize, options)); + ti += charSize; + } + + return llvm::StringRef(buffer.data(), buffer.size()); +} + /// getSpelling() - Return the 'spelling' of this token. The spelling of a /// token are the characters used to represent the token in the source file /// after trigraph expansion and escaped-newline folding. In particular, this @@ -626,7 +687,7 @@ SourceLocation Lexer::getLocForEndOfToken(SourceLocation Loc, unsigned Offset, else return Loc; - return AdvanceToTokenCharacter(Loc, Len, SM, Features); + return Loc.getFileLocWithOffset(Len); } //===----------------------------------------------------------------------===// @@ -1407,7 +1468,7 @@ bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) { return SaveBCPLComment(Result, CurPtr); // If we are inside a preprocessor directive and we see the end of line, - // return immediately, so that the lexer can return this as an EOM token. + // return immediately, so that the lexer can return this as an EOD token. if (ParsingPreprocessorDirective || CurPtr == BufferEnd) { BufferPtr = CurPtr; return false; @@ -1534,7 +1595,7 @@ static bool isEndOfBlockCommentWithEscapedNewLine(const char *CurPtr, /// some tokens, this will store the first token and return true. bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr) { // Scan one character past where we should, looking for a '/' character. Once - // we find it, check to see if it was preceeded by a *. This common + // we find it, check to see if it was preceded by a *. This common // optimization helps people who like to put a lot of * characters in their // comments. @@ -1715,14 +1776,14 @@ std::string Lexer::ReadToEndOfLine() { assert(CurPtr[-1] == Char && "Trigraphs for newline?"); BufferPtr = CurPtr-1; - // Next, lex the character, which should handle the EOM transition. + // Next, lex the character, which should handle the EOD transition. Lex(Tmp); if (Tmp.is(tok::code_completion)) { if (PP && PP->getCodeCompletionHandler()) PP->getCodeCompletionHandler()->CodeCompleteNaturalLanguage(); Lex(Tmp); } - assert(Tmp.is(tok::eom) && "Unexpected token!"); + assert(Tmp.is(tok::eod) && "Unexpected token!"); // Finally, we're done, return the string we found. return Result; @@ -1758,7 +1819,7 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) { // Done parsing the "line". ParsingPreprocessorDirective = false; // Update the location of token as well as BufferPtr. - FormTokenWithChars(Result, CurPtr, tok::eom); + FormTokenWithChars(Result, CurPtr, tok::eod); // Restore comment saving mode, in case it was disabled for directive. SetCommentRetentionState(PP->getCommentRetentionState()); @@ -2006,7 +2067,7 @@ void Lexer::LexTokenInternal(Token &Result) { case '\n': case '\r': // If we are inside a preprocessor directive and we see the end of line, - // we know we are done with the directive, so return an EOM token. + // we know we are done with the directive, so return an EOD token. if (ParsingPreprocessorDirective) { // Done parsing the "line". ParsingPreprocessorDirective = false; @@ -2017,7 +2078,7 @@ void Lexer::LexTokenInternal(Token &Result) { // Since we consumed a newline, we are back at the start of a line. IsAtStartOfLine = true; - Kind = tok::eom; + Kind = tok::eod; break; } // The returned token is at the start of the line. @@ -2043,7 +2104,7 @@ void Lexer::LexTokenInternal(Token &Result) { // If the next token is obviously a // or /* */ comment, skip it efficiently // too (without going through the big switch stmt). if (CurPtr[0] == '/' && CurPtr[1] == '/' && !inKeepCommentMode() && - Features.BCPLComment) { + Features.BCPLComment && !Features.TraditionalCPP) { if (SkipBCPLComment(Result, CurPtr+2)) return; // There is a token to return. goto SkipIgnoredUnits; @@ -2232,8 +2293,10 @@ void Lexer::LexTokenInternal(Token &Result) { // this as "foo / bar" and langauges with BCPL comments would lex it as // "foo". Check to see if the character after the second slash is a '*'. // If so, we will lex that as a "/" instead of the start of a comment. - if (Features.BCPLComment || - getCharAndSize(CurPtr+SizeTmp, SizeTmp2) != '*') { + // However, we never do this in -traditional-cpp mode. + if ((Features.BCPLComment || + getCharAndSize(CurPtr+SizeTmp, SizeTmp2) != '*') && + !Features.TraditionalCPP) { if (SkipBCPLComment(Result, ConsumeChar(CurPtr, SizeTmp, Result))) return; // There is a token to return. @@ -2335,6 +2398,21 @@ void Lexer::LexTokenInternal(Token &Result) { CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::lessequal; } else if (Features.Digraphs && Char == ':') { // '<:' -> '[' + if (Features.CPlusPlus0x && + getCharAndSize(CurPtr + SizeTmp, SizeTmp2) == ':') { + // C++0x [lex.pptoken]p3: + // Otherwise, if the next three characters are <:: and the subsequent + // character is neither : nor >, the < is treated as a preprocessor + // token by itself and not as the first character of the alternative + // token <:. + unsigned SizeTmp3; + char After = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3); + if (After != ':' && After != '>') { + Kind = tok::less; + break; + } + } + CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::l_square; } else if (Features.Digraphs && Char == '%') { // '<%' -> '{' diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp index 16d7b36f02ef..37e7bf4d628e 100644 --- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp @@ -710,7 +710,7 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, ++begin; // FIXME: The "Value" is an uint64_t so we can handle char literals of - // upto 64-bits. + // up to 64-bits. // FIXME: This extensively assumes that 'char' is 8-bits. assert(PP.getTargetInfo().getCharWidth() == 8 && "Assumes char is 8 bits"); diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp index 89f6368a277f..dee7da38aaa0 100644 --- a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp @@ -284,7 +284,7 @@ const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo, assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!"); if (StringifiedArgs.empty()) { StringifiedArgs.resize(getNumArguments()); - memset(&StringifiedArgs[0], 0, + memset((void*)&StringifiedArgs[0], 0, sizeof(StringifiedArgs[0])*getNumArguments()); } if (StringifiedArgs[ArgNo].isNot(tok::string_literal)) diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp index 3e871ae7ab47..af3fa6e2add7 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp @@ -81,17 +81,17 @@ void Preprocessor::ReleaseMacroInfo(MacroInfo *MI) { } /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the -/// current line until the tok::eom token is found. +/// current line until the tok::eod token is found. void Preprocessor::DiscardUntilEndOfDirective() { Token Tmp; do { LexUnexpandedToken(Tmp); assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens"); - } while (Tmp.isNot(tok::eom)); + } while (Tmp.isNot(tok::eod)); } /// ReadMacroName - Lex and validate a macro name, which occurs after a -/// #define or #undef. This sets the token kind to eom and discards the rest +/// #define or #undef. This sets the token kind to eod and discards the rest /// of the macro line if the macro name is invalid. isDefineUndef is 1 if /// this is due to a a #define, 2 if #undef directive, 0 if it is something /// else (e.g. #ifdef). @@ -107,7 +107,7 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, char isDefineUndef) { } // Missing macro name? - if (MacroNameTok.is(tok::eom)) { + if (MacroNameTok.is(tok::eod)) { Diag(MacroNameTok, diag::err_pp_missing_macro_name); return; } @@ -143,13 +143,13 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, char isDefineUndef) { } // Invalid macro name, read and discard the rest of the line. Then set the - // token kind to tok::eom. - MacroNameTok.setKind(tok::eom); + // token kind to tok::eod. + MacroNameTok.setKind(tok::eod); return DiscardUntilEndOfDirective(); } -/// CheckEndOfDirective - Ensure that the next token is a tok::eom token. If -/// not, emit a diagnostic and consume up until the eom. If EnableMacros is +/// CheckEndOfDirective - Ensure that the next token is a tok::eod token. If +/// not, emit a diagnostic and consume up until the eod. If EnableMacros is /// true, then we consider macros that expand to zero tokens as being ok. void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) { Token Tmp; @@ -166,7 +166,7 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) { while (Tmp.is(tok::comment)) // Skip comments in -C mode. LexUnexpandedToken(Tmp); - if (Tmp.isNot(tok::eom)) { + if (Tmp.isNot(tok::eod)) { // Add a fixit in GNU/C99/C++ mode. Don't offer a fixit for strict-C89, // or if this is a macro-style preprocessing directive, because it is more // trouble than it is worth to insert /**/ and check that there is no /**/ @@ -238,7 +238,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, // We just parsed a # character at the start of a line, so we're in // directive mode. Tell the lexer this so any newlines we see will be - // converted into an EOM token (this terminates the macro). + // converted into an EOD token (this terminates the macro). CurPPLexer->ParsingPreprocessorDirective = true; if (CurLexer) CurLexer->SetCommentRetentionState(false); @@ -425,7 +425,7 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() { if (!CondInfo.FoundNonSkip) { CondInfo.FoundNonSkip = true; - // Scan until the eom token. + // Scan until the eod token. CurPTHLexer->ParsingPreprocessorDirective = true; DiscardUntilEndOfDirective(); CurPTHLexer->ParsingPreprocessorDirective = false; @@ -469,10 +469,13 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() { /// LookupFile - Given a "foo" or reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system #include's or not (i.e. using <> instead of ""). -const FileEntry *Preprocessor::LookupFile(llvm::StringRef Filename, - bool isAngled, - const DirectoryLookup *FromDir, - const DirectoryLookup *&CurDir) { +const FileEntry *Preprocessor::LookupFile( + llvm::StringRef Filename, + bool isAngled, + const DirectoryLookup *FromDir, + const DirectoryLookup *&CurDir, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) { // If the header lookup mechanism may be relative to the current file, pass in // info about where the current file is. const FileEntry *CurFileEnt = 0; @@ -494,8 +497,9 @@ const FileEntry *Preprocessor::LookupFile(llvm::StringRef Filename, // Do a standard file entry lookup. CurDir = CurDirLookup; - const FileEntry *FE = - HeaderInfo.LookupFile(Filename, isAngled, FromDir, CurDir, CurFileEnt); + const FileEntry *FE = HeaderInfo.LookupFile( + Filename, isAngled, FromDir, CurDir, CurFileEnt, + SearchPath, RelativePath); if (FE) return FE; // Otherwise, see if this is a subframework header. If so, this is relative @@ -503,7 +507,8 @@ const FileEntry *Preprocessor::LookupFile(llvm::StringRef Filename, // headers on the #include stack and pass them to HeaderInfo. if (IsFileLexer()) { if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) - if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt))) + if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt, + SearchPath, RelativePath))) return FE; } @@ -512,7 +517,8 @@ const FileEntry *Preprocessor::LookupFile(llvm::StringRef Filename, if (IsFileLexer(ISEntry)) { if ((CurFileEnt = SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) - if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt))) + if ((FE = HeaderInfo.LookupSubframeworkHeader( + Filename, CurFileEnt, SearchPath, RelativePath))) return FE; } } @@ -535,7 +541,7 @@ void Preprocessor::HandleDirective(Token &Result) { // We just parsed a # character at the start of a line, so we're in directive // mode. Tell the lexer this so any newlines we see will be converted into an - // EOM token (which terminates the directive). + // EOD token (which terminates the directive). CurPPLexer->ParsingPreprocessorDirective = true; ++NumDirectives; @@ -563,7 +569,7 @@ void Preprocessor::HandleDirective(Token &Result) { TryAgain: switch (Result.getKind()) { - case tok::eom: + case tok::eod: return; // null directive. case tok::comment: // Handle stuff like "# /*foo*/ define X" in -E -C mode. @@ -686,7 +692,7 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val, if (DigitTok.isNot(tok::numeric_constant)) { PP.Diag(DigitTok, DiagID); - if (DigitTok.isNot(tok::eom)) + if (DigitTok.isNot(tok::eod)) PP.DiscardUntilEndOfDirective(); return true; } @@ -758,9 +764,9 @@ void Preprocessor::HandleLineDirective(Token &Tok) { Token StrTok; Lex(StrTok); - // If the StrTok is "eom", then it wasn't present. Otherwise, it must be a - // string followed by eom. - if (StrTok.is(tok::eom)) + // If the StrTok is "eod", then it wasn't present. Otherwise, it must be a + // string followed by eod. + if (StrTok.is(tok::eod)) ; // ok else if (StrTok.isNot(tok::string_literal)) { Diag(StrTok, diag::err_pp_line_invalid_filename); @@ -779,7 +785,7 @@ void Preprocessor::HandleLineDirective(Token &Tok) { FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString(), Literal.GetStringLength()); - // Verify that there is nothing after the string, other than EOM. Because + // Verify that there is nothing after the string, other than EOD. Because // of C99 6.10.4p5, macros that expand to empty tokens are ok. CheckEndOfDirective("line", true); } @@ -800,7 +806,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, unsigned FlagVal; Token FlagTok; PP.Lex(FlagTok); - if (FlagTok.is(tok::eom)) return false; + if (FlagTok.is(tok::eod)) return false; if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP)) return true; @@ -808,7 +814,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, IsFileEntry = true; PP.Lex(FlagTok); - if (FlagTok.is(tok::eom)) return false; + if (FlagTok.is(tok::eod)) return false; if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP)) return true; } else if (FlagVal == 2) { @@ -834,7 +840,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, } PP.Lex(FlagTok); - if (FlagTok.is(tok::eom)) return false; + if (FlagTok.is(tok::eod)) return false; if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP)) return true; } @@ -849,7 +855,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, IsSystemHeader = true; PP.Lex(FlagTok); - if (FlagTok.is(tok::eom)) return false; + if (FlagTok.is(tok::eod)) return false; if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP)) return true; @@ -863,7 +869,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, IsExternCHeader = true; PP.Lex(FlagTok); - if (FlagTok.is(tok::eom)) return false; + if (FlagTok.is(tok::eod)) return false; // There are no more valid flags here. PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag); @@ -893,9 +899,9 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) { bool IsSystemHeader = false, IsExternCHeader = false; int FilenameID = -1; - // If the StrTok is "eom", then it wasn't present. Otherwise, it must be a - // string followed by eom. - if (StrTok.is(tok::eom)) + // If the StrTok is "eod", then it wasn't present. Otherwise, it must be a + // string followed by eod. + if (StrTok.is(tok::eod)) ; // ok else if (StrTok.isNot(tok::string_literal)) { Diag(StrTok, diag::err_pp_linemarker_invalid_filename); @@ -978,12 +984,12 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) { if (StrTok.isNot(tok::string_literal) && StrTok.isNot(tok::wide_string_literal)) { Diag(StrTok, diag::err_pp_malformed_ident); - if (StrTok.isNot(tok::eom)) + if (StrTok.isNot(tok::eod)) DiscardUntilEndOfDirective(); return; } - // Verify that there is nothing after the string, other than EOM. + // Verify that there is nothing after the string, other than EOD. CheckEndOfDirective("ident"); if (Callbacks) { @@ -1052,14 +1058,14 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc, /// /// This code concatenates and consumes tokens up to the '>' token. It returns /// false if the > was found, otherwise it returns true if it finds and consumes -/// the EOM marker. +/// the EOD marker. bool Preprocessor::ConcatenateIncludeName( llvm::SmallString<128> &FilenameBuffer, SourceLocation &End) { Token CurTok; Lex(CurTok); - while (CurTok.isNot(tok::eom)) { + while (CurTok.isNot(tok::eod)) { End = CurTok.getLocation(); // FIXME: Provide code completion for #includes. @@ -1095,8 +1101,8 @@ bool Preprocessor::ConcatenateIncludeName( Lex(CurTok); } - // If we hit the eom marker, emit an error and return true so that the caller - // knows the EOM has been read. + // If we hit the eod marker, emit an error and return true so that the caller + // knows the EOD has been read. Diag(CurTok.getLocation(), diag::err_pp_expects_filename); return true; } @@ -1120,8 +1126,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, SourceLocation End; switch (FilenameTok.getKind()) { - case tok::eom: - // If the token kind is EOM, the error has already been diagnosed. + case tok::eod: + // If the token kind is EOD, the error has already been diagnosed. return; case tok::angle_string_literal: @@ -1135,7 +1141,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // case, glue the tokens together into FilenameBuffer and interpret those. FilenameBuffer.push_back('<'); if (ConcatenateIncludeName(FilenameBuffer, End)) - return; // Found but no ">"? Diagnostic already emitted. + return; // Found but no ">"? Diagnostic already emitted. Filename = FilenameBuffer.str(); break; default: @@ -1153,7 +1159,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, return; } - // Verify that there is nothing after the filename, other than EOM. Note that + // Verify that there is nothing after the filename, other than EOD. Note that // we allow macros that expand to nothing after the filename, because this // falls into the category of "#include pp-tokens new-line" specified in // C99 6.10.2p4. @@ -1167,7 +1173,13 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // Search include directories. const DirectoryLookup *CurDir; - const FileEntry *File = LookupFile(Filename, isAngled, LookupFrom, CurDir); + llvm::SmallString<1024> SearchPath; + llvm::SmallString<1024> RelativePath; + // We get the raw path only if we have 'Callbacks' to which we later pass + // the path. + const FileEntry *File = LookupFile( + Filename, isAngled, LookupFrom, CurDir, + Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL); if (File == 0) { Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; return; @@ -1175,9 +1187,9 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // Notify the callback object that we've seen an inclusion directive. if (Callbacks) - Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File, - End); - + Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File, + End, SearchPath, RelativePath); + // The #included file will be considered to be a system header if either it is // in a system include directory, or if the #includer is a system include // header. @@ -1302,7 +1314,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) { MI->setIsC99Varargs(); MI->setArgumentList(&Arguments[0], Arguments.size(), BP); return false; - case tok::eom: // #define X( + case tok::eod: // #define X( Diag(Tok, diag::err_pp_missing_rparen_in_macro_def); return true; default: @@ -1366,7 +1378,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { ReadMacroName(MacroNameTok, 1); // Error reading macro name? If so, diagnostic already issued. - if (MacroNameTok.is(tok::eom)) + if (MacroNameTok.is(tok::eod)) return; Token LastTok = MacroNameTok; @@ -1384,7 +1396,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // If this is a function-like macro definition, parse the argument list, // marking each of the identifiers as being used as macro arguments. Also, // check other constraints on the first token of the macro body. - if (Tok.is(tok::eom)) { + if (Tok.is(tok::eod)) { // If there is no body to this macro, we have no special handling here. } else if (Tok.hasLeadingSpace()) { // This is a normal token with leading space. Clear the leading space @@ -1439,13 +1451,13 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { Diag(Tok, diag::warn_missing_whitespace_after_macro_name); } - if (!Tok.is(tok::eom)) + if (!Tok.is(tok::eod)) LastTok = Tok; // Read the rest of the macro body. if (MI->isObjectLike()) { // Object-like macros are very simple, just read their body. - while (Tok.isNot(tok::eom)) { + while (Tok.isNot(tok::eod)) { LastTok = Tok; MI->AddTokenToBody(Tok); // Get the next token of the macro. @@ -1456,7 +1468,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // Otherwise, read the body of a function-like macro. While we are at it, // check C99 6.10.3.2p1: ensure that # operators are followed by macro // parameters in function-like macro expansions. - while (Tok.isNot(tok::eom)) { + while (Tok.isNot(tok::eod)) { LastTok = Tok; if (Tok.isNot(tok::hash)) { @@ -1478,7 +1490,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // the '#' because '#' is often a comment character. However, change // the kind of the token to tok::unknown so that the preprocessor isn't // confused. - if (getLangOptions().AsmPreprocessor && Tok.isNot(tok::eom)) { + if (getLangOptions().AsmPreprocessor && Tok.isNot(tok::eod)) { LastTok.setKind(tok::unknown); } else { Diag(Tok, diag::err_pp_stringize_not_parameter); @@ -1504,7 +1516,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // Disable __VA_ARGS__ again. Ident__VA_ARGS__->setIsPoisoned(true); - // Check that there is no paste (##) operator at the begining or end of the + // Check that there is no paste (##) operator at the beginning or end of the // replacement list. unsigned NumTokens = MI->getNumTokens(); if (NumTokens != 0) { @@ -1573,7 +1585,7 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) { ReadMacroName(MacroNameTok, 2); // Error reading macro name? If so, diagnostic already issued. - if (MacroNameTok.is(tok::eom)) + if (MacroNameTok.is(tok::eod)) return; // Check to see if this is the last token on the #undef line. @@ -1619,7 +1631,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, ReadMacroName(MacroNameTok); // Error reading macro name? If so, diagnostic already issued. - if (MacroNameTok.is(tok::eom)) { + if (MacroNameTok.is(tok::eod)) { // Skip code until we get to #endif. This helps with recovery by not // emitting an error when the #endif is reached. SkipExcludedConditionalBlock(DirectiveTok.getLocation(), diff --git a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp index 1451c5a1ef5f..8fcfc70a7c67 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp @@ -180,7 +180,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, default: // Non-value token. PP.Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr); return true; - case tok::eom: + case tok::eod: case tok::r_paren: // If there is no expression, report and exit. PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr); @@ -372,7 +372,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, /// token. This returns: /// ~0 - Invalid token. /// 14 -> 3 - various operators. -/// 0 - 'eom' or ')' +/// 0 - 'eod' or ')' static unsigned getPrecedence(tok::TokenKind Kind) { switch (Kind) { default: return ~0U; @@ -397,8 +397,8 @@ static unsigned getPrecedence(tok::TokenKind Kind) { case tok::question: return 4; case tok::comma: return 3; case tok::colon: return 2; - case tok::r_paren: return 0; // Lowest priority, end of expr. - case tok::eom: return 0; // Lowest priority, end of macro. + case tok::r_paren: return 0;// Lowest priority, end of expr. + case tok::eod: return 0;// Lowest priority, end of directive. } } @@ -713,7 +713,7 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { DefinedTracker DT; if (EvaluateValue(ResVal, Tok, DT, true, *this)) { // Parse error, skip the rest of the macro line. - if (Tok.isNot(tok::eom)) + if (Tok.isNot(tok::eod)) DiscardUntilEndOfDirective(); // Restore 'DisableMacroExpansion'. @@ -724,7 +724,7 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { // If we are at the end of the expression after just parsing a value, there // must be no (unparenthesized) binary operators involved, so we can exit // directly. - if (Tok.is(tok::eom)) { + if (Tok.is(tok::eod)) { // If the expression we parsed was of the form !defined(macro), return the // macro in IfNDefMacro. if (DT.State == DefinedTracker::NotDefinedMacro) @@ -740,7 +740,7 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question), Tok, true, *this)) { // Parse error, skip the rest of the macro line. - if (Tok.isNot(tok::eom)) + if (Tok.isNot(tok::eod)) DiscardUntilEndOfDirective(); // Restore 'DisableMacroExpansion'. @@ -748,9 +748,9 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { return false; } - // If we aren't at the tok::eom token, something bad happened, like an extra + // If we aren't at the tok::eod token, something bad happened, like an extra // ')' token. - if (Tok.isNot(tok::eom)) { + if (Tok.isNot(tok::eod)) { Diag(Tok, diag::err_pp_expected_eol); DiscardUntilEndOfDirective(); } diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp index eef42b69d87f..bf0a7fbfef18 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp @@ -301,7 +301,7 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { // We handle this by scanning for the closest real lexer, switching it to // raw mode and preprocessor mode. This will cause it to return \n as an - // explicit EOM token. + // explicit EOD token. PreprocessorLexer *FoundLexer = 0; bool LexerWasInPPMode = false; for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { @@ -309,11 +309,11 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { if (ISI.ThePPLexer == 0) continue; // Scan for a real lexer. // Once we find a real lexer, mark it as raw mode (disabling macro - // expansions) and preprocessor mode (return EOM). We know that the lexer + // expansions) and preprocessor mode (return EOD). We know that the lexer // was *not* in raw mode before, because the macro that the comment came // from was expanded. However, it could have already been in preprocessor // mode (#if COMMENT) in which case we have to return it to that mode and - // return EOM. + // return EOD. FoundLexer = ISI.ThePPLexer; FoundLexer->LexingRawMode = true; LexerWasInPPMode = FoundLexer->ParsingPreprocessorDirective; @@ -326,22 +326,22 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { // the next token. if (!HandleEndOfTokenLexer(Tok)) Lex(Tok); - // Discarding comments as long as we don't have EOF or EOM. This 'comments + // Discarding comments as long as we don't have EOF or EOD. This 'comments // out' the rest of the line, including any tokens that came from other macros // that were active, as in: // #define submacro a COMMENT b // submacro c // which should lex to 'a' only: 'b' and 'c' should be removed. - while (Tok.isNot(tok::eom) && Tok.isNot(tok::eof)) + while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) Lex(Tok); - // If we got an eom token, then we successfully found the end of the line. - if (Tok.is(tok::eom)) { + // If we got an eod token, then we successfully found the end of the line. + if (Tok.is(tok::eod)) { assert(FoundLexer && "Can't get end of line without an active lexer"); // Restore the lexer back to normal mode instead of raw mode. FoundLexer->LexingRawMode = false; - // If the lexer was already in preprocessor mode, just return the EOM token + // If the lexer was already in preprocessor mode, just return the EOD token // to finish the preprocessor line. if (LexerWasInPPMode) return; @@ -352,7 +352,7 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { // If we got an EOF token, then we reached the end of the token stream but // didn't find an explicit \n. This can only happen if there was no lexer - // active (an active lexer would return EOM at EOF if there was no \n in + // active (an active lexer would return EOD at EOF if there was no \n in // preprocessor directive mode), so just return EOF as our token. - assert(!FoundLexer && "Lexer should return EOM before EOF in PP mode"); + assert(!FoundLexer && "Lexer should return EOD before EOF in PP mode"); } diff --git a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp index ba9261491030..d6e0d3a1c08b 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp @@ -176,8 +176,6 @@ bool Preprocessor::isNextPPTokenLParen() { /// expanded as a macro, handle it and return the next token as 'Identifier'. bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, MacroInfo *MI) { - if (Callbacks) Callbacks->MacroExpands(Identifier, MI); - // If this is a macro expansion in the "#if !defined(x)" line for the file, // then the macro could expand to different things in other contexts, we need // to disable the optimization in this case. @@ -185,6 +183,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, // If this is a builtin macro, like __LINE__ or _Pragma, handle it specially. if (MI->isBuiltinMacro()) { + if (Callbacks) Callbacks->MacroExpands(Identifier, MI); ExpandBuiltinMacro(Identifier); return false; } @@ -225,8 +224,13 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, // Notice that this macro has been used. markMacroAsUsed(MI); + if (Callbacks) Callbacks->MacroExpands(Identifier, MI); + // If we started lexing a macro, enter the macro expansion body. + // Remember where the token is instantiated. + SourceLocation InstantiateLoc = Identifier.getLocation(); + // If this macro expands to no tokens, don't bother to push it onto the // expansion stack, only to take it right back off. if (MI->getNumTokens() == 0) { @@ -249,6 +253,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, if (HadLeadingSpace) Identifier.setFlag(Token::LeadingSpace); } Identifier.setFlag(Token::LeadingEmptyMacro); + LastEmptyMacroInstantiationLoc = InstantiateLoc; ++NumFastMacroExpanded; return false; @@ -267,9 +272,6 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, bool isAtStartOfLine = Identifier.isAtStartOfLine(); bool hasLeadingSpace = Identifier.hasLeadingSpace(); - // Remember where the token is instantiated. - SourceLocation InstantiateLoc = Identifier.getLocation(); - // Replace the result token. Identifier = MI->getReplacementToken(0); @@ -355,9 +357,9 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, LexUnexpandedToken(Tok); } - if (Tok.is(tok::eof) || Tok.is(tok::eom)) { // "#if f(" & "#if f(\n" + if (Tok.is(tok::eof) || Tok.is(tok::eod)) { // "#if f(" & "#if f(\n" Diag(MacroName, diag::err_unterm_macro_invoc); - // Do not lose the EOF/EOM. Return it to the client. + // Do not lose the EOF/EOD. Return it to the client. MacroName = Tok; return 0; } else if (Tok.is(tok::r_paren)) { @@ -410,9 +412,9 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, return 0; } - // Empty arguments are standard in C99 and supported as an extension in + // Empty arguments are standard in C99 and C++0x, and are supported as an extension in // other modes. - if (ArgTokens.size() == ArgTokenStart && !Features.C99) + if (ArgTokens.size() == ArgTokenStart && !Features.C99 && !Features.CPlusPlus0x) Diag(Tok, diag::ext_empty_fnmacro_arg); // Add a marker EOF token to the end of the token list for this argument. @@ -530,6 +532,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { return llvm::StringSwitch(II->getName()) .Case("attribute_analyzer_noreturn", true) + .Case("attribute_availability", true) .Case("attribute_cf_returns_not_retained", true) .Case("attribute_cf_returns_retained", true) .Case("attribute_deprecated_with_message", true) @@ -540,12 +543,14 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("attribute_ns_consumed", true) .Case("attribute_cf_consumed", true) .Case("attribute_objc_ivar_unused", true) + .Case("attribute_objc_method_family", true) .Case("attribute_overloadable", true) .Case("attribute_unavailable_with_message", true) .Case("blocks", LangOpts.Blocks) .Case("cxx_exceptions", LangOpts.Exceptions) .Case("cxx_rtti", LangOpts.RTTI) .Case("enumerator_attributes", true) + .Case("generic_selections", true) .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI) .Case("objc_weak_class", LangOpts.ObjCNonFragileABI) .Case("ownership_holds", true) @@ -556,10 +561,14 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("cxx_auto_type", LangOpts.CPlusPlus0x) .Case("cxx_decltype", LangOpts.CPlusPlus0x) .Case("cxx_default_function_template_args", LangOpts.CPlusPlus0x) + .Case("cxx_delegating_constructors", LangOpts.CPlusPlus0x) .Case("cxx_deleted_functions", LangOpts.CPlusPlus0x) .Case("cxx_inline_namespaces", LangOpts.CPlusPlus0x) //.Case("cxx_lambdas", false) + .Case("cxx_noexcept", LangOpts.CPlusPlus0x) //.Case("cxx_nullptr", false) + .Case("cxx_override_control", LangOpts.CPlusPlus0x) + .Case("cxx_range_for", LangOpts.CPlusPlus0x) .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus0x) .Case("cxx_rvalue_references", LangOpts.CPlusPlus0x) .Case("cxx_strong_enums", LangOpts.CPlusPlus0x) @@ -581,10 +590,11 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("is_convertible_to", LangOpts.CPlusPlus) .Case("is_empty", LangOpts.CPlusPlus) .Case("is_enum", LangOpts.CPlusPlus) + .Case("is_literal", LangOpts.CPlusPlus) .Case("is_pod", LangOpts.CPlusPlus) .Case("is_polymorphic", LangOpts.CPlusPlus) + .Case("is_trivial", LangOpts.CPlusPlus) .Case("is_union", LangOpts.CPlusPlus) - .Case("is_literal", LangOpts.CPlusPlus) .Case("tls", PP.getTargetInfo().isTLSSupported()) .Default(false); } @@ -626,8 +636,8 @@ static bool EvaluateHasIncludeCommon(Token &Tok, SourceLocation EndLoc; switch (Tok.getKind()) { - case tok::eom: - // If the token kind is EOM, the error has already been diagnosed. + case tok::eod: + // If the token kind is EOD, the error has already been diagnosed. return false; case tok::angle_string_literal: @@ -644,7 +654,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok, // case, glue the tokens together into FilenameBuffer and interpret those. FilenameBuffer.push_back('<'); if (PP.ConcatenateIncludeName(FilenameBuffer, EndLoc)) - return false; // Found but no ">"? Diagnostic already emitted. + return false; // Found but no ">"? Diagnostic already emitted. Filename = FilenameBuffer.str(); break; default: @@ -660,7 +670,8 @@ static bool EvaluateHasIncludeCommon(Token &Tok, // Search include directories. const DirectoryLookup *CurDir; - const FileEntry *File = PP.LookupFile(Filename, isAngled, LookupFrom, CurDir); + const FileEntry *File = + PP.LookupFile(Filename, isAngled, LookupFrom, CurDir, NULL, NULL); // Get the result value. Result = true means the file exists. bool Result = File != 0; diff --git a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp index 975753bc23bc..e5ef0fdf20eb 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp @@ -125,7 +125,7 @@ void PTHLexer::Lex(Token& Tok) { return PP->Lex(Tok); } - if (TKind == tok::eom) { + if (TKind == tok::eod) { assert(ParsingPreprocessorDirective); ParsingPreprocessorDirective = false; return; @@ -527,7 +527,7 @@ PTHManager *PTHManager::Create(const std::string &file, Diagnostic &Diags) { // Get the number of IdentifierInfos and pre-allocate the identifier cache. uint32_t NumIds = ReadLE32(IData); - // Pre-allocate the peristent ID -> IdentifierInfo* cache. We use calloc() + // Pre-allocate the persistent ID -> IdentifierInfo* cache. We use calloc() // so that we in the best case only zero out memory once when the OS returns // us new pages. IdentifierInfo** PerIDCache = 0; diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp index 80d3bb1d2790..0c180918dc26 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp @@ -229,8 +229,8 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { PragmaToks.front().setFlag(Token::LeadingSpace); - // Replace the ')' with an EOM to mark the end of the pragma. - PragmaToks.back().setKind(tok::eom); + // Replace the ')' with an EOD to mark the end of the pragma. + PragmaToks.back().setKind(tok::eod); Token *TokArray = new Token[PragmaToks.size()]; std::copy(PragmaToks.begin(), PragmaToks.end(), TokArray); @@ -283,7 +283,7 @@ void Preprocessor::HandlePragmaPoison(Token &PoisonTok) { if (CurPPLexer) CurPPLexer->LexingRawMode = false; // If we reached the end of line, we're done. - if (Tok.is(tok::eom)) return; + if (Tok.is(tok::eod)) return; // Can only poison identifiers. if (Tok.isNot(tok::raw_identifier)) { @@ -348,8 +348,8 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { Token FilenameTok; CurPPLexer->LexIncludeFilename(FilenameTok); - // If the token kind is EOM, the error has already been diagnosed. - if (FilenameTok.is(tok::eom)) + // If the token kind is EOD, the error has already been diagnosed. + if (FilenameTok.is(tok::eod)) return; // Reserve a buffer to get the spelling. @@ -368,7 +368,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { // Search include directories for this file. const DirectoryLookup *CurDir; - const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir); + const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir, NULL, NULL); if (File == 0) { Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; return; @@ -381,7 +381,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { // Lex tokens at the end of the message and include them in the message. std::string Message; Lex(DependencyTok); - while (DependencyTok.isNot(tok::eom)) { + while (DependencyTok.isNot(tok::eod)) { Message += getSpelling(DependencyTok) + " "; Lex(DependencyTok); } @@ -470,7 +470,7 @@ void Preprocessor::HandlePragmaComment(Token &Tok) { } Lex(Tok); // eat the r_paren. - if (Tok.isNot(tok::eom)) { + if (Tok.isNot(tok::eod)) { Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); return; } @@ -541,7 +541,7 @@ void Preprocessor::HandlePragmaMessage(Token &Tok) { Lex(Tok); // eat the r_paren. } - if (Tok.isNot(tok::eom)) { + if (Tok.isNot(tok::eod)) { Diag(Tok.getLocation(), diag::err_pragma_message_malformed); return; } @@ -737,10 +737,10 @@ bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) { return true; } - // Verify that this is followed by EOM. + // Verify that this is followed by EOD. LexUnexpandedToken(Tok); - if (Tok.isNot(tok::eom)) - Diag(Tok, diag::ext_pragma_syntax_eom); + if (Tok.isNot(tok::eod)) + Diag(Tok, diag::ext_pragma_syntax_eod); return false; } @@ -883,7 +883,7 @@ struct PragmaDiagnosticHandler : public PragmaHandler { PP.LexUnexpandedToken(Tok); } - if (Tok.isNot(tok::eom)) { + if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token); return; } diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp index 3a43ac11e4e0..9555611dc59d 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp @@ -146,12 +146,15 @@ void PreprocessingRecord::MacroUndefined(const Token &Id, MacroDefinitions.erase(Pos); } -void PreprocessingRecord::InclusionDirective(SourceLocation HashLoc, - const clang::Token &IncludeTok, - llvm::StringRef FileName, - bool IsAngled, - const FileEntry *File, - clang::SourceLocation EndLoc) { +void PreprocessingRecord::InclusionDirective( + SourceLocation HashLoc, + const clang::Token &IncludeTok, + llvm::StringRef FileName, + bool IsAngled, + const FileEntry *File, + clang::SourceLocation EndLoc, + llvm::StringRef SearchPath, + llvm::StringRef RelativePath) { InclusionDirective::InclusionKind Kind = InclusionDirective::Include; switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp index 6fe414b66414..31fd667a651d 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp @@ -89,6 +89,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts, // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. // This gets unpoisoned where it is allowed. (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned(); + SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use); // Initialize the pragma handlers. PragmaHandlers = new PragmaNamespace(llvm::StringRef()); @@ -96,6 +97,23 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts, // Initialize builtin macros like __LINE__ and friends. RegisterBuiltinMacros(); + + if(Features.Borland) { + Ident__exception_info = getIdentifierInfo("_exception_info"); + Ident___exception_info = getIdentifierInfo("__exception_info"); + Ident_GetExceptionInfo = getIdentifierInfo("GetExceptionInformation"); + Ident__exception_code = getIdentifierInfo("_exception_code"); + Ident___exception_code = getIdentifierInfo("__exception_code"); + Ident_GetExceptionCode = getIdentifierInfo("GetExceptionCode"); + Ident__abnormal_termination = getIdentifierInfo("_abnormal_termination"); + Ident___abnormal_termination = getIdentifierInfo("__abnormal_termination"); + Ident_AbnormalTermination = getIdentifierInfo("AbnormalTermination"); + } else { + Ident__exception_info = Ident__exception_code = Ident__abnormal_termination = 0; + Ident___exception_info = Ident___exception_code = Ident___abnormal_termination = 0; + Ident_GetExceptionInfo = Ident_GetExceptionCode = Ident_AbnormalTermination = 0; + } + } Preprocessor::~Preprocessor() { @@ -278,7 +296,6 @@ void Preprocessor::CodeCompleteNaturalLanguage() { CodeComplete->CodeCompleteNaturalLanguage(); } - /// getSpelling - This method is used to get the spelling of a token into a /// SmallVector. Note that the returned StringRef may not point to the /// supplied buffer if a copy can be avoided. @@ -400,6 +417,34 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const { return II; } +void Preprocessor::SetPoisonReason(IdentifierInfo *II, unsigned DiagID) { + PoisonReasons[II] = DiagID; +} + +void Preprocessor::PoisonSEHIdentifiers(bool Poison) { + assert(Ident__exception_code && Ident__exception_info); + assert(Ident___exception_code && Ident___exception_info); + Ident__exception_code->setIsPoisoned(Poison); + Ident___exception_code->setIsPoisoned(Poison); + Ident_GetExceptionCode->setIsPoisoned(Poison); + Ident__exception_info->setIsPoisoned(Poison); + Ident___exception_info->setIsPoisoned(Poison); + Ident_GetExceptionInfo->setIsPoisoned(Poison); + Ident__abnormal_termination->setIsPoisoned(Poison); + Ident___abnormal_termination->setIsPoisoned(Poison); + Ident_AbnormalTermination->setIsPoisoned(Poison); +} + +void Preprocessor::HandlePoisonedIdentifier(Token & Identifier) { + assert(Identifier.getIdentifierInfo() && + "Can't handle identifiers without identifier info!"); + llvm::DenseMap::const_iterator it = + PoisonReasons.find(Identifier.getIdentifierInfo()); + if(it == PoisonReasons.end()) + Diag(Identifier, diag::err_pp_used_poisoned_id); + else + Diag(Identifier,it->second) << Identifier.getIdentifierInfo(); +} /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier. This callback looks up the identifier in the map and/or @@ -418,10 +463,7 @@ void Preprocessor::HandleIdentifier(Token &Identifier) { // If this identifier was poisoned, and if it was not produced from a macro // expansion, emit an error. if (II.isPoisoned() && CurPPLexer) { - if (&II != Ident__VA_ARGS__) // We warn about __VA_ARGS__ with poisoning. - Diag(Identifier, diag::err_pp_used_poisoned_id); - else - Diag(Identifier, diag::ext_pp_bad_vaargs_use); + HandlePoisonedIdentifier(Identifier); } // If this is a macro to be expanded, do it. diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp index e005c494763c..808a81bd5e87 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp @@ -34,7 +34,7 @@ void PreprocessorLexer::LexIncludeFilename(Token &FilenameTok) { ParsingFilename = false; // No filename? - if (FilenameTok.is(tok::eom)) + if (FilenameTok.is(tok::eod)) PP->Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); } diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp index caa44bf4a146..65aff0d1d037 100644 --- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp @@ -367,11 +367,7 @@ void TokenLexer::Lex(Token &Tok) { // won't be handled by Preprocessor::HandleIdentifier because this is coming // from a macro expansion. if (II->isPoisoned() && TokenIsFromPaste) { - // We warn about __VA_ARGS__ with poisoning. - if (II->isStr("__VA_ARGS__")) - PP.Diag(Tok, diag::ext_pp_bad_vaargs_use); - else - PP.Diag(Tok, diag::err_pp_used_poisoned_id); + PP.HandlePoisonedIdentifier(Tok); } if (!DisableMacroExpansion && II->isHandleIdentifierCase()) @@ -546,7 +542,7 @@ unsigned TokenLexer::isNextTokenLParen() const { /// isParsingPreprocessorDirective - Return true if we are in the middle of a /// preprocessor directive. bool TokenLexer::isParsingPreprocessorDirective() const { - return Tokens[NumTokens-1].is(tok::eom) && !isAtEnd(); + return Tokens[NumTokens-1].is(tok::eod) && !isAtEnd(); } /// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp index edb1675b99e5..21917b23ffb6 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp @@ -21,6 +21,8 @@ #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Stmt.h" #include "clang/Parse/Parser.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/CrashRecoveryContext.h" #include using namespace clang; @@ -37,8 +39,15 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, ASTContext &Ctx, bool PrintStats, bool CompleteTranslationUnit, CodeCompleteConsumer *CompletionConsumer) { - Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer); - ParseAST(S, PrintStats); + + llvm::OwningPtr S(new Sema(PP, Ctx, *Consumer, + CompleteTranslationUnit, + CompletionConsumer)); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar CleaupSema(S.get()); + + ParseAST(*S.get(), PrintStats); } void clang::ParseAST(Sema &S, bool PrintStats) { @@ -50,7 +59,15 @@ void clang::ParseAST(Sema &S, bool PrintStats) { ASTConsumer *Consumer = &S.getASTConsumer(); - Parser P(S.getPreprocessor(), S); + llvm::OwningPtr ParseOP(new Parser(S.getPreprocessor(), S)); + Parser &P = *ParseOP.get(); + + PrettyStackTraceParserEntry CrashInfo(P); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar + CleaupParser(ParseOP.get()); + S.getPreprocessor().EnterMainSourceFile(); P.Initialize(); S.Initialize(); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp index 399473840a94..87e2f343748e 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -15,6 +15,7 @@ #include "clang/Parse/Parser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" +#include "clang/AST/DeclTemplate.h" using namespace clang; /// ParseCXXInlineMethodDef - We parsed and verified that the specified @@ -37,13 +38,6 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, true, move(TemplateParams)); else { // FIXME: pass template information through - if (VS.isOverrideSpecified()) - Diag(VS.getOverrideLoc(), diag::ext_override_inline) << "override"; - if (VS.isFinalSpecified()) - Diag(VS.getFinalLoc(), diag::ext_override_inline) << "final"; - if (VS.isNewSpecified()) - Diag(VS.getNewLoc(), diag::ext_override_inline) << "new"; - FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, move(TemplateParams), 0, VS, 0, /*IsDefinition*/true); @@ -53,6 +47,37 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, D.complete(FnD); + // In delayed template parsing mode, if we are within a class template + // or if we are about to parse function member template then consume + // the tokens and store them for parsing at the end of the translation unit. + if (getLang().DelayedTemplateParsing && + ((Actions.CurContext->isDependentContext() || + TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) && + !Actions.IsInsideALocalClassWithinATemplateFunction()) && + !D.getDeclSpec().isFriendSpecified()) { + + if (FnD) { + LateParsedTemplatedFunction *LPT = + new LateParsedTemplatedFunction(this, FnD); + + FunctionDecl *FD = 0; + if (FunctionTemplateDecl *FunTmpl = dyn_cast(FnD)) + FD = FunTmpl->getTemplatedDecl(); + else + FD = cast(FnD); + Actions.CheckForFunctionRedefinition(FD); + + LateParsedTemplateMap[FD] = LPT; + Actions.MarkAsLateParsedTemplate(FD); + LexTemplateFunctionForLateParsing(LPT->Toks); + } else { + CachedTokens Toks; + LexTemplateFunctionForLateParsing(Toks); + } + + return FnD; + } + // Consume the tokens and store them for later parsing. LexedMethod* LM = new LexedMethod(this, FnD); @@ -94,6 +119,14 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, } } + + if (!FnD) { + // If semantic analysis could not build a function declaration, + // just throw away the late-parsed declaration. + delete getCurrentClass().LateParsedDeclarations.back(); + getCurrentClass().LateParsedDeclarations.pop_back(); + } + return FnD; } @@ -261,7 +294,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); if (Tok.is(tok::kw_try)) { - ParseFunctionTryBlock(LM.D); + ParseFunctionTryBlock(LM.D, FnScope); assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, Tok.getLocation()) && "ParseFunctionTryBlock went over the cached tokens!"); @@ -276,13 +309,14 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { // Error recovery. if (!Tok.is(tok::l_brace)) { + FnScope.Exit(); Actions.ActOnFinishFunctionBody(LM.D, 0); return; } } else Actions.ActOnDefaultCtorInitializers(LM.D); - ParseFunctionStatementBody(LM.D); + ParseFunctionStatementBody(LM.D, FnScope); if (Tok.getLocation() != origLoc) { // Due to parsing error, we either went over the cached tokens or diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 077edd700ad6..a20e90bd0ea3 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -13,6 +13,7 @@ #include "clang/Parse/Parser.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Basic/OpenCL.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/PrettyDeclStackTrace.h" @@ -32,7 +33,7 @@ using namespace clang; TypeResult Parser::ParseTypeName(SourceRange *Range, Declarator::TheContext Context) { // Parse the common declaration-specifiers piece. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); // Parse the abstract-declarator, if present. @@ -111,8 +112,11 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); + // Availability attributes have their own grammar. + if (AttrName->isStr("availability")) + ParseAvailabilityAttribute(*AttrName, AttrNameLoc, attrs, endLoc); // check if we have a "parameterized" attribute - if (Tok.is(tok::l_paren)) { + else if (Tok.is(tok::l_paren)) { ConsumeParen(); // ignore the left paren loc for now if (Tok.is(tok::identifier)) { @@ -122,8 +126,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, if (Tok.is(tok::r_paren)) { // __attribute__(( mode(byte) )) ConsumeParen(); // ignore the right paren loc for now - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, - ParmName, ParmLoc, 0, 0)); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + ParmName, ParmLoc, 0, 0); } else if (Tok.is(tok::comma)) { ConsumeToken(); // __attribute__(( format(printf, 1, 2) )) @@ -146,9 +150,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, } if (ArgExprsOk && Tok.is(tok::r_paren)) { ConsumeParen(); // ignore the right paren loc for now - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, - AttrNameLoc, ParmName, ParmLoc, - ArgExprs.take(), ArgExprs.size())); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + ParmName, ParmLoc, ArgExprs.take(), ArgExprs.size()); } } } else { // not an identifier @@ -157,8 +160,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, // parse a possibly empty comma separated list of expressions // __attribute__(( nonnull() )) ConsumeParen(); // ignore the right paren loc for now - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0)); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0); break; case tok::kw_char: case tok::kw_wchar_t: @@ -168,6 +171,7 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, case tok::kw_short: case tok::kw_int: case tok::kw_long: + case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: case tok::kw_float: @@ -175,9 +179,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, case tok::kw_void: case tok::kw_typeof: { AttributeList *attr - = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0); - attrs.add(attr); + = attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0); if (attr->getKind() == AttributeList::AT_IBOutletCollection) Diag(Tok, diag::err_iboutletcollection_builtintype); // If it's a builtin type name, eat it and expect a rparen @@ -209,16 +212,16 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, // Match the ')'. if (ArgExprsOk && Tok.is(tok::r_paren)) { ConsumeParen(); // ignore the right paren loc for now - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, - AttrNameLoc, 0, SourceLocation(), - ArgExprs.take(), ArgExprs.size())); + attrs.addNew(AttrName, AttrNameLoc, 0, + AttrNameLoc, 0, SourceLocation(), + ArgExprs.take(), ArgExprs.size()); } break; } } } else { - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0)); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0); } } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) @@ -260,14 +263,14 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &attrs) { ExprResult ArgExpr(ParseAssignmentExpression()); if (!ArgExpr.isInvalid()) { Expr *ExprList = ArgExpr.take(); - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), &ExprList, 1, true)); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), &ExprList, 1, true); } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) SkipUntil(tok::r_paren, false); } else { - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0, true)); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0, true); } } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) @@ -286,8 +289,8 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) // FIXME: Support these properly! continue; - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, true)); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), 0, 0, true); } } @@ -296,8 +299,8 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { while (Tok.is(tok::kw___pascal)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, true)); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), 0, 0, true); } } @@ -305,12 +308,334 @@ void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) { // Treat these like attributes while (Tok.is(tok::kw___kernel)) { SourceLocation AttrNameLoc = ConsumeToken(); - attrs.add(AttrFactory.Create(PP.getIdentifierInfo("opencl_kernel_function"), - AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, false)); + attrs.addNew(PP.getIdentifierInfo("opencl_kernel_function"), + AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), 0, 0, false); } } +void Parser::ParseOpenCLQualifiers(DeclSpec &DS) { + SourceLocation Loc = Tok.getLocation(); + switch(Tok.getKind()) { + // OpenCL qualifiers: + case tok::kw___private: + case tok::kw_private: + DS.getAttributes().addNewInteger( + Actions.getASTContext(), + PP.getIdentifierInfo("address_space"), Loc, 0); + break; + + case tok::kw___global: + DS.getAttributes().addNewInteger( + Actions.getASTContext(), + PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_global); + break; + + case tok::kw___local: + DS.getAttributes().addNewInteger( + Actions.getASTContext(), + PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_local); + break; + + case tok::kw___constant: + DS.getAttributes().addNewInteger( + Actions.getASTContext(), + PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_constant); + break; + + case tok::kw___read_only: + DS.getAttributes().addNewInteger( + Actions.getASTContext(), + PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_only); + break; + + case tok::kw___write_only: + DS.getAttributes().addNewInteger( + Actions.getASTContext(), + PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_write_only); + break; + + case tok::kw___read_write: + DS.getAttributes().addNewInteger( + Actions.getASTContext(), + PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_write); + break; + default: break; + } +} + +/// \brief Parse a version number. +/// +/// version: +/// simple-integer +/// simple-integer ',' simple-integer +/// simple-integer ',' simple-integer ',' simple-integer +VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { + Range = Tok.getLocation(); + + if (!Tok.is(tok::numeric_constant)) { + Diag(Tok, diag::err_expected_version); + SkipUntil(tok::comma, tok::r_paren, true, true, true); + return VersionTuple(); + } + + // Parse the major (and possibly minor and subminor) versions, which + // are stored in the numeric constant. We utilize a quirk of the + // lexer, which is that it handles something like 1.2.3 as a single + // numeric constant, rather than two separate tokens. + llvm::SmallString<512> Buffer; + Buffer.resize(Tok.getLength()+1); + const char *ThisTokBegin = &Buffer[0]; + + // Get the spelling of the token, which eliminates trigraphs, etc. + bool Invalid = false; + unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid); + if (Invalid) + return VersionTuple(); + + // Parse the major version. + unsigned AfterMajor = 0; + unsigned Major = 0; + while (AfterMajor < ActualLength && isdigit(ThisTokBegin[AfterMajor])) { + Major = Major * 10 + ThisTokBegin[AfterMajor] - '0'; + ++AfterMajor; + } + + if (AfterMajor == 0) { + Diag(Tok, diag::err_expected_version); + SkipUntil(tok::comma, tok::r_paren, true, true, true); + return VersionTuple(); + } + + if (AfterMajor == ActualLength) { + ConsumeToken(); + + // We only had a single version component. + if (Major == 0) { + Diag(Tok, diag::err_zero_version); + return VersionTuple(); + } + + return VersionTuple(Major); + } + + if (ThisTokBegin[AfterMajor] != '.' || (AfterMajor + 1 == ActualLength)) { + Diag(Tok, diag::err_expected_version); + SkipUntil(tok::comma, tok::r_paren, true, true, true); + return VersionTuple(); + } + + // Parse the minor version. + unsigned AfterMinor = AfterMajor + 1; + unsigned Minor = 0; + while (AfterMinor < ActualLength && isdigit(ThisTokBegin[AfterMinor])) { + Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0'; + ++AfterMinor; + } + + if (AfterMinor == ActualLength) { + ConsumeToken(); + + // We had major.minor. + if (Major == 0 && Minor == 0) { + Diag(Tok, diag::err_zero_version); + return VersionTuple(); + } + + return VersionTuple(Major, Minor); + } + + // If what follows is not a '.', we have a problem. + if (ThisTokBegin[AfterMinor] != '.') { + Diag(Tok, diag::err_expected_version); + SkipUntil(tok::comma, tok::r_paren, true, true, true); + return VersionTuple(); + } + + // Parse the subminor version. + unsigned AfterSubminor = AfterMinor + 1; + unsigned Subminor = 0; + while (AfterSubminor < ActualLength && isdigit(ThisTokBegin[AfterSubminor])) { + Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0'; + ++AfterSubminor; + } + + if (AfterSubminor != ActualLength) { + Diag(Tok, diag::err_expected_version); + SkipUntil(tok::comma, tok::r_paren, true, true, true); + return VersionTuple(); + } + ConsumeToken(); + return VersionTuple(Major, Minor, Subminor); +} + +/// \brief Parse the contents of the "availability" attribute. +/// +/// availability-attribute: +/// 'availability' '(' platform ',' version-arg-list ')' +/// +/// platform: +/// identifier +/// +/// version-arg-list: +/// version-arg +/// version-arg ',' version-arg-list +/// +/// version-arg: +/// 'introduced' '=' version +/// 'deprecated' '=' version +/// 'removed' = version +/// 'unavailable' +void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, + SourceLocation AvailabilityLoc, + ParsedAttributes &attrs, + SourceLocation *endLoc) { + SourceLocation PlatformLoc; + IdentifierInfo *Platform = 0; + + enum { Introduced, Deprecated, Obsoleted, Unknown }; + AvailabilityChange Changes[Unknown]; + + // Opening '('. + SourceLocation LParenLoc; + if (!Tok.is(tok::l_paren)) { + Diag(Tok, diag::err_expected_lparen); + return; + } + LParenLoc = ConsumeParen(); + + // Parse the platform name, + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_availability_expected_platform); + SkipUntil(tok::r_paren); + return; + } + Platform = Tok.getIdentifierInfo(); + PlatformLoc = ConsumeToken(); + + // Parse the ',' following the platform name. + if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::r_paren)) + return; + + // If we haven't grabbed the pointers for the identifiers + // "introduced", "deprecated", and "obsoleted", do so now. + if (!Ident_introduced) { + Ident_introduced = PP.getIdentifierInfo("introduced"); + Ident_deprecated = PP.getIdentifierInfo("deprecated"); + Ident_obsoleted = PP.getIdentifierInfo("obsoleted"); + Ident_unavailable = PP.getIdentifierInfo("unavailable"); + } + + // Parse the set of introductions/deprecations/removals. + SourceLocation UnavailableLoc; + do { + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_availability_expected_change); + SkipUntil(tok::r_paren); + return; + } + IdentifierInfo *Keyword = Tok.getIdentifierInfo(); + SourceLocation KeywordLoc = ConsumeToken(); + + if (Keyword == Ident_unavailable) { + if (UnavailableLoc.isValid()) { + Diag(KeywordLoc, diag::err_availability_redundant) + << Keyword << SourceRange(UnavailableLoc); + } + UnavailableLoc = KeywordLoc; + + if (Tok.isNot(tok::comma)) + break; + + ConsumeToken(); + continue; + } + + if (Tok.isNot(tok::equal)) { + Diag(Tok, diag::err_expected_equal_after) + << Keyword; + SkipUntil(tok::r_paren); + return; + } + ConsumeToken(); + + SourceRange VersionRange; + VersionTuple Version = ParseVersionTuple(VersionRange); + + if (Version.empty()) { + SkipUntil(tok::r_paren); + return; + } + + unsigned Index; + if (Keyword == Ident_introduced) + Index = Introduced; + else if (Keyword == Ident_deprecated) + Index = Deprecated; + else if (Keyword == Ident_obsoleted) + Index = Obsoleted; + else + Index = Unknown; + + if (Index < Unknown) { + if (!Changes[Index].KeywordLoc.isInvalid()) { + Diag(KeywordLoc, diag::err_availability_redundant) + << Keyword + << SourceRange(Changes[Index].KeywordLoc, + Changes[Index].VersionRange.getEnd()); + } + + Changes[Index].KeywordLoc = KeywordLoc; + Changes[Index].Version = Version; + Changes[Index].VersionRange = VersionRange; + } else { + Diag(KeywordLoc, diag::err_availability_unknown_change) + << Keyword << VersionRange; + } + + if (Tok.isNot(tok::comma)) + break; + + ConsumeToken(); + } while (true); + + // Closing ')'. + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + if (RParenLoc.isInvalid()) + return; + + if (endLoc) + *endLoc = RParenLoc; + + // The 'unavailable' availability cannot be combined with any other + // availability changes. Make sure that hasn't happened. + if (UnavailableLoc.isValid()) { + bool Complained = false; + for (unsigned Index = Introduced; Index != Unknown; ++Index) { + if (Changes[Index].KeywordLoc.isValid()) { + if (!Complained) { + Diag(UnavailableLoc, diag::warn_availability_and_unavailable) + << SourceRange(Changes[Index].KeywordLoc, + Changes[Index].VersionRange.getEnd()); + Complained = true; + } + + // Clear out the availability. + Changes[Index] = AvailabilityChange(); + } + } + } + + // Record this attribute + attrs.addNew(&Availability, AvailabilityLoc, + 0, SourceLocation(), + Platform, PlatformLoc, + Changes[Introduced], + Changes[Deprecated], + Changes[Obsoleted], + UnavailableLoc, false, false); +} + void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) << attrs.Range; @@ -329,7 +654,7 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { /// [C++] namespace-definition /// [C++] using-directive /// [C++] using-declaration -/// [C++0x] static_assert-declaration +/// [C++0x/C1X] static_assert-declaration /// others... [FIXME] /// Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, @@ -364,6 +689,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, DeclEnd, attrs); break; case tok::kw_static_assert: + case tok::kw__Static_assert: ProhibitAttributes(attrs); SingleDecl = ParseStaticAssertDeclaration(DeclEnd); break; @@ -381,33 +707,42 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, ///[C90/C++]init-declarator-list ';' [TODO] /// [OMP] threadprivate-directive [TODO] /// +/// for-range-declaration: [C++0x 6.5p1: stmt.ranged] +/// attribute-specifier-seq[opt] type-specifier-seq declarator +/// /// If RequireSemi is false, this does not check for a ';' at the end of the /// declaration. If it is true, it checks for and eats it. +/// +/// If FRI is non-null, we might be parsing a for-range-declaration instead +/// of a simple-declaration. If we find that we are, we also parse the +/// for-range-initializer, and place it here. Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts, unsigned Context, SourceLocation &DeclEnd, ParsedAttributes &attrs, - bool RequireSemi) { + bool RequireSemi, + ForRangeInit *FRI) { // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this); DS.takeAttributesFrom(attrs); + ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, getDeclSpecContextFromDeclaratorContext(Context)); StmtResult R = Actions.ActOnVlaStmt(DS); if (R.isUsable()) Stmts.push_back(R.release()); - + // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { if (RequireSemi) ConsumeToken(); Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none, - DS); + DS); DS.complete(TheDecl); return Actions.ConvertDeclToDeclGroup(TheDecl); } - - return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd); + + return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd, FRI); } /// ParseDeclGroup - Having concluded that this is either a function @@ -416,7 +751,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts, Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, - SourceLocation *DeclEnd) { + SourceLocation *DeclEnd, + ForRangeInit *FRI) { // Parse the first declarator. ParsingDeclarator D(*this, DS, static_cast(Context)); ParseDeclarator(D); @@ -462,8 +798,24 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } } + if (ParseAttributesAfterDeclarator(D)) + return DeclGroupPtrTy(); + + // C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we + // must parse and analyze the for-range-initializer before the declaration is + // analyzed. + if (FRI && Tok.is(tok::colon)) { + FRI->ColonLoc = ConsumeToken(); + // FIXME: handle braced-init-list here. + FRI->RangeExpr = ParseExpression(); + Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); + Actions.ActOnCXXForRangeDecl(ThisDecl); + Actions.FinalizeDeclaration(ThisDecl); + return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, &ThisDecl, 1); + } + llvm::SmallVector DeclsInGroup; - Decl *FirstDecl = ParseDeclarationAfterDeclarator(D); + Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D); D.complete(FirstDecl); if (FirstDecl) DeclsInGroup.push_back(FirstDecl); @@ -517,6 +869,26 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, DeclsInGroup.size()); } +/// Parse an optional simple-asm-expr and attributes, and attach them to a +/// declarator. Returns true on an error. +bool Parser::ParseAttributesAfterDeclarator(Declarator &D) { + // If a simple-asm-expr is present, parse it. + if (Tok.is(tok::kw_asm)) { + SourceLocation Loc; + ExprResult AsmLabel(ParseSimpleAsm(&Loc)); + if (AsmLabel.isInvalid()) { + SkipUntil(tok::semi, true, true); + return true; + } + + D.setAsmLabel(AsmLabel.release()); + D.SetRangeEnd(Loc); + } + + MaybeParseGNUAttributes(D); + return false; +} + /// \brief Parse 'declaration' after parsing 'declaration-specifiers /// declarator'. This method parses the remainder of the declaration /// (including any attributes or initializer, among other things) and @@ -540,21 +912,14 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, /// Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, const ParsedTemplateInfo &TemplateInfo) { - // If a simple-asm-expr is present, parse it. - if (Tok.is(tok::kw_asm)) { - SourceLocation Loc; - ExprResult AsmLabel(ParseSimpleAsm(&Loc)); - if (AsmLabel.isInvalid()) { - SkipUntil(tok::semi, true, true); - return 0; - } + if (ParseAttributesAfterDeclarator(D)) + return 0; - D.setAsmLabel(AsmLabel.release()); - D.SetRangeEnd(Loc); - } - - MaybeParseGNUAttributes(D); + return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo); +} +Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, + const ParsedTemplateInfo &TemplateInfo) { // Inform the current actions module that we just parsed this declarator. Decl *ThisDecl = 0; switch (TemplateInfo.Kind) { @@ -780,21 +1145,25 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // // C++ doesn't need this, and isTagName doesn't take SS. if (SS == 0) { - const char *TagName = 0; + const char *TagName = 0, *FixitTagName = 0; tok::TokenKind TagKind = tok::unknown; switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) { default: break; - case DeclSpec::TST_enum: TagName="enum" ;TagKind=tok::kw_enum ;break; - case DeclSpec::TST_union: TagName="union" ;TagKind=tok::kw_union ;break; - case DeclSpec::TST_struct:TagName="struct";TagKind=tok::kw_struct;break; - case DeclSpec::TST_class: TagName="class" ;TagKind=tok::kw_class ;break; + case DeclSpec::TST_enum: + TagName="enum" ; FixitTagName = "enum " ; TagKind=tok::kw_enum ;break; + case DeclSpec::TST_union: + TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break; + case DeclSpec::TST_struct: + TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break; + case DeclSpec::TST_class: + TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break; } if (TagName) { Diag(Loc, diag::err_use_of_tag_name_without_tag) << Tok.getIdentifierInfo() << TagName << getLang().CPlusPlus - << FixItHint::CreateInsertion(Tok.getLocation(),TagName); + << FixItHint::CreateInsertion(Tok.getLocation(),FixitTagName); // Parse this as a tag as if the missing tag were present. if (TagKind == tok::kw_enum) @@ -887,9 +1256,12 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, - DeclSpecContext DSContext) { - DS.SetRangeStart(Tok.getLocation()); - DS.SetRangeEnd(Tok.getLocation()); + DeclSpecContext DSContext) { + if (DS.getSourceRange().isInvalid()) { + DS.SetRangeStart(Tok.getLocation()); + DS.SetRangeEnd(Tok.getLocation()); + } + while (1) { bool isInvalid = false; const char *PrevSpec = 0; @@ -1013,7 +1385,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ConsumeToken(); // The C++ scope. assert(Tok.is(tok::annot_template_id) && "ParseOptionalCXXScopeSpecifier not working"); - AnnotateTemplateIdTokenAsType(&SS); + AnnotateTemplateIdTokenAsType(); continue; } @@ -1056,7 +1428,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParsedType TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(), Next.getLocation(), - getCurScope(), &SS); + getCurScope(), &SS, + false, false, ParsedType(), + /*NonTrivialSourceInfo=*/true); // If the referenced identifier is not a type, then this declspec is // erroneous: We already checked about that it has no type specifier, and @@ -1105,6 +1479,24 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; } + case tok::kw___is_signed: + // GNU libstdc++ 4.4 uses __is_signed as an identifier, but Clang + // typically treats it as a trait. If we see __is_signed as it appears + // in libstdc++, e.g., + // + // static const bool __is_signed; + // + // then treat __is_signed as an identifier rather than as a keyword. + if (DS.getTypeSpecType() == TST_bool && + DS.getTypeQualifiers() == DeclSpec::TQ_const && + DS.getStorageClassSpec() == DeclSpec::SCS_static) { + Tok.getIdentifierInfo()->RevertTokenIDToIdentifier(); + Tok.setKind(tok::identifier); + } + + // We're done with the declaration-specifiers. + goto DoneWithDeclSpec; + // typedef-name case tok::identifier: { // In C++, check to see if this is a scope specifier like foo::bar::, if @@ -1247,7 +1639,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DiagID, getLang()); break; case tok::kw_auto: - if (getLang().CPlusPlus0x || getLang().ObjC2) { + if (getLang().CPlusPlus0x) { if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, DiagID, getLang()); @@ -1315,6 +1707,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID); break; + case tok::kw___int64: + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, + DiagID); + break; case tok::kw_signed: isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID); @@ -1370,6 +1766,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { PrevSpec = ""; // Not used by the diagnostic. DiagID = diag::err_bool_redeclaration; + // For better error recovery. + Tok.setKind(tok::identifier); isInvalid = true; } else { isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, @@ -1394,6 +1792,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___pixel: isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID); break; + case tok::kw___unknown_anytype: + isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc, + PrevSpec, DiagID); + break; // class-specifier: case tok::kw_class: @@ -1444,6 +1846,20 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParseDecltypeSpecifier(DS); continue; + // OpenCL qualifiers: + case tok::kw_private: + if (!getLang().OpenCL) + goto DoneWithDeclSpec; + case tok::kw___private: + case tok::kw___global: + case tok::kw___local: + case tok::kw___constant: + case tok::kw___read_only: + case tok::kw___write_only: + case tok::kw___read_write: + ParseOpenCLQualifiers(DS); + break; + case tok::less: // GCC ObjC supports types like "" as a synonym for // "id". This is hopelessly old fashioned and dangerous, @@ -1473,7 +1889,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } DS.SetRangeEnd(Tok.getLocation()); - ConsumeToken(); + if (DiagID != diag::err_bool_redeclaration) + ConsumeToken(); } } @@ -1592,6 +2009,10 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID); break; + case tok::kw___int64: + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, + DiagID); + break; case tok::kw_signed: isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID); break; @@ -1695,6 +2116,20 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, ParseDecltypeSpecifier(DS); return true; + // OpenCL qualifiers: + case tok::kw_private: + if (!getLang().OpenCL) + return false; + case tok::kw___private: + case tok::kw___global: + case tok::kw___local: + case tok::kw___constant: + case tok::kw___read_only: + case tok::kw___write_only: + case tok::kw___read_write: + ParseOpenCLQualifiers(DS); + break; + // C++0x auto support. case tok::kw_auto: if (!getLang().CPlusPlus0x) @@ -1856,7 +2291,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, } // Parse all the comma separated declarators. - DeclSpec DS; + DeclSpec DS(AttrFactory); if (!Tok.is(tok::at)) { struct CFieldCallback : FieldCallback { @@ -1917,7 +2352,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); // If attributes exist after struct contents, parse them. MaybeParseGNUAttributes(attrs); @@ -1967,7 +2402,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } // If attributes exist after tag, parse them. - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); CXXScopeSpec &SS = DS.getTypeSpecScope(); @@ -2121,7 +2556,6 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, bool Owned = false; bool IsDependent = false; - SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc; const char *PrevSpec = 0; unsigned DiagID; Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, @@ -2148,8 +2582,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } - if (DS.SetTypeSpecType(DeclSpec::TST_typename, TSTLoc, PrevSpec, DiagID, - Type.get())) + if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, + NameLoc.isValid() ? NameLoc : StartLoc, + PrevSpec, DiagID, Type.get())) Diag(StartLoc, DiagID) << PrevSpec; return; @@ -2170,10 +2605,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, if (Tok.is(tok::l_brace)) ParseEnumBody(StartLoc, TagDecl); - // FIXME: The DeclSpec should keep the locations of both the keyword - // and the name (if there is one). - if (DS.SetTypeSpecType(DeclSpec::TST_enum, TSTLoc, PrevSpec, DiagID, - TagDecl, Owned)) + if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, + NameLoc.isValid() ? NameLoc : StartLoc, + PrevSpec, DiagID, TagDecl, Owned)) Diag(StartLoc, DiagID) << PrevSpec; } @@ -2208,7 +2642,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { SourceLocation IdentLoc = ConsumeToken(); // If attributes exist after the enumerator, parse them. - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); SourceLocation EqualLoc; @@ -2252,7 +2686,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); // If attributes exist after the identifier list, parse them. - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl, @@ -2268,10 +2702,22 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { bool Parser::isTypeQualifier() const { switch (Tok.getKind()) { default: return false; + + // type-qualifier only in OpenCL + case tok::kw_private: + return getLang().OpenCL; + // type-qualifier case tok::kw_const: case tok::kw_volatile: case tok::kw_restrict: + case tok::kw___private: + case tok::kw___local: + case tok::kw___global: + case tok::kw___constant: + case tok::kw___read_only: + case tok::kw___read_write: + case tok::kw___write_only: return true; } } @@ -2285,6 +2731,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { // type-specifiers case tok::kw_short: case tok::kw_long: + case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: case tok::kw__Complex: @@ -2353,6 +2800,7 @@ bool Parser::isTypeSpecifierQualifier() { // type-specifiers case tok::kw_short: case tok::kw_long: + case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: case tok::kw__Complex: @@ -2399,7 +2847,19 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___w64: case tok::kw___ptr64: case tok::kw___pascal: + + case tok::kw___private: + case tok::kw___local: + case tok::kw___global: + case tok::kw___constant: + case tok::kw___read_only: + case tok::kw___read_write: + case tok::kw___write_only: + return true; + + case tok::kw_private: + return getLang().OpenCL; } } @@ -2412,6 +2872,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { switch (Tok.getKind()) { default: return false; + case tok::kw_private: + return getLang().OpenCL; + case tok::identifier: // foo::bar // Unfortunate hack to support "Class.factoryMethod" notation. if (getLang().ObjC1 && NextToken().is(tok::period)) @@ -2461,6 +2924,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { // type-specifiers case tok::kw_short: case tok::kw_long: + case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: case tok::kw__Complex: @@ -2498,8 +2962,8 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_virtual: case tok::kw_explicit: - // typedef-name - case tok::annot_typename: + // static_assert-declaration + case tok::kw__Static_assert: // GNU typeof support. case tok::kw_typeof: @@ -2512,6 +2976,11 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::less: return getLang().ObjC1; + // typedef-name + case tok::annot_typename: + return !DisambiguatingWithExpression || + !isStartOfObjCClassMessageMissingOpenBracket(); + case tok::kw___declspec: case tok::kw___cdecl: case tok::kw___stdcall: @@ -2521,6 +2990,15 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___ptr64: case tok::kw___forceinline: case tok::kw___pascal: + + case tok::kw___private: + case tok::kw___local: + case tok::kw___global: + case tok::kw___constant: + case tok::kw___read_only: + case tok::kw___read_write: + case tok::kw___write_only: + return true; } } @@ -2564,7 +3042,7 @@ bool Parser::isConstructorDeclarator() { DeclScopeObj.EnterDeclaratorScope(); // Optionally skip Microsoft attributes. - ParsedAttributes Attrs; + ParsedAttributes Attrs(AttrFactory); MaybeParseMicrosoftAttributes(Attrs); // Check whether the next token(s) are part of a declaration @@ -2592,14 +3070,16 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool CXX0XAttributesAllowed) { if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { SourceLocation Loc = Tok.getLocation(); - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); ParseCXX0XAttributes(attrs); if (CXX0XAttributesAllowed) DS.takeAttributesFrom(attrs); else Diag(Loc, diag::err_attributes_not_allowed); } - + + SourceLocation EndLoc; + while (1) { bool isInvalid = false; const char *PrevSpec = 0; @@ -2624,6 +3104,21 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, getLang()); break; + + // OpenCL qualifiers: + case tok::kw_private: + if (!getLang().OpenCL) + goto DoneWithTypeQuals; + case tok::kw___private: + case tok::kw___global: + case tok::kw___local: + case tok::kw___constant: + case tok::kw___read_only: + case tok::kw___write_only: + case tok::kw___read_write: + ParseOpenCLQualifiers(DS); + break; + case tok::kw___w64: case tok::kw___ptr64: case tok::kw___cdecl: @@ -2652,6 +3147,8 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, // If this is not a type-qualifier token, we're done reading type // qualifiers. First verify that DeclSpec's are consistent. DS.Finish(Diags, PP); + if (EndLoc.isValid()) + DS.SetRangeEnd(EndLoc); return; } @@ -2660,7 +3157,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, assert(PrevSpec && "Method did not return previous specifier!"); Diag(Tok, DiagID) << PrevSpec; } - ConsumeToken(); + EndLoc = ConsumeToken(); } } @@ -2719,7 +3216,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, SourceLocation Loc = ConsumeToken(); D.SetRangeEnd(Loc); - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseTypeQualifierListOpt(DS); D.ExtendWithDeclSpec(DS); @@ -2729,7 +3226,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(), - Loc, DS.takeAttributes()), + Loc), + DS.getAttributes(), /* Don't replace range end. */SourceLocation()); return; } @@ -2753,7 +3251,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, if (Kind == tok::star || Kind == tok::caret) { // Is a pointer. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseTypeQualifierListOpt(DS); D.ExtendWithDeclSpec(DS); @@ -2765,17 +3263,18 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(), DS.getVolatileSpecLoc(), - DS.getRestrictSpecLoc(), - DS.takeAttributes()), + DS.getRestrictSpecLoc()), + DS.getAttributes(), SourceLocation()); else // Remember that we parsed a Block type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), - Loc, DS.takeAttributes()), + Loc), + DS.getAttributes(), SourceLocation()); } else { // Is a reference - DeclSpec DS; + DeclSpec DS(AttrFactory); // Complain about rvalue references in C++03, but then go on and build // the declarator. @@ -2823,8 +3322,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Remember that we parsed a reference type. It doesn't have type-quals. D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc, - DS.takeAttributes(), Kind == tok::amp), + DS.getAttributes(), SourceLocation()); } } @@ -2989,7 +3488,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (!isCXXFunctionDeclarator(warnIfAmbiguous)) break; } - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); ParseFunctionDeclarator(ConsumeParen(), D, attrs); } else if (Tok.is(tok::l_square)) { ParseBracketDeclarator(D); @@ -3026,7 +3525,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { // In either case, we need to eat any attributes to be able to determine what // sort of paren this is. // - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); bool RequiresArg = false; if (Tok.is(tok::kw___attribute)) { ParseGNUAttributes(attrs); @@ -3072,13 +3571,12 @@ void Parser::ParseParenDeclarator(Declarator &D) { if (isGrouping) { bool hadGroupingParens = D.hasGroupingParens(); D.setGroupingParens(true); - if (!attrs.empty()) - D.addAttributes(attrs.getList(), SourceLocation()); ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); // Match the ')'. SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, StartLoc); - D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc), EndLoc); + D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc), + attrs, EndLoc); D.setGroupingParens(hadGroupingParens); return; @@ -3125,6 +3623,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { /// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]", /// C++0x "ref-qualifier[opt]" and "exception-specification[opt]". /// +/// [C++0x] exception-specification: +/// dynamic-exception-specification +/// noexcept-specification +/// void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, ParsedAttributes &attrs, bool RequiresArg) { @@ -3138,18 +3640,17 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); - SourceLocation RParenLoc = ConsumeParen(); // Eat the closing ')'. - SourceLocation EndLoc = RParenLoc; + SourceLocation EndLoc = ConsumeParen(); // Eat the closing ')'. // cv-qualifier-seq[opt]. - DeclSpec DS; + DeclSpec DS(AttrFactory); SourceLocation RefQualifierLoc; bool RefQualifierIsLValueRef = true; - bool hasExceptionSpec = false; - SourceLocation ThrowLoc; - bool hasAnyExceptionSpec = false; - llvm::SmallVector Exceptions; - llvm::SmallVector ExceptionRanges; + ExceptionSpecificationType ESpecType = EST_None; + SourceRange ESpecRange; + llvm::SmallVector DynamicExceptions; + llvm::SmallVector DynamicExceptionRanges; + ExprResult NoexceptExpr; if (getLang().CPlusPlus) { MaybeParseCXX0XAttributes(attrs); @@ -3161,21 +3662,19 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) { if (!getLang().CPlusPlus0x) Diag(Tok, diag::ext_ref_qualifier); - + RefQualifierIsLValueRef = Tok.is(tok::amp); RefQualifierLoc = ConsumeToken(); EndLoc = RefQualifierLoc; } - + // Parse exception-specification[opt]. - if (Tok.is(tok::kw_throw)) { - hasExceptionSpec = true; - ThrowLoc = Tok.getLocation(); - ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges, - hasAnyExceptionSpec); - assert(Exceptions.size() == ExceptionRanges.size() && - "Produced different number of exception types and ranges."); - } + ESpecType = MaybeParseExceptionSpecification(ESpecRange, + DynamicExceptions, + DynamicExceptionRanges, + NoexceptExpr); + if (ESpecType != EST_None) + EndLoc = ESpecRange.getEnd(); // Parse trailing-return-type. if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { @@ -3185,22 +3684,22 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Remember that we parsed a function type, and remember the attributes. // int() -> no prototype, no '...'. - D.AddTypeInfo(DeclaratorChunk::getFunction(attrs, - /*prototype*/getLang().CPlusPlus, + D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus, /*variadic*/ false, SourceLocation(), /*arglist*/ 0, 0, DS.getTypeQualifiers(), RefQualifierIsLValueRef, RefQualifierLoc, - hasExceptionSpec, ThrowLoc, - hasAnyExceptionSpec, - Exceptions.data(), - ExceptionRanges.data(), - Exceptions.size(), - LParenLoc, RParenLoc, D, + ESpecType, ESpecRange.getBegin(), + DynamicExceptions.data(), + DynamicExceptionRanges.data(), + DynamicExceptions.size(), + NoexceptExpr.isUsable() ? + NoexceptExpr.get() : 0, + LParenLoc, EndLoc, D, TrailingReturnType), - EndLoc); + attrs, EndLoc); return; } @@ -3264,7 +3763,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Parse the declaration-specifiers. // Just use the ParsingDeclaration "scope" of the declarator. - DeclSpec DS; + DeclSpec DS(AttrFactory); // Skip any Microsoft attributes before a param. if (getLang().Microsoft && Tok.is(tok::l_square)) @@ -3388,17 +3887,16 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, } // If we have the closing ')', eat it. - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - SourceLocation EndLoc = RParenLoc; + SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - DeclSpec DS; + DeclSpec DS(AttrFactory); SourceLocation RefQualifierLoc; bool RefQualifierIsLValueRef = true; - bool hasExceptionSpec = false; - SourceLocation ThrowLoc; - bool hasAnyExceptionSpec = false; - llvm::SmallVector Exceptions; - llvm::SmallVector ExceptionRanges; + ExceptionSpecificationType ESpecType = EST_None; + SourceRange ESpecRange; + llvm::SmallVector DynamicExceptions; + llvm::SmallVector DynamicExceptionRanges; + ExprResult NoexceptExpr; if (getLang().CPlusPlus) { MaybeParseCXX0XAttributes(attrs); @@ -3418,15 +3916,17 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, EndLoc = RefQualifierLoc; } + // FIXME: We should leave the prototype scope before parsing the exception + // specification, and then reenter it when parsing the trailing return type. + // FIXMEFIXME: Why? That wouldn't be right for the noexcept clause. + // Parse exception-specification[opt]. - if (Tok.is(tok::kw_throw)) { - hasExceptionSpec = true; - ThrowLoc = Tok.getLocation(); - ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges, - hasAnyExceptionSpec); - assert(Exceptions.size() == ExceptionRanges.size() && - "Produced different number of exception types and ranges."); - } + ESpecType = MaybeParseExceptionSpecification(ESpecRange, + DynamicExceptions, + DynamicExceptionRanges, + NoexceptExpr); + if (ESpecType != EST_None) + EndLoc = ESpecRange.getEnd(); // Parse trailing-return-type. if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { @@ -3434,28 +3934,25 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, } } - // FIXME: We should leave the prototype scope before parsing the exception - // specification, and then reenter it when parsing the trailing return type. - // Leave prototype scope. PrototypeScope.Exit(); // Remember that we parsed a function type, and remember the attributes. - D.AddTypeInfo(DeclaratorChunk::getFunction(attrs, - /*proto*/true, IsVariadic, + D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic, EllipsisLoc, ParamInfo.data(), ParamInfo.size(), DS.getTypeQualifiers(), RefQualifierIsLValueRef, RefQualifierLoc, - hasExceptionSpec, ThrowLoc, - hasAnyExceptionSpec, - Exceptions.data(), - ExceptionRanges.data(), - Exceptions.size(), - LParenLoc, RParenLoc, D, + ESpecType, ESpecRange.getBegin(), + DynamicExceptions.data(), + DynamicExceptionRanges.data(), + DynamicExceptions.size(), + NoexceptExpr.isUsable() ? + NoexceptExpr.get() : 0, + LParenLoc, EndLoc, D, TrailingReturnType), - EndLoc); + attrs, EndLoc); } /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator @@ -3524,16 +4021,15 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, // Remember that we parsed a function type, and remember the attributes. This // function type is always a K&R style function type, which is not varargs and // has no prototype. - D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(), - /*proto*/false, /*varargs*/false, + ParsedAttributes attrs(AttrFactory); + D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false, SourceLocation(), &ParamInfo[0], ParamInfo.size(), /*TypeQuals*/0, true, SourceLocation(), - /*exception*/false, - SourceLocation(), false, 0, 0, 0, - LParenLoc, RLoc, D), - RLoc); + EST_None, SourceLocation(), 0, 0, + 0, 0, LParenLoc, RLoc, D), + attrs, RLoc); } /// [C90] direct-declarator '[' constant-expression[opt] ']' @@ -3548,14 +4044,14 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // This code does a fast path to handle some of the most obvious cases. if (Tok.getKind() == tok::r_square) { SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); // Remember that we parsed the empty array type. ExprResult NumElements; - D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, false, 0, + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, StartLoc, EndLoc), - EndLoc); + attrs, EndLoc); return; } else if (Tok.getKind() == tok::numeric_constant && GetLookAheadToken(1).is(tok::r_square)) { @@ -3564,14 +4060,14 @@ void Parser::ParseBracketDeclarator(Declarator &D) { ConsumeToken(); SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, 0, + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(), StartLoc, EndLoc), - EndLoc); + attrs, EndLoc); return; } @@ -3582,7 +4078,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // If there is a type-qualifier-list, read it now. // Type qualifiers in an array subscript are a C99 feature. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseTypeQualifierListOpt(DS, false /*no attributes*/); // If we haven't already read 'static', check to see if there is one after the @@ -3630,15 +4126,15 @@ void Parser::ParseBracketDeclarator(Declarator &D) { SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), attrs, + D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), isStar, NumElements.release(), StartLoc, EndLoc), - EndLoc); + attrs, EndLoc); } /// [GNU] typeof-specifier: @@ -3656,10 +4152,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { bool isCastExpr; ParsedType CastTy; SourceRange CastRange; - ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok, - isCastExpr, - CastTy, - CastRange); + ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, + CastTy, CastRange); if (hasParens) DS.setTypeofParensRange(CastRange); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index b3ad25b024fc..8c0aa1ba694c 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -69,11 +69,9 @@ Decl *Parser::ParseNamespace(unsigned Context, } // Read label attributes, if present. - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); if (Tok.is(tok::kw___attribute)) { attrTok = Tok; - - // FIXME: save these somewhere. ParseGNUAttributes(attrs); } @@ -111,14 +109,14 @@ Decl *Parser::ParseNamespace(unsigned Context, ParseScope NamespaceScope(this, Scope::DeclScope); Decl *NamespcDecl = - Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, IdentLoc, Ident, - LBrace, attrs.getList()); + Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc, + IdentLoc, Ident, LBrace, attrs.getList()); PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc, "parsing namespace"); while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); MaybeParseMicrosoftAttributes(attrs); ParseExternalDeclaration(attrs); @@ -138,9 +136,9 @@ Decl *Parser::ParseNamespace(unsigned Context, /// alias definition. /// Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, - SourceLocation AliasLoc, - IdentifierInfo *Alias, - SourceLocation &DeclEnd) { + SourceLocation AliasLoc, + IdentifierInfo *Alias, + SourceLocation &DeclEnd) { assert(Tok.is(tok::equal) && "Not equal token"); ConsumeToken(); // eat the '='. @@ -194,16 +192,21 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { ParseScope LinkageScope(this, Scope::DeclScope); Decl *LinkageSpec = Actions.ActOnStartLinkageSpecification(getCurScope(), - /*FIXME: */SourceLocation(), + DS.getSourceRange().getBegin(), Loc, Lang, - Tok.is(tok::l_brace)? Tok.getLocation() + Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation()); - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); MaybeParseMicrosoftAttributes(attrs); if (Tok.isNot(tok::l_brace)) { + // Reset the source range in DS, as the leading "extern" + // does not really belong to the inner declaration ... + DS.SetRangeStart(SourceLocation()); + DS.SetRangeEnd(SourceLocation()); + // ... but anyway remember that such an "extern" was seen. DS.setExternInLinkageSpec(true); ParseExternalDeclaration(attrs, &DS); return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec, @@ -216,7 +219,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { SourceLocation LBrace = ConsumeBrace(); while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); MaybeParseMicrosoftAttributes(attrs); ParseExternalDeclaration(attrs); @@ -255,7 +258,7 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, return ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs); } - // Otherwise, it must be a using-declaration. + // Otherwise, it must be a using-declaration or an alias-declaration. // Using declarations can't have attributes. ProhibitAttributes(attrs); @@ -325,14 +328,17 @@ Decl *Parser::ParseUsingDirective(unsigned Context, IdentLoc, NamespcName, attrs.getList()); } -/// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that -/// 'using' was already seen. +/// ParseUsingDeclaration - Parse C++ using-declaration or alias-declaration. +/// Assumes that 'using' was already seen. /// /// using-declaration: [C++ 7.3.p3: namespace.udecl] /// 'using' 'typename'[opt] ::[opt] nested-name-specifier /// unqualified-id /// 'using' :: unqualified-id /// +/// alias-declaration: C++0x [decl.typedef]p2 +/// 'using' identifier = type-id ; +/// Decl *Parser::ParseUsingDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, @@ -342,10 +348,6 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, SourceLocation TypenameLoc; bool IsTypeName; - // TODO: in C++0x, if we have template parameters this must be a - // template alias: - // template <...> using id = type; - // Ignore optional 'typename'. // FIXME: This is wrong; we should parse this as a typename-specifier. if (Tok.is(tok::kw_typename)) { @@ -379,17 +381,48 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, return 0; } - // Parse (optional) attributes (most likely GNU strong-using extension). - ParsedAttributes attrs; - MaybeParseGNUAttributes(attrs); + ParsedAttributes attrs(AttrFactory); + + // Maybe this is an alias-declaration. + bool IsAliasDecl = Tok.is(tok::equal); + TypeResult TypeAlias; + if (IsAliasDecl) { + // TODO: Do we want to support attributes somewhere in an alias declaration? + // Can't follow GCC since it doesn't support them yet! + ConsumeToken(); + + if (!getLang().CPlusPlus0x) + Diag(Tok.getLocation(), diag::ext_alias_declaration); + + // Name must be an identifier. + if (Name.getKind() != UnqualifiedId::IK_Identifier) { + Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier); + // No removal fixit: can't recover from this. + SkipUntil(tok::semi); + return 0; + } else if (IsTypeName) + Diag(TypenameLoc, diag::err_alias_declaration_not_identifier) + << FixItHint::CreateRemoval(SourceRange(TypenameLoc, + SS.isNotEmpty() ? SS.getEndLoc() : TypenameLoc)); + else if (SS.isNotEmpty()) + Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) + << FixItHint::CreateRemoval(SS.getRange()); + + TypeAlias = ParseTypeName(0, Declarator::AliasDeclContext); + } else + // Parse (optional) attributes (most likely GNU strong-using extension). + MaybeParseGNUAttributes(attrs); // Eat ';'. DeclEnd = Tok.getLocation(); ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - !attrs.empty() ? "attributes list" : "using declaration", + !attrs.empty() ? "attributes list" : + IsAliasDecl ? "alias declaration" : "using declaration", tok::semi); // Diagnose an attempt to declare a templated using-declaration. + // TODO: in C++0x, alias-declarations can be templates: + // template <...> using id = type; if (TemplateInfo.Kind) { SourceRange R = TemplateInfo.getSourceRange(); Diag(UsingLoc, diag::err_templated_using_declaration) @@ -401,18 +434,30 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, return 0; } + if (IsAliasDecl) + return Actions.ActOnAliasDeclaration(getCurScope(), AS, UsingLoc, Name, + TypeAlias); + return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS, Name, attrs.getList(), IsTypeName, TypenameLoc); } -/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion. +/// ParseStaticAssertDeclaration - Parse C++0x or C1X static_assert-declaration. /// -/// static_assert-declaration: -/// static_assert ( constant-expression , string-literal ) ; +/// [C++0x] static_assert-declaration: +/// static_assert ( constant-expression , string-literal ) ; +/// +/// [C1X] static_assert-declaration: +/// _Static_assert ( constant-expression , string-literal ) ; /// Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ - assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration"); + assert((Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert)) && + "Not a static_assert declaration"); + + if (Tok.is(tok::kw__Static_assert) && !getLang().C1X) + Diag(Tok, diag::ext_c1x_static_assert); + SourceLocation StaticAssertLoc = ConsumeToken(); if (Tok.isNot(tok::l_paren)) { @@ -441,14 +486,15 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ if (AssertMessage.isInvalid()) return 0; - MatchRHSPunctuation(tok::r_paren, LParenLoc); + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); DeclEnd = Tok.getLocation(); ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert); return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, AssertExpr.take(), - AssertMessage.take()); + AssertMessage.take(), + RParenLoc); } /// ParseDecltypeSpecifier - Parse a C++0x decltype specifier. @@ -508,14 +554,14 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) { /// simple-template-id /// Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, - CXXScopeSpec *SS) { + CXXScopeSpec &SS) { // Check whether we have a template-id that names a type. if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = static_cast(Tok.getAnnotationValue()); if (TemplateId->Kind == TNK_Type_template || TemplateId->Kind == TNK_Dependent_template_name) { - AnnotateTemplateIdTokenAsType(SS); + AnnotateTemplateIdTokenAsType(); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); ParsedType Type = getTypeAnnotation(Tok); @@ -544,7 +590,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, TemplateNameKind TNK = TNK_Type_template; TemplateTy Template; if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(), - SS, Template, TNK)) { + &SS, Template, TNK)) { Diag(IdLoc, diag::err_unknown_template_name) << Id; } @@ -561,7 +607,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, SourceLocation(), true)) return true; if (TNK == TNK_Dependent_template_name) - AnnotateTemplateIdTokenAsType(SS); + AnnotateTemplateIdTokenAsType(); // If we didn't end up with a typename token, there's nothing more we // can do. @@ -577,7 +623,9 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, } // We have an identifier; check whether it is actually a type. - ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), SS, true); + ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true, + false, ParsedType(), + /*NonTrivialTypeSourceInfo=*/true); if (!Type) { Diag(IdLoc, diag::err_expected_class_name); return true; @@ -587,10 +635,10 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, EndLocation = IdLoc; // Fake up a Declarator to use with ActOnTypeName. - DeclSpec DS; + DeclSpec DS(AttrFactory); DS.SetRangeStart(IdLoc); DS.SetRangeEnd(EndLocation); - DS.getTypeSpecScope() = *SS; + DS.getTypeSpecScope() = SS; const char *PrevSpec = 0; unsigned DiagID; @@ -674,7 +722,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, SuppressingAccessChecks = true; } - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); // If attributes exist after tag, parse them. if (Tok.is(tok::kw___attribute)) ParseGNUAttributes(attrs); @@ -688,22 +736,30 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // styles of attributes? MaybeParseCXX0XAttributes(attrs); - if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) { - // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but - // __is_pod is a keyword in GCC >= 4.3. Therefore, when we see the - // token sequence "struct __is_pod", make __is_pod into a normal - // identifier rather than a keyword, to allow libstdc++ 4.2 to work - // properly. - Tok.getIdentifierInfo()->RevertTokenIDToIdentifier(); - Tok.setKind(tok::identifier); - } - - if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_empty)) { - // GNU libstdc++ 4.2 uses __is_empty as the name of a struct template, but - // __is_empty is a keyword in GCC >= 4.3. Therefore, when we see the - // token sequence "struct __is_empty", make __is_empty into a normal - // identifier rather than a keyword, to allow libstdc++ 4.2 to work - // properly. + if (TagType == DeclSpec::TST_struct && + !Tok.is(tok::identifier) && + Tok.getIdentifierInfo() && + (Tok.is(tok::kw___is_arithmetic) || + Tok.is(tok::kw___is_convertible) || + Tok.is(tok::kw___is_empty) || + Tok.is(tok::kw___is_floating_point) || + Tok.is(tok::kw___is_function) || + Tok.is(tok::kw___is_fundamental) || + Tok.is(tok::kw___is_integral) || + Tok.is(tok::kw___is_member_function_pointer) || + Tok.is(tok::kw___is_member_pointer) || + Tok.is(tok::kw___is_pod) || + Tok.is(tok::kw___is_pointer) || + Tok.is(tok::kw___is_same) || + Tok.is(tok::kw___is_scalar) || + Tok.is(tok::kw___is_signed) || + Tok.is(tok::kw___is_unsigned) || + Tok.is(tok::kw___is_void))) { + // GNU libstdc++ 4.2 and libc++ uaw certain intrinsic names as the + // name of struct templates, but some are keywords in GCC >= 4.3 + // and Clang. Therefore, when we see the token sequence "struct + // X", make X into a normal identifier rather than a keyword, to + // allow libstdc++ 4.2 and libc++ to work properly. Tok.getIdentifierInfo()->RevertTokenIDToIdentifier(); Tok.setKind(tok::identifier); } @@ -737,7 +793,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // a class (or template thereof). TemplateArgList TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS, + if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, SS, true, LAngleLoc, TemplateArgs, RAngleLoc)) { // We couldn't parse the template argument list at all, so don't @@ -779,7 +835,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateId = static_cast(Tok.getAnnotationValue()); NameLoc = ConsumeToken(); - if (TemplateId->Kind != TNK_Type_template) { + if (TemplateId->Kind != TNK_Type_template && + TemplateId->Kind != TNK_Dependent_template_name) { // The template-name in the simple-template-id refers to // something other than a class template. Give an appropriate // error message and skip to the ';'. @@ -808,7 +865,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // There are four options here. If we have 'struct foo;', then this // is either a forward declaration or a friend declaration, which // have to be treated differently. If we have 'struct foo {...', - // 'struct foo :...' or 'struct foo ' then this is a + // 'struct foo :...' or 'struct foo final[opt]' then this is a // definition. Otherwise we have something like 'struct foo xyz', a reference. // However, in some contexts, things look like declarations but are just // references, e.g. @@ -821,7 +878,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TUK = Sema::TUK_Reference; else if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon)) || - isCXX0XClassVirtSpecifier() != ClassVirtSpecifiers::CVS_None) { + isCXX0XFinalKeyword()) { if (DS.isFriendSpecified()) { // C++ [class.friend]p2: // A class shall not be defined in a friend declaration. @@ -891,15 +948,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } else if (TUK == Sema::TUK_Reference || (TUK == Sema::TUK_Friend && TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { - TypeResult - = Actions.ActOnTemplateIdType(TemplateId->Template, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc); - - TypeResult = Actions.ActOnTagTemplateIdType(SS, TypeResult, TUK, - TagType, StartLoc); + TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, + StartLoc, + TemplateId->SS, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); } else { // This is an explicit specialization or a class template // partial specialization. @@ -1007,26 +1063,24 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TUK == Sema::TUK_Definition) { assert(Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon)) || - isCXX0XClassVirtSpecifier() != ClassVirtSpecifiers::CVS_None); + isCXX0XFinalKeyword()); if (getLang().CPlusPlus) ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get()); else ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get()); } - // FIXME: The DeclSpec should keep the locations of both the keyword and the - // name (if there is one). - SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc; - const char *PrevSpec = 0; unsigned DiagID; bool Result; if (!TypeResult.isInvalid()) { - Result = DS.SetTypeSpecType(DeclSpec::TST_typename, TSTLoc, + Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, + NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec, DiagID, TypeResult.get()); } else if (!TagOrTempResult.isInvalid()) { - Result = DS.SetTypeSpecType(TagType, TSTLoc, PrevSpec, DiagID, - TagOrTempResult.get(), Owned); + Result = DS.SetTypeSpecType(TagType, StartLoc, + NameLoc.isValid() ? NameLoc : StartLoc, + PrevSpec, DiagID, TagOrTempResult.get(), Owned); } else { DS.SetTypeSpecError(); return; @@ -1072,7 +1126,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, case tok::kw_mutable: // struct foo {...} mutable x; // As shown above, type qualifiers and storage class specifiers absolutely // can occur after class specifiers according to the grammar. However, - // almost noone actually writes code like this. If we see one of these, + // almost no one actually writes code like this. If we see one of these, // it is much more likely that someone missed a semi colon and the // type/storage class specifier we're seeing is part of the *next* // intended declaration, as in: @@ -1195,7 +1249,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { // Parse the class-name. SourceLocation EndLocation; - TypeResult BaseType = ParseClassName(EndLocation, &SS); + TypeResult BaseType = ParseClassName(EndLocation, SS); if (BaseType.isInvalid()) return true; @@ -1270,14 +1324,10 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, /// virt-specifier: /// override /// final -/// new VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier() const { if (!getLang().CPlusPlus) return VirtSpecifiers::VS_None; - if (Tok.is(tok::kw_new)) - return VirtSpecifiers::VS_New; - if (Tok.is(tok::identifier)) { IdentifierInfo *II = Tok.getIdentifierInfo(); @@ -1323,61 +1373,22 @@ void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS) { } } -/// isCXX0XClassVirtSpecifier - Determine whether the next token is a C++0x -/// class-virt-specifier. -/// -/// class-virt-specifier: -/// final -/// explicit -ClassVirtSpecifiers::Specifier Parser::isCXX0XClassVirtSpecifier() const { +/// isCXX0XFinalKeyword - Determine whether the next token is a C++0x +/// contextual 'final' keyword. +bool Parser::isCXX0XFinalKeyword() const { if (!getLang().CPlusPlus) - return ClassVirtSpecifiers::CVS_None; + return false; - if (Tok.is(tok::kw_explicit)) - return ClassVirtSpecifiers::CVS_Explicit; + if (!Tok.is(tok::identifier)) + return false; - if (Tok.is(tok::identifier)) { - IdentifierInfo *II = Tok.getIdentifierInfo(); + // Initialize the contextual keywords. + if (!Ident_final) { + Ident_final = &PP.getIdentifierTable().get("final"); + Ident_override = &PP.getIdentifierTable().get("override"); + } - // Initialize the contextual keywords. - if (!Ident_final) { - Ident_final = &PP.getIdentifierTable().get("final"); - Ident_override = &PP.getIdentifierTable().get("override"); - } - - if (II == Ident_final) - return ClassVirtSpecifiers::CVS_Final; - } - - return ClassVirtSpecifiers::CVS_None; -} - -/// ParseOptionalCXX0XClassVirtSpecifierSeq - Parse a class-virt-specifier-seq. -/// -/// class-virt-specifier-seq: -/// class-virt-specifier -/// class-virt-specifier-seq class-virt-specifier -void Parser::ParseOptionalCXX0XClassVirtSpecifierSeq(ClassVirtSpecifiers &CVS) { - while (true) { - ClassVirtSpecifiers::Specifier Specifier = isCXX0XClassVirtSpecifier(); - if (Specifier == ClassVirtSpecifiers::CVS_None) - return; - - // C++ [class]p1: - // A class-virt-specifier-seq shall contain at most one of each - // class-virt-specifier. - const char *PrevSpec = 0; - if (CVS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec)) - Diag(Tok.getLocation(), diag::err_duplicate_class_virt_specifier) - << PrevSpec - << FixItHint::CreateRemoval(Tok.getLocation()); - - if (!getLang().CPlusPlus0x) - Diag(Tok.getLocation(), diag::ext_override_control_keyword) - << ClassVirtSpecifiers::getSpecifierName(Specifier); - - ConsumeToken(); - } + return Tok.getIdentifierInfo() == Ident_final; } /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration. @@ -1418,6 +1429,17 @@ void Parser::ParseOptionalCXX0XClassVirtSpecifierSeq(ClassVirtSpecifiers &CVS) { void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, const ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { + if (Tok.is(tok::at)) { + if (getLang().ObjC1 && NextToken().isObjCAtKeyword(tok::objc_defs)) + Diag(Tok, diag::err_at_defs_cxx); + else + Diag(Tok, diag::err_at_in_class); + + ConsumeToken(); + SkipUntil(tok::r_brace); + return; + } + // Access declarations. if (!TemplateInfo.Kind && (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) && @@ -1459,7 +1481,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } // static_assert-declaration - if (Tok.is(tok::kw_static_assert)) { + if (Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert)) { // FIXME: Check for templates SourceLocation DeclEnd; ParseStaticAssertDeclaration(DeclEnd); @@ -1487,7 +1509,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // is a bitfield. ColonProtectionRAIIObject X(*this); - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); // Optional C++0x attribute-specifier MaybeParseCXX0XAttributes(attrs); MaybeParseMicrosoftAttributes(attrs); @@ -1542,7 +1564,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Error parsing the declarator? if (!DeclaratorInfo.hasName()) { // If so, skip until the semi-colon or a }. - SkipUntil(tok::r_brace, true); + SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) ConsumeToken(); return; @@ -1763,8 +1785,24 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (TagDecl) Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); - ClassVirtSpecifiers CVS; - ParseOptionalCXX0XClassVirtSpecifierSeq(CVS); + SourceLocation FinalLoc; + + // Parse the optional 'final' keyword. + if (getLang().CPlusPlus && Tok.is(tok::identifier)) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + + // Initialize the contextual keywords. + if (!Ident_final) { + Ident_final = &PP.getIdentifierTable().get("final"); + Ident_override = &PP.getIdentifierTable().get("override"); + } + + if (II == Ident_final) + FinalLoc = ConsumeToken(); + + if (!getLang().CPlusPlus0x) + Diag(FinalLoc, diag::ext_override_control_keyword) << "final"; + } if (Tok.is(tok::colon)) { ParseBaseClause(TagDecl); @@ -1783,7 +1821,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, SourceLocation LBraceLoc = ConsumeBrace(); if (TagDecl) - Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, CVS, + Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc, LBraceLoc); // C++ 11p3: Members of a class defined with the keyword class are private @@ -1836,7 +1874,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } // If attributes exist after class contents, parse them. - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); if (TagDecl) @@ -1893,6 +1931,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'"); + // Poison the SEH identifiers so they are flagged as illegal in constructor initializers + PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); SourceLocation ColonLoc = ConsumeToken(); llvm::SmallVector MemInitializers; @@ -1956,7 +1996,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { = static_cast(Tok.getAnnotationValue()); if (TemplateId->Kind == TNK_Type_template || TemplateId->Kind == TNK_Dependent_template_name) { - AnnotateTemplateIdTokenAsType(&SS); + AnnotateTemplateIdTokenAsType(); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TemplateTypeTy = getTypeAnnotation(Tok); } @@ -1999,10 +2039,81 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { EllipsisLoc); } -/// ParseExceptionSpecification - Parse a C++ exception-specification -/// (C++ [except.spec]). +/// \brief Parse a C++ exception-specification if present (C++0x [except.spec]). /// /// exception-specification: +/// dynamic-exception-specification +/// noexcept-specification +/// +/// noexcept-specification: +/// 'noexcept' +/// 'noexcept' '(' constant-expression ')' +ExceptionSpecificationType +Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange, + llvm::SmallVectorImpl &DynamicExceptions, + llvm::SmallVectorImpl &DynamicExceptionRanges, + ExprResult &NoexceptExpr) { + ExceptionSpecificationType Result = EST_None; + + // See if there's a dynamic specification. + if (Tok.is(tok::kw_throw)) { + Result = ParseDynamicExceptionSpecification(SpecificationRange, + DynamicExceptions, + DynamicExceptionRanges); + assert(DynamicExceptions.size() == DynamicExceptionRanges.size() && + "Produced different number of exception types and ranges."); + } + + // If there's no noexcept specification, we're done. + if (Tok.isNot(tok::kw_noexcept)) + return Result; + + // If we already had a dynamic specification, parse the noexcept for, + // recovery, but emit a diagnostic and don't store the results. + SourceRange NoexceptRange; + ExceptionSpecificationType NoexceptType = EST_None; + + SourceLocation KeywordLoc = ConsumeToken(); + if (Tok.is(tok::l_paren)) { + // There is an argument. + SourceLocation LParenLoc = ConsumeParen(); + NoexceptType = EST_ComputedNoexcept; + NoexceptExpr = ParseConstantExpression(); + // The argument must be contextually convertible to bool. We use + // ActOnBooleanCondition for this purpose. + if (!NoexceptExpr.isInvalid()) + NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc, + NoexceptExpr.get()); + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + NoexceptRange = SourceRange(KeywordLoc, RParenLoc); + } else { + // There is no argument. + NoexceptType = EST_BasicNoexcept; + NoexceptRange = SourceRange(KeywordLoc, KeywordLoc); + } + + if (Result == EST_None) { + SpecificationRange = NoexceptRange; + Result = NoexceptType; + + // If there's a dynamic specification after a noexcept specification, + // parse that and ignore the results. + if (Tok.is(tok::kw_throw)) { + Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification); + ParseDynamicExceptionSpecification(NoexceptRange, DynamicExceptions, + DynamicExceptionRanges); + } + } else { + Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification); + } + + return Result; +} + +/// ParseDynamicExceptionSpecification - Parse a C++ +/// dynamic-exception-specification (C++ [except.spec]). +/// +/// dynamic-exception-specification: /// 'throw' '(' type-id-list [opt] ')' /// [MS] 'throw' '(' '...' ')' /// @@ -2010,46 +2121,47 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { /// type-id ... [opt] /// type-id-list ',' type-id ... [opt] /// -bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc, - llvm::SmallVectorImpl - &Exceptions, - llvm::SmallVectorImpl - &Ranges, - bool &hasAnyExceptionSpec) { +ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification( + SourceRange &SpecificationRange, + llvm::SmallVectorImpl &Exceptions, + llvm::SmallVectorImpl &Ranges) { assert(Tok.is(tok::kw_throw) && "expected throw"); - ConsumeToken(); + SpecificationRange.setBegin(ConsumeToken()); if (!Tok.is(tok::l_paren)) { - return Diag(Tok, diag::err_expected_lparen_after) << "throw"; + Diag(Tok, diag::err_expected_lparen_after) << "throw"; + SpecificationRange.setEnd(SpecificationRange.getBegin()); + return EST_DynamicNone; } SourceLocation LParenLoc = ConsumeParen(); // Parse throw(...), a Microsoft extension that means "this function // can throw anything". if (Tok.is(tok::ellipsis)) { - hasAnyExceptionSpec = true; SourceLocation EllipsisLoc = ConsumeToken(); if (!getLang().Microsoft) Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec); - EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - return false; + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + SpecificationRange.setEnd(RParenLoc); + return EST_MSAny; } // Parse the sequence of type-ids. SourceRange Range; while (Tok.isNot(tok::r_paren)) { TypeResult Res(ParseTypeName(&Range)); - + if (Tok.is(tok::ellipsis)) { // C++0x [temp.variadic]p5: // - In a dynamic-exception-specification (15.4); the pattern is a // type-id. SourceLocation Ellipsis = ConsumeToken(); + Range.setEnd(Ellipsis); if (!Res.isInvalid()) Res = Actions.ActOnPackExpansion(Res.get(), Ellipsis); } - + if (!Res.isInvalid()) { Exceptions.push_back(Res.get()); Ranges.push_back(Range); @@ -2061,8 +2173,8 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc, break; } - EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - return false; + SpecificationRange.setEnd(MatchRHSPunctuation(tok::r_paren, LParenLoc)); + return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic; } /// ParseTrailingReturnType - Parse a trailing return type on a new-style @@ -2236,8 +2348,8 @@ void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, break; } - attrs.add(AttrFactory.Create(AttrName, AttrLoc, 0, AttrLoc, 0, - SourceLocation(), 0, 0, false, true)); + attrs.addNew(AttrName, AttrLoc, 0, AttrLoc, 0, + SourceLocation(), 0, 0, false, true); AttrParsed = true; break; } @@ -2257,9 +2369,9 @@ void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, ExprVector ArgExprs(Actions); ArgExprs.push_back(ArgExpr.release()); - attrs.add(AttrFactory.Create(AttrName, AttrLoc, 0, AttrLoc, - 0, ParamLoc, ArgExprs.take(), 1, - false, true)); + attrs.addNew(AttrName, AttrLoc, 0, AttrLoc, + 0, ParamLoc, ArgExprs.take(), 1, + false, true); AttrParsed = true; break; @@ -2301,8 +2413,8 @@ ExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) { SourceLocation TypeLoc = Tok.getLocation(); ParsedType Ty = ParseTypeName().get(); SourceRange TypeRange(Start, Tok.getLocation()); - return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true, - Ty.getAsOpaquePtr(), TypeRange); + return Actions.ActOnUnaryExprOrTypeTraitExpr(TypeLoc, UETT_AlignOf, true, + Ty.getAsOpaquePtr(), TypeRange); } else return ParseConstantExpression(); } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index 616c251583fb..91fe1e1935e9 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -174,7 +174,6 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind, /// expression: [C99 6.5.17] /// assignment-expression ...[opt] /// expression ',' assignment-expression ...[opt] -/// ExprResult Parser::ParseExpression() { ExprResult LHS(ParseAssignmentExpression()); return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); @@ -212,7 +211,6 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { } /// ParseAssignmentExpression - Parse an expr that doesn't include commas. -/// ExprResult Parser::ParseAssignmentExpression() { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); @@ -222,7 +220,7 @@ ExprResult Parser::ParseAssignmentExpression() { if (Tok.is(tok::kw_throw)) return ParseThrowExpression(); - ExprResult LHS(ParseCastExpression(false)); + ExprResult LHS = ParseCastExpression(false, false, ParsedType()); return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment); } @@ -415,8 +413,8 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { /// due to member pointers. /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, - bool isAddressOfOperand, - ParsedType TypeOfCast) { + bool isAddressOfOperand, + ParsedType TypeOfCast) { bool NotCastExpr; ExprResult Res = ParseCastExpression(isUnaryExpression, isAddressOfOperand, @@ -465,6 +463,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// [C++] boolean-literal [C++ 2.13.5] /// [C++0x] 'nullptr' [C++0x 2.14.7] /// '(' expression ')' +/// [C1X] generic-selection /// '__func__' [C99 6.4.2.2] /// [GNU] '__FUNCTION__' /// [GNU] '__PRETTY_FUNCTION__' @@ -491,6 +490,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// [C++] 'this' [C++ 9.3.2] /// [G++] unary-type-trait '(' type-id ')' /// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO] +/// [EMBT] array-type-trait '(' type-id ',' integer ')' /// [clang] '^' block-literal /// /// constant: [C99 6.4.4] @@ -520,6 +520,34 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// '::'[opt] 'delete' cast-expression /// '::'[opt] 'delete' '[' ']' cast-expression /// +/// [GNU/Embarcadero] unary-type-trait: +/// '__is_arithmetic' +/// '__is_floating_point' +/// '__is_integral' +/// '__is_lvalue_expr' +/// '__is_rvalue_expr' +/// '__is_complete_type' +/// '__is_void' +/// '__is_array' +/// '__is_function' +/// '__is_reference' +/// '__is_lvalue_reference' +/// '__is_rvalue_reference' +/// '__is_fundamental' +/// '__is_object' +/// '__is_scalar' +/// '__is_compound' +/// '__is_pointer' +/// '__is_member_object_pointer' +/// '__is_member_function_pointer' +/// '__is_member_pointer' +/// '__is_const' +/// '__is_volatile' +/// '__is_trivial' +/// '__is_standard_layout' +/// '__is_signed' +/// '__is_unsigned' +/// /// [GNU] unary-type-trait: /// '__has_nothrow_assign' /// '__has_nothrow_copy' @@ -535,11 +563,22 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// '__is_enum' /// '__is_pod' /// '__is_polymorphic' +/// '__is_trivial' /// '__is_union' /// /// binary-type-trait: /// [GNU] '__is_base_of' /// [MS] '__is_convertible_to' +/// '__is_convertible' +/// '__is_same' +/// +/// [Embarcadero] array-type-trait: +/// '__array_rank' +/// '__array_extent' +/// +/// [Embarcadero] expression-trait: +/// '__is_lvalue_expr' +/// '__is_rvalue_expr' /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, @@ -610,6 +649,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_nullptr: return Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); + case tok::annot_primary_expr: + assert(Res.get() == 0 && "Stray primary-expression annotation?"); + Res = getExprAnnotation(Tok); + ConsumeToken(); + break; + case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant @@ -683,7 +728,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope())) if (Typ.get()->isObjCObjectOrInterfaceType()) { // Fake up a Declarator to use with ActOnTypeName. - DeclSpec DS; + DeclSpec DS(AttrFactory); DS.SetRangeStart(ILoc); DS.SetRangeEnd(ILoc); const char *PrevSpec = 0; @@ -731,6 +776,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::wide_string_literal: Res = ParseStringLiteralExpression(); break; + case tok::kw__Generic: // primary-expression: generic-selection [C1X 6.5.1] + Res = ParseGenericSelectionExpression(); + break; case tok::kw___builtin_va_arg: case tok::kw___builtin_offsetof: case tok::kw___builtin_choose_expr: @@ -788,7 +836,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___alignof: // unary-expression: '__alignof' unary-expression // unary-expression: '__alignof' '(' type-name ')' // unary-expression: 'alignof' '(' type-id ')' - return ParseSizeofAlignofExpression(); + case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression + return ParseUnaryExprOrTypeTraitExpression(); case tok::ampamp: { // unary-expression: '&&' identifier SourceLocation AmpAmpLoc = ConsumeToken(); if (Tok.isNot(tok::identifier)) @@ -825,7 +874,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, ParsedType Type = getTypeAnnotation(Tok); // Fake up a Declarator to use with ActOnTypeName. - DeclSpec DS; + DeclSpec DS(AttrFactory); DS.SetRangeStart(Tok.getLocation()); DS.SetRangeEnd(Tok.getLastLoc()); @@ -854,6 +903,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_short: case tok::kw_int: case tok::kw_long: + case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: case tok::kw_float: @@ -875,7 +925,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // postfix-expression: simple-type-specifier '(' expression-list[opt] ')' // - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseCXXSimpleTypeSpecifier(DS); if (Tok.isNot(tok::l_paren)) return ExprError(Diag(Tok, diag::err_expected_lparen_after_type) @@ -904,7 +954,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // cast expression. CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false); - AnnotateTemplateIdTokenAsType(&SS); + AnnotateTemplateIdTokenAsType(); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, TypeOfCast); } @@ -978,14 +1028,39 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return move(Result); } - case tok::kw___is_pod: // [GNU] unary-type-trait + case tok::kw___is_abstract: // [GNU] unary-type-trait case tok::kw___is_class: - case tok::kw___is_enum: - case tok::kw___is_union: case tok::kw___is_empty: - case tok::kw___is_polymorphic: - case tok::kw___is_abstract: + case tok::kw___is_enum: case tok::kw___is_literal: + case tok::kw___is_arithmetic: + case tok::kw___is_integral: + case tok::kw___is_floating_point: + case tok::kw___is_complete_type: + case tok::kw___is_void: + case tok::kw___is_array: + case tok::kw___is_function: + case tok::kw___is_reference: + case tok::kw___is_lvalue_reference: + case tok::kw___is_rvalue_reference: + case tok::kw___is_fundamental: + case tok::kw___is_object: + case tok::kw___is_scalar: + case tok::kw___is_compound: + case tok::kw___is_pointer: + case tok::kw___is_member_object_pointer: + case tok::kw___is_member_function_pointer: + case tok::kw___is_member_pointer: + case tok::kw___is_const: + case tok::kw___is_volatile: + case tok::kw___is_standard_layout: + case tok::kw___is_signed: + case tok::kw___is_unsigned: + case tok::kw___is_literal_type: + case tok::kw___is_pod: + case tok::kw___is_polymorphic: + case tok::kw___is_trivial: + case tok::kw___is_union: case tok::kw___has_trivial_constructor: case tok::kw___has_trivial_copy: case tok::kw___has_trivial_assign: @@ -998,9 +1073,19 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___builtin_types_compatible_p: case tok::kw___is_base_of: + case tok::kw___is_same: + case tok::kw___is_convertible: case tok::kw___is_convertible_to: return ParseBinaryTypeTrait(); + case tok::kw___array_rank: + case tok::kw___array_extent: + return ParseArrayTypeTrait(); + + case tok::kw___is_lvalue_expr: + case tok::kw___is_rvalue_expr: + return ParseExpressionTrait(); + case tok::at: { SourceLocation AtLoc = ConsumeToken(); return ParseObjCAtExpression(AtLoc); @@ -1256,10 +1341,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } } -/// ParseExprAfterTypeofSizeofAlignof - We parsed a typeof/sizeof/alignof and -/// we are at the start of an expression or a parenthesized type-id. -/// OpTok is the operand token (typeof/sizeof/alignof). Returns the expression -/// (isCastExpr == false) or the type (isCastExpr == true). +/// ParseExprAfterUnaryExprOrTypeTrait - We parsed a typeof/sizeof/alignof/ +/// vec_step and we are at the start of an expression or a parenthesized +/// type-id. OpTok is the operand token (typeof/sizeof/alignof). Returns the +/// expression (isCastExpr == false) or the type (isCastExpr == true). /// /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression @@ -1273,15 +1358,20 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /// typeof ( type-name ) /// [GNU/C++] typeof unary-expression /// +/// [OpenCL 1.1 6.11.12] vec_step built-in function: +/// vec_step ( expressions ) +/// vec_step ( type-name ) +/// ExprResult -Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, - bool &isCastExpr, - ParsedType &CastTy, - SourceRange &CastRange) { +Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, + bool &isCastExpr, + ParsedType &CastTy, + SourceRange &CastRange) { assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) || - OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) && - "Not a typeof/sizeof/alignof expression!"); + OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) || + OpTok.is(tok::kw_vec_step)) && + "Not a typeof/sizeof/alignof/vec_step expression!"); ExprResult Operand; @@ -1345,7 +1435,7 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, } -/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression. +/// ParseUnaryExprOrTypeTraitExpression - Parse a sizeof or alignof expression. /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' @@ -1353,10 +1443,10 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' /// [C++0x] 'alignof' '(' type-id ')' -ExprResult Parser::ParseSizeofAlignofExpression() { +ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) - || Tok.is(tok::kw_alignof)) && - "Not a sizeof/alignof expression!"); + || Tok.is(tok::kw_alignof) || Tok.is(tok::kw_vec_step)) && + "Not a sizeof/alignof/vec_step expression!"); Token OpTok = Tok; ConsumeToken(); @@ -1403,24 +1493,31 @@ ExprResult Parser::ParseSizeofAlignofExpression() { bool isCastExpr; ParsedType CastTy; SourceRange CastRange; - ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok, - isCastExpr, - CastTy, - CastRange); + ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok, + isCastExpr, + CastTy, + CastRange); + + UnaryExprOrTypeTrait ExprKind = UETT_SizeOf; + if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof)) + ExprKind = UETT_AlignOf; + else if (OpTok.is(tok::kw_vec_step)) + ExprKind = UETT_VecStep; if (isCastExpr) - return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(), - OpTok.is(tok::kw_sizeof), - /*isType=*/true, - CastTy.getAsOpaquePtr(), - CastRange); + return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), + ExprKind, + /*isType=*/true, + CastTy.getAsOpaquePtr(), + CastRange); // If we get here, the operand to the sizeof/alignof was an expresion. if (!Operand.isInvalid()) - Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(), - OpTok.is(tok::kw_sizeof), - /*isType=*/false, - Operand.release(), CastRange); + Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), + ExprKind, + /*isType=*/false, + Operand.release(), + CastRange); return move(Operand); } @@ -1618,15 +1715,18 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, ConsumeCodeCompletionToken(); return ExprError(); } + + // None of these cases should fall through with an invalid Result + // unless they've already reported an error. if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) { Diag(Tok, diag::ext_gnu_statement_expr); - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); StmtResult Stmt(ParseCompoundStatement(attrs, true)); ExprType = CompoundStmt; // If the substmt parsed correctly, build the AST node. - if (!Stmt.isInvalid() && Tok.is(tok::r_paren)) + if (!Stmt.isInvalid()) Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation()); } else if (ExprType >= CompoundLiteral && @@ -1724,6 +1824,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, Result = ParseExpression(); ExprType = SimpleExpr; + + // Don't build a paren expression unless we actually match a ')'. if (!Result.isInvalid() && Tok.is(tok::r_paren)) Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.take()); } @@ -1784,6 +1886,100 @@ ExprResult Parser::ParseStringLiteralExpression() { return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size()); } +/// ParseGenericSelectionExpression - Parse a C1X generic-selection +/// [C1X 6.5.1.1]. +/// +/// generic-selection: +/// _Generic ( assignment-expression , generic-assoc-list ) +/// generic-assoc-list: +/// generic-association +/// generic-assoc-list , generic-association +/// generic-association: +/// type-name : assignment-expression +/// default : assignment-expression +ExprResult Parser::ParseGenericSelectionExpression() { + assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected"); + SourceLocation KeyLoc = ConsumeToken(); + + if (!getLang().C1X) + Diag(KeyLoc, diag::ext_c1x_generic_selection); + + SourceLocation LParenLoc = Tok.getLocation(); + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, "")) + return ExprError(); + + ExprResult ControllingExpr; + { + // C1X 6.5.1.1p3 "The controlling expression of a generic selection is + // not evaluated." + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + ControllingExpr = ParseAssignmentExpression(); + if (ControllingExpr.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + } + + if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "")) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + SourceLocation DefaultLoc; + TypeVector Types(Actions); + ExprVector Exprs(Actions); + while (1) { + ParsedType Ty; + if (Tok.is(tok::kw_default)) { + // C1X 6.5.1.1p2 "A generic selection shall have no more than one default + // generic association." + if (!DefaultLoc.isInvalid()) { + Diag(Tok, diag::err_duplicate_default_assoc); + Diag(DefaultLoc, diag::note_previous_default_assoc); + SkipUntil(tok::r_paren); + return ExprError(); + } + DefaultLoc = ConsumeToken(); + Ty = ParsedType(); + } else { + ColonProtectionRAIIObject X(*this); + TypeResult TR = ParseTypeName(); + if (TR.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + Ty = TR.release(); + } + Types.push_back(Ty); + + if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "")) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + // FIXME: These expressions should be parsed in a potentially potentially + // evaluated context. + ExprResult ER(ParseAssignmentExpression()); + if (ER.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + Exprs.push_back(ER.release()); + + if (Tok.isNot(tok::comma)) + break; + ConsumeToken(); + } + + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + if (RParenLoc.isInvalid()) + return ExprError(); + + return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + ControllingExpr.release(), + move_arg(Types), move_arg(Exprs)); +} + /// ParseExpressionList - Used for C/C++ (argument-)expression-list. /// /// argument-expression-list: @@ -1837,7 +2033,7 @@ void Parser::ParseBlockId() { } // Parse the specifier-qualifier-list piece. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); // Parse the block-declarator. @@ -1845,7 +2041,7 @@ void Parser::ParseBlockId() { ParseDeclarator(DeclaratorInfo); // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes. - DeclaratorInfo.addAttributes(DS.takeAttributes()); + DeclaratorInfo.takeAttributes(DS.getAttributes(), SourceLocation()); MaybeParseGNUAttributes(DeclaratorInfo); @@ -1881,7 +2077,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { Actions.ActOnBlockStart(CaretLoc, getCurScope()); // Parse the return type if present. - DeclSpec DS; + DeclSpec DS(AttrFactory); Declarator ParamInfo(DS, Declarator::BlockLiteralContext); // FIXME: Since the return type isn't actually parsed, it can't be used to // fill ParamInfo with an initial valid range, so do it manually. @@ -1913,16 +2109,17 @@ ExprResult Parser::ParseBlockLiteralExpression() { ParseBlockId(); } else { // Otherwise, pretend we saw (void). - ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(), - true, false, + ParsedAttributes attrs(AttrFactory); + ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, SourceLocation(), 0, 0, 0, true, SourceLocation(), - false, SourceLocation(), - false, 0, 0, 0, + EST_None, + SourceLocation(), + 0, 0, 0, 0, CaretLoc, CaretLoc, ParamInfo), - CaretLoc); + attrs, CaretLoc); MaybeParseGNUAttributes(ParamInfo); @@ -1940,6 +2137,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { } StmtResult Stmt(ParseCompoundStatementBody()); + BlockScope.Exit(); if (!Stmt.isInvalid()) Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope()); else diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index d8db711809ed..8bf6f63d3ecd 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -20,6 +20,55 @@ using namespace clang; +static int SelectDigraphErrorMessage(tok::TokenKind Kind) { + switch (Kind) { + case tok::kw_template: return 0; + case tok::kw_const_cast: return 1; + case tok::kw_dynamic_cast: return 2; + case tok::kw_reinterpret_cast: return 3; + case tok::kw_static_cast: return 4; + default: + assert(0 && "Unknown type for digraph error message."); + return -1; + } +} + +// Are the two tokens adjacent in the same source file? +static bool AreTokensAdjacent(Preprocessor &PP, Token &First, Token &Second) { + SourceManager &SM = PP.getSourceManager(); + SourceLocation FirstLoc = SM.getSpellingLoc(First.getLocation()); + SourceLocation FirstEnd = FirstLoc.getFileLocWithOffset(First.getLength()); + return FirstEnd == SM.getSpellingLoc(Second.getLocation()); +} + +// Suggest fixit for "<::" after a cast. +static void FixDigraph(Parser &P, Preprocessor &PP, Token &DigraphToken, + Token &ColonToken, tok::TokenKind Kind, bool AtDigraph) { + // Pull '<:' and ':' off token stream. + if (!AtDigraph) + PP.Lex(DigraphToken); + PP.Lex(ColonToken); + + SourceRange Range; + Range.setBegin(DigraphToken.getLocation()); + Range.setEnd(ColonToken.getLocation()); + P.Diag(DigraphToken.getLocation(), diag::err_missing_whitespace_digraph) + << SelectDigraphErrorMessage(Kind) + << FixItHint::CreateReplacement(Range, "< ::"); + + // Update token information to reflect their change in token type. + ColonToken.setKind(tok::coloncolon); + ColonToken.setLocation(ColonToken.getLocation().getFileLocWithOffset(-1)); + ColonToken.setLength(2); + DigraphToken.setKind(tok::less); + DigraphToken.setLength(1); + + // Push new tokens back to token stream. + PP.EnterToken(ColonToken); + if (!AtDigraph) + PP.EnterToken(DigraphToken); +} + /// \brief Parse global scope or nested-name-specifier if present. /// /// Parses a C++ global scope specifier ('::') or nested-name-specifier (which @@ -60,7 +109,8 @@ using namespace clang; bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ParsedType ObjectType, bool EnteringContext, - bool *MayBePseudoDestructor) { + bool *MayBePseudoDestructor, + bool IsTypename) { assert(getLang().CPlusPlus && "Call sites of this function should be guarded by checking for C++"); @@ -111,7 +161,12 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Code completion for a nested-name-specifier, where the code // code completion token follows the '::'. Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext); - ConsumeCodeCompletionToken(); + SourceLocation ccLoc = ConsumeCodeCompletionToken(); + // Include code completion token into the range of the scope otherwise + // when we try to annotate the scope tokens the dangling code completion + // token will cause assertion in + // Preprocessor::AnnotatePreviousCachedTokens. + SS.setEndLoc(ccLoc); } } @@ -173,7 +228,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ObjectType, EnteringContext, Template)) { - if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, + if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, TemplateKWLoc, false)) return true; } else @@ -197,35 +252,37 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } - if (TemplateId->Kind == TNK_Type_template || - TemplateId->Kind == TNK_Dependent_template_name) { - AnnotateTemplateIdTokenAsType(&SS); + // Consume the template-id token. + ConsumeToken(); + + assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); + SourceLocation CCLoc = ConsumeToken(); - assert(Tok.is(tok::annot_typename) && - "AnnotateTemplateIdTokenAsType isn't working"); - Token TypeToken = Tok; - ConsumeToken(); - assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); - SourceLocation CCLoc = ConsumeToken(); - - if (!HasScopeSpecifier) - HasScopeSpecifier = true; - - if (ParsedType T = getTypeAnnotation(TypeToken)) { - if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), T, CCLoc, SS)) - SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc)); - - continue; - } else { - SourceLocation Start = SS.getBeginLoc().isValid()? SS.getBeginLoc() - : CCLoc; - SS.SetInvalid(SourceRange(Start, CCLoc)); - } - - continue; + if (!HasScopeSpecifier) + HasScopeSpecifier = true; + + ASTTemplateArgsPtr TemplateArgsPtr(Actions, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + + if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), + /*FIXME:*/SourceLocation(), + SS, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc, + CCLoc, + EnteringContext)) { + SourceLocation StartLoc + = SS.getBeginLoc().isValid()? SS.getBeginLoc() + : TemplateId->TemplateNameLoc; + SS.SetInvalid(SourceRange(StartLoc, CCLoc)); } - - assert(false && "FIXME: Only type template names supported here"); + + TemplateId->Destroy(); + continue; } @@ -284,6 +341,29 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, continue; } + // Check for '<::' which should be '< ::' instead of '[:' when following + // a template name. + if (Next.is(tok::l_square) && Next.getLength() == 2) { + Token SecondToken = GetLookAheadToken(2); + if (SecondToken.is(tok::colon) && + AreTokensAdjacent(PP, Next, SecondToken)) { + TemplateTy Template; + UnqualifiedId TemplateName; + TemplateName.setIdentifier(&II, Tok.getLocation()); + bool MemberOfUnknownSpecialization; + if (Actions.isTemplateName(getCurScope(), SS, + /*hasTemplateKeyword=*/false, + TemplateName, + ObjectType, + EnteringContext, + Template, + MemberOfUnknownSpecialization)) { + FixDigraph(*this, PP, Next, SecondToken, tok::kw_template, + /*AtDigraph*/false); + } + } + } + // nested-name-specifier: // type-name '<' if (Next.is(tok::less)) { @@ -305,19 +385,23 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // specializations) still want to see the original template-id // token. ConsumeToken(); - if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, + if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, SourceLocation(), false)) return true; continue; } if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) && - IsTemplateArgumentList(1)) { + (IsTypename || IsTemplateArgumentList(1))) { // We have something like t::getAs, where getAs is a // member of an unknown specialization. However, this will only // parse correctly as a template, so suggest the keyword 'template' // before 'getAs' and treat this as a dependent template name. - Diag(Tok.getLocation(), diag::err_missing_dependent_template_keyword) + unsigned DiagID = diag::err_missing_dependent_template_keyword; + if (getLang().Microsoft) + DiagID = diag::warn_missing_dependent_template_keyword; + + Diag(Tok.getLocation(), DiagID) << II.getName() << FixItHint::CreateInsertion(Tok.getLocation(), "template "); @@ -328,7 +412,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, EnteringContext, Template)) { // Consume the identifier. ConsumeToken(); - if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, + if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, SourceLocation(), false)) return true; } @@ -446,6 +530,13 @@ ExprResult Parser::ParseCXXCasts() { SourceLocation OpLoc = ConsumeToken(); SourceLocation LAngleBracketLoc = Tok.getLocation(); + // Check for "<::" which is parsed as "[:". If found, fix token stream, + // diagnose error, suggest fix, and recover parsing. + Token Next = NextToken(); + if (Tok.is(tok::l_square) && Tok.getLength() == 2 && Next.is(tok::colon) && + AreTokensAdjacent(PP, Tok, Next)) + FixDigraph(*this, PP, Tok, Next, Kind, /*AtDigraph*/true); + if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) return ExprError(); @@ -525,7 +616,15 @@ ExprResult Parser::ParseCXXTypeid() { RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); if (RParenLoc.isInvalid()) return ExprError(); - + + // If we are a foo that identifies a single function, resolve it now... + Expr* e = Result.get(); + if (e->getType() == Actions.Context.OverloadTy) { + ExprResult er = + Actions.ResolveAndFixSingleFunctionTemplateSpecialization(e); + if (er.isUsable()) + Result = er.release(); + } Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, Result.release(), RParenLoc); } @@ -790,7 +889,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, } // type-specifier-seq - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); // declarator @@ -846,6 +945,7 @@ bool Parser::isCXXSimpleTypeSpecifier() const { case tok::annot_typename: case tok::kw_short: case tok::kw_long: + case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: case tok::kw_void: @@ -857,8 +957,7 @@ bool Parser::isCXXSimpleTypeSpecifier() const { case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw_bool: - // FIXME: C++0x decltype support. - // GNU typeof support. + case tok::kw_decltype: case tok::kw_typeof: return true; @@ -938,6 +1037,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::kw_long: DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID); break; + case tok::kw___int64: + DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID); + break; case tok::kw_signed: DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID); break; @@ -1157,7 +1259,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, TemplateArgList TemplateArgs; if (Tok.is(tok::less) && ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, - &SS, true, LAngleLoc, + SS, true, LAngleLoc, TemplateArgs, RAngleLoc)) return true; @@ -1180,6 +1282,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, TemplateId->TemplateNameLoc = Id.StartLocation; } + TemplateId->SS = SS; TemplateId->Template = Template; TemplateId->Kind = TNK; TemplateId->LAngleLoc = LAngleLoc; @@ -1199,7 +1302,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Constructor and destructor names. TypeResult Type - = Actions.ActOnTemplateIdType(Template, NameLoc, + = Actions.ActOnTemplateIdType(SS, Template, NameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc); if (Type.isInvalid()) @@ -1380,7 +1483,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // ptr-operator conversion-declarator[opt] // Parse the type-specifier-seq. - DeclSpec DS; + DeclSpec DS(AttrFactory); if (ParseCXXTypeSpecifierSeq(DS)) // FIXME: ObjectType? return true; @@ -1465,7 +1568,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, Actions.isCurrentClassName(*Id, getCurScope(), &SS)) { // We have parsed a constructor name. Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, getCurScope(), - &SS, false), + &SS, false, false, + ParsedType(), + /*NonTrivialTypeSourceInfo=*/true), IdLoc, IdLoc); } else { // We have parsed an identifier. @@ -1503,7 +1608,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, Result.setConstructorName(Actions.getTypeName(*TemplateId->Name, TemplateId->TemplateNameLoc, getCurScope(), - &SS, false), + &SS, false, false, + ParsedType(), + /*NontrivialTypeSourceInfo=*/true), TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); TemplateId->Destroy(); @@ -1608,6 +1715,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, /// /// new-type-id: /// type-specifier-seq new-declarator[opt] +/// [GNU] attributes type-specifier-seq new-declarator[opt] /// /// new-declarator: /// ptr-operator new-declarator[opt] @@ -1629,7 +1737,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { SourceLocation PlacementLParen, PlacementRParen; SourceRange TypeIdParens; - DeclSpec DS; + DeclSpec DS(AttrFactory); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); if (Tok.is(tok::l_paren)) { // If it turns out to be a placement, we change the type location. @@ -1653,12 +1761,14 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { // We still need the type. if (Tok.is(tok::l_paren)) { TypeIdParens.setBegin(ConsumeParen()); + MaybeParseGNUAttributes(DeclaratorInfo); ParseSpecifierQualifierList(DS); DeclaratorInfo.SetSourceRange(DS.getSourceRange()); ParseDeclarator(DeclaratorInfo); TypeIdParens.setEnd(MatchRHSPunctuation(tok::r_paren, TypeIdParens.getBegin())); } else { + MaybeParseGNUAttributes(DeclaratorInfo); if (ParseCXXTypeSpecifierSeq(DS)) DeclaratorInfo.setInvalidType(true); else { @@ -1671,6 +1781,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { } else { // A new-type-id is a simplified type-id, where essentially the // direct-declarator is replaced by a direct-new-declarator. + MaybeParseGNUAttributes(DeclaratorInfo); if (ParseCXXTypeSpecifierSeq(DS)) DeclaratorInfo.setInvalidType(true); else { @@ -1731,10 +1842,12 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { first = false; SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc); - D.AddTypeInfo(DeclaratorChunk::getArray(0, ParsedAttributes(), + + ParsedAttributes attrs(AttrFactory); + D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, Size.release(), LLoc, RLoc), - RLoc); + attrs, RLoc); if (RLoc.isInvalid()) return; @@ -1803,23 +1916,48 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { switch(kind) { - default: llvm_unreachable("Not a known unary type trait"); + default: assert(false && "Not a known unary type trait."); case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; - case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; + case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign; - case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor; + case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor; case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor; case tok::kw___is_abstract: return UTT_IsAbstract; + case tok::kw___is_arithmetic: return UTT_IsArithmetic; + case tok::kw___is_array: return UTT_IsArray; case tok::kw___is_class: return UTT_IsClass; + case tok::kw___is_complete_type: return UTT_IsCompleteType; + case tok::kw___is_compound: return UTT_IsCompound; + case tok::kw___is_const: return UTT_IsConst; case tok::kw___is_empty: return UTT_IsEmpty; case tok::kw___is_enum: return UTT_IsEnum; - case tok::kw___is_pod: return UTT_IsPOD; - case tok::kw___is_polymorphic: return UTT_IsPolymorphic; - case tok::kw___is_union: return UTT_IsUnion; + case tok::kw___is_floating_point: return UTT_IsFloatingPoint; + case tok::kw___is_function: return UTT_IsFunction; + case tok::kw___is_fundamental: return UTT_IsFundamental; + case tok::kw___is_integral: return UTT_IsIntegral; + case tok::kw___is_lvalue_reference: return UTT_IsLvalueReference; + case tok::kw___is_member_function_pointer: return UTT_IsMemberFunctionPointer; + case tok::kw___is_member_object_pointer: return UTT_IsMemberObjectPointer; + case tok::kw___is_member_pointer: return UTT_IsMemberPointer; + case tok::kw___is_object: return UTT_IsObject; case tok::kw___is_literal: return UTT_IsLiteral; + case tok::kw___is_literal_type: return UTT_IsLiteral; + case tok::kw___is_pod: return UTT_IsPOD; + case tok::kw___is_pointer: return UTT_IsPointer; + case tok::kw___is_polymorphic: return UTT_IsPolymorphic; + case tok::kw___is_reference: return UTT_IsReference; + case tok::kw___is_rvalue_reference: return UTT_IsRvalueReference; + case tok::kw___is_scalar: return UTT_IsScalar; + case tok::kw___is_signed: return UTT_IsSigned; + case tok::kw___is_standard_layout: return UTT_IsStandardLayout; + case tok::kw___is_trivial: return UTT_IsTrivial; + case tok::kw___is_union: return UTT_IsUnion; + case tok::kw___is_unsigned: return UTT_IsUnsigned; + case tok::kw___is_void: return UTT_IsVoid; + case tok::kw___is_volatile: return UTT_IsVolatile; } } @@ -1827,11 +1965,29 @@ static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) { switch(kind) { default: llvm_unreachable("Not a known binary type trait"); case tok::kw___is_base_of: return BTT_IsBaseOf; + case tok::kw___is_convertible: return BTT_IsConvertible; + case tok::kw___is_same: return BTT_IsSame; case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible; case tok::kw___is_convertible_to: return BTT_IsConvertibleTo; } } +static ArrayTypeTrait ArrayTypeTraitFromTokKind(tok::TokenKind kind) { + switch(kind) { + default: llvm_unreachable("Not a known binary type trait"); + case tok::kw___array_rank: return ATT_ArrayRank; + case tok::kw___array_extent: return ATT_ArrayExtent; + } +} + +static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) { + switch(kind) { + default: assert(false && "Not a known unary expression trait."); + case tok::kw___is_lvalue_expr: return ET_IsLValueExpr; + case tok::kw___is_rvalue_expr: return ET_IsRValueExpr; + } +} + /// ParseUnaryTypeTrait - Parse the built-in unary type-trait /// pseudo-functions that allow implementation of the TR1/C++0x type traits /// templates. @@ -1897,6 +2053,72 @@ ExprResult Parser::ParseBinaryTypeTrait() { return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), RParen); } +/// ParseArrayTypeTrait - Parse the built-in array type-trait +/// pseudo-functions. +/// +/// primary-expression: +/// [Embarcadero] '__array_rank' '(' type-id ')' +/// [Embarcadero] '__array_extent' '(' type-id ',' expression ')' +/// +ExprResult Parser::ParseArrayTypeTrait() { + ArrayTypeTrait ATT = ArrayTypeTraitFromTokKind(Tok.getKind()); + SourceLocation Loc = ConsumeToken(); + + SourceLocation LParen = Tok.getLocation(); + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + return ExprError(); + + TypeResult Ty = ParseTypeName(); + if (Ty.isInvalid()) { + SkipUntil(tok::comma); + SkipUntil(tok::r_paren); + return ExprError(); + } + + switch (ATT) { + case ATT_ArrayRank: { + SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL, RParen); + } + case ATT_ArrayExtent: { + if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + ExprResult DimExpr = ParseExpression(); + SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + + return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), DimExpr.get(), RParen); + } + default: + break; + } + return ExprError(); +} + +/// ParseExpressionTrait - Parse built-in expression-trait +/// pseudo-functions like __is_lvalue_expr( xxx ). +/// +/// primary-expression: +/// [Embarcadero] expression-trait '(' expression ')' +/// +ExprResult Parser::ParseExpressionTrait() { + ExpressionTrait ET = ExpressionTraitFromTokKind(Tok.getKind()); + SourceLocation Loc = ConsumeToken(); + + SourceLocation LParen = Tok.getLocation(); + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + return ExprError(); + + ExprResult Expr = ParseExpression(); + + SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + + return Actions.ActOnExpressionTrait(ET, Loc, Expr.get(), RParen); +} + + /// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a /// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate /// based on the context past the parens. diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp index 82dda2b793d3..2c9278a90033 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp @@ -354,7 +354,7 @@ ExprResult Parser::ParseBraceInitializer() { InitExprsOk = false; // We have two ways to try to recover from this error: if the code looks - // gramatically ok (i.e. we have a comma coming up) try to continue + // grammatically ok (i.e. we have a comma coming up) try to continue // parsing the rest of the initializer. This allows us to emit // diagnostics for later elements that we find. If we don't see a comma, // assume there is a parse error, and just skip to recover. diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp index f32a322f024a..fdbedc54d1cd 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp @@ -41,11 +41,11 @@ Decl *Parser::ParseObjCAtDirectives() { case tok::objc_class: return ParseObjCAtClassDeclaration(AtLoc); case tok::objc_interface: { - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); return ParseObjCAtInterfaceDeclaration(AtLoc, attrs); } case tok::objc_protocol: { - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); return ParseObjCAtProtocolDeclaration(AtLoc, attrs); } case tok::objc_implementation: @@ -327,7 +327,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, // If this is a method prototype, parse it. if (Tok.is(tok::minus) || Tok.is(tok::plus)) { Decl *methodPrototype = - ParseObjCMethodPrototype(interfaceDecl, MethodImplKind); + ParseObjCMethodPrototype(interfaceDecl, MethodImplKind, false); allMethods.push_back(methodPrototype); // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for // method definitions. @@ -340,7 +340,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, ParseObjCMethodDecl(Tok.getLocation(), tok::minus, interfaceDecl, - MethodImplKind); + MethodImplKind, false); continue; } // Ignore excess semicolons. @@ -371,7 +371,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, // FIXME: as the name implies, this rule allows function definitions. // We could pass a flag or check for functions during semantic analysis. - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); continue; } @@ -439,11 +439,10 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, OCDS, AtLoc, MethodImplKind); // Parse all the comma separated declarators. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseStructDeclaration(DS, Callback); - ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "", - tok::at); + ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); break; } } @@ -582,12 +581,14 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) { /// __attribute__((deprecated)) /// Decl *Parser::ParseObjCMethodPrototype(Decl *IDecl, - tok::ObjCKeywordKind MethodImplKind) { + tok::ObjCKeywordKind MethodImplKind, + bool MethodDefinition) { assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-"); tok::TokenKind methodType = Tok.getKind(); SourceLocation mLoc = ConsumeToken(); - Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind); + Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind, + MethodDefinition); // Since this rule is used for both method declarations and definitions, // the caller is (optionally) responsible for consuming the ';'. return MDecl; @@ -720,10 +721,12 @@ bool Parser::isTokIdentifier_in() const { /// objc-type-qualifier /// objc-type-qualifiers objc-type-qualifier /// -void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter) { +void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, + ObjCTypeNameContext Context) { while (1) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPassingType(getCurScope(), DS, IsParameter); + Actions.CodeCompleteObjCPassingType(getCurScope(), DS, + Context == OTN_ParameterType); ConsumeCodeCompletionToken(); } @@ -760,18 +763,19 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter) { /// '(' objc-type-qualifiers[opt] type-name ')' /// '(' objc-type-qualifiers[opt] ')' /// -ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter) { +ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, + ObjCTypeNameContext Context) { assert(Tok.is(tok::l_paren) && "expected ("); SourceLocation LParenLoc = ConsumeParen(); SourceLocation TypeStartLoc = Tok.getLocation(); // Parse type qualifiers, in, inout, etc. - ParseObjCTypeQualifierList(DS, IsParameter); + ParseObjCTypeQualifierList(DS, Context); ParsedType Ty; if (isTypeSpecifierQualifier()) { - TypeResult TypeSpec = ParseTypeName(); + TypeResult TypeSpec = ParseTypeName(0, Declarator::ObjCPrototypeContext); if (!TypeSpec.isInvalid()) Ty = TypeSpec.get(); } @@ -821,7 +825,8 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter) { Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, Decl *IDecl, - tok::ObjCKeywordKind MethodImplKind) { + tok::ObjCKeywordKind MethodImplKind, + bool MethodDefinition) { ParsingDeclRAIIObject PD(*this); if (Tok.is(tok::code_completion)) { @@ -834,12 +839,12 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ParsedType ReturnType; ObjCDeclSpec DSRet; if (Tok.is(tok::l_paren)) - ReturnType = ParseObjCTypeName(DSRet, false); + ReturnType = ParseObjCTypeName(DSRet, OTN_ResultType); // If attributes exist before the method, parse them. - ParsedAttributes attrs; + ParsedAttributes methodAttrs(AttrFactory); if (getLang().ObjC2) - MaybeParseGNUAttributes(attrs); + MaybeParseGNUAttributes(methodAttrs); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, @@ -864,7 +869,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (Tok.isNot(tok::colon)) { // If attributes exist after the method, parse them. if (getLang().ObjC2) - MaybeParseGNUAttributes(attrs); + MaybeParseGNUAttributes(methodAttrs); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); Decl *Result @@ -872,7 +877,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, mType, IDecl, DSRet, ReturnType, Sel, 0, CParamInfo.data(), CParamInfo.size(), - attrs.getList(), MethodImplKind); + methodAttrs.getList(), MethodImplKind, + false, MethodDefinition); PD.complete(Result); return Result; } @@ -881,8 +887,11 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, llvm::SmallVector ArgInfos; ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope); + + AttributePool allParamAttrs(AttrFactory); while (1) { + ParsedAttributes paramAttrs(AttrFactory); Sema::ObjCArgInfo ArgInfo; // Each iteration parses a single keyword argument. @@ -894,14 +903,13 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ArgInfo.Type = ParsedType(); if (Tok.is(tok::l_paren)) // Parse the argument type if present. - ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, true); + ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, OTN_ParameterType); // If attributes exist before the argument name, parse them. ArgInfo.ArgAttrs = 0; if (getLang().ObjC2) { - ParsedAttributes attrs; - MaybeParseGNUAttributes(attrs); - ArgInfo.ArgAttrs = attrs.getList(); + MaybeParseGNUAttributes(paramAttrs); + ArgInfo.ArgAttrs = paramAttrs.getList(); } // Code completion for the next piece of the selector. @@ -930,6 +938,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ArgInfos.push_back(ArgInfo); KeyIdents.push_back(SelIdent); + // Make sure the attributes persist. + allParamAttrs.takeAllFrom(paramAttrs.getPool()); + // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { ConsumeCodeCompletionToken(); @@ -960,7 +971,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ConsumeToken(); break; } - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // Parse the declarator. Declarator ParmDecl(DS, Declarator::PrototypeContext); @@ -977,7 +988,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // FIXME: Add support for optional parameter list... // If attributes exist after the method, parse them. if (getLang().ObjC2) - MaybeParseGNUAttributes(attrs); + MaybeParseGNUAttributes(methodAttrs); if (KeyIdents.size() == 0) { // Leave prototype scope. @@ -992,8 +1003,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, mType, IDecl, DSRet, ReturnType, Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), - attrs.getList(), - MethodImplKind, isVariadic); + methodAttrs.getList(), + MethodImplKind, isVariadic, MethodDefinition); // Leave prototype scope. PrototypeScope.Exit(); @@ -1165,7 +1176,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, } Callback(*this, interfaceDecl, visibility, AllIvarDecls); // Parse all the comma separated declarators. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseStructDeclaration(DS, Callback); if (Tok.is(tok::semi)) { @@ -1376,7 +1387,7 @@ Decl *Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { } else { // missing @implementation - Diag(atEnd.getBegin(), diag::warn_expected_implementation); + Diag(atEnd.getBegin(), diag::err_expected_implementation); } return Result; } @@ -1609,7 +1620,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ConsumeParen(); ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope); if (Tok.isNot(tok::ellipsis)) { - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // For some odd reason, the name of the exception variable is // optional. As a result, we need to use "PrototypeContext", because @@ -1717,9 +1728,12 @@ Decl *Parser::ParseObjCMethodDefinition() { // specified Declarator for the method. Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl); - if (PP.isCodeCompletionEnabled()) - if (trySkippingFunctionBodyForCodeCompletion()) + if (PP.isCodeCompletionEnabled()) { + if (trySkippingFunctionBodyForCodeCompletion()) { + BodyScope.Exit(); return Actions.ActOnFinishFunctionBody(MDecl, 0); + } + } StmtResult FnBody(ParseCompoundStatementBody()); @@ -1728,12 +1742,11 @@ Decl *Parser::ParseObjCMethodDefinition() { FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc, MultiStmtArg(Actions), false); - // TODO: Pass argument information. - Actions.ActOnFinishFunctionBody(MDecl, FnBody.take()); - // Leave the function body scope. BodyScope.Exit(); - + + // TODO: Pass argument information. + Actions.ActOnFinishFunctionBody(MDecl, FnBody.take()); return MDecl; } @@ -1839,7 +1852,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { // typename-specifier // simple-type-specifier // expression (that starts with one of the above) - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseCXXSimpleTypeSpecifier(DS); if (Tok.is(tok::l_paren)) { @@ -2337,7 +2350,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { return ExprError(Diag(Tok, diag::err_expected_colon)); ++nColons; - ConsumeToken(); // Eat the ':'. + ConsumeToken(); // Eat the ':' or '::'. if (Tok.is(tok::r_paren)) break; @@ -2353,7 +2366,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { SourceLocation Loc; SelIdent = ParseObjCSelectorPiece(Loc); KeyIdents.push_back(SelIdent); - if (!SelIdent && Tok.isNot(tok::colon)) + if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon)) break; } } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp index dfd0da079df5..46225c8e7910 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp @@ -74,7 +74,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, return; } PP.Lex(Tok); - if (Tok.isNot(tok::eom)) { + if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "visibility"; return; @@ -168,7 +168,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, SourceLocation RParenLoc = Tok.getLocation(); PP.Lex(Tok); - if (Tok.isNot(tok::eom)) { + if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack"; return; } @@ -177,6 +177,38 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, LParenLoc, RParenLoc); } +// #pragma ms_struct on +// #pragma ms_struct off +void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &MSStructTok) { + Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF; + + Token Tok; + PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); + return; + } + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II->isStr("on")) { + Kind = Sema::PMSST_ON; + PP.Lex(Tok); + } + else if (II->isStr("off") || II->isStr("reset")) + PP.Lex(Tok); + else { + PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); + return; + } + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "ms_struct"; + return; + } + Actions.ActOnPragmaMSStruct(Kind); +} + // #pragma 'align' '=' {'native','natural','mac68k','power','reset'} // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok, @@ -228,7 +260,7 @@ static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok, SourceLocation KindLoc = Tok.getLocation(); PP.Lex(Tok); - if (Tok.isNot(tok::eom)) { + if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << (IsOptions ? "options" : "align"); return; @@ -302,7 +334,7 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, } PP.Lex(Tok); - if (Tok.isNot(tok::eom)) { + if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "unused"; return; @@ -359,7 +391,7 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP, PP.Lex(Tok); } - if (Tok.isNot(tok::eom)) { + if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak"; return; } @@ -387,7 +419,7 @@ void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) { - PP.Lex(Tok); + PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::identifier)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "OPENCL"; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h index bee6af3f4cfd..1d3138fa70a8 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h +++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h @@ -58,6 +58,16 @@ class PragmaPackHandler : public PragmaHandler { virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken); }; + +class PragmaMSStructHandler : public PragmaHandler { + Sema &Actions; +public: + explicit PragmaMSStructHandler(Sema &A) : PragmaHandler("ms_struct"), + Actions(A) {} + + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); +}; class PragmaUnusedHandler : public PragmaHandler { Sema &Actions; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index 2d9758333f0c..f0ab53108033 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -40,6 +40,7 @@ using namespace clang; /// jump-statement /// [C++] declaration-statement /// [C++] try-block +/// [MS] seh-try-block /// [OBC] objc-throw-statement /// [OBC] objc-try-catch-statement /// [OBC] objc-synchronized-statement @@ -81,12 +82,13 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { ParenBraceBracketBalancer BalancerRAIIObj(*this); - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); // Cases in this switch statement should fall through if the parser expects // the token to end in a semicolon (in which case SemiError should be set), // or they directly 'return;' if not. +Retry: tok::TokenKind Kind = Tok.getKind(); SourceLocation AtLoc; switch (Kind) { @@ -101,13 +103,103 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { ConsumeCodeCompletionToken(); return ParseStatementOrDeclaration(Stmts, OnlyStatement); - case tok::identifier: - if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement + case tok::identifier: { + Token Next = NextToken(); + if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement // identifier ':' statement return ParseLabeledStatement(attrs); } - // PASS THROUGH. - + + if (Next.isNot(tok::coloncolon)) { + CXXScopeSpec SS; + IdentifierInfo *Name = Tok.getIdentifierInfo(); + SourceLocation NameLoc = Tok.getLocation(); + Sema::NameClassification Classification + = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next); + switch (Classification.getKind()) { + case Sema::NC_Keyword: + // The identifier was corrected to a keyword. Update the token + // to this keyword, and try again. + if (Name->getTokenID() != tok::identifier) { + Tok.setIdentifierInfo(Name); + Tok.setKind(Name->getTokenID()); + goto Retry; + } + + // Fall through via the normal error path. + // FIXME: This seems like it could only happen for context-sensitive + // keywords. + + case Sema::NC_Error: + // Handle errors here by skipping up to the next semicolon or '}', and + // eat the semicolon if that's what stopped us. + SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); + if (Tok.is(tok::semi)) + ConsumeToken(); + return StmtError(); + + case Sema::NC_Unknown: + // Either we don't know anything about this identifier, or we know that + // we're in a syntactic context we haven't handled yet. + break; + + case Sema::NC_Type: + Tok.setKind(tok::annot_typename); + setTypeAnnotation(Tok, Classification.getType()); + Tok.setAnnotationEndLoc(NameLoc); + PP.AnnotateCachedTokens(Tok); + break; + + case Sema::NC_Expression: + Tok.setKind(tok::annot_primary_expr); + setExprAnnotation(Tok, Classification.getExpression()); + Tok.setAnnotationEndLoc(NameLoc); + PP.AnnotateCachedTokens(Tok); + break; + + case Sema::NC_TypeTemplate: + case Sema::NC_FunctionTemplate: { + ConsumeToken(); // the identifier + UnqualifiedId Id; + Id.setIdentifier(Name, NameLoc); + if (AnnotateTemplateIdToken( + TemplateTy::make(Classification.getTemplateName()), + Classification.getTemplateNameKind(), + SS, Id, SourceLocation(), + /*AllowTypeAnnotation=*/false)) { + // Handle errors here by skipping up to the next semicolon or '}', and + // eat the semicolon if that's what stopped us. + SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); + if (Tok.is(tok::semi)) + ConsumeToken(); + return StmtError(); + } + + // If the next token is '::', jump right into parsing a + // nested-name-specifier. We don't want to leave the template-id + // hanging. + if (NextToken().is(tok::coloncolon) && TryAnnotateCXXScopeToken(false)){ + // Handle errors here by skipping up to the next semicolon or '}', and + // eat the semicolon if that's what stopped us. + SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); + if (Tok.is(tok::semi)) + ConsumeToken(); + return StmtError(); + } + + // We've annotated a template-id, so try again now. + goto Retry; + } + + case Sema::NC_NestedNameSpecifier: + // FIXME: Implement this! + break; + } + } + + // Fall through + } + default: { if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; @@ -121,21 +213,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { return StmtError(); } - // FIXME: Use the attributes - // expression[opt] ';' - ExprResult Expr(ParseExpression()); - if (Expr.isInvalid()) { - // If the expression is invalid, skip ahead to the next semicolon or '}'. - // Not doing this opens us up to the possibility of infinite loops if - // ParseExpression does not consume any tokens. - SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); - if (Tok.is(tok::semi)) - ConsumeToken(); - return StmtError(); - } - // Otherwise, eat the semicolon. - ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get())); + return ParseExprStatement(attrs); } case tok::kw_case: // C99 6.8.1: labeled-statement @@ -146,8 +224,10 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { case tok::l_brace: // C99 6.8.2: compound-statement return ParseCompoundStatement(attrs); case tok::semi: { // C99 6.8.3p3: expression[opt] ';' - bool LeadingEmptyMacro = Tok.hasLeadingEmptyMacro(); - return Actions.ActOnNullStmt(ConsumeToken(), LeadingEmptyMacro); + SourceLocation LeadingEmptyMacroLoc; + if (Tok.hasLeadingEmptyMacro()) + LeadingEmptyMacroLoc = PP.getLastEmptyMacroInstantiationLoc(); + return Actions.ActOnNullStmt(ConsumeToken(), LeadingEmptyMacroLoc); } case tok::kw_if: // C99 6.8.4.1: if-statement @@ -193,6 +273,9 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { case tok::kw_try: // C++ 15: try-block return ParseCXXTryBlock(attrs); + + case tok::kw___try: + return ParseSEHTryBlock(attrs); } // If we reached this code, the statement must end in a semicolon. @@ -210,6 +293,145 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { return move(Res); } +/// \brief Parse an expression statement. +StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) { + // If a case keyword is missing, this is where it should be inserted. + Token OldToken = Tok; + + // FIXME: Use the attributes + // expression[opt] ';' + ExprResult Expr(ParseExpression()); + if (Expr.isInvalid()) { + // If the expression is invalid, skip ahead to the next semicolon or '}'. + // Not doing this opens us up to the possibility of infinite loops if + // ParseExpression does not consume any tokens. + SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); + if (Tok.is(tok::semi)) + ConsumeToken(); + return StmtError(); + } + + if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() && + Actions.CheckCaseExpression(Expr.get())) { + // If a constant expression is followed by a colon inside a switch block, + // suggest a missing case keyword. + Diag(OldToken, diag::err_expected_case_before_expression) + << FixItHint::CreateInsertion(OldToken.getLocation(), "case "); + + // Recover parsing as a case statement. + return ParseCaseStatement(Attrs, /*MissingCase=*/true, Expr); + } + + // Otherwise, eat the semicolon. + ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); + return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get())); +} + +StmtResult Parser::ParseSEHTryBlock(ParsedAttributes & Attrs) { + assert(Tok.is(tok::kw___try) && "Expected '__try'"); + SourceLocation Loc = ConsumeToken(); + return ParseSEHTryBlockCommon(Loc); +} + +/// ParseSEHTryBlockCommon +/// +/// seh-try-block: +/// '__try' compound-statement seh-handler +/// +/// seh-handler: +/// seh-except-block +/// seh-finally-block +/// +StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { + if(Tok.isNot(tok::l_brace)) + return StmtError(Diag(Tok,diag::err_expected_lbrace)); + + ParsedAttributesWithRange attrs(AttrFactory); + StmtResult TryBlock(ParseCompoundStatement(attrs)); + if(TryBlock.isInvalid()) + return move(TryBlock); + + StmtResult Handler; + if(Tok.is(tok::kw___except)) { + SourceLocation Loc = ConsumeToken(); + Handler = ParseSEHExceptBlock(Loc); + } else if (Tok.is(tok::kw___finally)) { + SourceLocation Loc = ConsumeToken(); + Handler = ParseSEHFinallyBlock(Loc); + } else { + return StmtError(Diag(Tok,diag::err_seh_expected_handler)); + } + + if(Handler.isInvalid()) + return move(Handler); + + return Actions.ActOnSEHTryBlock(false /* IsCXXTry */, + TryLoc, + TryBlock.take(), + Handler.take()); +} + +/// ParseSEHExceptBlock - Handle __except +/// +/// seh-except-block: +/// '__except' '(' seh-filter-expression ')' compound-statement +/// +StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { + PoisonIdentifierRAIIObject raii(Ident__exception_code, false), + raii2(Ident___exception_code, false), + raii3(Ident_GetExceptionCode, false); + + if(ExpectAndConsume(tok::l_paren,diag::err_expected_lparen)) + return StmtError(); + + ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope); + + if (getLang().Borland) { + Ident__exception_info->setIsPoisoned(false); + Ident___exception_info->setIsPoisoned(false); + Ident_GetExceptionInfo->setIsPoisoned(false); + } + ExprResult FilterExpr(ParseExpression()); + + if (getLang().Borland) { + Ident__exception_info->setIsPoisoned(true); + Ident___exception_info->setIsPoisoned(true); + Ident_GetExceptionInfo->setIsPoisoned(true); + } + + if(FilterExpr.isInvalid()) + return StmtError(); + + if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen)) + return StmtError(); + + ParsedAttributesWithRange attrs(AttrFactory); + StmtResult Block(ParseCompoundStatement(attrs)); + + if(Block.isInvalid()) + return move(Block); + + return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.take(), Block.take()); +} + +/// ParseSEHFinallyBlock - Handle __finally +/// +/// seh-finally-block: +/// '__finally' compound-statement +/// +StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) { + PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false), + raii2(Ident___abnormal_termination, false), + raii3(Ident_AbnormalTermination, false); + + ParsedAttributesWithRange attrs(AttrFactory); + StmtResult Block(ParseCompoundStatement(attrs)); + if(Block.isInvalid()) + return move(Block); + + return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.take()); +} + /// ParseLabeledStatement - We have an identifier and a ':' after it. /// /// labeled-statement: @@ -251,8 +473,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) { /// 'case' constant-expression ':' statement /// [GNU] 'case' constant-expression '...' constant-expression ':' statement /// -StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs) { - assert(Tok.is(tok::kw_case) && "Not a case stmt!"); +StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, + ExprResult Expr) { + assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!"); // FIXME: Use attributes? // It is very very common for code to contain many case statements recursively @@ -280,7 +503,8 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs) { // While we have case statements, eat and stack them. do { - SourceLocation CaseLoc = ConsumeToken(); // eat the 'case'. + SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() : + ConsumeToken(); // eat the 'case'. if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCase(getCurScope()); @@ -292,7 +516,8 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs) { /// expression. ColonProtectionRAIIObject ColonProtection(*this); - ExprResult LHS(ParseConstantExpression()); + ExprResult LHS(MissingCase ? Expr : ParseConstantExpression()); + MissingCase = false; if (LHS.isInvalid()) { SkipUntil(tok::colon); return StmtError(); @@ -493,14 +718,14 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { IdentifierInfo *II = Tok.getIdentifierInfo(); SourceLocation IdLoc = ConsumeToken(); - DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, true)); + DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc)); if (!Tok.is(tok::comma)) break; ConsumeToken(); } - DeclSpec DS; + DeclSpec DS(AttrFactory); DeclGroupPtrTy Res = Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup.data(), DeclsInGroup.size()); StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation()); @@ -528,7 +753,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { while (Tok.is(tok::kw___extension__)) ConsumeToken(); - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); // If this is the start of a declaration, parse it as such. @@ -775,7 +1000,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { // while, for, and switch statements are local to the if, while, for, or // switch statement (including the controlled statement). // - unsigned ScopeFlags = Scope::BreakScope; + unsigned ScopeFlags = Scope::BreakScope | Scope::SwitchScope; if (C99orCXX) ScopeFlags |= Scope::DeclScope | Scope::ControlScope; ParseScope SwitchScope(this, ScopeFlags); @@ -977,6 +1202,7 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { /// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement /// [C++] 'for' '(' for-init-statement condition[opt] ';' expression[opt] ')' /// [C++] statement +/// [C++0x] 'for' '(' for-range-declaration : for-range-initializer ) statement /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement /// [OBJC2] 'for' '(' expr 'in' expr ')' statement /// @@ -984,6 +1210,11 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { /// [C++] expression-statement /// [C++] simple-declaration /// +/// [C++0x] for-range-declaration: +/// [C++0x] attribute-specifier-seq[opt] type-specifier-seq declarator +/// [C++0x] for-range-initializer: +/// [C++0x] expression +/// [C++0x] braced-init-list [TODO] StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { // FIXME: Use attributes? @@ -1025,11 +1256,12 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { SourceLocation LParenLoc = ConsumeParen(); ExprResult Value; - bool ForEach = false; + bool ForEach = false, ForRange = false; StmtResult FirstPart; bool SecondPartIsInvalid = false; FullExprArg SecondPart(Actions); ExprResult Collection; + ForRangeInit ForRangeInit; FullExprArg ThirdPart(Actions); Decl *SecondVar = 0; @@ -1049,16 +1281,24 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); + // In C++0x, "for (T NS:a" might not be a typo for :: + bool MightBeForRangeStmt = getLang().CPlusPlus; + ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); + SourceLocation DeclStart = Tok.getLocation(), DeclEnd; StmtVector Stmts(Actions); DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, - DeclEnd, attrs, false); + DeclEnd, attrs, false, + MightBeForRangeStmt ? + &ForRangeInit : 0); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); - if (Tok.is(tok::semi)) { // for (int x = 4; + if (ForRangeInit.ParsedForRangeDecl()) { + ForRange = true; + } else if (Tok.is(tok::semi)) { // for (int x = 4; ConsumeToken(); } else if ((ForEach = isTokIdentifier_in())) { Actions.ActOnForEachDeclStmt(DG); @@ -1107,7 +1347,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { } } } - if (!ForEach) { + if (!ForEach && !ForRange) { assert(!SecondPart.get() && "Shouldn't have a second expression yet."); // Parse the second part of the for specifier. if (Tok.is(tok::semi)) { // for (...;; @@ -1149,6 +1389,17 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { // Match the ')'. SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + // We need to perform most of the semantic analysis for a C++0x for-range + // statememt before parsing the body, in order to be able to deduce the type + // of an auto-typed loop variable. + StmtResult ForRangeStmt; + if (ForRange) + ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, LParenLoc, + FirstPart.take(), + ForRangeInit.ColonLoc, + ForRangeInit.RangeExpr.get(), + RParenLoc); + // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1175,15 +1426,19 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { if (Body.isInvalid()) return StmtError(); - if (!ForEach) - return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart, - SecondVar, ThirdPart, RParenLoc, Body.take()); + if (ForEach) + // FIXME: It isn't clear how to communicate the late destruction of + // C++ temporaries used to create the collection. + return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, + FirstPart.take(), + Collection.take(), RParenLoc, + Body.take()); - // FIXME: It isn't clear how to communicate the late destruction of - // C++ temporaries used to create the collection. - return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, FirstPart.take(), - Collection.take(), RParenLoc, - Body.take()); + if (ForRange) + return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take()); + + return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart, + SecondVar, ThirdPart, RParenLoc, Body.take()); } /// ParseGotoStatement @@ -1267,7 +1522,16 @@ StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) { return StmtError(); } - R = ParseExpression(); + // FIXME: This is a hack to allow something like C++0x's generalized + // initializer lists, but only enough of this feature to allow Clang to + // parse libstdc++ 4.5's headers. + if (Tok.is(tok::l_brace) && getLang().CPlusPlus) { + R = ParseInitializer(); + if (R.isUsable() && !getLang().CPlusPlus0x) + Diag(R.get()->getLocStart(), diag::ext_generalized_initializer_lists) + << R.get()->getSourceRange(); + } else + R = ParseExpression(); if (R.isInvalid()) { // Skip to the semicolon, but don't consume it. SkipUntil(tok::semi, false, true); return StmtError(); @@ -1350,7 +1614,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { msAsm = true; return FuzzyParseMicrosoftAsmStatement(AsmLoc); } - DeclSpec DS; + DeclSpec DS(AttrFactory); SourceLocation Loc = Tok.getLocation(); ParseTypeQualifierListOpt(DS, true, false); @@ -1522,14 +1786,17 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl &Names, return true; } -Decl *Parser::ParseFunctionStatementBody(Decl *Decl) { +Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { assert(Tok.is(tok::l_brace)); SourceLocation LBraceLoc = Tok.getLocation(); - if (PP.isCodeCompletionEnabled()) - if (trySkippingFunctionBodyForCodeCompletion()) + if (PP.isCodeCompletionEnabled()) { + if (trySkippingFunctionBodyForCodeCompletion()) { + BodyScope.Exit(); return Actions.ActOnFinishFunctionBody(Decl, 0); - + } + } + PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, "parsing function body"); @@ -1543,6 +1810,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl) { FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, MultiStmtArg(Actions), false); + BodyScope.Exit(); return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); } @@ -1551,7 +1819,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl) { /// function-try-block: /// 'try' ctor-initializer[opt] compound-statement handler-seq /// -Decl *Parser::ParseFunctionTryBlock(Decl *Decl) { +Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { assert(Tok.is(tok::kw_try) && "Expected 'try'"); SourceLocation TryLoc = ConsumeToken(); @@ -1562,9 +1830,12 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl) { if (Tok.is(tok::colon)) ParseConstructorInitializer(Decl); - if (PP.isCodeCompletionEnabled()) - if (trySkippingFunctionBodyForCodeCompletion()) + if (PP.isCodeCompletionEnabled()) { + if (trySkippingFunctionBodyForCodeCompletion()) { + BodyScope.Exit(); return Actions.ActOnFinishFunctionBody(Decl, 0); + } + } SourceLocation LBraceLoc = Tok.getLocation(); StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc)); @@ -1574,6 +1845,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl) { FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, MultiStmtArg(Actions), false); + BodyScope.Exit(); return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); } @@ -1622,32 +1894,58 @@ StmtResult Parser::ParseCXXTryBlock(ParsedAttributes &attrs) { /// handler-seq: /// handler handler-seq[opt] /// +/// [Borland] try-block: +/// 'try' compound-statement seh-except-block +/// 'try' compound-statment seh-finally-block +/// StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { if (Tok.isNot(tok::l_brace)) return StmtError(Diag(Tok, diag::err_expected_lbrace)); // FIXME: Possible draft standard bug: attribute-specifier should be allowed? - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); StmtResult TryBlock(ParseCompoundStatement(attrs)); if (TryBlock.isInvalid()) return move(TryBlock); - StmtVector Handlers(Actions); - MaybeParseCXX0XAttributes(attrs); - ProhibitAttributes(attrs); + // Borland allows SEH-handlers with 'try' + if(Tok.is(tok::kw___except) || Tok.is(tok::kw___finally)) { + // TODO: Factor into common return ParseSEHHandlerCommon(...) + StmtResult Handler; + if(Tok.is(tok::kw___except)) { + SourceLocation Loc = ConsumeToken(); + Handler = ParseSEHExceptBlock(Loc); + } + else { + SourceLocation Loc = ConsumeToken(); + Handler = ParseSEHFinallyBlock(Loc); + } + if(Handler.isInvalid()) + return move(Handler); - if (Tok.isNot(tok::kw_catch)) - return StmtError(Diag(Tok, diag::err_expected_catch)); - while (Tok.is(tok::kw_catch)) { - StmtResult Handler(ParseCXXCatchBlock()); - if (!Handler.isInvalid()) - Handlers.push_back(Handler.release()); + return Actions.ActOnSEHTryBlock(true /* IsCXXTry */, + TryLoc, + TryBlock.take(), + Handler.take()); } - // Don't bother creating the full statement if we don't have any usable - // handlers. - if (Handlers.empty()) - return StmtError(); + else { + StmtVector Handlers(Actions); + MaybeParseCXX0XAttributes(attrs); + ProhibitAttributes(attrs); - return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), move_arg(Handlers)); + if (Tok.isNot(tok::kw_catch)) + return StmtError(Diag(Tok, diag::err_expected_catch)); + while (Tok.is(tok::kw_catch)) { + StmtResult Handler(ParseCXXCatchBlock()); + if (!Handler.isInvalid()) + Handlers.push_back(Handler.release()); + } + // Don't bother creating the full statement if we don't have any usable + // handlers. + if (Handlers.empty()) + return StmtError(); + + return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), move_arg(Handlers)); + } } /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard @@ -1679,7 +1977,7 @@ StmtResult Parser::ParseCXXCatchBlock() { // without default arguments. Decl *ExceptionDecl = 0; if (Tok.isNot(tok::ellipsis)) { - DeclSpec DS; + DeclSpec DS(AttrFactory); if (ParseCXXTypeSpecifierSeq(DS)) return StmtError(); Declarator ExDecl(DS, Declarator::CXXCatchContext); @@ -1695,7 +1993,7 @@ StmtResult Parser::ParseCXXCatchBlock() { return StmtError(Diag(Tok, diag::err_expected_lbrace)); // FIXME: Possible draft standard bug: attribute-specifier should be allowed? - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); StmtResult Block(ParseCompoundStatement(attrs)); if (Block.isInvalid()) return move(Block); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index 59ced8b07fc5..12e38daf0029 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -17,6 +17,8 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "RAIIObjectsForParser.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ASTConsumer.h" using namespace clang; /// \brief Parse a template declaration, explicit instantiation, or @@ -196,7 +198,7 @@ Parser::ParseSingleDeclarationAfterTemplate( return 0; } - ParsedAttributesWithRange prefixAttrs; + ParsedAttributesWithRange prefixAttrs(AttrFactory); MaybeParseCXX0XAttributes(prefixAttrs); if (Tok.is(tok::kw_using)) @@ -205,7 +207,7 @@ Parser::ParseSingleDeclarationAfterTemplate( // Parse the declaration specifiers, stealing the accumulated // diagnostics from the template parameters. - ParsingDeclSpec DS(DiagsFromTParams); + ParsingDeclSpec DS(*this, &DiagsFromTParams); DS.takeAttributesFrom(prefixAttrs); @@ -598,7 +600,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // Parse the declaration-specifiers (i.e., the type). // FIXME: The type should probably be restricted in some way... Not all // declarators (parts of declarators?) are accepted for parameters. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // Parse this as a typename. @@ -661,7 +663,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { bool Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, SourceLocation TemplateNameLoc, - const CXXScopeSpec *SS, + const CXXScopeSpec &SS, bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, @@ -756,7 +758,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, /// formed, this function returns true. /// bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, - const CXXScopeSpec *SS, + CXXScopeSpec &SS, UnqualifiedId &TemplateName, SourceLocation TemplateKWLoc, bool AllowTypeAnnotation) { @@ -790,7 +792,8 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // Build the annotation token. if (TNK == TNK_Type_template && AllowTypeAnnotation) { TypeResult Type - = Actions.ActOnTemplateIdType(Template, TemplateNameLoc, + = Actions.ActOnTemplateIdType(SS, + Template, TemplateNameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc); if (Type.isInvalid()) { @@ -803,8 +806,8 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Type.get()); - if (SS && SS->isNotEmpty()) - Tok.setLocation(SS->getBeginLoc()); + if (SS.isNotEmpty()) + Tok.setLocation(SS.getBeginLoc()); else if (TemplateKWLoc.isValid()) Tok.setLocation(TemplateKWLoc); else @@ -823,6 +826,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, TemplateId->Name = 0; TemplateId->Operator = TemplateName.OperatorFunctionId.Operator; } + TemplateId->SS = SS; TemplateId->Template = Template; TemplateId->Kind = TNK; TemplateId->LAngleLoc = LAngleLoc; @@ -854,7 +858,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, /// If there was a failure when forming the type from the template-id, /// a type annotation token will still be created, but will have a /// NULL type pointer to signify an error. -void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { +void Parser::AnnotateTemplateIdTokenAsType() { assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens"); TemplateIdAnnotation *TemplateId @@ -868,7 +872,8 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { TemplateId->NumArgs); TypeResult Type - = Actions.ActOnTemplateIdType(TemplateId->Template, + = Actions.ActOnTemplateIdType(TemplateId->SS, + TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, @@ -876,8 +881,8 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { // Create the new "type" annotation token. Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Type.isInvalid() ? ParsedType() : Type.get()); - if (SS && SS->isNotEmpty()) // it was a C++ qualified type name. - Tok.setLocation(SS->getBeginLoc()); + if (TemplateId->SS.isNotEmpty()) // it was a C++ qualified type name. + Tok.setLocation(TemplateId->SS.getBeginLoc()); // End location stays the same // Replace the template-id annotation token, and possible the scope-specifier @@ -1122,3 +1127,125 @@ SourceRange Parser::ParsedTemplateInfo::getSourceRange() const { R.setBegin(ExternLoc); return R; } + +void Parser::LateTemplateParserCallback(void *P, const FunctionDecl *FD) { + ((Parser*)P)->LateTemplateParser(FD); +} + + +void Parser::LateTemplateParser(const FunctionDecl *FD) { + LateParsedTemplatedFunction *LPT = LateParsedTemplateMap[FD]; + if (LPT) { + ParseLateTemplatedFuncDef(*LPT); + return; + } + + llvm_unreachable("Late templated function without associated lexed tokens"); +} + +/// \brief Late parse a C++ function template in Microsoft mode. +void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { + if(!LMT.D) + return; + + // If this is a member template, introduce the template parameter scope. + ParseScope TemplateScope(this, Scope::TemplateParamScope); + + // Get the FunctionDecl. + FunctionDecl *FD = 0; + if (FunctionTemplateDecl *FunTmpl = dyn_cast(LMT.D)) + FD = FunTmpl->getTemplatedDecl(); + else + FD = cast(LMT.D); + + // Reinject the template parameters. + DeclaratorDecl* Declarator = dyn_cast(FD); + if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { + Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); + Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); + } else { + Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); + + DeclContext *DD = FD->getLexicalParent(); + while (DD && DD->isRecord()) { + if (ClassTemplatePartialSpecializationDecl* MD = + dyn_cast_or_null(DD)) + Actions.ActOnReenterTemplateScope(getCurScope(), MD); + else if (CXXRecordDecl* MD = dyn_cast_or_null(DD)) + Actions.ActOnReenterTemplateScope(getCurScope(), + MD->getDescribedClassTemplate()); + + DD = DD->getLexicalParent(); + } + } + assert(!LMT.Toks.empty() && "Empty body!"); + + // Append the current token at the end of the new token stream so that it + // doesn't get lost. + LMT.Toks.push_back(Tok); + PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false); + + // Consume the previously pushed token. + ConsumeAnyToken(); + assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) + && "Inline method not starting with '{', ':' or 'try'"); + + // Parse the method body. Function body parsing code is similar enough + // to be re-used for method bodies as well. + ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); + + // Recreate the DeclContext. + Sema::ContextRAII SavedContext(Actions, Actions.getContainingDC(FD)); + + if (FunctionTemplateDecl *FunctionTemplate + = dyn_cast_or_null(LMT.D)) + Actions.ActOnStartOfFunctionDef(getCurScope(), + FunctionTemplate->getTemplatedDecl()); + if (FunctionDecl *Function = dyn_cast_or_null(LMT.D)) + Actions.ActOnStartOfFunctionDef(getCurScope(), Function); + + + if (Tok.is(tok::kw_try)) { + ParseFunctionTryBlock(LMT.D, FnScope); + return; + } + if (Tok.is(tok::colon)) { + ParseConstructorInitializer(LMT.D); + + // Error recovery. + if (!Tok.is(tok::l_brace)) { + Actions.ActOnFinishFunctionBody(LMT.D, 0); + return; + } + } else + Actions.ActOnDefaultCtorInitializers(LMT.D); + + ParseFunctionStatementBody(LMT.D, FnScope); + Actions.MarkAsLateParsedTemplate(FD, false); + + DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D); + if (grp) + Actions.getASTConsumer().HandleTopLevelDecl(grp.get()); +} + +/// \brief Lex a delayed template function for late parsing. +void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) { + tok::TokenKind kind = Tok.getKind(); + // We may have a constructor initializer or function-try-block here. + if (kind == tok::colon || kind == tok::kw_try) + ConsumeAndStoreUntil(tok::l_brace, Toks); + else { + Toks.push_back(Tok); + ConsumeBrace(); + } + // Consume everything up to (and including) the matching right brace. + ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); + + // If we're in a function-try-block, we need to store all the catch blocks. + if (kind == tok::kw_try) { + while (Tok.is(tok::kw_catch)) { + ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); + ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); + } + } +} diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp index a603c37a53e5..1c4e2b3ddc8b 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp @@ -58,6 +58,7 @@ bool Parser::isCXXDeclarationStatement() { case tok::kw_using: // static_assert-declaration case tok::kw_static_assert: + case tok::kw__Static_assert: return true; // simple-declaration default: @@ -658,10 +659,12 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___is_convertible_to: case tok::kw___is_empty: case tok::kw___is_enum: + case tok::kw___is_literal: + case tok::kw___is_literal_type: case tok::kw___is_pod: case tok::kw___is_polymorphic: + case tok::kw___is_trivial: case tok::kw___is_union: - case tok::kw___is_literal: case tok::kw___uuidof: return TPResult::True(); @@ -673,6 +676,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw_float: case tok::kw_int: case tok::kw_long: + case tok::kw___int64: case tok::kw_restrict: case tok::kw_short: case tok::kw_signed: @@ -907,7 +911,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { if (TemplateId->Kind != TNK_Type_template) return TPResult::False(); CXXScopeSpec SS; - AnnotateTemplateIdTokenAsType(&SS); + AnnotateTemplateIdTokenAsType(); assert(Tok.is(tok::annot_typename)); goto case_typename; } @@ -968,6 +972,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw_short: case tok::kw_int: case tok::kw_long: + case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: case tok::kw_float: @@ -1151,7 +1156,7 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause() { return TPResult::True(); // '...' is a sign of a function declarator. } - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); MaybeParseMicrosoftAttributes(attrs); // decl-specifier-seq @@ -1238,6 +1243,16 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() { if (!SkipUntil(tok::r_paren)) return TPResult::Error(); } + if (Tok.is(tok::kw_noexcept)) { + ConsumeToken(); + // Possibly an expression as well. + if (Tok.is(tok::l_paren)) { + // Find the matching rparen. + ConsumeParen(); + if (!SkipUntil(tok::r_paren)) + return TPResult::Error(); + } + } return TPResult::Ambiguous(); } diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 07e592cdb05b..4d08699bdd39 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -19,10 +19,11 @@ #include "llvm/Support/raw_ostream.h" #include "RAIIObjectsForParser.h" #include "ParsePragma.h" +#include "clang/AST/DeclTemplate.h" using namespace clang; Parser::Parser(Preprocessor &pp, Sema &actions) - : CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()), + : PP(pp), Actions(actions), Diags(PP.getDiagnostics()), GreaterThanIsOperator(true), ColonIsSacred(false), InMessageExpression(false), TemplateParameterDepth(0) { Tok.setKind(tok::eof); @@ -44,6 +45,9 @@ Parser::Parser(Preprocessor &pp, Sema &actions) PackHandler.reset(new PragmaPackHandler(actions)); PP.AddPragmaHandler(PackHandler.get()); + + MSStructHandler.reset(new PragmaMSStructHandler(actions)); + PP.AddPragmaHandler(MSStructHandler.get()); UnusedHandler.reset(new PragmaUnusedHandler(actions, *this)); PP.AddPragmaHandler(UnusedHandler.get()); @@ -362,6 +366,11 @@ Parser::~Parser() { for (unsigned i = 0, e = NumCachedScopes; i != e; ++i) delete ScopeCache[i]; + // Free LateParsedTemplatedFunction nodes. + for (LateParsedTemplateMapT::iterator it = LateParsedTemplateMap.begin(); + it != LateParsedTemplateMap.end(); ++it) + delete it->second; + // Remove the pragma handlers we installed. PP.RemovePragmaHandler(AlignHandler.get()); AlignHandler.reset(); @@ -371,6 +380,8 @@ Parser::~Parser() { OptionsHandler.reset(); PP.RemovePragmaHandler(PackHandler.get()); PackHandler.reset(); + PP.RemovePragmaHandler(MSStructHandler.get()); + MSStructHandler.reset(); PP.RemovePragmaHandler(UnusedHandler.get()); UnusedHandler.reset(); PP.RemovePragmaHandler(WeakHandler.get()); @@ -422,6 +433,37 @@ void Parser::Initialize() { Ident_vector = &PP.getIdentifierTable().get("vector"); Ident_pixel = &PP.getIdentifierTable().get("pixel"); } + + Ident_introduced = 0; + Ident_deprecated = 0; + Ident_obsoleted = 0; + Ident_unavailable = 0; + + Ident__exception_code = Ident__exception_info = Ident__abnormal_termination = 0; + Ident___exception_code = Ident___exception_info = Ident___abnormal_termination = 0; + Ident_GetExceptionCode = Ident_GetExceptionInfo = Ident_AbnormalTermination = 0; + + if(getLang().Borland) { + Ident__exception_info = PP.getIdentifierInfo("_exception_info"); + Ident___exception_info = PP.getIdentifierInfo("__exception_info"); + Ident_GetExceptionInfo = PP.getIdentifierInfo("GetExceptionInformation"); + Ident__exception_code = PP.getIdentifierInfo("_exception_code"); + Ident___exception_code = PP.getIdentifierInfo("__exception_code"); + Ident_GetExceptionCode = PP.getIdentifierInfo("GetExceptionCode"); + Ident__abnormal_termination = PP.getIdentifierInfo("_abnormal_termination"); + Ident___abnormal_termination = PP.getIdentifierInfo("__abnormal_termination"); + Ident_AbnormalTermination = PP.getIdentifierInfo("AbnormalTermination"); + + PP.SetPoisonReason(Ident__exception_code,diag::err_seh___except_block); + PP.SetPoisonReason(Ident___exception_code,diag::err_seh___except_block); + PP.SetPoisonReason(Ident_GetExceptionCode,diag::err_seh___except_block); + PP.SetPoisonReason(Ident__exception_info,diag::err_seh___except_filter); + PP.SetPoisonReason(Ident___exception_info,diag::err_seh___except_filter); + PP.SetPoisonReason(Ident_GetExceptionInfo,diag::err_seh___except_filter); + PP.SetPoisonReason(Ident__abnormal_termination,diag::err_seh___finally_block); + PP.SetPoisonReason(Ident___abnormal_termination,diag::err_seh___finally_block); + PP.SetPoisonReason(Ident_AbnormalTermination,diag::err_seh___finally_block); + } } /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the @@ -433,11 +475,15 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { Result = DeclGroupPtrTy(); if (Tok.is(tok::eof)) { + // Late template parsing can begin. + if (getLang().DelayedTemplateParsing) + Actions.SetLateTemplateParser(LateTemplateParserCallback, this); + Actions.ActOnEndOfTranslationUnit(); return true; } - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); MaybeParseMicrosoftAttributes(attrs); @@ -513,14 +559,16 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::kw_asm: { ProhibitAttributes(attrs); - ExprResult Result(ParseSimpleAsm()); + SourceLocation StartLoc = Tok.getLocation(); + SourceLocation EndLoc; + ExprResult Result(ParseSimpleAsm(&EndLoc)); ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "top-level asm block"); if (Result.isInvalid()) return DeclGroupPtrTy(); - SingleDecl = Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), Result.get()); + SingleDecl = Actions.ActOnFileScopeAsmDecl(Result.get(), StartLoc, EndLoc); break; } case tok::at: @@ -550,6 +598,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::kw_template: case tok::kw_export: // As in 'export template' case tok::kw_static_assert: + case tok::kw__Static_assert: // A function definition cannot start with a these keywords. { SourceLocation DeclEnd; @@ -743,6 +792,8 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs, /// Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo) { + // Poison the SEH identifiers so they are flagged as illegal in function bodies + PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // If this is C90 and the declspecs were completely missing, fudge in an @@ -778,6 +829,44 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, return 0; } + // In delayed template parsing mode, for function template we consume the + // tokens and store them for late parsing at the end of the translation unit. + if (getLang().DelayedTemplateParsing && + TemplateInfo.Kind == ParsedTemplateInfo::Template) { + MultiTemplateParamsArg TemplateParameterLists(Actions, + TemplateInfo.TemplateParams->data(), + TemplateInfo.TemplateParams->size()); + + ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); + Scope *ParentScope = getCurScope()->getParent(); + + Decl *DP = Actions.HandleDeclarator(ParentScope, D, + move(TemplateParameterLists), + /*IsFunctionDefinition=*/true); + D.complete(DP); + D.getMutableDeclSpec().abort(); + + if (DP) { + LateParsedTemplatedFunction *LPT = new LateParsedTemplatedFunction(this, DP); + + FunctionDecl *FnD = 0; + if (FunctionTemplateDecl *FunTmpl = dyn_cast(DP)) + FnD = FunTmpl->getTemplatedDecl(); + else + FnD = cast(DP); + Actions.CheckForFunctionRedefinition(FnD); + + LateParsedTemplateMap[FnD] = LPT; + Actions.MarkAsLateParsedTemplate(FnD); + LexTemplateFunctionForLateParsing(LPT->Toks); + } else { + CachedTokens Toks; + LexTemplateFunctionForLateParsing(Toks); + } + return DP; + } + + // Enter a scope for the function body. ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); @@ -799,7 +888,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, D.getMutableDeclSpec().abort(); if (Tok.is(tok::kw_try)) - return ParseFunctionTryBlock(Res); + return ParseFunctionTryBlock(Res, BodyScope); // If we have a colon, then we're probably parsing a C++ // ctor-initializer. @@ -808,13 +897,14 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Recover from error. if (!Tok.is(tok::l_brace)) { + BodyScope.Exit(); Actions.ActOnFinishFunctionBody(Res, 0); return Res; } } else Actions.ActOnDefaultCtorInitializers(Res); - return ParseFunctionStatementBody(Res); + return ParseFunctionStatementBody(Res, BodyScope); } /// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides @@ -832,7 +922,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { SourceLocation DSStart = Tok.getLocation(); // Parse the common declaration-specifiers piece. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // C99 6.9.1p6: 'each declaration in the declaration list shall have at @@ -1029,10 +1119,14 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { // simple-template-id SourceLocation TypenameLoc = ConsumeToken(); CXXScopeSpec SS; - if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), false)) + if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), false, + 0, /*IsTypename*/true)) return true; if (!SS.isSet()) { - Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); + if (getLang().Microsoft) + Diag(Tok.getLocation(), diag::warn_expected_qualified_after_typename); + else + Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); return true; } @@ -1051,15 +1145,18 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { return true; } - AnnotateTemplateIdTokenAsType(0); - assert(Tok.is(tok::annot_typename) && - "AnnotateTemplateIdTokenAsType isn't working properly"); - if (Tok.getAnnotationValue()) - Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, - SourceLocation(), - getTypeAnnotation(Tok)); - else - Ty = true; + ASTTemplateArgsPtr TemplateArgsPtr(Actions, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + + Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, + /*FIXME:*/SourceLocation(), + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); + TemplateId->Destroy(); } else { Diag(Tok, diag::err_expected_type_name_after_typename) << SS.getRange(); @@ -1088,7 +1185,9 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS, false, - NextToken().is(tok::period))) { + NextToken().is(tok::period), + ParsedType(), + /*NonTrivialTypeSourceInfo*/true)) { // This is a typename. Replace the current token in-place with an // annotation type token. Tok.setKind(tok::annot_typename); @@ -1124,7 +1223,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { Template, MemberOfUnknownSpecialization)) { // Consume the identifier. ConsumeToken(); - if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName)) { + if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName)) { // If an unrecoverable error occurred, we need to return true here, // because the token stream is in a damaged state. We may not return // a valid identifier. @@ -1147,7 +1246,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { // template-id annotation in a context where we weren't allowed // to produce a type annotation token. Update the template-id // annotation token to a type annotation token now. - AnnotateTemplateIdTokenAsType(&SS); + AnnotateTemplateIdTokenAsType(); return false; } } @@ -1184,7 +1283,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { assert(getLang().CPlusPlus && "Call sites of this function should be guarded by checking for C++"); - assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) && + assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || + (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)))&& "Cannot be a type or scope token!"); CXXScopeSpec SS; diff --git a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h index 583f18428d68..3765f92348ea 100644 --- a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h +++ b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h @@ -112,7 +112,31 @@ namespace clang { P.BraceCount = BraceCount; } }; - + + class PoisonSEHIdentifiersRAIIObject { + PoisonIdentifierRAIIObject Ident_AbnormalTermination; + PoisonIdentifierRAIIObject Ident_GetExceptionCode; + PoisonIdentifierRAIIObject Ident_GetExceptionInfo; + PoisonIdentifierRAIIObject Ident__abnormal_termination; + PoisonIdentifierRAIIObject Ident__exception_code; + PoisonIdentifierRAIIObject Ident__exception_info; + PoisonIdentifierRAIIObject Ident___abnormal_termination; + PoisonIdentifierRAIIObject Ident___exception_code; + PoisonIdentifierRAIIObject Ident___exception_info; + public: + PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue) + : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue), + Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue), + Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue), + Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue), + Ident__exception_code(Self.Ident__exception_code, NewValue), + Ident__exception_info(Self.Ident__exception_info, NewValue), + Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue), + Ident___exception_code(Self.Ident___exception_code, NewValue), + Ident___exception_info(Self.Ident___exception_info, NewValue) { + } + }; + } // end namespace clang #endif diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp index 0263f657a6e3..d6e34ef8fa46 100644 --- a/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp @@ -1426,7 +1426,8 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, RecName += "_IMPL"; IdentifierInfo *II = &Context->Idents.get(RecName); RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), II); + SourceLocation(), SourceLocation(), + II); assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, @@ -1472,7 +1473,8 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, RecName += "_IMPL"; IdentifierInfo *II = &Context->Idents.get(RecName); RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), II); + SourceLocation(), SourceLocation(), + II); assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, @@ -2109,7 +2111,8 @@ Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { std::string StrEncoding; Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); Expr *Replacement = StringLiteral::Create(*Context,StrEncoding.c_str(), - StrEncoding.length(), false,StrType, + StrEncoding.length(), + false, false, StrType, SourceLocation()); ReplaceStmt(Exp, Replacement); @@ -2128,7 +2131,8 @@ Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { SelExprs.push_back(StringLiteral::Create(*Context, Exp->getSelector().getAsString().c_str(), Exp->getSelector().getAsString().size(), - false, argType, SourceLocation())); + false, false, argType, + SourceLocation())); CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, &SelExprs[0], SelExprs.size()); ReplaceStmt(Exp, SelExp); @@ -2360,6 +2364,7 @@ void RewriteObjC::SynthSelGetUidFunctionDecl() { QualType getFuncType = getSimpleFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size()); SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), SelGetUidIdent, getFuncType, 0, SC_Extern, @@ -2456,6 +2461,7 @@ void RewriteObjC::SynthSuperContructorFunctionDecl() { QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size()); SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), msgSendIdent, msgSendType, 0, SC_Extern, @@ -2476,6 +2482,7 @@ void RewriteObjC::SynthMsgSendFunctionDecl() { &ArgTys[0], ArgTys.size(), true /*isVariadic*/); MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), msgSendIdent, msgSendType, 0, SC_Extern, @@ -2487,7 +2494,7 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() { IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); llvm::SmallVector ArgTys; RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), + SourceLocation(), SourceLocation(), &Context->Idents.get("objc_super")); QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); @@ -2499,6 +2506,7 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() { &ArgTys[0], ArgTys.size(), true /*isVariadic*/); MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), msgSendIdent, msgSendType, 0, SC_Extern, @@ -2519,6 +2527,7 @@ void RewriteObjC::SynthMsgSendStretFunctionDecl() { &ArgTys[0], ArgTys.size(), true /*isVariadic*/); MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), msgSendIdent, msgSendType, 0, SC_Extern, @@ -2532,7 +2541,7 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { &Context->Idents.get("objc_msgSendSuper_stret"); llvm::SmallVector ArgTys; RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), + SourceLocation(), SourceLocation(), &Context->Idents.get("objc_super")); QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); @@ -2545,6 +2554,7 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { true /*isVariadic*/); MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), + SourceLocation(), msgSendIdent, msgSendType, 0, SC_Extern, SC_None, false); @@ -2564,6 +2574,7 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() { &ArgTys[0], ArgTys.size(), true /*isVariadic*/); MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), msgSendIdent, msgSendType, 0, SC_Extern, @@ -2578,6 +2589,7 @@ void RewriteObjC::SynthGetClassFunctionDecl() { QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size()); GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), getClassIdent, getClassType, 0, SC_Extern, @@ -2593,6 +2605,7 @@ void RewriteObjC::SynthGetSuperClassFunctionDecl() { QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), &ArgTys[0], ArgTys.size()); GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), getSuperClassIdent, getClassType, 0, @@ -2609,6 +2622,7 @@ void RewriteObjC::SynthGetMetaClassFunctionDecl() { QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size()); GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), getClassIdent, getClassType, 0, SC_Extern, @@ -2645,8 +2659,8 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), - &Context->Idents.get(S), strType, 0, - SC_Static, SC_None); + SourceLocation(), &Context->Idents.get(S), + strType, 0, SC_Static, SC_None); DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, VK_LValue, SourceLocation()); Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, @@ -2665,7 +2679,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { QualType RewriteObjC::getSuperStructType() { if (!SuperStructDecl) { SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), + SourceLocation(), SourceLocation(), &Context->Idents.get("objc_super")); QualType FieldTypes[2]; @@ -2677,6 +2691,7 @@ QualType RewriteObjC::getSuperStructType() { // Create fields for (unsigned i = 0; i < 2; ++i) { SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, + SourceLocation(), SourceLocation(), 0, FieldTypes[i], 0, /*BitWidth=*/0, @@ -2691,7 +2706,7 @@ QualType RewriteObjC::getSuperStructType() { QualType RewriteObjC::getConstantStringStructType() { if (!ConstantStringDecl) { ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), + SourceLocation(), SourceLocation(), &Context->Idents.get("__NSConstantStringImpl")); QualType FieldTypes[4]; @@ -2708,6 +2723,7 @@ QualType RewriteObjC::getConstantStringStructType() { for (unsigned i = 0; i < 4; ++i) { ConstantStringDecl->addDecl(FieldDecl::Create(*Context, ConstantStringDecl, + SourceLocation(), SourceLocation(), 0, FieldTypes[i], 0, /*BitWidth=*/0, @@ -2782,7 +2798,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, ClsExprs.push_back(StringLiteral::Create(*Context, ClassDecl->getIdentifier()->getNameStart(), ClassDecl->getIdentifier()->getLength(), - false, argType, SourceLocation())); + false, false, argType, SourceLocation())); CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, &ClsExprs[0], ClsExprs.size(), @@ -2861,8 +2877,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, ClsExprs.push_back(StringLiteral::Create(*Context, clsName->getNameStart(), clsName->getLength(), - false, argType, - SourceLocation())); + false, false, + argType, SourceLocation())); CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, &ClsExprs[0], ClsExprs.size(), @@ -2893,7 +2909,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, ClsExprs.push_back(StringLiteral::Create(*Context, ClassDecl->getIdentifier()->getNameStart(), ClassDecl->getIdentifier()->getLength(), - false, argType, SourceLocation())); + false, false, argType, SourceLocation())); CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, &ClsExprs[0], ClsExprs.size(), @@ -2975,7 +2991,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SelExprs.push_back(StringLiteral::Create(*Context, Exp->getSelector().getAsString().c_str(), Exp->getSelector().getAsString().size(), - false, argType, SourceLocation())); + false, false, argType, SourceLocation())); CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, &SelExprs[0], SelExprs.size(), StartLoc, @@ -3102,10 +3118,11 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SourceLocation()); // Build sizeof(returnType) - SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true, - Context->getTrivialTypeSourceInfo(returnType), - Context->getSizeType(), - SourceLocation(), SourceLocation()); + UnaryExprOrTypeTraitExpr *sizeofExpr = + new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf, + Context->getTrivialTypeSourceInfo(returnType), + Context->getSizeType(), SourceLocation(), + SourceLocation()); // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases. // For X86 it is more complicated and some kind of target specific routine @@ -3149,7 +3166,7 @@ QualType RewriteObjC::getProtocolType() { TypeSourceInfo *TInfo = Context->getTrivialTypeSourceInfo(Context->getObjCIdType()); ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, - SourceLocation(), + SourceLocation(), SourceLocation(), &Context->Idents.get("Protocol"), TInfo); } @@ -3164,7 +3181,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString(); IdentifierInfo *ID = &Context->Idents.get(Name); VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), - ID, getProtocolType(), 0, + SourceLocation(), ID, getProtocolType(), 0, SC_Extern, SC_None); DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), VK_LValue, SourceLocation()); @@ -3745,7 +3762,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, std::string &Result) { ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); - // Explictly declared @interface's are already synthesized. + // Explicitly declared @interface's are already synthesized. if (CDecl->isImplicitInterfaceDecl()) { // FIXME: Implementation of a class with no @interface (legacy) doese not // produce correct synthesis as yet. @@ -4315,20 +4332,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, S += " "; std::string FieldName = (*I)->getNameAsString(); std::string ArgName = "_" + FieldName; - // Handle nested closure invocation. For example: - // - // void (^myImportedBlock)(void); - // myImportedBlock = ^(void) { setGlobalInt(x + y); }; - // - // void (^anotherBlock)(void); - // anotherBlock = ^(void) { - // myImportedBlock(); // import and invoke the closure - // }; - // - if (isTopLevelBlockPointerType((*I)->getType())) { - S += "struct __block_impl *"; - Constructor += ", void *" + ArgName; - } else { + { std::string TypeString; RewriteByRefString(TypeString, FieldName, (*I)); TypeString += " *"; @@ -4366,11 +4370,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, } else Constructor += ", "; - if (isTopLevelBlockPointerType((*I)->getType())) - Constructor += Name + "((struct __block_impl *)_" - + Name + "->__forwarding)"; - else - Constructor += Name + "(_" + Name + "->__forwarding)"; + Constructor += Name + "(_" + Name + "->__forwarding)"; } Constructor += " {\n"; @@ -4601,7 +4601,7 @@ void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, /// convertFunctionTypeOfBlocks - This routine converts a function type /// whose result type may be a block pointer or whose argument type(s) -/// might be block pointers to an equivalent funtion type replacing +/// might be block pointers to an equivalent function type replacing /// all block pointers to function pointers. QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { const FunctionProtoType *FTP = dyn_cast(FT); @@ -4672,7 +4672,7 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { // FTP will be null for closures that don't take arguments. RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), + SourceLocation(), SourceLocation(), &Context->Idents.get("__block_impl")); QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD)); @@ -4706,7 +4706,9 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { //PE->dump(); FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), - &Context->Idents.get("FuncPtr"), Context->VoidPtrTy, 0, + SourceLocation(), + &Context->Idents.get("FuncPtr"), + Context->VoidPtrTy, 0, /*BitWidth=*/0, /*Mutable=*/true); MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), FD->getType(), VK_LValue, @@ -4758,6 +4760,7 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) { } FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), + SourceLocation(), &Context->Idents.get("__forwarding"), Context->VoidPtrTy, 0, /*BitWidth=*/0, /*Mutable=*/true); @@ -4767,7 +4770,7 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) { OK_Ordinary); llvm::StringRef Name = VD->getName(); - FD = FieldDecl::Create(*Context, 0, SourceLocation(), + FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), &Context->Idents.get(Name), Context->VoidPtrTy, 0, /*BitWidth=*/0, /*Mutable=*/true); @@ -4777,7 +4780,8 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) { // Need parens to enforce precedence. - ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), + ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), + DeclRefExp->getExprLoc(), ME); ReplaceStmt(DeclRefExp, PE); return PE; @@ -4949,7 +4953,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { QualType DeclT; if (VarDecl *VD = dyn_cast(ND)) DeclT = VD->getType(); - else if (TypedefDecl *TDD = dyn_cast(ND)) + else if (TypedefNameDecl *TDD = dyn_cast(ND)) DeclT = TDD->getUnderlyingType(); else if (FieldDecl *FD = dyn_cast(ND)) DeclT = FD->getType(); @@ -5053,7 +5057,7 @@ std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, unsigned VoidPtrSize = static_cast(Context->getTypeSize(Context->VoidPtrTy)); - unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/8; + unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth(); S += " _Block_object_assign((char*)dst + "; S += utostr(offset); S += ", *(void * *) ((char*)src + "; @@ -5124,8 +5128,11 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; } - - Ty.getAsStringInternal(Name, Context->PrintingPolicy); + + QualType T = Ty; + (void)convertBlockPointerToFunctionPointer(T); + T.getAsStringInternal(Name, Context->PrintingPolicy); + ByrefType += " " + Name + ";\n"; ByrefType += "};\n"; // Insert this type in global scope. It is needed by helper function. @@ -5183,7 +5190,12 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { ByrefType += utostr(flag); } ByrefType += "};\n"; - ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), ByrefType); + unsigned nameSize = Name.size(); + // for block or function pointer declaration. Name is aleady + // part of the declaration. + if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) + nameSize = 1; + ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType); } else { SourceLocation startLoc; @@ -5263,8 +5275,8 @@ void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(llvm::StringRef name) { IdentifierInfo *ID = &Context->Idents.get(name); QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); - return FunctionDecl::Create(*Context, TUDecl,SourceLocation(), - ID, FType, 0, SC_Extern, + return FunctionDecl::Create(*Context, TUDecl, SourceLocation(), + SourceLocation(), ID, FType, 0, SC_Extern, SC_None, false, false); } @@ -5345,10 +5357,11 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, // Initialize the block descriptor. std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA"; - VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), - &Context->Idents.get(DescData.c_str()), - Context->VoidPtrTy, 0, - SC_Static, SC_None); + VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, + SourceLocation(), SourceLocation(), + &Context->Idents.get(DescData.c_str()), + Context->VoidPtrTy, 0, + SC_Static, SC_None); UnaryOperator *DescRefExpr = new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, Context->VoidPtrTy, @@ -5407,7 +5420,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, IdentifierInfo *II = &Context->Idents.get(RecName.c_str() + sizeof("struct")); RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), II); + SourceLocation(), SourceLocation(), + II); assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); @@ -5507,27 +5521,34 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { for (Stmt::child_range CI = S->children(); CI; ++CI) if (*CI) { Stmt *newStmt; - Stmt *S = (*CI); - if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast(S)) { + Stmt *ChildStmt = (*CI); + if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast(ChildStmt)) { Expr *OldBase = IvarRefExpr->getBase(); bool replaced = false; - newStmt = RewriteObjCNestedIvarRefExpr(S, replaced); + newStmt = RewriteObjCNestedIvarRefExpr(ChildStmt, replaced); if (replaced) { if (ObjCIvarRefExpr *IRE = dyn_cast(newStmt)) ReplaceStmt(OldBase, IRE->getBase()); else - ReplaceStmt(S, newStmt); + ReplaceStmt(ChildStmt, newStmt); } } else - newStmt = RewriteFunctionBodyOrGlobalInitializer(S); - if (newStmt) - *CI = newStmt; + newStmt = RewriteFunctionBodyOrGlobalInitializer(ChildStmt); + if (newStmt) { + if (Expr *PropOrImplicitRefExpr = dyn_cast(ChildStmt)) + if (PropSetters[PropOrImplicitRefExpr] == S) { + S = newStmt; + newStmt = 0; + } + if (newStmt) + *CI = newStmt; + } // If dealing with an assignment with LHS being a property reference // expression, the entire assignment tree is rewritten into a property // setter messaging. This involvs the RHS too. Do not attempt to rewrite // RHS again. - if (Expr *Exp = dyn_cast(S)) + if (Expr *Exp = dyn_cast(ChildStmt)) if (isa(Exp)) { if (PropSetters[Exp]) { ++CI; @@ -5546,13 +5567,14 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { // Rewrite the block body in place. Stmt *SaveCurrentBody = CurrentBody; CurrentBody = BE->getBody(); + CollectPropertySetters(CurrentBody); PropParentMap = 0; RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); CurrentBody = SaveCurrentBody; PropParentMap = 0; ImportedLocalExternalDecls.clear(); // Now we snarf the rewritten text and stash it away for later use. - std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); + std::string Str = Rewrite.ConvertToString(BE->getBody()); RewrittenBlockExprs[BE] = Str; Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs); @@ -5714,7 +5736,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { RewriteTypeOfDecl(VD); } } - if (TypedefDecl *TD = dyn_cast(SD)) { + if (TypedefNameDecl *TD = dyn_cast(SD)) { if (isTopLevelBlockPointerType(TD->getUnderlyingType())) RewriteBlockPointerDecl(TD); else if (TD->getUnderlyingType()->isFunctionPointerType()) @@ -5884,7 +5906,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { } return; } - if (TypedefDecl *TD = dyn_cast(D)) { + if (TypedefNameDecl *TD = dyn_cast(D)) { if (isTopLevelBlockPointerType(TD->getUnderlyingType())) RewriteBlockPointerDecl(TD); else if (TD->getUnderlyingType()->isFunctionPointerType()) diff --git a/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp index 92e2b03f76ff..51fe379fee0d 100644 --- a/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp +++ b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp @@ -26,7 +26,23 @@ llvm::raw_ostream &RewriteBuffer::write(llvm::raw_ostream &os) const { return os; } -void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size) { +/// \brief Return true if this character is non-new-line whitespace: +/// ' ', '\t', '\f', '\v', '\r'. +static inline bool isWhitespace(unsigned char c) { + switch (c) { + case ' ': + case '\t': + case '\f': + case '\v': + case '\r': + return true; + default: + return false; + } +} + +void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size, + bool removeLineIfEmpty) { // Nothing to remove, exit early. if (Size == 0) return; @@ -38,6 +54,34 @@ void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size) { // Add a delta so that future changes are offset correctly. AddReplaceDelta(OrigOffset, -Size); + + if (removeLineIfEmpty) { + // Find the line that the remove occurred and if it is completely empty + // remove the line as well. + + iterator curLineStart = begin(); + unsigned curLineStartOffs = 0; + iterator posI = begin(); + for (unsigned i = 0; i != RealOffset; ++i) { + if (*posI == '\n') { + curLineStart = posI; + ++curLineStart; + curLineStartOffs = i + 1; + } + ++posI; + } + + unsigned lineSize = 0; + posI = curLineStart; + while (posI != end() && isWhitespace(*posI)) { + ++posI; + ++lineSize; + } + if (posI != end() && *posI == '\n') { + Buffer.erase(curLineStartOffs, lineSize + 1/* + '\n'*/); + AddReplaceDelta(curLineStartOffs, -(lineSize + 1/* + '\n'*/)); + } + } } void RewriteBuffer::InsertText(unsigned OrigOffset, llvm::StringRef Str, @@ -72,7 +116,8 @@ void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength, /// getRangeSize - Return the size in bytes of the specified range if they /// are in the same file. If not, this returns -1. -int Rewriter::getRangeSize(const CharSourceRange &Range) const { +int Rewriter::getRangeSize(const CharSourceRange &Range, + RewriteOptions opts) const { if (!isRewritable(Range.getBegin()) || !isRewritable(Range.getEnd())) return -1; @@ -91,8 +136,8 @@ int Rewriter::getRangeSize(const CharSourceRange &Range) const { RewriteBuffers.find(StartFileID); if (I != RewriteBuffers.end()) { const RewriteBuffer &RB = I->second; - EndOff = RB.getMappedOffset(EndOff, true); - StartOff = RB.getMappedOffset(StartOff); + EndOff = RB.getMappedOffset(EndOff, opts.IncludeInsertsAtEndOfRange); + StartOff = RB.getMappedOffset(StartOff, !opts.IncludeInsertsAtBeginOfRange); } @@ -104,8 +149,8 @@ int Rewriter::getRangeSize(const CharSourceRange &Range) const { return EndOff-StartOff; } -int Rewriter::getRangeSize(SourceRange Range) const { - return getRangeSize(CharSourceRange::getTokenRange(Range)); +int Rewriter::getRangeSize(SourceRange Range, RewriteOptions opts) const { + return getRangeSize(CharSourceRange::getTokenRange(Range), opts); } @@ -194,12 +239,24 @@ bool Rewriter::InsertText(SourceLocation Loc, llvm::StringRef Str, return false; } +bool Rewriter::InsertTextAfterToken(SourceLocation Loc, llvm::StringRef Str) { + if (!isRewritable(Loc)) return true; + FileID FID; + unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID); + RewriteOptions rangeOpts; + rangeOpts.IncludeInsertsAtBeginOfRange = false; + StartOffs += getRangeSize(SourceRange(Loc, Loc), rangeOpts); + getEditBuffer(FID).InsertText(StartOffs, Str, /*InsertAfter*/true); + return false; +} + /// RemoveText - Remove the specified text region. -bool Rewriter::RemoveText(SourceLocation Start, unsigned Length) { +bool Rewriter::RemoveText(SourceLocation Start, unsigned Length, + RewriteOptions opts) { if (!isRewritable(Start)) return true; FileID FID; unsigned StartOffs = getLocationOffsetAndFileID(Start, FID); - getEditBuffer(FID).RemoveText(StartOffs, Length); + getEditBuffer(FID).RemoveText(StartOffs, Length, opts.RemoveLineIfEmpty); return false; } @@ -216,6 +273,20 @@ bool Rewriter::ReplaceText(SourceLocation Start, unsigned OrigLength, return false; } +bool Rewriter::ReplaceText(SourceRange range, SourceRange replacementRange) { + if (!isRewritable(range.getBegin())) return true; + if (!isRewritable(range.getEnd())) return true; + if (replacementRange.isInvalid()) return true; + SourceLocation start = range.getBegin(); + unsigned origLength = getRangeSize(range); + unsigned newLength = getRangeSize(replacementRange); + FileID FID; + unsigned newOffs = getLocationOffsetAndFileID(replacementRange.getBegin(), + FID); + llvm::StringRef MB = SourceMgr->getBufferData(FID); + return ReplaceText(start, origLength, MB.substr(newOffs, newLength)); +} + /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty /// printer to generate the replacement code. This returns true if the input /// could not be rewritten, or false if successful. @@ -234,3 +305,93 @@ bool Rewriter::ReplaceStmt(Stmt *From, Stmt *To) { ReplaceText(From->getLocStart(), Size, Str); return false; } + +std::string Rewriter::ConvertToString(Stmt *From) { + std::string SStr; + llvm::raw_string_ostream S(SStr); + From->printPretty(S, 0, PrintingPolicy(*LangOpts)); + return S.str(); +} + +bool Rewriter::IncreaseIndentation(CharSourceRange range, + SourceLocation parentIndent) { + using llvm::StringRef; + + if (!isRewritable(range.getBegin())) return true; + if (!isRewritable(range.getEnd())) return true; + if (!isRewritable(parentIndent)) return true; + + FileID StartFileID, EndFileID, parentFileID; + unsigned StartOff, EndOff, parentOff; + + StartOff = getLocationOffsetAndFileID(range.getBegin(), StartFileID); + EndOff = getLocationOffsetAndFileID(range.getEnd(), EndFileID); + parentOff = getLocationOffsetAndFileID(parentIndent, parentFileID); + + if (StartFileID != EndFileID || StartFileID != parentFileID) + return true; + if (StartOff >= EndOff || parentOff >= StartOff) + return true; + + FileID FID = StartFileID; + StringRef MB = SourceMgr->getBufferData(FID); + + unsigned parentLineNo = SourceMgr->getLineNumber(FID, parentOff) - 1; + unsigned startLineNo = SourceMgr->getLineNumber(FID, StartOff) - 1; + unsigned endLineNo = SourceMgr->getLineNumber(FID, EndOff) - 1; + + const SrcMgr::ContentCache * + Content = SourceMgr->getSLocEntry(FID).getFile().getContentCache(); + + // Find where the line starts for the three offsets. + unsigned parentLineOffs = Content->SourceLineCache[parentLineNo]; + unsigned startLineOffs = Content->SourceLineCache[startLineNo]; + unsigned endLineOffs = Content->SourceLineCache[endLineNo]; + + if (startLineOffs == endLineOffs || startLineOffs == parentLineOffs) + return true; + + // Find the whitespace at the start of each line. + StringRef parentSpace, startSpace, endSpace; + { + unsigned i = parentLineOffs; + while (isWhitespace(MB[i])) + ++i; + parentSpace = MB.substr(parentLineOffs, i-parentLineOffs); + + i = startLineOffs; + while (isWhitespace(MB[i])) + ++i; + startSpace = MB.substr(startLineOffs, i-startLineOffs); + + i = endLineOffs; + while (isWhitespace(MB[i])) + ++i; + endSpace = MB.substr(endLineOffs, i-endLineOffs); + } + if (parentSpace.size() >= startSpace.size()) + return true; + if (!startSpace.startswith(parentSpace)) + return true; + + llvm::StringRef indent = startSpace.substr(parentSpace.size()); + + // Indent the lines between start/end offsets. + RewriteBuffer &RB = getEditBuffer(FID); + for (unsigned i = startLineOffs; i != endLineOffs; ++i) { + if (MB[i] == '\n') { + unsigned startOfLine = i+1; + if (startOfLine == endLineOffs) + break; + StringRef origIndent; + unsigned ws = startOfLine; + while (isWhitespace(MB[ws])) + ++ws; + origIndent = MB.substr(startOfLine, ws-startOfLine); + if (origIndent.startswith(startSpace)) + RB.InsertText(startOfLine, indent, /*InsertAfter=*/false); + } + } + + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp index 6a422242a9d4..e482172ca3eb 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -24,12 +24,13 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/Analyses/ReachableCode.h" #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" #include "clang/Analysis/CFGStmtMap.h" -#include "clang/Analysis/Analyses/UninitializedValuesV2.h" +#include "clang/Analysis/Analyses/UninitializedValues.h" #include "llvm/ADT/BitVector.h" #include "llvm/Support/Casting.h" @@ -129,12 +130,27 @@ static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { // normal. We need to look pass the destructors for the return // statement (if it exists). CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); + bool hasNoReturnDtor = false; + for ( ; ri != re ; ++ri) { CFGElement CE = *ri; + + // FIXME: The right solution is to just sever the edges in the + // CFG itself. + if (const CFGImplicitDtor *iDtor = ri->getAs()) + if (iDtor->isNoReturn(AC.getASTContext())) { + hasNoReturnDtor = true; + HasFakeEdge = true; + break; + } + if (isa(CE)) break; } + if (hasNoReturnDtor) + continue; + // No more CFGElements in the block? if (ri == re) { if (B.getTerminator() && isa(B.getTerminator())) { @@ -362,18 +378,146 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, // -Wuninitialized //===----------------------------------------------------------------------===// +namespace { +/// ContainsReference - A visitor class to search for references to +/// a particular declaration (the needle) within any evaluated component of an +/// expression (recursively). +class ContainsReference : public EvaluatedExprVisitor { + bool FoundReference; + const DeclRefExpr *Needle; + +public: + ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) + : EvaluatedExprVisitor(Context), + FoundReference(false), Needle(Needle) {} + + void VisitExpr(Expr *E) { + // Stop evaluating if we already have a reference. + if (FoundReference) + return; + + EvaluatedExprVisitor::VisitExpr(E); + } + + void VisitDeclRefExpr(DeclRefExpr *E) { + if (E == Needle) + FoundReference = true; + else + EvaluatedExprVisitor::VisitDeclRefExpr(E); + } + + bool doesContainReference() const { return FoundReference; } +}; +} + +/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an +/// uninitialized variable. This manages the different forms of diagnostic +/// emitted for particular types of uses. Returns true if the use was diagnosed +/// as a warning. If a pariticular use is one we omit warnings for, returns +/// false. +static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, + const Expr *E, bool isAlwaysUninit) { + bool isSelfInit = false; + + if (const DeclRefExpr *DRE = dyn_cast(E)) { + if (isAlwaysUninit) { + // Inspect the initializer of the variable declaration which is + // being referenced prior to its initialization. We emit + // specialized diagnostics for self-initialization, and we + // specifically avoid warning about self references which take the + // form of: + // + // int x = x; + // + // This is used to indicate to GCC that 'x' is intentionally left + // uninitialized. Proven code paths which access 'x' in + // an uninitialized state after this will still warn. + // + // TODO: Should we suppress maybe-uninitialized warnings for + // variables initialized in this way? + if (const Expr *Initializer = VD->getInit()) { + if (DRE == Initializer->IgnoreParenImpCasts()) + return false; + + ContainsReference CR(S.Context, DRE); + CR.Visit(const_cast(Initializer)); + isSelfInit = CR.doesContainReference(); + } + if (isSelfInit) { + S.Diag(DRE->getLocStart(), + diag::warn_uninit_self_reference_in_init) + << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); + } else { + S.Diag(DRE->getLocStart(), diag::warn_uninit_var) + << VD->getDeclName() << DRE->getSourceRange(); + } + } else { + S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var) + << VD->getDeclName() << DRE->getSourceRange(); + } + } else { + const BlockExpr *BE = cast(E); + S.Diag(BE->getLocStart(), + isAlwaysUninit ? diag::warn_uninit_var_captured_by_block + : diag::warn_maybe_uninit_var_captured_by_block) + << VD->getDeclName(); + } + + // Report where the variable was declared when the use wasn't within + // the initializer of that declaration. + if (!isSelfInit) + S.Diag(VD->getLocStart(), diag::note_uninit_var_def) + << VD->getDeclName(); + + return true; +} + +static void SuggestInitializationFixit(Sema &S, const VarDecl *VD) { + // Don't issue a fixit if there is already an initializer. + if (VD->getInit()) + return; + + // Suggest possible initialization (if any). + const char *initialization = 0; + QualType VariableTy = VD->getType().getCanonicalType(); + + if (VariableTy->getAs()) { + // Check if 'nil' is defined. + if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) + initialization = " = nil"; + else + initialization = " = 0"; + } + else if (VariableTy->isRealFloatingType()) + initialization = " = 0.0"; + else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) + initialization = " = false"; + else if (VariableTy->isEnumeralType()) + return; + else if (VariableTy->isScalarType()) + initialization = " = 0"; + + if (initialization) { + SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); + S.Diag(loc, diag::note_var_fixit_add_initialization) + << FixItHint::CreateInsertion(loc, initialization); + } +} + +typedef std::pair UninitUse; + namespace { struct SLocSort { - bool operator()(const Expr *a, const Expr *b) { - SourceLocation aLoc = a->getLocStart(); - SourceLocation bLoc = b->getLocStart(); + bool operator()(const UninitUse &a, const UninitUse &b) { + SourceLocation aLoc = a.first->getLocStart(); + SourceLocation bLoc = b.first->getLocStart(); return aLoc.getRawEncoding() < bLoc.getRawEncoding(); } }; class UninitValsDiagReporter : public UninitVariablesHandler { Sema &S; - typedef llvm::SmallVector UsesVec; + typedef llvm::SmallVector UsesVec; typedef llvm::DenseMap UsesMap; UsesMap *uses; @@ -383,7 +527,8 @@ class UninitValsDiagReporter : public UninitVariablesHandler { flushDiagnostics(); } - void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd) { + void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, + bool isAlwaysUninit) { if (!uses) uses = new UsesMap(); @@ -391,7 +536,7 @@ class UninitValsDiagReporter : public UninitVariablesHandler { if (!vec) vec = new UsesVec(); - vec->push_back(ex); + vec->push_back(std::make_pair(ex, isAlwaysUninit)); } void flushDiagnostics() { @@ -409,54 +554,19 @@ class UninitValsDiagReporter : public UninitVariablesHandler { // a stable ordering. std::sort(vec->begin(), vec->end(), SLocSort()); - for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi) - { - if (const DeclRefExpr *dr = dyn_cast(*vi)) { - S.Diag(dr->getLocStart(), diag::warn_uninit_var) - << vd->getDeclName() << dr->getSourceRange(); - } - else { - const BlockExpr *be = cast(*vi); - S.Diag(be->getLocStart(), diag::warn_uninit_var_captured_by_block) - << vd->getDeclName(); - } - - // Report where the variable was declared. - S.Diag(vd->getLocStart(), diag::note_uninit_var_def) - << vd->getDeclName(); - - // Only report the fixit once. - if (fixitIssued) + for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; + ++vi) { + if (!DiagnoseUninitializedUse(S, vd, vi->first, + /*isAlwaysUninit=*/vi->second)) continue; - - fixitIssued = true; - // Suggest possible initialization (if any). - const char *initialization = 0; - QualType vdTy = vd->getType().getCanonicalType(); - - if (vdTy->getAs()) { - // Check if 'nil' is defined. - if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) - initialization = " = nil"; - else - initialization = " = 0"; - } - else if (vdTy->isRealFloatingType()) - initialization = " = 0.0"; - else if (vdTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) - initialization = " = false"; - else if (vdTy->isEnumeralType()) - continue; - else if (vdTy->isScalarType()) - initialization = " = 0"; - - if (initialization) { - SourceLocation loc = S.PP.getLocForEndOfToken(vd->getLocEnd()); - S.Diag(loc, diag::note_var_fixit_add_initialization) - << FixItHint::CreateInsertion(loc, initialization); + // Suggest a fixit hint the first time we diagnose a use of a variable. + if (!fixitIssued) { + SuggestInitializationFixit(S, vd); + fixitIssued = true; } } + delete vec; } delete uses; @@ -531,25 +641,41 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, // Emit delayed diagnostics. if (!fscope->PossiblyUnreachableDiags.empty()) { bool analyzed = false; - if (CFGReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) - if (CFGStmtMap *csm = AC.getCFGStmtMap()) { - analyzed = true; - for (llvm::SmallVectorImpl::iterator - i = fscope->PossiblyUnreachableDiags.begin(), - e = fscope->PossiblyUnreachableDiags.end(); - i != e; ++i) { - const sema::PossiblyUnreachableDiag &D = *i; - if (const CFGBlock *blk = csm->getBlock(D.stmt)) { + + // Register the expressions with the CFGBuilder. + for (llvm::SmallVectorImpl::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + if (const Stmt *stmt = i->stmt) + AC.registerForcedBlockExpression(stmt); + } + + if (AC.getCFG()) { + analyzed = true; + for (llvm::SmallVectorImpl::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) + { + const sema::PossiblyUnreachableDiag &D = *i; + bool processed = false; + if (const Stmt *stmt = i->stmt) { + const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); + assert(block); + if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) { // Can this block be reached from the entrance? - if (cra->isReachable(&AC.getCFG()->getEntry(), blk)) + if (cra->isReachable(&AC.getCFG()->getEntry(), block)) S.Diag(D.Loc, D.PD); - } - else { - // Emit the warning anyway if we cannot map to a basic block. - S.Diag(D.Loc, D.PD); + processed = true; } } + if (!processed) { + // Emit the warning anyway if we cannot map to a basic block. + S.Diag(D.Loc, D.PD); + } } + } if (!analyzed) flushDiagnostics(S, fscope); @@ -569,25 +695,10 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, CheckUnreachable(S, AC); if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) + != Diagnostic::Ignored || + Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) != Diagnostic::Ignored) { - ASTContext &ctx = D->getASTContext(); - llvm::OwningPtr tmpCFG; - bool useAlternateCFG = false; - if (ctx.getLangOptions().CPlusPlus) { - // Temporary workaround: implicit dtors in the CFG can confuse - // the path-sensitivity in the uninitialized values analysis. - // For now create (if necessary) a separate CFG without implicit dtors. - // FIXME: We should not need to do this, as it results in multiple - // CFGs getting constructed. - CFG::BuildOptions B; - B.AddEHEdges = false; - B.AddImplicitDtors = false; - B.AddInitializers = true; - tmpCFG.reset(CFG::buildCFG(D, AC.getBody(), &ctx, B)); - useAlternateCFG = true; - } - CFG *cfg = useAlternateCFG ? tmpCFG.get() : AC.getCFG(); - if (cfg) { + if (CFG *cfg = AC.getCFG()) { UninitValsDiagReporter reporter(S); runUninitializedVariablesAnalysis(*cast(D), *cfg, AC, reporter); diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp index c0a305365afc..619a5b961bfe 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp @@ -12,28 +12,89 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/AttributeList.h" +#include "clang/AST/Expr.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/StringSwitch.h" using namespace clang; -AttributeList::AttributeList(llvm::BumpPtrAllocator &Alloc, - IdentifierInfo *aName, SourceLocation aLoc, - IdentifierInfo *sName, SourceLocation sLoc, - IdentifierInfo *pName, SourceLocation pLoc, - Expr **ExprList, unsigned numArgs, - bool declspec, bool cxx0x) - : AttrName(aName), AttrLoc(aLoc), ScopeName(sName), - ScopeLoc(sLoc), - ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(0), - DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false) { +size_t AttributeList::allocated_size() const { + if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; + return (sizeof(AttributeList) + NumArgs * sizeof(Expr*)); +} - if (numArgs == 0) - Args = 0; - else { - // Allocate the Args array using the BumpPtrAllocator. - Args = Alloc.Allocate(numArgs); - memcpy(Args, ExprList, numArgs*sizeof(Args[0])); +AttributeFactory::AttributeFactory() { + // Go ahead and configure all the inline capacity. This is just a memset. + FreeLists.resize(InlineFreeListsCapacity); +} +AttributeFactory::~AttributeFactory() {} + +static size_t getFreeListIndexForSize(size_t size) { + assert(size >= sizeof(AttributeList)); + assert((size % sizeof(void*)) == 0); + return ((size - sizeof(AttributeList)) / sizeof(void*)); +} + +void *AttributeFactory::allocate(size_t size) { + // Check for a previously reclaimed attribute. + size_t index = getFreeListIndexForSize(size); + if (index < FreeLists.size()) { + if (AttributeList *attr = FreeLists[index]) { + FreeLists[index] = attr->NextInPool; + return attr; + } } + + // Otherwise, allocate something new. + return Alloc.Allocate(size, llvm::AlignOf::Alignment); +} + +void AttributeFactory::reclaimPool(AttributeList *cur) { + assert(cur && "reclaiming empty pool!"); + do { + // Read this here, because we're going to overwrite NextInPool + // when we toss 'cur' into the appropriate queue. + AttributeList *next = cur->NextInPool; + + size_t size = cur->allocated_size(); + size_t freeListIndex = getFreeListIndexForSize(size); + + // Expand FreeLists to the appropriate size, if required. + if (freeListIndex >= FreeLists.size()) + FreeLists.resize(freeListIndex+1); + + // Add 'cur' to the appropriate free-list. + cur->NextInPool = FreeLists[freeListIndex]; + FreeLists[freeListIndex] = cur; + + cur = next; + } while (cur); +} + +void AttributePool::takePool(AttributeList *pool) { + assert(pool); + + // Fast path: this pool is empty. + if (!Head) { + Head = pool; + return; + } + + // Reverse the pool onto the current head. This optimizes for the + // pattern of pulling a lot of pools into a single pool. + do { + AttributeList *next = pool->NextInPool; + pool->NextInPool = Head; + Head = pool; + pool = next; + } while (pool); +} + +AttributeList * +AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, + SourceLocation TokLoc, int Arg) { + Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg), + C.IntTy, TokLoc); + return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, 0); } AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { @@ -83,6 +144,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("may_alias", AT_may_alias) .Case("base_check", AT_base_check) .Case("deprecated", AT_deprecated) + .Case("availability", AT_availability) .Case("visibility", AT_visibility) .Case("destructor", AT_destructor) .Case("format_arg", AT_format_arg) @@ -94,10 +156,12 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("unavailable", AT_unavailable) .Case("overloadable", AT_overloadable) .Case("address_space", AT_address_space) + .Case("opencl_image_access", AT_opencl_image_access) .Case("always_inline", AT_always_inline) .Case("returns_twice", IgnoredAttribute) .Case("vec_type_hint", IgnoredAttribute) .Case("objc_exception", AT_objc_exception) + .Case("objc_method_family", AT_objc_method_family) .Case("ext_vector_type", AT_ext_vector_type) .Case("neon_vector_type", AT_neon_vector_type) .Case("neon_polyvector_type", AT_neon_polyvector_type) @@ -137,5 +201,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("nocommon", AT_nocommon) .Case("opencl_kernel_function", AT_opencl_kernel_function) .Case("uuid", AT_uuid) + .Case("pcs", AT_pcs) + .Case("ms_struct", AT_MsStruct) .Default(UnknownAttribute); } diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp index b7037ce83e7f..2334ab5128a7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -375,12 +375,21 @@ void CodeCompletionResult::computeCursorKindAndAvailability() { switch (Kind) { case RK_Declaration: // Set the availability based on attributes. - Availability = CXAvailability_Available; - if (Declaration->getAttr()) - Availability = CXAvailability_NotAvailable; - else if (Declaration->getAttr()) - Availability = CXAvailability_Deprecated; + switch (Declaration->getAvailability()) { + case AR_Available: + case AR_NotYetIntroduced: + Availability = CXAvailability_Available; + break; + case AR_Deprecated: + Availability = CXAvailability_Deprecated; + break; + + case AR_Unavailable: + Availability = CXAvailability_NotAvailable; + break; + } + if (FunctionDecl *Function = dyn_cast(Declaration)) if (Function->isDeleted()) Availability = CXAvailability_NotAvailable; diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp index 037594a44a1c..0f20d10b076a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -47,278 +47,130 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { EndLocation = TemplateId->RAngleLoc; } -CXXScopeSpec::CXXScopeSpec(const CXXScopeSpec &Other) - : Range(Other.Range), ScopeRep(Other.ScopeRep), Buffer(0), - BufferSize(Other.BufferSize), BufferCapacity(Other.BufferSize) -{ - if (BufferSize) { - Buffer = static_cast(malloc(BufferSize)); - memcpy(Buffer, Other.Buffer, BufferSize); - } -} - -CXXScopeSpec &CXXScopeSpec::operator=(const CXXScopeSpec &Other) { - Range = Other.Range; - ScopeRep = Other.ScopeRep; - if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { - // Re-use our storage. - BufferSize = Other.BufferSize; - memcpy(Buffer, Other.Buffer, BufferSize); - return *this; - } - - if (BufferCapacity) - free(Buffer); - if (Other.Buffer) { - BufferSize = Other.BufferSize; - BufferCapacity = BufferSize; - Buffer = static_cast(malloc(BufferSize)); - memcpy(Buffer, Other.Buffer, BufferSize); - } else { - Buffer = 0; - BufferSize = 0; - BufferCapacity = 0; - } - return *this; -} - -CXXScopeSpec::~CXXScopeSpec() { - if (BufferCapacity) - free(Buffer); -} - -namespace { - void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, - unsigned &BufferCapacity) { - if (BufferSize + (End - Start) > BufferCapacity) { - // Reallocate the buffer. - unsigned NewCapacity - = std::max((unsigned)(BufferCapacity? BufferCapacity * 2 - : sizeof(void*) * 2), - (unsigned)(BufferSize + (End - Start))); - char *NewBuffer = static_cast(malloc(NewCapacity)); - memcpy(NewBuffer, Buffer, BufferSize); - - if (BufferCapacity) - free(Buffer); - Buffer = NewBuffer; - BufferCapacity = NewCapacity; - } - - memcpy(Buffer + BufferSize, Start, End - Start); - BufferSize += End-Start; - } - - /// \brief Save a source location to the given buffer. - void SaveSourceLocation(SourceLocation Loc, char *&Buffer, - unsigned &BufferSize, unsigned &BufferCapacity) { - unsigned Raw = Loc.getRawEncoding(); - Append(reinterpret_cast(&Raw), - reinterpret_cast(&Raw) + sizeof(unsigned), - Buffer, BufferSize, BufferCapacity); - } - - /// \brief Save a pointer to the given buffer. - void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, - unsigned &BufferCapacity) { - Append(reinterpret_cast(&Ptr), - reinterpret_cast(&Ptr) + sizeof(void *), - Buffer, BufferSize, BufferCapacity); - } -} void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, SourceLocation ColonColonLoc) { - ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, - TemplateKWLoc.isValid(), - TL.getTypePtr()); + Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc); if (Range.getBegin().isInvalid()) Range.setBegin(TL.getBeginLoc()); Range.setEnd(ColonColonLoc); - // Push source-location info into the buffer. - SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); - - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, SourceLocation IdentifierLoc, SourceLocation ColonColonLoc) { - ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier); + Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc); + if (Range.getBegin().isInvalid()) Range.setBegin(IdentifierLoc); Range.setEnd(ColonColonLoc); - // Push source-location info into the buffer. - SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); - - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc) { - ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace); + Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc); + if (Range.getBegin().isInvalid()) Range.setBegin(NamespaceLoc); Range.setEnd(ColonColonLoc); - // Push source-location info into the buffer. - SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); - - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, SourceLocation AliasLoc, SourceLocation ColonColonLoc) { - ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias); + Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc); + if (Range.getBegin().isInvalid()) Range.setBegin(AliasLoc); Range.setEnd(ColonColonLoc); - // Push source-location info into the buffer. - SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); - - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc) { - assert(!ScopeRep && "Already have a nested-name-specifier!?"); - ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context); + Builder.MakeGlobal(Context, ColonColonLoc); + Range = SourceRange(ColonColonLoc); - // Push source-location info into the buffer. - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); - - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R) { - ScopeRep = Qualifier; + Builder.MakeTrivial(Context, Qualifier, R); Range = R; - - // Construct bogus (but well-formed) source information for the - // nested-name-specifier. - BufferSize = 0; - llvm::SmallVector Stack; - for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) - Stack.push_back(NNS); - while (!Stack.empty()) { - NestedNameSpecifier *NNS = Stack.back(); - Stack.pop_back(); - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); - break; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - TypeSourceInfo *TSInfo - = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), - R.getBegin()); - SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, - BufferCapacity); - break; - } - - case NestedNameSpecifier::Global: - break; - } - - // Save the location of the '::'. - SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), - Buffer, BufferSize, BufferCapacity); - } } void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) { if (!Other) { Range = SourceRange(); - ScopeRep = 0; + Builder.Clear(); return; } - - if (BufferCapacity) - free(Buffer); - - // Rather than copying the data (which is wasteful), "adopt" the - // pointer (which points into the ASTContext) but set the capacity to zero to - // indicate that we don't own it. + Range = Other.getSourceRange(); - ScopeRep = Other.getNestedNameSpecifier(); - Buffer = static_cast(Other.getOpaqueData()); - BufferSize = Other.getDataLength(); - BufferCapacity = 0; + Builder.Adopt(Other); } NestedNameSpecifierLoc CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { - if (isEmpty() || isInvalid()) + if (!Builder.getRepresentation()) return NestedNameSpecifierLoc(); - // If we adopted our data pointer from elsewhere in the AST context, there's - // no need to copy the memory. - if (BufferCapacity == 0) - return NestedNameSpecifierLoc(ScopeRep, Buffer); - - void *Mem = Context.Allocate(BufferSize, llvm::alignOf()); - memcpy(Mem, Buffer, BufferSize); - return NestedNameSpecifierLoc(ScopeRep, Mem); + return Builder.getWithLocInContext(Context); } /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. -DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs, - bool hasProto, bool isVariadic, +DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, SourceLocation EllipsisLoc, ParamInfo *ArgInfo, unsigned NumArgs, unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, - bool hasExceptionSpec, - SourceLocation ThrowLoc, - bool hasAnyExceptionSpec, + ExceptionSpecificationType + ESpecType, + SourceLocation ESpecLoc, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, - SourceLocation LPLoc, - SourceLocation RPLoc, + Expr *NoexceptExpr, + SourceLocation LocalRangeBegin, + SourceLocation LocalRangeEnd, Declarator &TheDeclarator, ParsedType TrailingReturnType) { DeclaratorChunk I; - I.Kind = Function; - I.Loc = LPLoc; - I.EndLoc = RPLoc; - I.Fun.AttrList = attrs.getList(); - I.Fun.hasPrototype = hasProto; - I.Fun.isVariadic = isVariadic; - I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); - I.Fun.DeleteArgInfo = false; - I.Fun.TypeQuals = TypeQuals; - I.Fun.NumArgs = NumArgs; - I.Fun.ArgInfo = 0; + I.Kind = Function; + I.Loc = LocalRangeBegin; + I.EndLoc = LocalRangeEnd; + I.Fun.AttrList = 0; + I.Fun.hasPrototype = hasProto; + I.Fun.isVariadic = isVariadic; + I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); + I.Fun.DeleteArgInfo = false; + I.Fun.TypeQuals = TypeQuals; + I.Fun.NumArgs = NumArgs; + I.Fun.ArgInfo = 0; I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; - I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); - I.Fun.hasExceptionSpec = hasExceptionSpec; - I.Fun.ThrowLoc = ThrowLoc.getRawEncoding(); - I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec; - I.Fun.NumExceptions = NumExceptions; - I.Fun.Exceptions = 0; + I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); + I.Fun.ExceptionSpecType = ESpecType; + I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding(); + I.Fun.NumExceptions = 0; + I.Fun.Exceptions = 0; + I.Fun.NoexceptExpr = 0; I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr(); // new[] an argument array if needed. @@ -338,13 +190,25 @@ DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs, } memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs); } - // new[] an exception array if needed - if (NumExceptions) { - I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; - for (unsigned i = 0; i != NumExceptions; ++i) { - I.Fun.Exceptions[i].Ty = Exceptions[i]; - I.Fun.Exceptions[i].Range = ExceptionRanges[i]; + + // Check what exception specification information we should actually store. + switch (ESpecType) { + default: break; // By default, save nothing. + case EST_Dynamic: + // new[] an exception array if needed + if (NumExceptions) { + I.Fun.NumExceptions = NumExceptions; + I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; + for (unsigned i = 0; i != NumExceptions; ++i) { + I.Fun.Exceptions[i].Ty = Exceptions[i]; + I.Fun.Exceptions[i].Range = ExceptionRanges[i]; + } } + break; + + case EST_ComputedNoexcept: + I.Fun.NoexceptExpr = NoexceptExpr; + break; } return I; } @@ -445,6 +309,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_typeofExpr: return "typeof"; case DeclSpec::TST_auto: return "auto"; case DeclSpec::TST_decltype: return "(decltype)"; + case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; case DeclSpec::TST_error: return "(error)"; } llvm_unreachable("Unknown typespec!"); @@ -515,12 +380,14 @@ bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc, bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { - if (TypeSpecWidth != TSW_unspecified && - // Allow turning long -> long long. - (W != TSW_longlong || TypeSpecWidth != TSW_long)) + // Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that + // for 'long long' we will keep the source location of the first 'long'. + if (TypeSpecWidth == TSW_unspecified) + TSWLoc = Loc; + // Allow turning long -> long long. + else if (W != TSW_longlong || TypeSpecWidth != TSW_long) return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); TypeSpecWidth = W; - TSWLoc = Loc; if (TypeAltiVecVector && !TypeAltiVecBool && ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); @@ -554,6 +421,14 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, ParsedType Rep) { + return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep); +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, + const char *&PrevSpec, + unsigned &DiagID, + ParsedType Rep) { assert(isTypeRep(T) && "T does not store a type"); assert(Rep && "no type provided!"); if (TypeSpecType != TST_unspecified) { @@ -563,7 +438,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, } TypeSpecType = T; TypeRep = Rep; - TSTLoc = Loc; + TSTLoc = TagKwLoc; + TSTNameLoc = TagNameLoc; TypeSpecOwned = false; return false; } @@ -582,6 +458,7 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, TypeSpecType = T; ExprRep = Rep; TSTLoc = Loc; + TSTNameLoc = Loc; TypeSpecOwned = false; return false; } @@ -590,6 +467,14 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, Decl *Rep, bool Owned) { + return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned); +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, + const char *&PrevSpec, + unsigned &DiagID, + Decl *Rep, bool Owned) { assert(isDeclRep(T) && "T does not store a decl"); // Unlike the other cases, we don't assert that we actually get a decl. @@ -600,7 +485,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, } TypeSpecType = T; DeclRep = Rep; - TSTLoc = Loc; + TSTLoc = TagKwLoc; + TSTNameLoc = TagNameLoc; TypeSpecOwned = Owned; return false; } @@ -615,13 +501,13 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, DiagID = diag::err_invalid_decl_spec_combination; return true; } + TSTLoc = Loc; + TSTNameLoc = Loc; if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) { TypeAltiVecBool = true; - TSTLoc = Loc; return false; } TypeSpecType = T; - TSTLoc = Loc; TypeSpecOwned = false; if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); @@ -653,6 +539,7 @@ bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, } TypeAltiVecPixel = isAltiVecPixel; TSTLoc = Loc; + TSTNameLoc = Loc; return false; } @@ -660,6 +547,7 @@ bool DeclSpec::SetTypeSpecError() { TypeSpecType = TST_error; TypeSpecOwned = false; TSTLoc = SourceLocation(); + TSTNameLoc = SourceLocation(); return false; } @@ -929,6 +817,8 @@ void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, const char *&PrevSpec) { + LastLocation = Loc; + if (Specifiers & VS) { PrevSpec = getSpecifierName(VS); return true; @@ -940,7 +830,6 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, default: assert(0 && "Unknown specifier!"); case VS_Override: VS_overrideLoc = Loc; break; case VS_Final: VS_finalLoc = Loc; break; - case VS_New: VS_newLoc = Loc; break; } return false; @@ -951,33 +840,5 @@ const char *VirtSpecifiers::getSpecifierName(Specifier VS) { default: assert(0 && "Unknown specifier"); case VS_Override: return "override"; case VS_Final: return "final"; - case VS_New: return "new"; } } - -bool ClassVirtSpecifiers::SetSpecifier(Specifier CVS, SourceLocation Loc, - const char *&PrevSpec) { - if (Specifiers & CVS) { - PrevSpec = getSpecifierName(CVS); - return true; - } - - Specifiers |= CVS; - - switch (CVS) { - default: assert(0 && "Unknown specifier!"); - case CVS_Final: CVS_finalLoc = Loc; break; - case CVS_Explicit: CVS_explicitLoc = Loc; break; - } - - return false; -} - -const char *ClassVirtSpecifiers::getSpecifierName(Specifier CVS) { - switch (CVS) { - default: assert(0 && "Unknown specifier"); - case CVS_Final: return "final"; - case CVS_Explicit: return "explicit"; - } -} - diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp new file mode 100644 index 000000000000..af548fe13460 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp @@ -0,0 +1,51 @@ +//===--- DelayedDiagnostic.cpp - Delayed declarator diagnostics -*- 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 DelayedDiagnostic class implementation, which +// is used to record diagnostics that are being conditionally produced +// during declarator parsing. +// +// This file also defines AccessedEntity. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/DelayedDiagnostic.h" +#include +using namespace clang; +using namespace sema; + +DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, + const NamedDecl *D, + llvm::StringRef Msg) { + DelayedDiagnostic DD; + DD.Kind = Deprecation; + DD.Triggered = false; + DD.Loc = Loc; + DD.DeprecationData.Decl = D; + char *MessageData = 0; + if (Msg.size()) { + MessageData = new char [Msg.size()]; + memcpy(MessageData, Msg.data(), Msg.size()); + } + + DD.DeprecationData.Message = MessageData; + DD.DeprecationData.MessageLen = Msg.size(); + return DD; +} + +void DelayedDiagnostic::Destroy() { + switch (Kind) { + case Access: + getAccessData().~AccessedEntity(); + break; + + case Deprecation: + delete [] DeprecationData.Message; + break; + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp index 3f16ed772352..95420a316ad0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp @@ -104,7 +104,8 @@ IdentifierResolver::~IdentifierResolver() { /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns /// true if 'D' belongs to the given declaration context. bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, - ASTContext &Context, Scope *S) const { + ASTContext &Context, Scope *S, + bool ExplicitInstantiationOrSpecialization) const { Ctx = Ctx->getRedeclContext(); if (Ctx->isFunctionOrMethod()) { @@ -135,7 +136,10 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, return false; } - return D->getDeclContext()->getRedeclContext()->Equals(Ctx); + DeclContext *DCtx = D->getDeclContext()->getRedeclContext(); + return ExplicitInstantiationOrSpecialization + ? Ctx->InEnclosingNamespaceSetOf(DCtx) + : Ctx->Equals(DCtx); } /// AddDecl - Link the decl to its shadowed decl chain. @@ -164,6 +168,44 @@ void IdentifierResolver::AddDecl(NamedDecl *D) { IDI->AddDecl(D); } +void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { + DeclarationName Name = D->getDeclName(); + void *Ptr = Name.getFETokenInfo(); + + if (!Ptr) { + AddDecl(D); + return; + } + + if (isDeclPtr(Ptr)) { + // We only have a single declaration: insert before or after it, + // as appropriate. + if (Pos == iterator()) { + // Add the new declaration before the existing declaration. + NamedDecl *PrevD = static_cast(Ptr); + RemoveDecl(PrevD); + AddDecl(D); + AddDecl(PrevD); + } else { + // Add new declaration after the existing declaration. + AddDecl(D); + } + + return; + } + + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + II->setIsFromAST(false); + + // General case: insert the declaration at the appropriate point in the + // list, which already has at least two elements. + IdDeclInfo *IDI = toIdDeclInfo(Ptr); + if (Pos.isIterator()) { + IDI->InsertDecl(Pos.getIterator() + 1, D); + } else + IDI->InsertDecl(IDI->decls_begin(), D); +} + /// RemoveDecl - Unlink the decl from its shadowed decl chain. /// The decl must already be part of the decl chain. void IdentifierResolver::RemoveDecl(NamedDecl *D) { diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index b73f0e9f1452..867d78fef6a7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -149,6 +149,11 @@ static std::pair return std::make_pair((unsigned) diag::note_protected_by_vla_typedef, 0); } + if (const TypeAliasDecl *TD = dyn_cast(D)) { + if (TD->getUnderlyingType()->isVariablyModifiedType()) + return std::make_pair((unsigned) diag::note_protected_by_vla_type_alias, 0); + } + return std::make_pair(0U, 0U); } diff --git a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp new file mode 100644 index 000000000000..833a59fdceea --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp @@ -0,0 +1,57 @@ +//===- Scope.cpp - Lexical scope information --------------------*- 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 the Scope class, which is used for recording +// information about a lexical scope. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/Scope.h" + +using namespace clang; + +void Scope::Init(Scope *parent, unsigned flags) { + AnyParent = parent; + Flags = flags; + + if (parent) { + Depth = parent->Depth + 1; + PrototypeDepth = parent->PrototypeDepth; + PrototypeIndex = 0; + FnParent = parent->FnParent; + BreakParent = parent->BreakParent; + ContinueParent = parent->ContinueParent; + ControlParent = parent->ControlParent; + BlockParent = parent->BlockParent; + TemplateParamParent = parent->TemplateParamParent; + } else { + Depth = 0; + PrototypeDepth = 0; + PrototypeIndex = 0; + FnParent = BreakParent = ContinueParent = BlockParent = 0; + ControlParent = 0; + TemplateParamParent = 0; + } + + // If this scope is a function or contains breaks/continues, remember it. + if (flags & FnScope) FnParent = this; + if (flags & BreakScope) BreakParent = this; + if (flags & ContinueScope) ContinueParent = this; + if (flags & ControlScope) ControlParent = this; + if (flags & BlockScope) BlockParent = this; + if (flags & TemplateParamScope) TemplateParamParent = this; + + // If this is a prototype scope, record that. + if (flags & FunctionPrototypeScope) PrototypeDepth++; + + DeclsInScope.clear(); + UsingDirectives.clear(); + Entity = 0; + ErrorTrap.reset(); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index 0c39e1325393..7707fb1104be 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -66,12 +66,14 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { // Install [u]int128_t for 64-bit targets. TInfo = Context.getTrivialTypeSourceInfo(Context.Int128Ty); PushOnScopeChains(TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), &Context.Idents.get("__int128_t"), TInfo), TUScope); TInfo = Context.getTrivialTypeSourceInfo(Context.UnsignedInt128Ty); PushOnScopeChains(TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), &Context.Idents.get("__uint128_t"), TInfo), TUScope); @@ -87,7 +89,8 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy); TypeSourceInfo *SelInfo = Context.getTrivialTypeSourceInfo(SelT); TypedefDecl *SelTypedef - = TypedefDecl::Create(Context, CurContext, SourceLocation(), + = TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), &Context.Idents.get("SEL"), SelInfo); PushOnScopeChains(SelTypedef, TUScope); Context.setObjCSelType(Context.getTypeDeclType(SelTypedef)); @@ -109,7 +112,8 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { T = Context.getObjCObjectPointerType(T); TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(T); TypedefDecl *IdTypedef - = TypedefDecl::Create(Context, CurContext, SourceLocation(), + = TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), &Context.Idents.get("id"), IdInfo); PushOnScopeChains(IdTypedef, TUScope); Context.setObjCIdType(Context.getTypeDeclType(IdTypedef)); @@ -121,7 +125,8 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { T = Context.getObjCObjectPointerType(T); TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(T); TypedefDecl *ClassTypedef - = TypedefDecl::Create(Context, CurContext, SourceLocation(), + = TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), &Context.Idents.get("Class"), ClassInfo); PushOnScopeChains(ClassTypedef, TUScope); Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef)); @@ -136,7 +141,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), - PackContext(0), VisContext(0), + PackContext(0), MSStructPragmaOn(false), VisContext(0), + LateTemplateParser(0), OpaqueParser(0), IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0), GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), @@ -178,7 +184,7 @@ Sema::~Sema() { if (PackContext) FreePackedContext(); if (VisContext) FreeVisContext(); delete TheTargetAttributesSema; - + MSStructPragmaOn = false; // Kill all the active scopes. for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I) delete FunctionScopes[I]; @@ -195,39 +201,58 @@ Sema::~Sema() { ExternalSema->ForgetSema(); } +ASTMutationListener *Sema::getASTMutationListener() const { + return getASTConsumer().GetASTMutationListener(); +} + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. /// If there is already an implicit cast, merge into the existing one. /// The result is of the given category. -void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, - CastKind Kind, ExprValueKind VK, - const CXXCastPath *BasePath) { - QualType ExprTy = Context.getCanonicalType(Expr->getType()); +ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, + CastKind Kind, ExprValueKind VK, + const CXXCastPath *BasePath) { + QualType ExprTy = Context.getCanonicalType(E->getType()); QualType TypeTy = Context.getCanonicalType(Ty); if (ExprTy == TypeTy) - return; + return Owned(E); // If this is a derived-to-base cast to a through a virtual base, we // need a vtable. if (Kind == CK_DerivedToBase && BasePathInvolvesVirtualBase(*BasePath)) { - QualType T = Expr->getType(); + QualType T = E->getType(); if (const PointerType *Pointer = T->getAs()) T = Pointer->getPointeeType(); if (const RecordType *RecordTy = T->getAs()) - MarkVTableUsed(Expr->getLocStart(), + MarkVTableUsed(E->getLocStart(), cast(RecordTy->getDecl())); } - if (ImplicitCastExpr *ImpCast = dyn_cast(Expr)) { + if (ImplicitCastExpr *ImpCast = dyn_cast(E)) { if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { ImpCast->setType(Ty); ImpCast->setValueKind(VK); - return; + return Owned(E); } } - Expr = ImplicitCastExpr::Create(Context, Ty, Kind, Expr, BasePath, VK); + return Owned(ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK)); +} + +/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding +/// to the conversion from scalar type ScalarTy to the Boolean type. +CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) { + switch (ScalarTy->getScalarTypeKind()) { + case Type::STK_Bool: return CK_NoOp; + case Type::STK_Pointer: return CK_PointerToBoolean; + case Type::STK_MemberPointer: return CK_MemberPointerToBoolean; + case Type::STK_Integral: return CK_IntegralToBoolean; + case Type::STK_Floating: return CK_FloatingToBoolean; + case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean; + case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean; + } + return CK_Invalid; } ExprValueKind Sema::CastCategory(Expr *E) { @@ -352,22 +377,30 @@ void Sema::ActOnEndOfTranslationUnit() { } } - // If DefinedUsedVTables ends up marking any virtual member functions it - // might lead to more pending template instantiations, which we then need - // to instantiate. - DefineUsedVTables(); + bool SomethingChanged; + do { + SomethingChanged = false; + + // If DefinedUsedVTables ends up marking any virtual member functions it + // might lead to more pending template instantiations, which we then need + // to instantiate. + if (DefineUsedVTables()) + SomethingChanged = true; - // C++: Perform implicit template instantiations. - // - // FIXME: When we perform these implicit instantiations, we do not - // carefully keep track of the point of instantiation (C++ [temp.point]). - // This means that name lookup that occurs within the template - // instantiation will always happen at the end of the translation unit, - // so it will find some names that should not be found. Although this is - // common behavior for C++ compilers, it is technically wrong. In the - // future, we either need to be able to filter the results of name lookup - // or we need to perform template instantiations earlier. - PerformPendingInstantiations(); + // C++: Perform implicit template instantiations. + // + // FIXME: When we perform these implicit instantiations, we do not + // carefully keep track of the point of instantiation (C++ [temp.point]). + // This means that name lookup that occurs within the template + // instantiation will always happen at the end of the translation unit, + // so it will find some names that should not be found. Although this is + // common behavior for C++ compilers, it is technically wrong. In the + // future, we either need to be able to filter the results of name lookup + // or we need to perform template instantiations earlier. + if (PerformPendingInstantiations()) + SomethingChanged = true; + + } while (SomethingChanged); } // Remove file scoped decls that turned out to be used. @@ -451,16 +484,32 @@ void Sema::ActOnEndOfTranslationUnit() { const FunctionDecl *DiagD; if (!FD->hasBody(DiagD)) DiagD = FD; - Diag(DiagD->getLocation(), - isa(DiagD) ? diag::warn_unused_member_function - : diag::warn_unused_function) - << DiagD->getDeclName(); + if (DiagD->isDeleted()) + continue; // Deleted functions are supposed to be unused. + if (DiagD->isReferenced()) { + if (isa(DiagD)) + Diag(DiagD->getLocation(), diag::warn_unneeded_member_function) + << DiagD->getDeclName(); + else + Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) + << /*function*/0 << DiagD->getDeclName(); + } else { + Diag(DiagD->getLocation(), + isa(DiagD) ? diag::warn_unused_member_function + : diag::warn_unused_function) + << DiagD->getDeclName(); + } } else { const VarDecl *DiagD = cast(*I)->getDefinition(); if (!DiagD) DiagD = cast(*I); - Diag(DiagD->getLocation(), diag::warn_unused_variable) - << DiagD->getDeclName(); + if (DiagD->isReferenced()) { + Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) + << /*variable*/1 << DiagD->getDeclName(); + } else { + Diag(DiagD->getLocation(), diag::warn_unused_variable) + << DiagD->getDeclName(); + } } } @@ -585,6 +634,27 @@ Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { return Builder; } +/// \brief Looks through the macro-instantiation chain for the given +/// location, looking for a macro instantiation with the given name. +/// If one is found, returns true and sets the location to that +/// instantiation loc. +bool Sema::findMacroSpelling(SourceLocation &locref, llvm::StringRef name) { + SourceLocation loc = locref; + if (!loc.isMacroID()) return false; + + // There's no good way right now to look at the intermediate + // instantiations, so just jump to the instantiation location. + loc = getSourceManager().getInstantiationLoc(loc); + + // If that's written with the name, stop here. + llvm::SmallVector buffer; + if (getPreprocessor().getSpelling(loc, buffer) == name) { + locref = loc; + return true; + } + return false; +} + /// \brief Determines the active Scope associated with the given declaration /// context. /// diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp index 4f9bf1c5edd7..411d424dd8df 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp @@ -1011,16 +1011,16 @@ static void DiagnoseAccessPath(Sema &S, // Find an original declaration. while (D->isOutOfLine()) { NamedDecl *PrevDecl = 0; - if (isa(D)) - PrevDecl = cast(D)->getPreviousDeclaration(); - else if (isa(D)) - PrevDecl = cast(D)->getPreviousDeclaration(); - else if (isa(D)) - PrevDecl = cast(D)->getPreviousDeclaration(); - else if (isa(D)) { + if (VarDecl *VD = dyn_cast(D)) + PrevDecl = VD->getPreviousDeclaration(); + else if (FunctionDecl *FD = dyn_cast(D)) + PrevDecl = FD->getPreviousDeclaration(); + else if (TypedefNameDecl *TND = dyn_cast(D)) + PrevDecl = TND->getPreviousDeclaration(); + else if (TagDecl *TD = dyn_cast(D)) { if (isa(D) && cast(D)->isInjectedClassName()) break; - PrevDecl = cast(D)->getPreviousDeclaration(); + PrevDecl = TD->getPreviousDeclaration(); } if (!PrevDecl) break; D = PrevDecl; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp index 794b0b1f1cfa..53dd297aebb3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp @@ -129,6 +129,12 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { } } +void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { + if (!MSStructPragmaOn) + return; + RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context)); +} + void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc, SourceLocation KindLoc) { @@ -263,6 +269,10 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, } } +void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { + MSStructPragmaOn = (Kind == PMSST_ON); +} + void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, SourceLocation PragmaLoc) { @@ -297,7 +307,7 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) { if (!VisContext) return; - if (D->hasAttr()) + if (isa(D) && cast(D)->getExplicitVisibility()) return; VisStack *Stack = static_cast(VisContext); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp index 506d2612ffbc..ed54f0f54425 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp @@ -42,21 +42,21 @@ enum CastType { -static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +static void CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange); -static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +static void CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange, CastKind &Kind); -static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +static void CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, CastKind &Kind, CXXCastPath &BasePath); -static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +static void CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange, @@ -100,7 +100,7 @@ static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, QualType OrigDestType, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath); -static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestType,bool CStyle, const SourceRange &OpRange, @@ -108,12 +108,12 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, CastKind &Kind, CXXCastPath &BasePath); -static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind); -static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, @@ -121,24 +121,13 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, CXXCastPath &BasePath); static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, unsigned &msg); -static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind); -static ExprResult -ResolveAndFixSingleFunctionTemplateSpecialization( - Sema &Self, Expr *SrcExpr, - bool DoFunctionPointerConverion = false, - bool Complain = false, - const SourceRange& OpRangeForComplaining = SourceRange(), - QualType DestTypeForComplaining = QualType(), - unsigned DiagIDForComplaining = 0); - - - /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. ExprResult Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, @@ -159,8 +148,9 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, ExprResult Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, - TypeSourceInfo *DestTInfo, Expr *Ex, + TypeSourceInfo *DestTInfo, Expr *E, SourceRange AngleBrackets, SourceRange Parens) { + ExprResult Ex = Owned(E); QualType DestType = DestTInfo->getType(); SourceRange OpRange(OpLoc, Parens.getEnd()); @@ -168,11 +158,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, // If the type is dependent, we won't do the semantic analysis now. // FIXME: should we check this in a more fine-grained manner? - bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent(); - - if (Ex->isBoundMemberFunction(Context)) - Diag(Ex->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << Ex->getSourceRange(); + bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent(); ExprValueKind VK = VK_RValue; if (TypeDependent) @@ -182,42 +168,54 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, default: llvm_unreachable("Unknown C++ cast!"); case tok::kw_const_cast: - if (!TypeDependent) + if (!TypeDependent) { CheckConstCast(*this, Ex, DestType, VK, OpRange, DestRange); + if (Ex.isInvalid()) + return ExprError(); + } return Owned(CXXConstCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - VK, Ex, DestTInfo, OpLoc, + VK, Ex.take(), DestTInfo, OpLoc, Parens.getEnd())); case tok::kw_dynamic_cast: { CastKind Kind = CK_Dependent; CXXCastPath BasePath; - if (!TypeDependent) + if (!TypeDependent) { CheckDynamicCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind, BasePath); + if (Ex.isInvalid()) + return ExprError(); + } return Owned(CXXDynamicCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - VK, Kind, Ex, &BasePath, DestTInfo, + VK, Kind, Ex.take(), &BasePath, DestTInfo, OpLoc, Parens.getEnd())); } case tok::kw_reinterpret_cast: { CastKind Kind = CK_Dependent; - if (!TypeDependent) + if (!TypeDependent) { CheckReinterpretCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind); + if (Ex.isInvalid()) + return ExprError(); + } return Owned(CXXReinterpretCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - VK, Kind, Ex, 0, + VK, Kind, Ex.take(), 0, DestTInfo, OpLoc, Parens.getEnd())); } case tok::kw_static_cast: { CastKind Kind = CK_Dependent; CXXCastPath BasePath; - if (!TypeDependent) + if (!TypeDependent) { CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath); + if (Ex.isInvalid()) + return ExprError(); + } return Owned(CXXStaticCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - VK, Kind, Ex, &BasePath, + VK, Kind, Ex.take(), &BasePath, DestTInfo, OpLoc, Parens.getEnd())); } } @@ -303,6 +301,11 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, /// Diagnose a failed cast. static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, SourceRange opRange, Expr *src, QualType destType) { + if (src->getType() == S.Context.BoundMemberTy) { + (void) S.CheckPlaceholderExpr(src); // will always fail + return; + } + if (msg == diag::err_bad_cxx_cast_generic && tryDiagnoseOverloadedCast(S, castType, opRange, src, destType)) return; @@ -388,15 +391,17 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { UnwrappedDestType = Self.Context.getCanonicalType(DestType); llvm::SmallVector cv1, cv2; - // Find the qualifications. + // Find the qualifiers. We only care about cvr-qualifiers for the + // purpose of this check, because other qualifiers (address spaces, + // Objective-C GC, etc.) are part of the type's identity. while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { Qualifiers SrcQuals; Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals); - cv1.push_back(SrcQuals); + cv1.push_back(Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers())); Qualifiers DestQuals; Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals); - cv2.push_back(DestQuals); + cv2.push_back(Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers())); } if (cv1.empty()) return false; @@ -424,11 +429,11 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { /// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime- /// checked downcasts in class hierarchies. static void -CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange, CastKind &Kind, CXXCastPath &BasePath) { - QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType(); + QualType OrigDestType = DestType, OrigSrcType = SrcExpr.get()->getType(); DestType = Self.Context.getCanonicalType(DestType); // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type, @@ -475,11 +480,11 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, SrcPointee = SrcPointer->getPointeeType(); } else { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr) - << OrigSrcType << SrcExpr->getSourceRange(); + << OrigSrcType << SrcExpr.get()->getSourceRange(); return; } } else if (DestReference->isLValueReferenceType()) { - if (!SrcExpr->isLValue()) { + if (!SrcExpr.get()->isLValue()) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) << CT_Dynamic << OrigSrcType << OrigDestType << OpRange; } @@ -492,11 +497,11 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, if (SrcRecord) { if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee, Self.PDiag(diag::err_bad_dynamic_cast_incomplete) - << SrcExpr->getSourceRange())) + << SrcExpr.get()->getSourceRange())) return; } else { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) - << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange(); + << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); return; } @@ -508,7 +513,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness. if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) + Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away) << CT_Dynamic << OrigSrcType << OrigDestType << OpRange; return; } @@ -543,7 +548,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, assert(SrcDecl && "Definition missing"); if (!cast(SrcDecl)->isPolymorphic()) { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) - << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange(); + << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); } Self.MarkVTableUsed(OpRange.getBegin(), cast(SrcRecord->getDecl())); @@ -558,17 +563,20 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, /// const char *str = "literal"; /// legacy_function(const_cast\(str)); void -CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, ExprValueKind &VK, +CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange) { VK = Expr::getValueKindForType(DestType); - if (VK == VK_RValue) - Self.DefaultFunctionArrayLvalueConversion(SrcExpr); + if (VK == VK_RValue) { + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + } unsigned msg = diag::err_bad_cxx_cast_generic; - if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success + if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success && msg != 0) Self.Diag(OpRange.getBegin(), msg) << CT_Const - << SrcExpr->getType() << DestType << OpRange; + << SrcExpr.get()->getType() << DestType << OpRange; } /// CheckReinterpretCast - Check that a reinterpret_cast\(SrcExpr) is @@ -577,27 +585,32 @@ CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, ExprValueKind &VK, /// like this: /// char *bytes = reinterpret_cast\(int_ptr); void -CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange, CastKind &Kind) { VK = Expr::getValueKindForType(DestType); - if (VK == VK_RValue) - Self.DefaultFunctionArrayLvalueConversion(SrcExpr); + if (VK == VK_RValue) { + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + } unsigned msg = diag::err_bad_cxx_cast_generic; if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg, Kind) != TC_Success && msg != 0) { - if (SrcExpr->getType() == Self.Context.OverloadTy) { + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { //FIXME: &f; is overloaded and resolvable Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload) - << OverloadExpr::find(SrcExpr).Expression->getName() + << OverloadExpr::find(SrcExpr.get()).Expression->getName() << DestType << OpRange; - Self.NoteAllOverloadCandidates(SrcExpr); + Self.NoteAllOverloadCandidates(SrcExpr.get()); } else { - diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr, DestType); + diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType); } } } @@ -607,23 +620,25 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, /// Refer to C++ 5.2.9 for details. Static casts are mostly used for making /// implicit conversions explicit and getting rid of data loss warnings. void -CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, CastKind &Kind, CXXCastPath &BasePath) { // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (DestType->isVoidType()) { - Self.IgnoredValueConversions(SrcExpr); - if (SrcExpr->getType() == Self.Context.OverloadTy) { + SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { ExprResult SingleFunctionExpression = - ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr, + Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), false, // Decay Function to ptr true, // Complain OpRange, DestType, diag::err_bad_static_cast_overload); if (SingleFunctionExpression.isUsable()) { - SrcExpr = SingleFunctionExpression.release(); + SrcExpr = SingleFunctionExpression; Kind = CK_ToVoid; } } @@ -633,29 +648,35 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, } VK = Expr::getValueKindForType(DestType); - if (VK == VK_RValue && !DestType->isRecordType()) - Self.DefaultFunctionArrayLvalueConversion(SrcExpr); + if (VK == VK_RValue && !DestType->isRecordType()) { + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + } unsigned msg = diag::err_bad_cxx_cast_generic; if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg, Kind, BasePath) != TC_Success && msg != 0) { - if (SrcExpr->getType() == Self.Context.OverloadTy) { - OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression; + if (SrcExpr.isInvalid()) + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + OverloadExpr* oe = OverloadExpr::find(SrcExpr.get()).Expression; Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload) - << oe->getName() << DestType << OpRange << oe->getQualifierRange(); - Self.NoteAllOverloadCandidates(SrcExpr); + << oe->getName() << DestType << OpRange + << oe->getQualifierLoc().getSourceRange(); + Self.NoteAllOverloadCandidates(SrcExpr.get()); } else { - diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr, DestType); + diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType); } } else if (Kind == CK_BitCast) - Self.CheckCastAlign(SrcExpr, DestType, OpRange); + Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange); } /// TryStaticCast - Check if a static cast can be performed, and do so if /// possible. If @p CStyle, ignore access restrictions on hierarchy casting /// and casting away constness. -static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind, @@ -680,7 +701,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // C++ 5.2.9p5, reference downcast. // See the function for details. // DR 427 specifies that this is to be applied before paragraph 2. - tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle, OpRange, + tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, OpRange, msg, Kind, BasePath); if (tcr != TC_NotApplicable) return tcr; @@ -688,7 +709,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // C++0x [expr.static.cast]p3: // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2 // T2" if "cv2 T2" is reference-compatible with "cv1 T1". - tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, CStyle, Kind, BasePath, + tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, BasePath, msg); if (tcr != TC_NotApplicable) return tcr; @@ -697,6 +718,8 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // [...] if the declaration "T t(e);" is well-formed, [...]. tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg, Kind); + if (SrcExpr.isInvalid()) + return TC_Failed; if (tcr != TC_NotApplicable) return tcr; @@ -708,7 +731,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // In the CStyle case, the earlier attempt to const_cast should have taken // care of reverse qualification conversions. - QualType SrcType = Self.Context.getCanonicalType(SrcExpr->getType()); + QualType SrcType = Self.Context.getCanonicalType(SrcExpr.get()->getType()); // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly // converted to an integral type. [...] A value of a scoped enumeration type @@ -772,7 +795,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // This is definitely the intended conversion, but it might fail due // to a const violation. if (!CStyle && !DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { - msg = diag::err_bad_cxx_cast_const_away; + msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } Kind = CK_BitCast; @@ -963,7 +986,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, // Must preserve cv, as always, unless we're in C-style mode. if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) { - msg = diag::err_bad_cxx_cast_const_away; + msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } @@ -1038,7 +1061,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, /// where B is a base class of D [...]. /// TryCastResult -TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, +TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind, @@ -1049,9 +1072,9 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, bool WasOverloadedFunction = false; DeclAccessPair FoundOverload; - if (SrcExpr->getType() == Self.Context.OverloadTy) { + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { if (FunctionDecl *Fn - = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false, + = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false, FoundOverload)) { CXXMethodDecl *M = cast(Fn); SrcType = Self.Context.getMemberPointerType(Fn->getType(), @@ -1122,7 +1145,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, if (WasOverloadedFunction) { // Resolve the address of the overloaded function again, this time // allowing complaints if something goes wrong. - FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr, + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, true, FoundOverload); @@ -1132,7 +1155,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, } SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn); - if (!SrcExpr) { + if (!SrcExpr.isUsable()) { msg = 0; return TC_Failed; } @@ -1149,7 +1172,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, /// An expression e can be explicitly converted to a type T using a /// @c static_cast if the declaration "T t(e);" is well-formed [...]. TryCastResult -TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind) { if (DestType->isRecordType()) { @@ -1163,7 +1186,8 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType); InitializationKind InitKind = InitializationKind::CreateCast(/*FIXME:*/OpRange, CStyle); - InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExpr, 1); + Expr *SrcExprRaw = SrcExpr.get(); + InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1); // At this point of CheckStaticCast, if the destination is a reference, // or the expression is an overload expression this has to work. @@ -1176,7 +1200,7 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, return TC_NotApplicable; ExprResult Result - = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExpr, 1)); + = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExprRaw, 1)); if (Result.isInvalid()) { msg = 0; return TC_Failed; @@ -1187,7 +1211,7 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, else Kind = CK_NoOp; - SrcExpr = Result.takeAs(); + SrcExpr = move(Result); return TC_Success; } @@ -1240,16 +1264,21 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are // completely equal. - // FIXME: const_cast should probably not be able to convert between pointers - // to different address spaces. // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers // in multi-level pointers may change, but the level count must be the same, // as must be the final pointee type. while (SrcType != DestType && Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) { - Qualifiers Quals; - SrcType = Self.Context.getUnqualifiedArrayType(SrcType, Quals); - DestType = Self.Context.getUnqualifiedArrayType(DestType, Quals); + Qualifiers SrcQuals, DestQuals; + SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals); + DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals); + + // const_cast is permitted to strip cvr-qualifiers, only. Make sure that + // the other qualifiers (e.g., address spaces) are identical. + SrcQuals.removeCVRQualifiers(); + DestQuals.removeCVRQualifiers(); + if (SrcQuals != DestQuals) + return TC_NotApplicable; } // Since we're dealing in canonical types, the remainder must be the same. @@ -1259,43 +1288,8 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, return TC_Success; } -// A helper function to resolve and fix an overloaded expression that -// can be resolved because it identifies a single function -// template specialization -// Last three arguments should only be supplied if Complain = true -static ExprResult ResolveAndFixSingleFunctionTemplateSpecialization( - Sema &Self, Expr *SrcExpr, - bool DoFunctionPointerConverion, - bool Complain, - const SourceRange& OpRangeForComplaining, - QualType DestTypeForComplaining, - unsigned DiagIDForComplaining) { - assert(SrcExpr->getType() == Self.Context.OverloadTy); - DeclAccessPair Found; - Expr* SingleFunctionExpression = 0; - if (FunctionDecl* Fn = Self.ResolveSingleFunctionTemplateSpecialization( - SrcExpr, false, // false -> Complain - &Found)) { - if (!Self.DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) { - // mark the expression as resolved to Fn - SingleFunctionExpression = Self.FixOverloadedFunctionReference(SrcExpr, - Found, Fn); - - if (DoFunctionPointerConverion) - Self.DefaultFunctionArrayLvalueConversion(SingleFunctionExpression); - } - } - if (!SingleFunctionExpression && Complain) { - OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression; - Self.Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining) - << oe->getName() << DestTypeForComplaining << OpRangeForComplaining - << oe->getQualifierRange(); - Self.NoteAllOverloadCandidates(SrcExpr); - } - return SingleFunctionExpression; -} -static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, @@ -1303,19 +1297,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, bool IsLValueCast = false; DestType = Self.Context.getCanonicalType(DestType); - QualType SrcType = SrcExpr->getType(); + QualType SrcType = SrcExpr.get()->getType(); // Is the source an overloaded name? (i.e. &foo) // If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ... if (SrcType == Self.Context.OverloadTy) { // ... unless foo resolves to an lvalue unambiguously ExprResult SingleFunctionExpr = - ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr, + Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr ); if (SingleFunctionExpr.isUsable()) { - SrcExpr = SingleFunctionExpr.release(); - SrcType = SrcExpr->getType(); + SrcExpr = move(SingleFunctionExpr); + SrcType = SrcExpr.get()->getType(); } else return TC_NotApplicable; @@ -1323,7 +1317,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, if (const ReferenceType *DestTypeTmp = DestType->getAs()) { bool LValue = DestTypeTmp->isLValueReferenceType(); - if (LValue && !SrcExpr->isLValue()) { + if (LValue && !SrcExpr.get()->isLValue()) { // Cannot cast non-lvalue to lvalue reference type. See the similar // comment in const_cast. msg = diag::err_bad_cxx_cast_rvalue; @@ -1333,6 +1327,23 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, // C++ 5.2.10p10: [...] a reference cast reinterpret_cast(x) has the // same effect as the conversion *reinterpret_cast(&x) with the // built-in & and * operators. + + const char *inappropriate = 0; + switch (SrcExpr.get()->getObjectKind()) { + case OK_Ordinary: + break; + case OK_BitField: inappropriate = "bit-field"; break; + case OK_VectorComponent: inappropriate = "vector element"; break; + case OK_ObjCProperty: inappropriate = "property expression"; break; + } + if (inappropriate) { + Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_reference) + << inappropriate << DestType + << OpRange << SrcExpr.get()->getSourceRange(); + msg = 0; SrcExpr = ExprError(); + return TC_NotApplicable; + } + // This code does this transformation for the checked types. DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); SrcType = Self.Context.getPointerType(SrcType); @@ -1359,7 +1370,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, // A reinterpret_cast followed by a const_cast can, though, so in C-style, // we accept it. if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) { - msg = diag::err_bad_cxx_cast_const_away; + msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } @@ -1472,7 +1483,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. // The C-style cast operator can. if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) { - msg = diag::err_bad_cxx_cast_const_away; + msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } @@ -1525,39 +1536,39 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, return TC_Success; } -bool +ExprResult Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, - Expr *&CastExpr, CastKind &Kind, + Expr *CastExpr, CastKind &Kind, CXXCastPath &BasePath, bool FunctionalStyle) { - if (CastExpr->isBoundMemberFunction(Context)) - return Diag(CastExpr->getLocStart(), - diag::err_invalid_use_of_bound_member_func) - << CastExpr->getSourceRange(); - // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (CastTy->isVoidType()) { - IgnoredValueConversions(CastExpr); - bool ret = false; // false is 'able to convert' + Kind = CK_ToVoid; + + ExprResult CastExprRes = IgnoredValueConversions(CastExpr); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); + + if (CastExpr->getType() == Context.BoundMemberTy) + return CheckPlaceholderExpr(CastExpr); // will always fail + if (CastExpr->getType() == Context.OverloadTy) { ExprResult SingleFunctionExpr = - ResolveAndFixSingleFunctionTemplateSpecialization(*this, - CastExpr, - /* Decay Function to ptr */ false, - /* Complain */ true, - R, CastTy, diag::err_bad_cstyle_cast_overload); - if (SingleFunctionExpr.isUsable()) { - CastExpr = SingleFunctionExpr.release(); - Kind = CK_ToVoid; - } - else - ret = true; + ResolveAndFixSingleFunctionTemplateSpecialization( + CastExpr, /* Decay Function to ptr */ false, + /* Complain */ true, R, CastTy, + diag::err_bad_cstyle_cast_overload); + if (SingleFunctionExpr.isInvalid()) + return ExprError(); + CastExpr = SingleFunctionExpr.take(); } - else - Kind = CK_ToVoid; - return ret; + + assert(!CastExpr->getType()->isPlaceholderType()); + + return Owned(CastExpr); } // Make sure we determine the value kind before we bail out for @@ -1567,11 +1578,24 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, // If the type is dependent, we won't do any other semantic analysis now. if (CastTy->isDependentType() || CastExpr->isTypeDependent()) { Kind = CK_Dependent; - return false; + return Owned(CastExpr); } - if (VK == VK_RValue && !CastTy->isRecordType()) - DefaultFunctionArrayLvalueConversion(CastExpr); + if (VK == VK_RValue && !CastTy->isRecordType()) { + ExprResult CastExprRes = DefaultFunctionArrayLvalueConversion(CastExpr); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); + } + + // AltiVec vector initialization with a single literal. + if (const VectorType *vecTy = CastTy->getAs()) + if (vecTy->getVectorKind() == VectorType::AltiVecVector + && (CastExpr->getType()->isIntegerType() + || CastExpr->getType()->isFloatingType())) { + Kind = CK_VectorSplat; + return Owned(CastExpr); + } // C++ [expr.cast]p5: The conversions performed by // - a const_cast, @@ -1592,25 +1616,32 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, if (tcr == TC_NotApplicable) { // ... or if that is not possible, a static_cast, ignoring const, ... - tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg, Kind, - BasePath); + ExprResult CastExprRes = Owned(CastExpr); + tcr = TryStaticCast(*this, CastExprRes, CastTy, /*CStyle*/true, R, msg, + Kind, BasePath); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); if (tcr == TC_NotApplicable) { // ... and finally a reinterpret_cast, ignoring const. - tcr = TryReinterpretCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg, - Kind); + CastExprRes = Owned(CastExpr); + tcr = TryReinterpretCast(*this, CastExprRes, CastTy, /*CStyle*/true, R, + msg, Kind); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); } } if (tcr != TC_Success && msg != 0) { if (CastExpr->getType() == Context.OverloadTy) { DeclAccessPair Found; - FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr, + FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr, CastTy, /* Complain */ true, Found); - assert(!Fn - && "cast failed but able to resolve overload expression!!"); + assert(!Fn && "cast failed but able to resolve overload expression!!"); (void)Fn; } else { @@ -1621,5 +1652,8 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, else if (Kind == CK_BitCast) CheckCastAlign(CastExpr, CastTy, R); - return tcr != TC_Success; + if (tcr != TC_Success) + return ExprError(); + + return Owned(CastExpr); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp index 7ad4b459451d..7049f6b01d26 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -255,7 +255,7 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { QualType T = Context.getTypeDeclType(cast(SD)); if (T->isDependentType()) return true; - else if (TypedefDecl *TD = dyn_cast(SD)) { + else if (TypedefNameDecl *TD = dyn_cast(SD)) { if (TD->getUnderlyingType()->isRecordType() || (Context.getLangOptions().CPlusPlus0x && TD->getUnderlyingType()->isEnumeralType())) @@ -549,7 +549,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, } else if (isa(SD)) { RecordTypeLoc RecordTL = TLB.push(T); RecordTL.setNameLoc(IdentifierLoc); - } else if (isa(SD)) { + } else if (isa(SD)) { TypedefTypeLoc TypedefTL = TLB.push(T); TypedefTL.setNameLoc(IdentifierLoc); } else if (isa(SD)) { @@ -641,20 +641,87 @@ bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, } bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, - ParsedType Type, + SourceLocation TemplateLoc, + CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, SourceLocation CCLoc, - CXXScopeSpec &SS) { + bool EnteringContext) { if (SS.isInvalid()) return true; - TypeSourceInfo *TSInfo; - QualType T = GetTypeFromParser(Type, &TSInfo); + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){ + // Handle a dependent template specialization for which we cannot resolve + // the template name. + assert(DTN->getQualifier() + == static_cast(SS.getScopeRep())); + QualType T = Context.getDependentTemplateSpecializationType(ETK_None, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Create source-location information for this type. + TypeLocBuilder Builder; + DependentTemplateSpecializationTypeLoc SpecTL + = Builder.push(T); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setKeywordLoc(SourceLocation()); + SpecTL.setNameLoc(TemplateNameLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), + CCLoc); + return false; + } + + + if (Template.get().getAsOverloadedTemplate() || + isa(Template.get().getAsTemplateDecl())) { + SourceRange R(TemplateNameLoc, RAngleLoc); + if (SS.getRange().isValid()) + R.setBegin(SS.getRange().getBegin()); + + Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier) + << Template.get() << R; + NoteAllFoundTemplates(Template.get()); + return true; + } + + // We were able to resolve the template name to an actual template. + // Build an appropriate nested-name-specifier. + QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc, + TemplateArgs); if (T.isNull()) return true; - assert(TSInfo && "Not TypeSourceInfo in nested-name-specifier?"); - // FIXME: location of the 'template' keyword? - SS.Extend(Context, SourceLocation(), TSInfo->getTypeLoc(), CCLoc); + // FIXME: Template aliases will need to check the resulting type to make + // sure that it's either dependent or a tag type. + + // Provide source-location information for the template specialization + // type. + TypeLocBuilder Builder; + TemplateSpecializationTypeLoc SpecTL + = Builder.push(T); + + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + + SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), + CCLoc); return false; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 3ffa74818b49..5b645df8d293 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -180,6 +180,7 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case Builtin::BI__sync_bool_compare_and_swap: case Builtin::BI__sync_lock_test_and_set: case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_swap: return SemaBuiltinAtomicOverloaded(move(TheCallResult)); } @@ -313,9 +314,14 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { for (specific_attr_iterator i = FDecl->specific_attr_begin(), e = FDecl->specific_attr_end(); i != e; ++i) { - CheckNonNullArguments(*i, TheCall); + CheckNonNullArguments(*i, TheCall->getArgs(), + TheCall->getCallee()->getLocStart()); } + // Memset handling + if (FnInfo->isStr("memset")) + CheckMemsetArguments(TheCall); + return false; } @@ -414,7 +420,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { BUILTIN_ROW(__sync_val_compare_and_swap), BUILTIN_ROW(__sync_bool_compare_and_swap), BUILTIN_ROW(__sync_lock_test_and_set), - BUILTIN_ROW(__sync_lock_release) + BUILTIN_ROW(__sync_lock_release), + BUILTIN_ROW(__sync_swap) }; #undef BUILTIN_ROW @@ -467,6 +474,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { NumFixed = 0; ResultType = Context.VoidTy; break; + case Builtin::BI__sync_swap: BuiltinIndex = 14; break; } // Now that we know how many fixed arguments we expect, first check that we @@ -491,14 +499,14 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // deduce the types of the rest of the arguments accordingly. Walk // the remaining arguments, converting them to the deduced value type. for (unsigned i = 0; i != NumFixed; ++i) { - Expr *Arg = TheCall->getArg(i+1); + ExprResult Arg = TheCall->getArg(i+1); // If the argument is an implicit cast, then there was a promotion due to // "...", just remove it now. - if (ImplicitCastExpr *ICE = dyn_cast(Arg)) { + if (ImplicitCastExpr *ICE = dyn_cast(Arg.get())) { Arg = ICE->getSubExpr(); ICE->setSubExpr(0); - TheCall->setArg(i+1, Arg); + TheCall->setArg(i+1, Arg.get()); } // GCC does an implicit conversion to the pointer or integer ValType. This @@ -506,7 +514,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { CastKind Kind = CK_Invalid; ExprValueKind VK = VK_RValue; CXXCastPath BasePath; - if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, VK, BasePath)) + Arg = CheckCastTypes(Arg.get()->getSourceRange(), ValType, Arg.take(), Kind, VK, BasePath); + if (Arg.isInvalid()) return ExprError(); // Okay, we have something that *can* be converted to the right type. Check @@ -515,8 +524,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // pass in 42. The 42 gets converted to char. This is even more strange // for things like 45.123 -> char, etc. // FIXME: Do this check. - ImpCastExprToType(Arg, ValType, Kind, VK, &BasePath); - TheCall->setArg(i+1, Arg); + Arg = ImpCastExprToType(Arg.take(), ValType, Kind, VK, &BasePath); + TheCall->setArg(i+1, Arg.get()); } // Switch the DeclRefExpr to refer to the new decl. @@ -525,9 +534,10 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // Set the callee in the CallExpr. // FIXME: This leaks the original parens and implicit casts. - Expr *PromotedCall = DRE; - UsualUnaryConversions(PromotedCall); - TheCall->setCallee(PromotedCall); + ExprResult PromotedCall = UsualUnaryConversions(DRE); + if (PromotedCall.isInvalid()) + return ExprError(); + TheCall->setCallee(PromotedCall.take()); // Change the result type of the call to match the original value type. This // is arbitrary, but the codegen for these builtins ins design to handle it @@ -552,12 +562,6 @@ bool Sema::CheckObjCString(Expr *Arg) { return true; } - size_t NulPos = Literal->getString().find('\0'); - if (NulPos != llvm::StringRef::npos) { - Diag(getLocationOfStringLiteralByte(Literal, NulPos), - diag::warn_cfstring_literal_contains_nul_character) - << Arg->getSourceRange(); - } if (Literal->containsNonAsciiOrNull()) { llvm::StringRef String = Literal->getString(); unsigned NumBytes = String.size(); @@ -650,29 +654,31 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { << SourceRange(TheCall->getArg(2)->getLocStart(), (*(TheCall->arg_end()-1))->getLocEnd()); - Expr *OrigArg0 = TheCall->getArg(0); - Expr *OrigArg1 = TheCall->getArg(1); + ExprResult OrigArg0 = TheCall->getArg(0); + ExprResult OrigArg1 = TheCall->getArg(1); // Do standard promotions between the two arguments, returning their common // type. QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); + if (OrigArg0.isInvalid() || OrigArg1.isInvalid()) + return true; // Make sure any conversions are pushed back into the call; this is // type safe since unordered compare builtins are declared as "_Bool // foo(...)". - TheCall->setArg(0, OrigArg0); - TheCall->setArg(1, OrigArg1); + TheCall->setArg(0, OrigArg0.get()); + TheCall->setArg(1, OrigArg1.get()); - if (OrigArg0->isTypeDependent() || OrigArg1->isTypeDependent()) + if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent()) return false; // If the common type isn't a real floating type, then the arguments were // invalid for this operation. if (!Res->isRealFloatingType()) - return Diag(OrigArg0->getLocStart(), + return Diag(OrigArg0.get()->getLocStart(), diag::err_typecheck_call_invalid_ordered_compare) - << OrigArg0->getType() << OrigArg1->getType() - << SourceRange(OrigArg0->getLocStart(), OrigArg1->getLocEnd()); + << OrigArg0.get()->getType() << OrigArg1.get()->getType() + << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); return false; } @@ -860,7 +866,7 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, /// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr, /// int type). This simply type checks that type is one of the defined /// constants (0-3). -// For compatability check 0-3, llvm only handles 0 and 2. +// For compatibility check 0-3, llvm only handles 0 and 2. bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { llvm::APSInt Result; @@ -903,6 +909,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, if (E->isTypeDependent() || E->isValueDependent()) return false; + E = E->IgnoreParens(); + switch (E->getStmtClass()) { case Stmt::BinaryConditionalOperatorClass: case Stmt::ConditionalOperatorClass: { @@ -925,11 +933,6 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, goto tryAgain; } - case Stmt::ParenExprClass: { - E = cast(E)->getSubExpr(); - goto tryAgain; - } - case Stmt::OpaqueValueExprClass: if (const Expr *src = cast(E)->getSourceExpr()) { E = src; @@ -1036,15 +1039,15 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, void Sema::CheckNonNullArguments(const NonNullAttr *NonNull, - const CallExpr *TheCall) { + const Expr * const *ExprArgs, + SourceLocation CallSiteLoc) { for (NonNullAttr::args_iterator i = NonNull->args_begin(), e = NonNull->args_end(); i != e; ++i) { - const Expr *ArgExpr = TheCall->getArg(*i); + const Expr *ArgExpr = ExprArgs[*i]; if (ArgExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) - Diag(TheCall->getCallee()->getLocStart(), diag::warn_null_arg) - << ArgExpr->getSourceRange(); + Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); } } @@ -1218,10 +1221,12 @@ void CheckFormatHandler::HandleZeroPosition(const char *startPos, } void CheckFormatHandler::HandleNullChar(const char *nullCharacter) { - // The presence of a null character is likely an error. - S.Diag(getLocationOfByte(nullCharacter), - diag::warn_printf_format_string_contains_null_char) - << getFormatStringRange(); + if (!IsObjCLiteral) { + // The presence of a null character is likely an error. + S.Diag(getLocationOfByte(nullCharacter), + diag::warn_printf_format_string_contains_null_char) + << getFormatStringRange(); + } } const Expr *CheckFormatHandler::getDataArg(unsigned i) const { @@ -1825,6 +1830,54 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, } } +//===--- CHECK: Standard memory functions ---------------------------------===// + +/// \brief Check for dangerous or invalid arguments to memset(). +/// +/// This issues warnings on known problematic or dangerous or unspecified +/// arguments to the standard 'memset' function call. +/// +/// \param Call The call expression to diagnose. +void Sema::CheckMemsetArguments(const CallExpr *Call) { + // It is possible to have a non-standard definition of memset. Validate + // we have the proper number of arguments, and if not, abort further + // checking. + if (Call->getNumArgs() != 3) + return; + + const Expr *Dest = Call->getArg(0)->IgnoreParenImpCasts(); + + // The type checking for this warning is moderately expensive, only do it + // when enabled. + if (getDiagnostics().getDiagnosticLevel(diag::warn_non_pod_memset, + Dest->getExprLoc()) == + Diagnostic::Ignored) + return; + + QualType DestTy = Dest->getType(); + if (const PointerType *DestPtrTy = DestTy->getAs()) { + QualType PointeeTy = DestPtrTy->getPointeeType(); + if (PointeeTy->isVoidType()) + return; + + // Check the C++11 POD definition regardless of language mode; it is more + // relaxed than earlier definitions and we don't want spurrious warnings. + if (PointeeTy->isCXX11PODType()) + return; + + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::warn_non_pod_memset) + << PointeeTy << Call->getCallee()->getSourceRange()); + + SourceRange ArgRange = Call->getArg(0)->getSourceRange(); + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::note_non_pod_memset_silence) + << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); + } +} + //===--- CHECK: Return Address of Stack Variable --------------------------===// static Expr *EvalVal(Expr *E, llvm::SmallVectorImpl &refVars); @@ -1928,14 +1981,12 @@ static Expr *EvalAddr(Expr *E, llvm::SmallVectorImpl &refVars) { E->getType()->isObjCQualifiedIdType()) && "EvalAddr only works on pointers"); + E = E->IgnoreParens(); + // Our "symbolic interpreter" is just a dispatch off the currently // viewed AST node. We then recursively traverse the AST by calling // EvalAddr and EvalVal appropriately. switch (E->getStmtClass()) { - case Stmt::ParenExprClass: - // Ignore parentheses. - return EvalAddr(cast(E)->getSubExpr(), refVars); - case Stmt::DeclRefExprClass: { DeclRefExpr *DR = cast(E); @@ -2065,6 +2116,8 @@ do { // Our "symbolic interpreter" is just a dispatch off the currently // viewed AST node. We then recursively traverse the AST by calling // EvalAddr and EvalVal appropriately. + + E = E->IgnoreParens(); switch (E->getStmtClass()) { case Stmt::ImplicitCastExprClass: { ImplicitCastExpr *IE = cast(E); @@ -2098,12 +2151,6 @@ do { return NULL; } - case Stmt::ParenExprClass: { - // Ignore parentheses. - E = cast(E)->getSubExpr(); - continue; - } - case Stmt::UnaryOperatorClass: { // The only unary operator that make sense to handle here // is Deref. All others don't resolve to a "name." This includes @@ -2781,11 +2828,49 @@ void AnalyzeAssignment(Sema &S, BinaryOperator *E) { AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); } +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, + SourceLocation CContext, unsigned diag) { + S.Diag(E->getExprLoc(), diag) + << SourceType << T << E->getSourceRange() << SourceRange(CContext); +} + /// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, unsigned diag) { - S.Diag(E->getExprLoc(), diag) - << E->getType() << T << E->getSourceRange() << SourceRange(CContext); + DiagnoseImpCast(S, E, E->getType(), T, CContext, diag); +} + +/// Diagnose an implicit cast from a literal expression. Also attemps to supply +/// fixit hints when the cast wouldn't lose information to simply write the +/// expression with the expected type. +void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, + SourceLocation CContext) { + // Emit the primary warning first, then try to emit a fixit hint note if + // reasonable. + S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) + << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext); + + const llvm::APFloat &Value = FL->getValue(); + + // Don't attempt to fix PPC double double literals. + if (&Value.getSemantics() == &llvm::APFloat::PPCDoubleDouble) + return; + + // Try to convert this exactly to an 64-bit integer. FIXME: It would be + // nice to support arbitrarily large integers here. + bool isExact = false; + uint64_t IntegerPart; + if (Value.convertToInteger(&IntegerPart, 64, /*isSigned=*/true, + llvm::APFloat::rmTowardZero, &isExact) + != llvm::APFloat::opOK || !isExact) + return; + + llvm::APInt IntegerValue(64, IntegerPart, /*isSigned=*/true); + + std::string LiteralValue = IntegerValue.toString(10, /*isSigned=*/true); + S.Diag(FL->getExprLoc(), diag::note_fix_integral_float_as_integer) + << FixItHint::CreateReplacement(FL->getSourceRange(), LiteralValue); } std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { @@ -2797,6 +2882,11 @@ std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { return ValueInRange.toString(10); } +static bool isFromSystemMacro(Sema &S, SourceLocation loc) { + SourceManager &smgr = S.Context.getSourceManager(); + return loc.isMacroID() && smgr.isInSystemHeader(smgr.getSpellingLoc(loc)); +} + void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, bool *ICContext = 0) { if (E->isTypeDependent() || E->isValueDependent()) return; @@ -2806,11 +2896,12 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (Source == Target) return; if (Target->isDependentType()) return; - // If the conversion context location is invalid or instantiated - // from a system macro, don't complain. - if (CC.isInvalid() || - (CC.isMacroID() && S.Context.getSourceManager().isInSystemHeader( - S.Context.getSourceManager().getSpellingLoc(CC)))) + // If the conversion context location is invalid don't complain. + // We also don't want to emit a warning if the issue occurs from the + // instantiation of a system macro. The problem is that 'getSpellingLoc()' + // is slow, so we delay this check as long as possible. Once we detect + // we are in that scenario, we just return. + if (CC.isInvalid()) return; // Never diagnose implicit casts to bool. @@ -2819,8 +2910,11 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // Strip vector types. if (isa(Source)) { - if (!isa(Target)) + if (!isa(Target)) { + if (isFromSystemMacro(S, CC)) + return; return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar); + } Source = cast(Source)->getElementType().getTypePtr(); Target = cast(Target)->getElementType().getTypePtr(); @@ -2828,8 +2922,12 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // Strip complex types. if (isa(Source)) { - if (!isa(Target)) + if (!isa(Target)) { + if (isFromSystemMacro(S, CC)) + return; + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar); + } Source = cast(Source)->getElementType().getTypePtr(); Target = cast(Target)->getElementType().getTypePtr(); @@ -2857,17 +2955,22 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; } + if (isFromSystemMacro(S, CC)) + return; + DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision); } return; } - // If the target is integral, always warn. + // If the target is integral, always warn. if ((TargetBT && TargetBT->isInteger())) { + if (isFromSystemMacro(S, CC)) + return; + Expr *InnerE = E->IgnoreParenImpCasts(); - if (FloatingLiteral *LiteralExpr = dyn_cast(InnerE)) { - DiagnoseImpCast(S, LiteralExpr, T, CC, - diag::warn_impcast_literal_float_to_integer); + if (FloatingLiteral *FL = dyn_cast(InnerE)) { + DiagnoseFloatingLiteralImpCast(S, FL, T, CC); } else { DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer); } @@ -2887,6 +2990,9 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // TODO: this should happen for bitfield stores, too. llvm::APSInt Value(32); if (E->isIntegerConstantExpr(Value, S.Context)) { + if (isFromSystemMacro(S, CC)) + return; + std::string PrettySourceValue = Value.toString(10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); @@ -2898,6 +3004,10 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // People want to build with -Wshorten-64-to-32 and not -Wconversion // and by god we'll let them. + + if (isFromSystemMacro(S, CC)) + return; + if (SourceRange.Width == 64 && TargetRange.Width == 32) return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32); return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision); @@ -2906,6 +3016,10 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if ((TargetRange.NonNegative && !SourceRange.NonNegative) || (!TargetRange.NonNegative && SourceRange.NonNegative && SourceRange.Width == TargetRange.Width)) { + + if (isFromSystemMacro(S, CC)) + return; + unsigned DiagID = diag::warn_impcast_integer_sign; // Traditionally, gcc has warned about this under -Wsign-compare. @@ -2922,15 +3036,31 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } // Diagnose conversions between different enumeration types. + // In C, we pretend that the type of an EnumConstantDecl is its enumeration + // type, to give us better diagnostics. + QualType SourceType = E->getType(); + if (!S.getLangOptions().CPlusPlus) { + if (DeclRefExpr *DRE = dyn_cast(E)) + if (EnumConstantDecl *ECD = dyn_cast(DRE->getDecl())) { + EnumDecl *Enum = cast(ECD->getDeclContext()); + SourceType = S.Context.getTypeDeclType(Enum); + Source = S.Context.getCanonicalType(SourceType).getTypePtr(); + } + } + if (const EnumType *SourceEnum = Source->getAs()) if (const EnumType *TargetEnum = Target->getAs()) if ((SourceEnum->getDecl()->getIdentifier() || - SourceEnum->getDecl()->getTypedefForAnonDecl()) && + SourceEnum->getDecl()->getTypedefNameForAnonDecl()) && (TargetEnum->getDecl()->getIdentifier() || - TargetEnum->getDecl()->getTypedefForAnonDecl()) && - SourceEnum != TargetEnum) - return DiagnoseImpCast(S, E, T, CC, + TargetEnum->getDecl()->getTypedefNameForAnonDecl()) && + SourceEnum != TargetEnum) { + if (isFromSystemMacro(S, CC)) + return; + + return DiagnoseImpCast(S, E, SourceType, T, CC, diag::warn_impcast_different_enum_types); + } return; } @@ -3039,7 +3169,7 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { if (isa(E)) return; // Don't descend into unevaluated contexts. - if (isa(E)) return; + if (isa(E)) return; // Now just recurse over the expression's children. CC = E->getExprLoc(); @@ -3169,10 +3299,11 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { << TRange << Op->getSourceRange(); } -void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { +static void CheckArrayAccess_Check(Sema &S, + const clang::ArraySubscriptExpr *E) { const Expr *BaseExpr = E->getBase()->IgnoreParenImpCasts(); const ConstantArrayType *ArrayTy = - Context.getAsConstantArrayType(BaseExpr->getType()); + S.Context.getAsConstantArrayType(BaseExpr->getType()); if (!ArrayTy) return; @@ -3180,7 +3311,7 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { if (IndexExpr->isValueDependent()) return; llvm::APSInt index; - if (!IndexExpr->isIntegerConstantExpr(index, Context)) + if (!IndexExpr->isIntegerConstantExpr(index, S.Context)) return; if (index.isUnsigned() || !index.isNegative()) { @@ -3195,15 +3326,16 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { if (index.slt(size)) return; - DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, - PDiag(diag::warn_array_index_exceeds_bounds) - << index.toString(10, true) << size.toString(10, true) - << IndexExpr->getSourceRange()); + S.DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, + S.PDiag(diag::warn_array_index_exceeds_bounds) + << index.toString(10, true) + << size.toString(10, true) + << IndexExpr->getSourceRange()); } else { - DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, - PDiag(diag::warn_array_index_precedes_bounds) - << index.toString(10, true) - << IndexExpr->getSourceRange()); + S.DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, + S.PDiag(diag::warn_array_index_precedes_bounds) + << index.toString(10, true) + << IndexExpr->getSourceRange()); } const NamedDecl *ND = NULL; @@ -3212,8 +3344,28 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { if (const MemberExpr *ME = dyn_cast(BaseExpr)) ND = dyn_cast(ME->getMemberDecl()); if (ND) - DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, - PDiag(diag::note_array_index_out_of_bounds) - << ND->getDeclName()); + S.DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, + S.PDiag(diag::note_array_index_out_of_bounds) + << ND->getDeclName()); } +void Sema::CheckArrayAccess(const Expr *expr) { + while (true) { + expr = expr->IgnoreParens(); + switch (expr->getStmtClass()) { + case Stmt::ArraySubscriptExprClass: + CheckArrayAccess_Check(*this, cast(expr)); + return; + case Stmt::ConditionalOperatorClass: { + const ConditionalOperator *cond = cast(expr); + if (const Expr *lhs = cond->getLHS()) + CheckArrayAccess(lhs); + if (const Expr *rhs = cond->getRHS()) + CheckArrayAccess(rhs); + return; + } + default: + return; + } + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index bab665a38da7..cc8726de9df8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -667,8 +667,39 @@ QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) { T = Value->getType(); else return QualType(); - - return T.getNonReferenceType(); + + // Dig through references, function pointers, and block pointers to + // get down to the likely type of an expression when the entity is + // used. + do { + if (const ReferenceType *Ref = T->getAs()) { + T = Ref->getPointeeType(); + continue; + } + + if (const PointerType *Pointer = T->getAs()) { + if (Pointer->getPointeeType()->isFunctionType()) { + T = Pointer->getPointeeType(); + continue; + } + + break; + } + + if (const BlockPointerType *Block = T->getAs()) { + T = Block->getPointeeType(); + continue; + } + + if (const FunctionType *Function = T->getAs()) { + T = Function->getResultType(); + continue; + } + + break; + } while (true); + + return T; } void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { @@ -1482,7 +1513,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, case Sema::PCC_Statement: { AddTypedefResult(Results); - if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) { + if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns() && + SemaRef.getLangOptions().CXXExceptions) { Builder.AddTypedTextChunk("try"); Builder.AddChunk(CodeCompletionString::CK_LeftBrace); Builder.AddPlaceholderChunk("statements"); @@ -1655,15 +1687,17 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result("true")); Results.AddResult(Result("false")); - // dynamic_cast < type-id > ( expression ) - Builder.AddTypedTextChunk("dynamic_cast"); - Builder.AddChunk(CodeCompletionString::CK_LeftAngle); - Builder.AddPlaceholderChunk("type"); - Builder.AddChunk(CodeCompletionString::CK_RightAngle); - Builder.AddChunk(CodeCompletionString::CK_LeftParen); - Builder.AddPlaceholderChunk("expression"); - Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); + if (SemaRef.getLangOptions().RTTI) { + // dynamic_cast < type-id > ( expression ) + Builder.AddTypedTextChunk("dynamic_cast"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } // static_cast < type-id > ( expression ) Builder.AddTypedTextChunk("static_cast"); @@ -1695,13 +1729,15 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(Result(Builder.TakeString())); - // typeid ( expression-or-type ) - Builder.AddTypedTextChunk("typeid"); - Builder.AddChunk(CodeCompletionString::CK_LeftParen); - Builder.AddPlaceholderChunk("expression-or-type"); - Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); - + if (SemaRef.getLangOptions().RTTI) { + // typeid ( expression-or-type ) + Builder.AddTypedTextChunk("typeid"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression-or-type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } + // new T ( ... ) Builder.AddTypedTextChunk("new"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -1738,11 +1774,13 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("expression"); Results.AddResult(Result(Builder.TakeString())); - // throw expression - Builder.AddTypedTextChunk("throw"); - Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); - Builder.AddPlaceholderChunk("expression"); - Results.AddResult(Result(Builder.TakeString())); + if (SemaRef.getLangOptions().CXXExceptions) { + // throw expression + Builder.AddTypedTextChunk("throw"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + } // FIXME: Rethrow? } @@ -1785,9 +1823,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, /// /// This routine provides a fast path where we provide constant strings for /// common type names. -const char *GetCompletionTypeString(QualType T, - ASTContext &Context, - CodeCompletionAllocator &Allocator) { +static const char *GetCompletionTypeString(QualType T, + ASTContext &Context, + CodeCompletionAllocator &Allocator) { PrintingPolicy Policy(Context.PrintingPolicy); Policy.AnonymousTagLocations = false; @@ -1799,7 +1837,7 @@ const char *GetCompletionTypeString(QualType T, // Anonymous tag types are constant strings. if (const TagType *TagT = dyn_cast(T)) if (TagDecl *Tag = TagT->getDecl()) - if (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()) { + if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { switch (Tag->getTagKind()) { case TTK_Struct: return "struct "; case TTK_Class: return "class "; @@ -1902,7 +1940,7 @@ static std::string FormatFunctionParameter(ASTContext &Context, // Look through typedefs. if (TypedefTypeLoc *TypedefTL = dyn_cast(&TL)) { if (TypeSourceInfo *InnerTSInfo - = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) { + = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) { TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); continue; } @@ -2602,6 +2640,7 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) { case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl; case Decl::ParmVar: return CXCursor_ParmDecl; case Decl::Typedef: return CXCursor_TypedefDecl; + case Decl::TypeAlias: return CXCursor_TypeAliasDecl; case Decl::Var: return CXCursor_VarDecl; case Decl::Namespace: return CXCursor_Namespace; case Decl::NamespaceAlias: return CXCursor_NamespaceAlias; @@ -4816,8 +4855,12 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. - if (RecExpr) - DefaultFunctionArrayLvalueConversion(RecExpr); + if (RecExpr) { + ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr); + if (Conv.isInvalid()) // conversion failed. bail. + return; + RecExpr = Conv.take(); + } QualType ReceiverType = RecExpr? RecExpr->getType() : Super? Context.getObjCObjectPointerType( Context.getObjCInterfaceType(Super)) @@ -5327,16 +5370,65 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, Class = cast(Container)->getCategoryDecl() ->getClassInterface(); + // Determine the type of the property we're synthesizing. + QualType PropertyType = Context.getObjCIdType(); + if (Class) { + if (ObjCPropertyDecl *Property + = Class->FindPropertyDeclaration(PropertyName)) { + PropertyType + = Property->getType().getNonReferenceType().getUnqualifiedType(); + + // Give preference to ivars + Results.setPreferredType(PropertyType); + } + } + // Add all of the instance variables in this class and its superclasses. Results.EnterNewScope(); + bool SawSimilarlyNamedIvar = false; + std::string NameWithPrefix; + NameWithPrefix += '_'; + NameWithPrefix += PropertyName->getName().str(); + std::string NameWithSuffix = PropertyName->getName().str(); + NameWithSuffix += '_'; for(; Class; Class = Class->getSuperClass()) { - // FIXME: We could screen the type of each ivar for compatibility with - // the property, but is that being too paternal? - for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(), - IVarEnd = Class->ivar_end(); - IVar != IVarEnd; ++IVar) - Results.AddResult(Result(*IVar, 0), CurContext, 0, false); + for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; + Ivar = Ivar->getNextIvar()) { + Results.AddResult(Result(Ivar, 0), CurContext, 0, false); + + // Determine whether we've seen an ivar with a name similar to the + // property. + if ((PropertyName == Ivar->getIdentifier() || + NameWithPrefix == Ivar->getName() || + NameWithSuffix == Ivar->getName())) { + SawSimilarlyNamedIvar = true; + + // Reduce the priority of this result by one, to give it a slight + // advantage over other results whose names don't match so closely. + if (Results.size() && + Results.data()[Results.size() - 1].Kind + == CodeCompletionResult::RK_Declaration && + Results.data()[Results.size() - 1].Declaration == Ivar) + Results.data()[Results.size() - 1].Priority--; + } + } } + + if (!SawSimilarlyNamedIvar) { + // Create ivar result _propName, that the user can use to synthesize + // an ivar of the appropriate type. + unsigned Priority = CCP_MemberDeclaration + 1; + typedef CodeCompletionResult Result; + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available); + + Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context, + Allocator)); + Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); + Results.AddResult(Result(Builder.TakeString(), Priority, + CXCursor_ObjCIvarDecl)); + } + Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index d6efd7a6c9dd..7214988bdafc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -17,6 +17,7 @@ #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "TypeLocBuilder.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -24,6 +25,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/CharUnits.h" @@ -61,7 +63,8 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) { ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName, bool HasTrailingDot, - ParsedType ObjectTypePtr) { + ParsedType ObjectTypePtr, + bool WantNontrivialTypeSourceInfo) { // Determine where we will perform name lookup. DeclContext *LookupCtx = 0; if (ObjectTypePtr) { @@ -87,10 +90,15 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // We know from the grammar that this name refers to a type, // so build a dependent node to describe the type. + if (WantNontrivialTypeSourceInfo) + return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get(); + + NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context); QualType T = - CheckTypenameType(ETK_None, SS->getScopeRep(), II, - SourceLocation(), SS->getRange(), NameLoc); - return ParsedType::make(T); + CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc, + II, NameLoc); + + return ParsedType::make(T); } return ParsedType(); @@ -189,10 +197,23 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (T.isNull()) T = Context.getTypeDeclType(TD); - if (SS) - T = getElaboratedType(ETK_None, *SS, T); - + if (SS && SS->isNotEmpty()) { + if (WantNontrivialTypeSourceInfo) { + // Construct a type with type-source information. + TypeLocBuilder Builder; + Builder.pushTypeSpec(T).setNameLoc(NameLoc); + + T = getElaboratedType(ETK_None, *SS, T); + ElaboratedTypeLoc ElabTL = Builder.push(T); + ElabTL.setKeywordLoc(SourceLocation()); + ElabTL.setQualifierLoc(SS->getWithLocInContext(Context)); + return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); + } else { + T = getElaboratedType(ETK_None, *SS, T); + } + } } else if (ObjCInterfaceDecl *IDecl = dyn_cast(IIDecl)) { + (void)DiagnoseUseOfDecl(IDecl, NameLoc); if (!HasTrailingDot) T = Context.getObjCInterfaceType(IDecl); } @@ -229,6 +250,33 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { return DeclSpec::TST_unspecified; } +/// isMicrosoftMissingTypename - In Microsoft mode, within class scope, +/// if a CXXScopeSpec's type is equal to the type of one of the base classes +/// then downgrade the missing typename error to a warning. +/// This is needed for MSVC compatibility; Example: +/// @code +/// template class A { +/// public: +/// typedef int TYPE; +/// }; +/// template class B : public A { +/// public: +/// A::TYPE a; // no typename required because A is a base class. +/// }; +/// @endcode +bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) { + if (CurContext->isRecord()) { + const Type *Ty = SS->getScopeRep()->getAsType(); + + CXXRecordDecl *RD = cast(CurContext); + for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(), + BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) + if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType())) + return true; + } + return false; +} + bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, @@ -263,7 +311,9 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, Diag(Result->getLocation(), diag::note_previous_decl) << Result->getDeclName(); - SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS); + SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS, + false, false, ParsedType(), + /*NonTrivialTypeSourceInfo=*/true); return true; } } else if (Lookup.empty()) { @@ -304,7 +354,11 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, Diag(IILoc, diag::err_typename_nested_not_found) << &II << DC << SS->getRange(); else if (isDependentScopeSpecifier(*SS)) { - Diag(SS->getRange().getBegin(), diag::err_typename_missing) + unsigned DiagID = diag::err_typename_missing; + if (getLangOptions().Microsoft && isMicrosoftMissingTypename(SS)) + DiagID = diag::warn_typename_missing; + + Diag(SS->getRange().getBegin(), DiagID) << (NestedNameSpecifier *)SS->getScopeRep() << II.getName() << SourceRange(SS->getRange().getBegin(), IILoc) << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); @@ -317,6 +371,328 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, return true; } +/// \brief Determine whether the given result set contains either a type name +/// or +static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) { + bool CheckTemplate = R.getSema().getLangOptions().CPlusPlus && + NextToken.is(tok::less); + + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { + if (isa(*I) || isa(*I)) + return true; + + if (CheckTemplate && isa(*I)) + return true; + } + + return false; +} + +Sema::NameClassification Sema::ClassifyName(Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *&Name, + SourceLocation NameLoc, + const Token &NextToken) { + DeclarationNameInfo NameInfo(Name, NameLoc); + ObjCMethodDecl *CurMethod = getCurMethodDecl(); + + if (NextToken.is(tok::coloncolon)) { + BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(), + QualType(), false, SS, 0, false); + + } + + LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); + LookupParsedName(Result, S, &SS, !CurMethod); + + // Perform lookup for Objective-C instance variables (including automatically + // synthesized instance variables), if we're in an Objective-C method. + // FIXME: This lookup really, really needs to be folded in to the normal + // unqualified lookup mechanism. + if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { + ExprResult E = LookupInObjCMethod(Result, S, Name, true); + if (E.get() || E.isInvalid()) + return E; + + // Synthesize ivars lazily. + if (getLangOptions().ObjCDefaultSynthProperties && + getLangOptions().ObjCNonFragileABI2) { + if (SynthesizeProvisionalIvar(Result, Name, NameLoc)) { + if (const ObjCPropertyDecl *Property = + canSynthesizeProvisionalIvar(Name)) { + Diag(NameLoc, diag::warn_synthesized_ivar_access) << Name; + Diag(Property->getLocation(), diag::note_property_declare); + } + + // FIXME: This is strange. Shouldn't we just take the ivar returned + // from SynthesizeProvisionalIvar and continue with that? + E = LookupInObjCMethod(Result, S, Name, true); + if (E.get() || E.isInvalid()) + return E; + } + } + } + + bool SecondTry = false; + bool IsFilteredTemplateName = false; + +Corrected: + switch (Result.getResultKind()) { + case LookupResult::NotFound: + // If an unqualified-id is followed by a '(', then we have a function + // call. + if (!SS.isSet() && NextToken.is(tok::l_paren)) { + // In C++, this is an ADL-only call. + // FIXME: Reference? + if (getLangOptions().CPlusPlus) + return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true); + + // C90 6.3.2.2: + // If the expression that precedes the parenthesized argument list in a + // function call consists solely of an identifier, and if no + // declaration is visible for this identifier, the identifier is + // implicitly declared exactly as if, in the innermost block containing + // the function call, the declaration + // + // extern int identifier (); + // + // appeared. + // + // We also allow this in C99 as an extension. + if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) { + Result.addDecl(D); + Result.resolveKind(); + return BuildDeclarationNameExpr(SS, Result, /*ADL=*/false); + } + } + + // In C, we first see whether there is a tag type by the same name, in + // which case it's likely that the user just forget to write "enum", + // "struct", or "union". + if (!getLangOptions().CPlusPlus && !SecondTry) { + Result.clear(LookupTagName); + LookupParsedName(Result, S, &SS); + if (TagDecl *Tag = Result.getAsSingle()) { + const char *TagName = 0; + const char *FixItTagName = 0; + switch (Tag->getTagKind()) { + case TTK_Class: + TagName = "class"; + FixItTagName = "class "; + break; + + case TTK_Enum: + TagName = "enum"; + FixItTagName = "enum "; + break; + + case TTK_Struct: + TagName = "struct"; + FixItTagName = "struct "; + break; + + case TTK_Union: + TagName = "union"; + FixItTagName = "union "; + break; + } + + Diag(NameLoc, diag::err_use_of_tag_name_without_tag) + << Name << TagName << getLangOptions().CPlusPlus + << FixItHint::CreateInsertion(NameLoc, FixItTagName); + break; + } + + Result.clear(LookupOrdinaryName); + } + + // Perform typo correction to determine if there is another name that is + // close to this name. + if (!SecondTry) { + if (DeclarationName Corrected = CorrectTypo(Result, S, &SS)) { + unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; + unsigned QualifiedDiag = diag::err_no_member_suggest; + + NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin(); + NamedDecl *UnderlyingFirstDecl + = FirstDecl? FirstDecl->getUnderlyingDecl() : 0; + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + UnderlyingFirstDecl && isa(UnderlyingFirstDecl)) { + UnqualifiedDiag = diag::err_no_template_suggest; + QualifiedDiag = diag::err_no_member_template_suggest; + } else if (UnderlyingFirstDecl && + (isa(UnderlyingFirstDecl) || + isa(UnderlyingFirstDecl) || + isa(UnderlyingFirstDecl))) { + UnqualifiedDiag = diag::err_unknown_typename_suggest; + QualifiedDiag = diag::err_unknown_nested_typename_suggest; + } + + if (SS.isEmpty()) + Diag(NameLoc, UnqualifiedDiag) + << Name << Corrected + << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + else + Diag(NameLoc, QualifiedDiag) + << Name << computeDeclContext(SS, false) << Corrected + << SS.getRange() + << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + + // Update the name, so that the caller has the new name. + Name = Corrected.getAsIdentifierInfo(); + + // Typo correction corrected to a keyword. + if (Result.empty()) + return Corrected.getAsIdentifierInfo(); + + Diag(FirstDecl->getLocation(), diag::note_previous_decl) + << FirstDecl->getDeclName(); + + // If we found an Objective-C instance variable, let + // LookupInObjCMethod build the appropriate expression to + // reference the ivar. + // FIXME: This is a gross hack. + if (ObjCIvarDecl *Ivar = Result.getAsSingle()) { + Result.clear(); + ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier())); + return move(E); + } + + goto Corrected; + } + } + + // We failed to correct; just fall through and let the parser deal with it. + Result.suppressDiagnostics(); + return NameClassification::Unknown(); + + case LookupResult::NotFoundInCurrentInstantiation: + // We performed name lookup into the current instantiation, and there were + // dependent bases, so we treat this result the same way as any other + // dependent nested-name-specifier. + + // C++ [temp.res]p2: + // A name used in a template declaration or definition and that is + // dependent on a template-parameter is assumed not to name a type + // unless the applicable name lookup finds a type name or the name is + // qualified by the keyword typename. + // + // FIXME: If the next token is '<', we might want to ask the parser to + // perform some heroics to see if we actually have a + // template-argument-list, which would indicate a missing 'template' + // keyword here. + return BuildDependentDeclRefExpr(SS, NameInfo, /*TemplateArgs=*/0); + + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + break; + + case LookupResult::Ambiguous: + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + hasAnyAcceptableTemplateNames(Result)) { + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in an + // ambiguity in certain cases (for example, if it is found in more than + // one base class). If all of the injected-class-names that are found + // refer to specializations of the same class template, and if the name + // is followed by a template-argument-list, the reference refers to the + // class template itself and not a specialization thereof, and is not + // ambiguous. + // + // This filtering can make an ambiguous result into an unambiguous one, + // so try again after filtering out template names. + FilterAcceptableTemplateNames(Result); + if (!Result.isAmbiguous()) { + IsFilteredTemplateName = true; + break; + } + } + + // Diagnose the ambiguity and return an error. + return NameClassification::Error(); + } + + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) { + // C++ [temp.names]p3: + // After name lookup (3.4) finds that a name is a template-name or that + // an operator-function-id or a literal- operator-id refers to a set of + // overloaded functions any member of which is a function template if + // this is followed by a <, the < is always taken as the delimiter of a + // template-argument-list and never as the less-than operator. + if (!IsFilteredTemplateName) + FilterAcceptableTemplateNames(Result); + + if (!Result.empty()) { + bool IsFunctionTemplate; + TemplateName Template; + if (Result.end() - Result.begin() > 1) { + IsFunctionTemplate = true; + Template = Context.getOverloadedTemplateName(Result.begin(), + Result.end()); + } else { + TemplateDecl *TD + = cast((*Result.begin())->getUnderlyingDecl()); + IsFunctionTemplate = isa(TD); + + if (SS.isSet() && !SS.isInvalid()) + Template = Context.getQualifiedTemplateName(SS.getScopeRep(), + /*TemplateKeyword=*/false, + TD); + else + Template = TemplateName(TD); + } + + if (IsFunctionTemplate) { + // Function templates always go through overload resolution, at which + // point we'll perform the various checks (e.g., accessibility) we need + // to based on which function we selected. + Result.suppressDiagnostics(); + + return NameClassification::FunctionTemplate(Template); + } + + return NameClassification::TypeTemplate(Template); + } + } + + NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); + if (TypeDecl *Type = dyn_cast(FirstDecl)) { + DiagnoseUseOfDecl(Type, NameLoc); + QualType T = Context.getTypeDeclType(Type); + return ParsedType::make(T); + } + + ObjCInterfaceDecl *Class = dyn_cast(FirstDecl); + if (!Class) { + // FIXME: It's unfortunate that we don't have a Type node for handling this. + if (ObjCCompatibleAliasDecl *Alias + = dyn_cast(FirstDecl)) + Class = Alias->getClassInterface(); + } + + if (Class) { + DiagnoseUseOfDecl(Class, NameLoc); + + if (NextToken.is(tok::period)) { + // Interface. is parsed as a property reference expression. + // Just return "unknown" as a fall-through for now. + Result.suppressDiagnostics(); + return NameClassification::Unknown(); + } + + QualType T = Context.getObjCInterfaceType(Class); + return ParsedType::make(T); + } + + if (!Result.empty() && (*Result.begin())->isCXXClassMember()) + return BuildPossibleImplicitMemberExpr(SS, Result, 0); + + bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); + return BuildDeclarationNameExpr(SS, Result, ADL); +} + // Determines the context to return to after temporarily entering a // context. This depends in an unnecessarily complicated way on the // exact ordering of callbacks from the parser. @@ -472,11 +848,30 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { } S->AddDecl(D); - IdResolver.AddDecl(D); + + if (isa(D) && !cast(D)->isGnuLocal()) { + // Implicitly-generated labels may end up getting generated in an order that + // isn't strictly lexical, which breaks name lookup. Be careful to insert + // the label at the appropriate place in the identifier chain. + for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) { + DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext(); + if (IDC == CurContext) { + if (!S->isDeclScope(*I)) + continue; + } else if (IDC->Encloses(CurContext)) + break; + } + + IdResolver.InsertDeclAfter(I, D); + } else { + IdResolver.AddDecl(D); + } } -bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) { - return IdResolver.isDeclInScope(D, Ctx, Context, S); +bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, + bool ExplicitInstantiationOrSpecialization) { + return IdResolver.isDeclInScope(D, Ctx, Context, S, + ExplicitInstantiationOrSpecialization); } Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) { @@ -498,12 +893,13 @@ static bool isOutOfScopePreviousDeclaration(NamedDecl *, /// as determined by isDeclInScope. static void FilterLookupForScope(Sema &SemaRef, LookupResult &R, DeclContext *Ctx, Scope *S, - bool ConsiderLinkage) { + bool ConsiderLinkage, + bool ExplicitInstantiationOrSpecialization) { LookupResult::Filter F = R.makeFilter(); while (F.hasNext()) { NamedDecl *D = F.next(); - if (SemaRef.isDeclInScope(D, Ctx, S)) + if (SemaRef.isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization)) continue; if (ConsiderLinkage && @@ -841,7 +1237,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, FunctionDecl *New = FunctionDecl::Create(Context, Context.getTranslationUnitDecl(), - Loc, II, R, /*TInfo=*/0, + Loc, Loc, II, R, /*TInfo=*/0, SC_Extern, SC_None, false, /*hasPrototype=*/true); @@ -851,10 +1247,15 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, // FunctionDecl. if (const FunctionProtoType *FT = dyn_cast(R)) { llvm::SmallVector Params; - for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) - Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0, - FT->getArgType(i), /*TInfo=*/0, - SC_None, SC_None, 0)); + for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { + ParmVarDecl *parm = + ParmVarDecl::Create(Context, New, SourceLocation(), + SourceLocation(), 0, + FT->getArgType(i), /*TInfo=*/0, + SC_None, SC_None, 0); + parm->setScopeInfo(0, i); + Params.push_back(parm); + } New->setParams(Params.data(), Params.size()); } @@ -871,12 +1272,12 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, return New; } -/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the +/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the /// same name and scope as a previous declaration 'Old'. Figure out /// how to resolve this situation, merging decls or emitting /// diagnostics as appropriate. If there was an error, set New to be invalid. /// -void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { +void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { // If the new decl is known invalid already, don't bother doing any // merging checks. if (New->isInvalidDecl()) return; @@ -936,7 +1337,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // Determine the "old" type we'll use for checking and diagnostics. QualType OldType; - if (TypedefDecl *OldTypedef = dyn_cast(Old)) + if (TypedefNameDecl *OldTypedef = dyn_cast(Old)) OldType = OldTypedef->getUnderlyingType(); else OldType = Context.getTypeDeclType(Old); @@ -947,8 +1348,11 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { if (OldType != New->getUnderlyingType() && Context.getCanonicalType(OldType) != Context.getCanonicalType(New->getUnderlyingType())) { + int Kind = 0; + if (isa(Old)) + Kind = 1; Diag(New->getLocation(), diag::err_redefinition_different_typedef) - << New->getUnderlyingType() << OldType; + << Kind << New->getUnderlyingType() << OldType; if (Old->getLocation().isValid()) Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -958,8 +1362,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // declaration was a typedef. // FIXME: this is a potential source of wierdness if the type // spellings don't match exactly. - if (isa(Old)) - New->setPreviousDeclaration(cast(Old)); + if (TypedefNameDecl *Typedef = dyn_cast(Old)) + New->setPreviousDeclaration(Typedef); if (getLangOptions().Microsoft) return; @@ -993,7 +1397,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // }; // // since that was the intent of DR56. - if (!isa(Old)) + if (!isa(Old)) return; Diag(New->getLocation(), diag::err_redefinition) @@ -1033,23 +1437,58 @@ DeclHasAttr(const Decl *D, const Attr *A) { return false; } -/// MergeDeclAttributes - append attributes from the Old decl to the New one. -static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) { - if (!Old->hasAttrs()) +/// mergeDeclAttributes - Copy attributes from the Old decl to the New one. +static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl, + ASTContext &C) { + if (!oldDecl->hasAttrs()) return; + + bool foundAny = newDecl->hasAttrs(); + // Ensure that any moving of objects within the allocated map is done before // we process them. - if (!New->hasAttrs()) - New->setAttrs(AttrVec()); + if (!foundAny) newDecl->setAttrs(AttrVec()); + for (specific_attr_iterator - i = Old->specific_attr_begin(), - e = Old->specific_attr_end(); i != e; ++i) { - if (!DeclHasAttr(New, *i)) { - InheritableAttr *NewAttr = cast((*i)->clone(C)); - NewAttr->setInherited(true); - New->addAttr(NewAttr); + i = oldDecl->specific_attr_begin(), + e = oldDecl->specific_attr_end(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast((*i)->clone(C)); + newAttr->setInherited(true); + newDecl->addAttr(newAttr); + foundAny = true; } } + + if (!foundAny) newDecl->dropAttrs(); +} + +/// mergeParamDeclAttributes - Copy attributes from the old parameter +/// to the new one. +static void mergeParamDeclAttributes(ParmVarDecl *newDecl, + const ParmVarDecl *oldDecl, + ASTContext &C) { + if (!oldDecl->hasAttrs()) + return; + + bool foundAny = newDecl->hasAttrs(); + + // Ensure that any moving of objects within the allocated map is + // done before we process them. + if (!foundAny) newDecl->setAttrs(AttrVec()); + + for (specific_attr_iterator + i = oldDecl->specific_attr_begin(), + e = oldDecl->specific_attr_end(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast((*i)->clone(C)); + newAttr->setInherited(true); + newDecl->addAttr(newAttr); + foundAny = true; + } + } + + if (!foundAny) newDecl->dropAttrs(); } namespace { @@ -1145,10 +1584,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { New->getStorageClass() == SC_Static && Old->getStorageClass() != SC_Static && !canRedefineFunction(Old, getLangOptions())) { - Diag(New->getLocation(), diag::err_static_non_static) - << New; - Diag(Old->getLocation(), PrevDiag); - return true; + if (getLangOptions().Microsoft) { + Diag(New->getLocation(), diag::warn_static_non_static) << New; + Diag(Old->getLocation(), PrevDiag); + } else { + Diag(New->getLocation(), diag::err_static_non_static) << New; + Diag(Old->getLocation(), PrevDiag); + return true; + } } // If a function is first declared with a calling convention, but is @@ -1191,8 +1634,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { } // Merge regparm attribute. - if (OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { - if (NewTypeInfo.getRegParm()) { + if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() || + OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { + if (NewTypeInfo.getHasRegParm()) { Diag(New->getLocation(), diag::err_regparm_mismatch) << NewType->getRegParmType() << OldType->getRegParmType(); @@ -1335,10 +1779,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { ParamEnd = OldProto->arg_type_end(); ParamType != ParamEnd; ++ParamType) { ParmVarDecl *Param = ParmVarDecl::Create(Context, New, + SourceLocation(), SourceLocation(), 0, *ParamType, /*TInfo=*/0, SC_None, SC_None, 0); + Param->setScopeInfo(0, Params.size()); Param->setImplicit(); Params.push_back(Param); } @@ -1450,7 +1896,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { /// \returns false bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { // Merge the attributes - MergeDeclAttributes(New, Old, Context); + mergeDeclAttributes(New, Old, Context); // Merge the storage class. if (Old->getStorageClass() != SC_Extern && @@ -1465,14 +1911,33 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { if (Old->isDeleted()) New->setDeleted(); + // Merge attributes from the parameters. These can mismatch with K&R + // declarations. + if (New->getNumParams() == Old->getNumParams()) + for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) + mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i), + Context); + if (getLangOptions().CPlusPlus) return MergeCXXFunctionDecl(New, Old); return false; } -/// MergeVarDecl - We parsed a variable 'New' which has the same name and scope -/// as a previous declaration 'Old'. Figure out how to merge their types, +void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, + const ObjCMethodDecl *oldMethod) { + // Merge the attributes. + mergeDeclAttributes(newMethod, oldMethod, Context); + + // Merge attributes from the parameters. + for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(), + ni = newMethod->param_begin(), ne = newMethod->param_end(); + ni != ne; ++ni, ++oi) + mergeParamDeclAttributes(*ni, *oi, Context); +} + +/// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and +/// scope as a previous declaration 'Old'. Figure out how to merge their types, /// emitting diagnostics as appropriate. /// /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back @@ -1489,8 +1954,10 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { if (AT && !AT->isDeduced()) { // We don't know what the new type is until the initializer is attached. return; - } else if (Context.hasSameType(New->getType(), Old->getType())) - return; + } else if (Context.hasSameType(New->getType(), Old->getType())) { + // These could still be something that needs exception specs checked. + return MergeVarDeclExceptionSpecs(New, Old); + } // C++ [basic.link]p10: // [...] the types specified by all declarations referring to a given // object or function shall be identical, except that declarations for an @@ -1564,7 +2031,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setInvalidDecl(); } - MergeDeclAttributes(New, Old, Context); + mergeDeclAttributes(New, Old, Context); // Merge the types. MergeVarDeclTypes(New, Old); @@ -1664,12 +2131,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, - DeclSpec &DS) { - // FIXME: Error on inline/virtual/explicit - // FIXME: Warn on useless __thread - // FIXME: Warn on useless const/volatile - // FIXME: Warn on useless static/extern/typedef/private_extern/mutable - // FIXME: Warn on useless attributes + DeclSpec &DS) { Decl *TagD = 0; TagDecl *Tag = 0; if (DS.getTypeSpecType() == DeclSpec::TST_class || @@ -1703,6 +2165,10 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return 0; return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0)); } + + // Track whether we warned about the fact that there aren't any + // declarators. + bool emittedWarning = false; if (RecordDecl *Record = dyn_cast_or_null(Tag)) { ProcessDeclAttributeList(S, Record, DS.getAttributes().getList()); @@ -1715,6 +2181,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) << DS.getSourceRange(); + emittedWarning = true; } } @@ -1740,12 +2207,16 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DS.getStorageClassSpec() != DeclSpec::SCS_typedef) if (EnumDecl *Enum = dyn_cast_or_null(Tag)) if (Enum->enumerator_begin() == Enum->enumerator_end() && - !Enum->getIdentifier() && !Enum->isInvalidDecl()) + !Enum->getIdentifier() && !Enum->isInvalidDecl()) { Diag(Enum->getLocation(), diag::ext_no_declarators) << DS.getSourceRange(); + emittedWarning = true; + } + + // Skip all the checks below if we have a type error. + if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD; - if (!DS.isMissingDeclaratorOk() && - DS.getTypeSpecType() != DeclSpec::TST_error) { + if (!DS.isMissingDeclaratorOk()) { // Warn about typedefs of enums without names, since this is an // extension in both Microsoft and GNU. if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef && @@ -1757,8 +2228,41 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) << DS.getSourceRange(); + emittedWarning = true; } + // We're going to complain about a bunch of spurious specifiers; + // only do this if we're declaring a tag, because otherwise we + // should be getting diag::ext_no_declarators. + if (emittedWarning || (TagD && TagD->isInvalidDecl())) + return TagD; + + // Note that a linkage-specification sets a storage class, but + // 'extern "C" struct foo;' is actually valid and not theoretically + // useless. + if (DeclSpec::SCS scs = DS.getStorageClassSpec()) + if (!DS.isExternInLinkageSpec()) + Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier) + << DeclSpec::getSpecifierName(scs); + + if (DS.isThreadSpecified()) + Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread"; + if (DS.getTypeQualifiers()) { + if (DS.getTypeQualifiers() & DeclSpec::TQ_const) + Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) + Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile"; + // Restrict is covered above. + } + if (DS.isInlineSpecified()) + Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline"; + if (DS.isVirtualSpecified()) + Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual"; + if (DS.isExplicitSpecified()) + Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit"; + + // FIXME: Warn on useless attributes + return TagD; } @@ -2062,7 +2566,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Create a declaration for this anonymous struct/union. NamedDecl *Anon = 0; if (RecordDecl *OwningClass = dyn_cast(Owner)) { - Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(), + Anon = FieldDecl::Create(Context, OwningClass, + DS.getSourceRange().getBegin(), + Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, @@ -2086,8 +2592,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, VarDecl::StorageClass SCAsWritten = StorageClassSpecToVarDeclStorageClass(SCSpec); - Anon = VarDecl::Create(Context, Owner, Record->getLocation(), - /*IdentifierInfo=*/0, + Anon = VarDecl::Create(Context, Owner, + DS.getSourceRange().getBegin(), + Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, SC, SCAsWritten); } @@ -2151,6 +2658,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, NamedDecl* Anon = FieldDecl::Create(Context, cast(CurContext), DS.getSourceRange().getBegin(), + DS.getSourceRange().getBegin(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, @@ -2379,6 +2887,26 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false); } +/// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: +/// If T is the name of a class, then each of the following shall have a +/// name different from T: +/// - every static data member of class T; +/// - every member function of class T +/// - every member of class T that is itself a type; +/// \returns true if the declaration name violates these rules. +bool Sema::DiagnoseClassNameShadow(DeclContext *DC, + DeclarationNameInfo NameInfo) { + DeclarationName Name = NameInfo.getName(); + + if (CXXRecordDecl *Record = dyn_cast(DC)) + if (Record->getIdentifier() && Record->getDeclName() == Name) { + Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name; + return true; + } + + return false; +} + Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition) { @@ -2466,23 +2994,12 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, D.setInvalidType(); } } - - // C++ [class.mem]p13: - // If T is the name of a class, then each of the following shall have a - // name different from T: - // - every static data member of class T; - // - every member function of class T - // - every member of class T that is itself a type; - if (CXXRecordDecl *Record = dyn_cast(DC)) - if (Record->getIdentifier() && Record->getDeclName() == Name) { - Diag(D.getIdentifierLoc(), diag::err_member_name_of_class) - << Name; - - // If this is a typedef, we'll end up spewing multiple diagnostics. - // Just return early; it's safer. - if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - return 0; - } + + if (DiagnoseClassNameShadow(DC, NameInfo)) + // If this is a typedef, we'll end up spewing multiple diagnostics. + // Just return early; it's safer. + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + return 0; NamedDecl *New; @@ -2777,6 +3294,15 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewTD, D); + return ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration); +} + +/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which +/// declares a typedef-name, either using the 'typedef' type specifier or via +/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. +NamedDecl* +Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, + LookupResult &Previous, bool &Redeclaration) { // C99 6.7.7p2: If a typedef name specifies a variably modified type // then it shall have block scope. // Note that variably modified types must be fixed before merging the decl so @@ -2792,18 +3318,17 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, Oversized); if (!FixedTy.isNull()) { - Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size); + Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size); NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy)); } else { if (SizeIsNegative) - Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size); + Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size); else if (T->isVariableArrayType()) - Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope); + Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope); else if (Oversized.getBoolValue()) - Diag(D.getIdentifierLoc(), diag::err_array_too_large) - << Oversized.toString(10); + Diag(NewTD->getLocation(), diag::err_array_too_large) << Oversized.toString(10); else - Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope); + Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope); NewTD->setInvalidDecl(); } } @@ -2811,10 +3336,11 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Merge the decl with the existing one if appropriate. If the decl is // in an outer scope, it isn't the same thing. - FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false); + FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false, + /*ExplicitInstantiationOrSpecialization=*/false); if (!Previous.empty()) { Redeclaration = true; - MergeTypeDefDecl(NewTD, Previous); + MergeTypedefNameDecl(NewTD, Previous); } // If this is the C FILE type, notify the AST context. @@ -2952,8 +3478,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool isExplicitSpecialization = false; VarDecl *NewVD; if (!getLangOptions().CPlusPlus) { - NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), - II, R, TInfo, SC, SCAsWritten); + NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + R, TInfo, SC, SCAsWritten); if (D.isInvalidType()) NewVD->setInvalidDecl(); @@ -2988,7 +3515,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TemplateParamLists.size(); bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( @@ -2999,9 +3525,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, /*never a friend*/ false, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - if (TemplateParams->size() > 0) { // There is no such thing as a variable template. Diag(D.getIdentifierLoc(), diag::err_template_variable) @@ -3017,13 +3540,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, << II << SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc()); - isExplicitSpecialization = true; } } - NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), - II, R, TInfo, SC, SCAsWritten); + NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + R, TInfo, SC, SCAsWritten); // If this decl has an auto type in need of deduction, make a note of the // Decl so we can diagnose uses of it in its own initializer. @@ -3036,9 +3559,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, SetNestedNameSpecifier(NewVD, D); - if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { + if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) { NewVD->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParamLists.size(), TemplateParamLists.release()); } } @@ -3092,7 +3615,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Don't consider existing declarations that are in a different // scope and are out-of-semantic-context declarations (if the new // declaration has linkage). - FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage()); + FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage(), + isExplicitSpecialization); if (!getLangOptions().CPlusPlus) CheckVariableDeclaration(NewVD, Previous, Redeclaration); @@ -3169,10 +3693,11 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { return; // Don't diagnose declarations at file scope. - DeclContext *NewDC = D->getDeclContext(); - if (NewDC->isFileContext()) + if (D->hasGlobalStorage()) return; - + + DeclContext *NewDC = D->getDeclContext(); + // Only diagnose if we're shadowing an unambiguous field or variable. if (R.getResultKind() != LookupResult::Found) return; @@ -3189,17 +3714,6 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { if (VarDecl *shadowedVar = dyn_cast(ShadowedDecl)) if (shadowedVar->isExternC()) { - // Don't warn for this case: - // - // @code - // extern int bob; - // void f() { - // extern int bob; - // } - // @endcode - if (D->isExternC()) - return; - // For shadowing external vars, make sure that we point to the global // declaration, not a locally scoped extern declaration. for (VarDecl::redecl_iterator @@ -3528,8 +4042,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, FunctionTemplateDecl *FunctionTemplate = 0; bool isExplicitSpecialization = false; bool isFunctionTemplateSpecialization = false; - unsigned NumMatchedTemplateParamLists = 0; - + if (!getLangOptions().CPlusPlus) { // Determine whether the function was written with a // prototype. This true when: @@ -3540,7 +4053,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (!isa(R.getTypePtr()) && R->isFunctionProtoType()); - NewFD = FunctionDecl::Create(Context, DC, + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), NameInfo, R, TInfo, SC, SCAsWritten, isInline, HasPrototype); if (D.isInvalidType()) @@ -3549,7 +4062,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Set the lexical context. NewFD->setLexicalDeclContext(CurContext); // Filter out previous declarations that don't match the scope. - FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage()); + FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(), + /*ExplicitInstantiationOrSpecialization=*/false); } else { isFriend = D.getDeclSpec().isFriendSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); @@ -3566,14 +4080,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, AbstractReturnType)) D.setInvalidType(); - - if (isFriend) { - // C++ [class.friend]p5 - // A function can be defined in a friend declaration of a - // class . . . . Such a function is implicitly inline. - isInline |= IsFunctionDefinition; - } - if (Name.getNameKind() == DeclarationName::CXXConstructorName) { // This is a C++ constructor declaration. assert(DC->isRecord() && @@ -3584,6 +4090,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Create the new declaration NewFD = CXXConstructorDecl::Create(Context, cast(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false); @@ -3594,6 +4101,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewFD = CXXDestructorDecl::Create(Context, cast(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, isInline, /*isImplicitlyDeclared=*/false); @@ -3603,8 +4111,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Create a FunctionDecl to satisfy the function definition parsing // code path. - NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(), - Name, R, TInfo, SC, SCAsWritten, isInline, + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), Name, R, TInfo, + SC, SCAsWritten, isInline, /*hasPrototype=*/true); D.setInvalidType(); } @@ -3617,8 +4126,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, CheckConversionDeclarator(D, R, SC); NewFD = CXXConversionDecl::Create(Context, cast(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, - isInline, isExplicit); + isInline, isExplicit, + SourceLocation()); isVirtualOkay = true; } else if (DC->isRecord()) { @@ -3636,7 +4147,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } bool isStatic = SC == SC_Static; - + // [class.free]p1: // Any allocation function for a class T is a static member // (even if not explicitly declared static). @@ -3649,25 +4160,34 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Name.getCXXOverloadedOperator() == OO_Delete || Name.getCXXOverloadedOperator() == OO_Array_Delete) isStatic = true; - + // This is a C++ method declaration. NewFD = CXXMethodDecl::Create(Context, cast(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, - isStatic, SCAsWritten, isInline); + isStatic, SCAsWritten, isInline, + SourceLocation()); isVirtualOkay = !isStatic; } else { // Determine whether the function was written with a // prototype. This true when: // - we're in C++ (where every function has a prototype), - NewFD = FunctionDecl::Create(Context, DC, + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), NameInfo, R, TInfo, SC, SCAsWritten, isInline, true/*HasPrototype*/); } + + if (isFriend && !isInline && IsFunctionDefinition) { + // C++ [class.friend]p5 + // A function can be defined in a friend declaration of a + // class . . . . Such a function is implicitly inline. + NewFD->setImplicitlyInline(); + } + SetNestedNameSpecifier(NewFD, D); isExplicitSpecialization = false; isFunctionTemplateSpecialization = false; - NumMatchedTemplateParamLists = TemplateParamLists.size(); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -3680,7 +4200,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // determine whether we have a template or a template specialization. bool Invalid = false; if (TemplateParameterList *TemplateParams - = MatchTemplateParametersToScopeSpecifier( + = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getSourceRange().getBegin(), D.getCXXScopeSpec(), TemplateParamLists.get(), @@ -3688,54 +4208,71 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isFriend, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; + if (TemplateParams->size() > 0) { + // This is a function template - if (TemplateParams->size() > 0) { - // This is a function template + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return 0; - // Check that we can declare a template here. - if (CheckTemplateDeclScope(S, TemplateParams)) - return 0; - - FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, - NewFD->getLocation(), - Name, TemplateParams, - NewFD); - FunctionTemplate->setLexicalDeclContext(CurContext); - NewFD->setDescribedFunctionTemplate(FunctionTemplate); - } else { - // This is a function template specialization. - isFunctionTemplateSpecialization = true; - - // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". - if (isFriend && isFunctionTemplateSpecialization) { - // We want to remove the "template<>", found here. - SourceRange RemoveRange = TemplateParams->getSourceRange(); - - // If we remove the template<> and the name is not a - // template-id, we're actually silently creating a problem: - // the friend declaration will refer to an untemplated decl, - // and clearly the user wants a template specialization. So - // we need to insert '<>' after the name. - SourceLocation InsertLoc; - if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { - InsertLoc = D.getName().getSourceRange().getEnd(); - InsertLoc = PP.getLocForEndOfToken(InsertLoc); - } - - Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) - << Name << RemoveRange - << FixItHint::CreateRemoval(RemoveRange) - << FixItHint::CreateInsertion(InsertLoc, "<>"); - } - } + // A destructor cannot be a template. + if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + Diag(NewFD->getLocation(), diag::err_destructor_template); + return 0; } - if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { - NewFD->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, - TemplateParamLists.release()); + FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, + NewFD->getLocation(), + Name, TemplateParams, + NewFD); + FunctionTemplate->setLexicalDeclContext(CurContext); + NewFD->setDescribedFunctionTemplate(FunctionTemplate); + + // For source fidelity, store the other template param lists. + if (TemplateParamLists.size() > 1) { + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size() - 1, + TemplateParamLists.release()); + } + } else { + // This is a function template specialization. + isFunctionTemplateSpecialization = true; + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); + + // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". + if (isFriend) { + // We want to remove the "template<>", found here. + SourceRange RemoveRange = TemplateParams->getSourceRange(); + + // If we remove the template<> and the name is not a + // template-id, we're actually silently creating a problem: + // the friend declaration will refer to an untemplated decl, + // and clearly the user wants a template specialization. So + // we need to insert '<>' after the name. + SourceLocation InsertLoc; + if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + InsertLoc = D.getName().getSourceRange().getEnd(); + InsertLoc = PP.getLocForEndOfToken(InsertLoc); + } + + Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) + << Name << RemoveRange + << FixItHint::CreateRemoval(RemoveRange) + << FixItHint::CreateInsertion(InsertLoc, "<>"); + } + } + } + else { + // All template param lists were matched against the scope specifier: + // this is NOT (an explicit specialization of) a template. + if (TemplateParamLists.size() > 0) + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); } if (Invalid) { @@ -3802,7 +4339,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } // Filter out previous declarations that don't match the scope. - FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage()); + FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(), + isExplicitSpecialization || + isFunctionTemplateSpecialization); if (isFriend) { // For now, claim that the objects have no previous declaration. @@ -3863,8 +4402,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // In C++, the empty parameter-type-list must be spelled "void"; a // typedef of void is not permitted. if (getLangOptions().CPlusPlus && - Param->getType().getUnqualifiedType() != Context.VoidTy) - Diag(Param->getLocation(), diag::err_param_typedef_of_void); + Param->getType().getUnqualifiedType() != Context.VoidTy) { + bool IsTypeAlias = false; + if (const TypedefType *TT = Param->getType()->getAs()) + IsTypeAlias = isa(TT->getDecl()); + Diag(Param->getLocation(), diag::err_param_typedef_of_void) + << IsTypeAlias; + } } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) { for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { ParmVarDecl *Param = cast(FTI.ArgInfo[i].Param); @@ -3892,6 +4436,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, AE = FT->arg_type_end(); AI != AE; ++AI) { ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI); + Param->setScopeInfo(0, Params.size()); Params.push_back(Param); } } else { @@ -3977,9 +4522,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Previous)) NewFD->setInvalidDecl(); } else if (isFunctionTemplateSpecialization) { - if (CheckFunctionTemplateSpecialization(NewFD, - (HasExplicitTemplateArgs ? &TemplateArgs : 0), - Previous)) + if (CurContext->isDependentContext() && CurContext->isRecord() + && !isFriend) { + Diag(NewFD->getLocation(), diag::err_function_specialization_in_class) + << NewFD->getDeclName(); + NewFD->setInvalidDecl(); + return 0; + } else if (CheckFunctionTemplateSpecialization(NewFD, + (HasExplicitTemplateArgs ? &TemplateArgs : 0), + Previous)) NewFD->setInvalidDecl(); } else if (isExplicitSpecialization && isa(NewFD)) { if (CheckMemberSpecialization(NewFD, Previous)) @@ -4049,7 +4600,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // are situations where these conditions don't apply and we // can actually do this check immediately. if (isFriend && - (NumMatchedTemplateParamLists || + (TemplateParamLists.size() || D.getCXXScopeSpec().getScopeRep()->isDependent() || CurContext->isDependentContext())) { // ignore these @@ -4146,7 +4697,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, RegisterLocallyScopedExternCDecl(NewFD, Previous, S); // Set this FunctionDecl's range up to the right paren. - NewFD->setLocEnd(D.getSourceRange().getEnd()); + NewFD->setRangeEnd(D.getSourceRange().getEnd()); if (getLangOptions().CPlusPlus) { if (FunctionTemplate) { @@ -4420,8 +4971,7 @@ void Sema::CheckMain(FunctionDecl* FD) { // Darwin passes an undocumented fourth argument of type char**. If // other platforms start sprouting these, the logic below will start // getting shifty. - if (nparams == 4 && - Context.Target.getTriple().getOS() == llvm::Triple::Darwin) + if (nparams == 4 && Context.Target.getTriple().isOSDarwin()) HasExtraParameters = false; if (HasExtraParameters) { @@ -4493,6 +5043,46 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { return true; } +namespace { + // Visits an initialization expression to see if OrigDecl is evaluated in + // its own initialization and throws a warning if it does. + class SelfReferenceChecker + : public EvaluatedExprVisitor { + Sema &S; + Decl *OrigDecl; + + public: + typedef EvaluatedExprVisitor Inherited; + + SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context), + S(S), OrigDecl(OrigDecl) { } + + void VisitExpr(Expr *E) { + if (isa(*E)) return; + Inherited::VisitExpr(E); + } + + void VisitImplicitCastExpr(ImplicitCastExpr *E) { + CheckForSelfReference(E); + Inherited::VisitImplicitCastExpr(E); + } + + void CheckForSelfReference(ImplicitCastExpr *E) { + if (E->getCastKind() != CK_LValueToRValue) return; + Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts(); + DeclRefExpr *DRE = dyn_cast(SubExpr); + if (!DRE) return; + Decl* ReferenceDecl = DRE->getDecl(); + if (OrigDecl != ReferenceDecl) return; + LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName, + Sema::NotForRedeclaration); + S.Diag(SubExpr->getLocStart(), diag::warn_uninit_self_reference_in_init) + << Result.getLookupName() << OrigDecl->getLocation() + << SubExpr->getSourceRange(); + } + }; +} + /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. @@ -4503,6 +5093,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (RealDecl == 0 || RealDecl->isInvalidDecl()) return; + // Check for self-references within variable initializers. + if (VarDecl *vd = dyn_cast(RealDecl)) { + // Variables declared within a function/method body are handled + // by a dataflow analysis. + if (!vd->hasLocalStorage() && !vd->isStaticLocal()) + SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + } + else { + SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + } + if (CXXMethodDecl *Method = dyn_cast(RealDecl)) { // With declarators parsed the way they are, the parser cannot // distinguish between a normal initializer and a pure-specifier. @@ -4533,15 +5134,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { - QualType DeducedType; - if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) { + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) << VDecl->getDeclName() << VDecl->getType() << Init->getType() << Init->getSourceRange(); + if (!DeducedType) { RealDecl->setInvalidDecl(); return; } - VDecl->setType(DeducedType); + VDecl->setTypeSourceInfo(DeducedType); + VDecl->setType(DeducedType->getType()); // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. @@ -4952,7 +5555,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, const RecordType *Record = Context.getBaseElementType(Type)->getAs(); - if (Record && getLangOptions().CPlusPlus && !getLangOptions().CPlusPlus0x && + if (Record && getLangOptions().CPlusPlus && cast(Record->getDecl())->isPOD()) { // C++03 [dcl.init]p9: // If no initializer is specified for an object, and the @@ -4965,7 +5568,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, // any, have an indeterminate initial value); if the object // or any of its subobjects are of const-qualified type, the // program is ill-formed. - // FIXME: DPG thinks it is very fishy that C++0x disables this. } else { // Check for jumps past the implicit initializer. C++0x // clarifies that this applies to a "variable with automatic @@ -4990,6 +5592,47 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, } } +void Sema::ActOnCXXForRangeDecl(Decl *D) { + VarDecl *VD = dyn_cast(D); + if (!VD) { + Diag(D->getLocation(), diag::err_for_range_decl_must_be_var); + D->setInvalidDecl(); + return; + } + + VD->setCXXForRangeDecl(true); + + // for-range-declaration cannot be given a storage class specifier. + int Error = -1; + switch (VD->getStorageClassAsWritten()) { + case SC_None: + break; + case SC_Extern: + Error = 0; + break; + case SC_Static: + Error = 1; + break; + case SC_PrivateExtern: + Error = 2; + break; + case SC_Auto: + Error = 3; + break; + case SC_Register: + Error = 4; + break; + } + // FIXME: constexpr isn't allowed here. + //if (DS.isConstexprSpecified()) + // Error = 5; + if (Error != -1) { + Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class) + << VD->getDeclName() << Error; + D->setInvalidDecl(); + } +} + void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (var->isInvalidDecl()) return; @@ -5058,7 +5701,7 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (Decl *D = Group[i]) Decls.push_back(D); - return BuildDeclaratorGroup(Decls.data(), Decls.size(), + return BuildDeclaratorGroup(Decls.data(), Decls.size(), DS.getTypeSpecType() == DeclSpec::TST_auto); } @@ -5195,12 +5838,18 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // the enclosing context. This prevents them from accidentally // looking like class members in C++. ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), - TInfo, parmDeclType, II, - D.getIdentifierLoc(), + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + parmDeclType, TInfo, StorageClass, StorageClassAsWritten); if (D.isInvalidType()) - New->setInvalidDecl(); + New->setInvalidDecl(); + + assert(S->isFunctionPrototypeScope()); + assert(S->getFunctionPrototypeDepth() >= 1); + New->setScopeInfo(S->getFunctionPrototypeDepth() - 1, + S->getNextFunctionPrototypeIndex()); // Add the parameter declaration into this scope. S->AddDecl(New); @@ -5220,7 +5869,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T) { - ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0, + /* FIXME: setting StartLoc == Loc. + Would it be worth to modify callers so as to provide proper source + location for the unnamed parameters, embedding the parameter's type? */ + ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0, T, Context.getTrivialTypeSourceInfo(T, Loc), SC_None, SC_None, 0); Param->setImplicit(); @@ -5272,14 +5924,13 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, } } -ParmVarDecl *Sema::CheckParameter(DeclContext *DC, - TypeSourceInfo *TSInfo, QualType T, - IdentifierInfo *Name, - SourceLocation NameLoc, +ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, + SourceLocation NameLoc, IdentifierInfo *Name, + QualType T, TypeSourceInfo *TSInfo, VarDecl::StorageClass StorageClass, VarDecl::StorageClass StorageClassAsWritten) { - ParmVarDecl *New = ParmVarDecl::Create(Context, DC, NameLoc, Name, - adjustParameterType(T), TSInfo, + ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, + adjustParameterType(T), TSInfo, StorageClass, StorageClassAsWritten, 0); @@ -5331,7 +5982,8 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, // Implicitly declare the argument as type 'int' for lack of a better // type. - DeclSpec DS; + AttributeFactory attrs; + DeclSpec DS(attrs); const char* PrevSpec; // unused unsigned DiagID; // unused DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, @@ -5374,7 +6026,7 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { return false; // Don't warn about inline functions. - if (FD->isInlineSpecified()) + if (FD->isInlined()) return false; // Don't warn about function templates. @@ -5400,6 +6052,22 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { return MissingPrototype; } +void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) { + // Don't complain if we're in GNU89 mode and the previous definition + // was an extern inline function. + const FunctionDecl *Definition; + if (FD->hasBody(Definition) && + !canRedefineFunction(Definition, getLangOptions())) { + if (getLangOptions().GNUMode && Definition->isInlineSpecified() && + Definition->getStorageClass() == SC_Extern) + Diag(FD->getLocation(), diag::err_redefinition_extern_inline) + << FD->getDeclName() << getLangOptions().CPlusPlus; + else + Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); + Diag(Definition->getLocation(), diag::note_previous_definition); + } +} + Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // Clear the last template instantiation error context. LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); @@ -5417,19 +6085,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { PushFunctionScope(); // See if this is a redefinition. - // But don't complain if we're in GNU89 mode and the previous definition - // was an extern inline function. - const FunctionDecl *Definition; - if (FD->hasBody(Definition) && - !canRedefineFunction(Definition, getLangOptions())) { - if (getLangOptions().GNUMode && Definition->isInlineSpecified() && - Definition->getStorageClass() == SC_Extern) - Diag(FD->getLocation(), diag::err_redefinition_extern_inline) - << FD->getDeclName() << getLangOptions().CPlusPlus; - else - Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); - Diag(Definition->getLocation(), diag::note_previous_definition); - } + if (!FD->isLateTemplateParsed()) + CheckForFunctionRedefinition(FD); // Builtin functions cannot be defined. if (unsigned BuiltinID = FD->getBuiltinID()) { @@ -5481,7 +6138,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { DLLImportAttr *DA = FD->getAttr(); if (DA && (!FD->getAttr())) { // dllimport attribute cannot be directly applied to definition. - if (!DA->isInherited()) { + // Microsoft accepts dllimport for functions defined within class scope. + if (!DA->isInherited() && + !(LangOpts.Microsoft && FD->getLexicalDeclContext()->isRecord())) { Diag(FD->getLocation(), diag::err_attribute_can_be_applied_only_to_symbol_declaration) << "dllimport"; @@ -5615,7 +6274,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. - if (PP.getDiagnostics().hasErrorOccurred()) + if (PP.getDiagnostics().hasErrorOccurred() || + PP.getDiagnostics().getSuppressAllDiagnostics()) ExprTemporaries.clear(); else if (!isa(dcl)) { // Since the body is valid, issue any analysis-based warnings that are @@ -5666,17 +6326,18 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, // Set a Declarator for the implicit definition: int foo(); const char *Dummy; - DeclSpec DS; + AttributeFactory attrFactory; + DeclSpec DS(attrFactory); unsigned DiagID; bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID); (void)Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); Declarator D(DS, Declarator::BlockContext); - D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(), - false, false, SourceLocation(), 0, + D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0, 0, 0, true, SourceLocation(), - false, SourceLocation(), - false, 0,0,0, Loc, Loc, D), + EST_None, SourceLocation(), + 0, 0, 0, 0, Loc, Loc, D), + DS.getAttributes(), SourceLocation()); D.SetIdentifier(&II, Loc); @@ -5784,6 +6445,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, // Scope manipulation handled by caller. TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, + D.getSourceRange().getBegin(), D.getIdentifierLoc(), D.getIdentifier(), TInfo); @@ -5810,7 +6472,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, // Do nothing if the tag is not anonymous or already has an // associated typedef (from an earlier typedef in this decl group). if (tagFromDeclSpec->getIdentifier()) break; - if (tagFromDeclSpec->getTypedefForAnonDecl()) break; + if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break; // A well-formed anonymous tag must always be a TUK_Definition. assert(tagFromDeclSpec->isThisDeclarationADefinition()); @@ -5820,7 +6482,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, break; // Otherwise, set this is the anon-decl typedef for the tag. - tagFromDeclSpec->setTypedefForAnonDecl(NewTD); + tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); break; } @@ -5897,36 +6559,33 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: Check explicit specializations more carefully. bool isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); bool Invalid = false; // We only need to do this matching if we have template parameters // or a scope specifier, which also conveniently avoids this work // for non-C++ cases. - if (NumMatchedTemplateParamLists || + if (TemplateParameterLists.size() > 0 || (SS.isNotEmpty() && TUK != TUK_Reference)) { if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(KWLoc, SS, TemplateParameterLists.get(), - TemplateParameterLists.size(), + TemplateParameterLists.size(), TUK == TUK_Friend, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - if (TemplateParams->size() > 0) { // This is a declaration or definition of a class template (which may // be a member of another template). + if (Invalid) return 0; - + OwnedDecl = false; DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attr, - TemplateParams, - AS); - TemplateParameterLists.release(); + TemplateParams, AS, + TemplateParameterLists.size() - 1, + (TemplateParameterList**) TemplateParameterLists.release()); return Result.get(); } else { // The "template<>" header is extraneous. @@ -6164,7 +6823,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // okay according to the likely resolution of an open issue; // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 if (getLangOptions().CPlusPlus) { - if (TypedefDecl *TD = dyn_cast(PrevDecl)) { + if (TypedefNameDecl *TD = dyn_cast(PrevDecl)) { if (const TagType *TT = TD->getUnderlyingType()->getAs()) { TagDecl *Tag = TT->getDecl(); if (Tag->getDeclName() == Name && @@ -6184,7 +6843,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // in the same scope (so that the definition/declaration completes or // rementions the tag), reuse the decl. if (TUK == TUK_Reference || TUK == TUK_Friend || - isDeclInScope(PrevDecl, SearchDC, S)) { + isDeclInScope(PrevDecl, SearchDC, S, isExplicitSpecialization)) { // Make sure that this wasn't declared as an enum and now used as a // struct or something similar. if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, KWLoc, *Name)) { @@ -6322,30 +6981,34 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, !Previous.isForRedeclaration()) { unsigned Kind = 0; if (isa(PrevDecl)) Kind = 1; - else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 3; Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind; Diag(PrevDecl->getLocation(), diag::note_declared_at); Invalid = true; // Otherwise, only diagnose if the declaration is in scope. - } else if (!isDeclInScope(PrevDecl, SearchDC, S)) { + } else if (!isDeclInScope(PrevDecl, SearchDC, S, + isExplicitSpecialization)) { // do nothing // Diagnose implicit declarations introduced by elaborated types. } else if (TUK == TUK_Reference || TUK == TUK_Friend) { unsigned Kind = 0; if (isa(PrevDecl)) Kind = 1; - else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 3; Diag(NameLoc, diag::err_tag_reference_conflict) << Kind; Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; // Otherwise it's a declaration. Call out a particularly common // case here. - } else if (isa(PrevDecl)) { + } else if (TypedefNameDecl *TND = dyn_cast(PrevDecl)) { + unsigned Kind = 0; + if (isa(PrevDecl)) Kind = 1; Diag(NameLoc, diag::err_tag_definition_of_typedef) - << Name - << cast(PrevDecl)->getUnderlyingType(); + << Name << Kind << TND->getUnderlyingType(); Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; @@ -6385,7 +7048,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Kind == TTK_Enum) { // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // enum X { A, B, C } D; D should chain to X. - New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc, + New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, cast_or_null(PrevDecl), ScopedEnum, ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); // If this is an undefined enum, warn. @@ -6431,13 +7094,13 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // struct X { int A; } D; D should chain to X. if (getLangOptions().CPlusPlus) { // FIXME: Look for a way to use RecordDecl for simple structs. - New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, + New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, cast_or_null(PrevDecl)); - + if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit())) StdBadAlloc = cast(New); } else - New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, + New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, cast_or_null(PrevDecl)); } @@ -6445,9 +7108,9 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (SS.isNotEmpty()) { if (SS.isSet()) { New->setQualifierInfo(SS.getWithLocInContext(Context)); - if (NumMatchedTemplateParamLists > 0) { + if (TemplateParameterLists.size() > 0) { New->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size(), (TemplateParameterList**) TemplateParameterLists.release()); } } @@ -6466,6 +7129,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // the #pragma tokens are effectively skipped over during the // parsing of the struct). AddAlignmentAttributesForRecord(RD); + + AddMsStructLayoutForRecord(RD); } // If this is a specialization of a member class (of a class template), @@ -6541,7 +7206,7 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { } void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, - ClassVirtSpecifiers &CVS, + SourceLocation FinalLoc, SourceLocation LBraceLoc) { AdjustDeclIfTemplate(TagD); CXXRecordDecl *Record = cast(TagD); @@ -6551,10 +7216,8 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, if (!Record->getIdentifier()) return; - if (CVS.isFinalSpecified()) - Record->addAttr(new (Context) FinalAttr(CVS.getFinalLoc(), Context)); - if (CVS.isExplicitSpecified()) - Record->addAttr(new (Context) ExplicitAttr(CVS.getExplicitLoc(), Context)); + if (FinalLoc.isValid()) + Record->addAttr(new (Context) FinalAttr(FinalLoc, Context)); // C++ [class]p2: // [...] The class-name is also inserted into the scope of the @@ -6562,10 +7225,9 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, // purposes of access checking, the injected-class-name is treated // as if it were a public member name. CXXRecordDecl *InjectedClassName - = CXXRecordDecl::Create(Context, Record->getTagKind(), - CurContext, Record->getLocation(), + = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext, + Record->getLocStart(), Record->getLocation(), Record->getIdentifier(), - Record->getTagKeywordLoc(), /*PrevDecl=*/0, /*DelayTypeCreation=*/true); Context.getTypeDeclType(InjectedClassName, Record); @@ -6852,7 +7514,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } } - FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, TInfo, + FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo, BitWidth, Mutable); if (InvalidDecl) NewFD->setInvalidDecl(); @@ -7152,8 +7814,8 @@ Decl *Sema::ActOnIvar(Scope *S, } // Construct the decl. - ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, - EnclosingContext, Loc, II, T, + ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext, + DeclStart, Loc, II, T, TInfo, ac, (Expr *)BitfieldWidth); if (II) { @@ -7216,7 +7878,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc); Ivar = ObjCIvarDecl::Create(Context, cast(EnclosingDecl), - DeclLoc, 0, + DeclLoc, DeclLoc, 0, Context.CharTy, Context.CreateTypeSourceInfo(Context.CharTy), ObjCIvarDecl::Private, BW, @@ -7281,20 +7943,27 @@ void Sema::ActOnFields(Scope* S, continue; } else if (FDTy->isIncompleteArrayType() && Record && ((i == NumFields - 1 && !Record->isUnion()) || - (getLangOptions().Microsoft && + ((getLangOptions().Microsoft || getLangOptions().CPlusPlus) && (i == NumFields - 1 || Record->isUnion())))) { // Flexible array member. - // Microsoft is more permissive regarding flexible array. + // Microsoft and g++ is more permissive regarding flexible array. // It will accept flexible array in union and also // as the sole element of a struct/class. if (getLangOptions().Microsoft) { if (Record->isUnion()) - Diag(FD->getLocation(), diag::ext_flexible_array_union) + Diag(FD->getLocation(), diag::ext_flexible_array_union_ms) << FD->getDeclName(); else if (NumFields == 1) - Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_ms) << FD->getDeclName() << Record->getTagKind(); - } else if (NumNamedMembers < 1) { + } else if (getLangOptions().CPlusPlus) { + if (Record->isUnion()) + Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu) + << FD->getDeclName(); + else if (NumFields == 1) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu) + << FD->getDeclName() << Record->getTagKind(); + } else if (NumNamedMembers < 1) { Diag(FD->getLocation(), diag::err_flexible_array_empty_struct) << FD->getDeclName(); FD->setInvalidDecl(); @@ -7547,7 +8216,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { // Force the type of the expression to 'int'. - ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast); + Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take(); } } @@ -7560,12 +8229,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) { if (getLangOptions().Microsoft) { Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy; - ImpCastExprToType(Val, EltTy, CK_IntegralCast); + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); } else Diag(IdLoc, diag::err_enumerator_too_large) << EltTy; } else - ImpCastExprToType(Val, EltTy, CK_IntegralCast); + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); } else { // C++0x [dcl.enum]p5: @@ -7949,11 +8618,14 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, NumPositiveBits, NumNegativeBits); } -Decl *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr) { +Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, + SourceLocation StartLoc, + SourceLocation EndLoc) { StringLiteral *AsmString = cast(expr); FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext, - Loc, AsmString); + AsmString, StartLoc, + EndLoc); CurContext->addDecl(New); return New; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index 893cf6ac26e4..7f93ab72d6d1 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -24,6 +24,26 @@ using namespace clang; using namespace sema; +/// These constants match the enumerated choices of +/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. +enum { + ExpectedFunction, + ExpectedUnion, + ExpectedVariableOrFunction, + ExpectedFunctionOrMethod, + ExpectedParameter, + ExpectedParameterOrMethod, + ExpectedFunctionMethodOrBlock, + ExpectedClassOrVirtualMethod, + ExpectedFunctionMethodOrParameter, + ExpectedClass, + ExpectedVirtualMethod, + ExpectedClassMember, + ExpectedVariable, + ExpectedMethod, + ExpectedVariableFunctionOrLabel +}; + //===----------------------------------------------------------------------===// // Helper functions //===----------------------------------------------------------------------===// @@ -35,7 +55,7 @@ static const FunctionType *getFunctionType(const Decl *d, Ty = decl->getType(); else if (const FieldDecl *decl = dyn_cast(d)) Ty = decl->getType(); - else if (const TypedefDecl* decl = dyn_cast(d)) + else if (const TypedefNameDecl* decl = dyn_cast(d)) Ty = decl->getUnderlyingType(); else return 0; @@ -81,8 +101,8 @@ static bool isFunctionOrMethodOrBlock(const Decl *d) { /// Return true if the given decl has a declarator that should have /// been processed by Sema::GetTypeForDeclarator. static bool hasDeclarator(const Decl *d) { - // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl. - return isa(d) || isa(d) || isa(d); + // In some sense, TypedefNameDecl really *ought* to be a DeclaratorDecl. + return isa(d) || isa(d) || isa(d); } /// hasFunctionProto - Return true if the given decl has a argument @@ -182,7 +202,7 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) { static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, const AttributeList &Attr, Sema &S) { - TypedefDecl *tDecl = dyn_cast(d); + TypedefNameDecl *tDecl = dyn_cast(d); if (tDecl == 0) { S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); return; @@ -241,6 +261,13 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } +static void HandleMsStructAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (TagDecl *TD = dyn_cast(d)) + TD->addAttr(::new (S.Context) MsStructAttr(Attr.getLoc(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() > 0) { @@ -332,7 +359,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { // ignore it as well if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -474,8 +501,8 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { } if (!isFunction(d) || !hasFunctionProto(d)) { - S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL.getName() - << 0 /*function*/; + S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) + << AL.getName() << ExpectedFunction; return; } @@ -615,7 +642,7 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa(d) && !isa(d)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variables and functions*/; + << Attr.getName() << ExpectedVariableOrFunction; return; } @@ -701,7 +728,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - if (S.Context.Target.getTriple().getOS() == llvm::Triple::Darwin) { + if (S.Context.Target.getTriple().isOSDarwin()) { S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); return; } @@ -722,7 +749,7 @@ static void HandleNakedAttr(Decl *d, const AttributeList &Attr, if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -732,14 +759,14 @@ static void HandleNakedAttr(Decl *d, const AttributeList &Attr, static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { // Check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -748,7 +775,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { // Check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -780,7 +807,7 @@ static void HandleNoCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) NoCommonAttr(Attr.getLoc(), S.Context)); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 12 /* variable */; + << Attr.getName() << ExpectedVariable; } static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -789,7 +816,7 @@ static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) CommonAttr(Attr.getLoc(), S.Context)); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 12 /* variable */; + << Attr.getName() << ExpectedVariable; } static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) { @@ -799,7 +826,7 @@ static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) { if (!isa(d)) { S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << 0 /*function*/; + << attr.getName() << ExpectedFunctionOrMethod; return; } @@ -807,7 +834,7 @@ static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) { } bool Sema::CheckNoReturnAttr(const AttributeList &attr) { - if (attr.getNumArgs() != 0) { + if (attr.hasParameterOrArguments()) { Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; attr.setInvalid(); return true; @@ -834,7 +861,7 @@ static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, S.Diag(Attr.getLoc(), Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type : diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } } @@ -870,7 +897,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, */ if (!isa(d)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) - << Attr.getName() << 9 /*class*/; + << Attr.getName() << ExpectedClass; return; } @@ -907,7 +934,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isFunctionOrMethod(d) && !isa(d)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) - << Attr.getName() << 8 /*function, method, or parameter*/; + << Attr.getName() << ExpectedFunctionMethodOrParameter; return; } // FIXME: Actually store the attribute on the declaration @@ -915,7 +942,7 @@ static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -923,7 +950,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa(d) && !isa(d) && !isFunctionOrMethod(d) && !isa(d) && !isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 14 /*variable, function, labels*/; + << Attr.getName() << ExpectedVariableFunctionOrLabel; return; } @@ -932,7 +959,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -944,7 +971,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { } } else if (!isFunctionOrMethod(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variable and function*/; + << Attr.getName() << ExpectedVariableOrFunction; return; } @@ -953,9 +980,8 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << "0 or 1"; + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } @@ -974,7 +1000,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -984,9 +1010,8 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << "0 or 1"; + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } @@ -1005,7 +1030,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -1016,8 +1041,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { unsigned NumArgs = Attr.getNumArgs(); if (NumArgs > 1) { - S.Diag(Attr.getLoc(), - diag::err_attribute_wrong_number_arguments) << "0 or 1"; + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } @@ -1039,8 +1063,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { unsigned NumArgs = Attr.getNumArgs(); if (NumArgs > 1) { - S.Diag(Attr.getLoc(), - diag::err_attribute_wrong_number_arguments) << "0 or 1"; + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } @@ -1058,6 +1081,59 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str)); } +static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + IdentifierInfo *Platform = Attr.getParameterName(); + SourceLocation PlatformLoc = Attr.getParameterLoc(); + + llvm::StringRef PlatformName + = AvailabilityAttr::getPrettyPlatformName(Platform->getName()); + if (PlatformName.empty()) { + S.Diag(PlatformLoc, diag::warn_availability_unknown_platform) + << Platform; + + PlatformName = Platform->getName(); + } + + AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); + AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); + AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); + bool IsUnavailable = Attr.getUnavailableLoc().isValid(); + + // Ensure that Introduced < Deprecated < Obsoleted (although not all + // of these steps are needed). + if (Introduced.isValid() && Deprecated.isValid() && + !(Introduced.Version < Deprecated.Version)) { + S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering) + << 1 << PlatformName << Deprecated.Version.getAsString() + << 0 << Introduced.Version.getAsString(); + return; + } + + if (Introduced.isValid() && Obsoleted.isValid() && + !(Introduced.Version < Obsoleted.Version)) { + S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering) + << 2 << PlatformName << Obsoleted.Version.getAsString() + << 0 << Introduced.Version.getAsString(); + return; + } + + if (Deprecated.isValid() && Obsoleted.isValid() && + !(Deprecated.Version < Obsoleted.Version)) { + S.Diag(Deprecated.KeywordLoc, diag::warn_availability_version_ordering) + << 2 << PlatformName << Obsoleted.Version.getAsString() + << 1 << Deprecated.Version.getAsString(); + return; + } + + d->addAttr(::new (S.Context) AvailabilityAttr(Attr.getLoc(), S.Context, + Platform, + Introduced.Version, + Deprecated.Version, + Obsoleted.Version, + IsUnavailable)); +} + static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 1) { @@ -1094,6 +1170,51 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type)); } +static void HandleObjCMethodFamilyAttr(Decl *decl, const AttributeList &attr, + Sema &S) { + ObjCMethodDecl *method = dyn_cast(decl); + if (!method) { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_decl_type) + << ExpectedMethod; + return; + } + + if (attr.getNumArgs() != 0 || !attr.getParameterName()) { + if (!attr.getParameterName() && attr.getNumArgs() == 1) { + S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "objc_method_family" << 1; + } else { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + } + attr.setInvalid(); + return; + } + + llvm::StringRef param = attr.getParameterName()->getName(); + ObjCMethodFamilyAttr::FamilyKind family; + if (param == "none") + family = ObjCMethodFamilyAttr::OMF_None; + else if (param == "alloc") + family = ObjCMethodFamilyAttr::OMF_alloc; + else if (param == "copy") + family = ObjCMethodFamilyAttr::OMF_copy; + else if (param == "init") + family = ObjCMethodFamilyAttr::OMF_init; + else if (param == "mutableCopy") + family = ObjCMethodFamilyAttr::OMF_mutableCopy; + else if (param == "new") + family = ObjCMethodFamilyAttr::OMF_new; + else { + // Just warn and ignore it. This is future-proof against new + // families being used in system headers. + S.Diag(attr.getParameterLoc(), diag::warn_unknown_method_family); + return; + } + + decl->addAttr(new (S.Context) ObjCMethodFamilyAttr(attr.getLoc(), + S.Context, family)); +} + static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, Sema &S) { if (Attr.getNumArgs() != 0) { @@ -1115,7 +1236,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; } - if (TypedefDecl *TD = dyn_cast(D)) { + if (TypedefNameDecl *TD = dyn_cast(D)) { QualType T = TD->getUnderlyingType(); if (!T->isPointerType() || !T->getAs()->getPointeeType()->isRecordType()) { @@ -1168,8 +1289,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() > 2) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << "0, 1 or 2"; + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; return; } @@ -1247,12 +1367,12 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { } } else { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 6 /*function, method or block */; + << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } } else { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 6 /*function, method or block */; + << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, @@ -1268,7 +1388,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) if (!isFunction(D) && !isa(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunctionOrMethod; return; } @@ -1289,14 +1409,14 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) static void HandleWeakAttr(Decl *d, const AttributeList &attr, Sema &S) { // check the attribute arguments. - if (attr.getNumArgs() != 0) { + if (attr.hasParameterOrArguments()) { S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } if (!isa(d) && !isa(d)) { S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << 2 /*variables and functions*/; + << attr.getName() << ExpectedVariableOrFunction; return; } @@ -1320,27 +1440,19 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // weak_import only applies to variable & function declarations. bool isDef = false; - if (VarDecl *VD = dyn_cast(D)) { - isDef = (!VD->hasExternalStorage() || VD->getInit()); - } else if (FunctionDecl *FD = dyn_cast(D)) { - isDef = FD->hasBody(); - } else if (isa(D) || isa(D)) { - // We ignore weak import on properties and methods - return; - } else if (!(S.LangOpts.ObjCNonFragileABI && isa(D))) { - // Don't issue the warning for darwin as target; yet, ignore the attribute. - if (S.Context.Target.getTriple().getOS() != llvm::Triple::Darwin || - !isa(D)) + if (!D->canBeWeakImported(isDef)) { + if (isDef) + S.Diag(Attr.getLoc(), + diag::warn_attribute_weak_import_invalid_on_definition) + << "weak_import" << 2 /*variable and function*/; + else if (isa(D) || isa(D) || + (S.Context.Target.getTriple().isOSDarwin() && + isa(D))) { + // Nothing to warn about here. + } else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variable and function*/; - return; - } + << Attr.getName() << ExpectedVariableOrFunction; - // Merge should handle any subsequent violations. - if (isDef) { - S.Diag(Attr.getLoc(), - diag::warn_attribute_weak_import_invalid_on_definition) - << "weak_import" << 2 /*variable and function*/; return; } @@ -1409,7 +1521,7 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -1419,7 +1531,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -1506,7 +1618,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { } if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -1674,7 +1786,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -1807,7 +1919,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, // Try to find the underlying union declaration. RecordDecl *RD = 0; - TypedefDecl *TD = dyn_cast(d); + TypedefNameDecl *TD = dyn_cast(d); if (TD && TD->getUnderlyingType()->isUnionType()) RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); else @@ -1815,7 +1927,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, if (!RD || !RD->isUnion()) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 1 /*union*/; + << Attr.getName() << ExpectedUnion; return; } @@ -1998,7 +2110,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { } QualType OldTy; - if (TypedefDecl *TD = dyn_cast(D)) + if (TypedefNameDecl *TD = dyn_cast(D)) OldTy = TD->getUnderlyingType(); else if (ValueDecl *VD = dyn_cast(D)) OldTy = VD->getType(); @@ -2097,7 +2209,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { } // Install the new type. - if (TypedefDecl *TD = dyn_cast(D)) { + if (TypedefNameDecl *TD = dyn_cast(D)) { // FIXME: preserve existing source info. TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy)); } else @@ -2113,7 +2225,7 @@ static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isFunctionOrMethod(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2129,7 +2241,7 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2146,7 +2258,7 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2157,14 +2269,14 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, static void HandleConstantAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (S.LangOpts.CUDA) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 12 /*variable*/; + << Attr.getName() << ExpectedVariable; return; } @@ -2184,7 +2296,7 @@ static void HandleDeviceAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa(d) && !isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variable and function*/; + << Attr.getName() << ExpectedVariableOrFunction; return; } @@ -2204,7 +2316,7 @@ static void HandleGlobalAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2239,7 +2351,7 @@ static void HandleHostAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2259,7 +2371,7 @@ static void HandleSharedAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 12 /*variable*/; + << Attr.getName() << ExpectedVariable; return; } @@ -2279,7 +2391,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { FunctionDecl *Fn = dyn_cast(d); if (Fn == 0) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2302,7 +2414,7 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) { if (!isa(d)) { S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << 0 /*function*/; + << attr.getName() << ExpectedFunctionOrMethod; return; } @@ -2322,6 +2434,30 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) { case AttributeList::AT_pascal: d->addAttr(::new (S.Context) PascalAttr(attr.getLoc(), S.Context)); return; + case AttributeList::AT_pcs: { + Expr *Arg = attr.getArg(0); + StringLiteral *Str = dyn_cast(Arg); + if (Str == 0 || Str->isWide()) { + S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + attr.setInvalid(); + return; + } + + llvm::StringRef StrRef = Str->getString(); + PcsAttr::PCSType PCS; + if (StrRef == "aapcs") + PCS = PcsAttr::AAPCS; + else if (StrRef == "aapcs-vfp") + PCS = PcsAttr::AAPCS_VFP; + else { + S.Diag(attr.getLoc(), diag::err_invalid_pcs); + attr.setInvalid(); + return; + } + + d->addAttr(::new (S.Context) PcsAttr(attr.getLoc(), S.Context, PCS)); + } default: llvm_unreachable("unexpected attribute kind"); return; @@ -2337,19 +2473,42 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { if (attr.isInvalid()) return true; - if (attr.getNumArgs() != 0) { + if ((attr.getNumArgs() != 0 && + !(attr.getKind() == AttributeList::AT_pcs && attr.getNumArgs() == 1)) || + attr.getParameterName()) { Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; attr.setInvalid(); return true; } - // TODO: diagnose uses of these conventions on the wrong target. + // TODO: diagnose uses of these conventions on the wrong target. Or, better + // move to TargetAttributesSema one day. switch (attr.getKind()) { case AttributeList::AT_cdecl: CC = CC_C; break; case AttributeList::AT_fastcall: CC = CC_X86FastCall; break; case AttributeList::AT_stdcall: CC = CC_X86StdCall; break; case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break; case AttributeList::AT_pascal: CC = CC_X86Pascal; break; + case AttributeList::AT_pcs: { + Expr *Arg = attr.getArg(0); + StringLiteral *Str = dyn_cast(Arg); + if (Str == 0 || Str->isWide()) { + Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + attr.setInvalid(); + return true; + } + + llvm::StringRef StrRef = Str->getString(); + if (StrRef == "aapcs") { + CC = CC_AAPCS; + break; + } else if (StrRef == "aapcs-vfp") { + CC = CC_AAPCS_VFP; + break; + } + // FALLS THROUGH + } default: llvm_unreachable("unexpected attribute kind"); return true; } @@ -2365,7 +2524,7 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &attr, Sema &S) { if (!isa(d)) { S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << 0 /*function*/; + << attr.getName() << ExpectedFunctionOrMethod; return; } @@ -2416,14 +2575,14 @@ static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){ if (S.LangOpts.CUDA) { // check the attribute arguments. if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << "1 or 2"; + // FIXME: 0 is not okay. + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; return; } if (!isFunctionOrMethod(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunctionOrMethod; return; } @@ -2472,7 +2631,7 @@ static void HandleNSConsumedAttr(Decl *d, const AttributeList &attr, Sema &S) { ParmVarDecl *param = dyn_cast(d); if (!param) { S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) - << SourceRange(attr.getLoc()) << attr.getName() << 4 /*parameter*/; + << SourceRange(attr.getLoc()) << attr.getName() << ExpectedParameter; return; } @@ -2501,7 +2660,7 @@ static void HandleNSConsumesSelfAttr(Decl *d, const AttributeList &attr, Sema &S) { if (!isa(d)) { S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) - << SourceRange(attr.getLoc()) << attr.getName() << 13 /*method*/; + << SourceRange(attr.getLoc()) << attr.getName() << ExpectedMethod; return; } @@ -2520,7 +2679,7 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr, else { S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) << SourceRange(attr.getLoc()) << attr.getName() - << 3 /* function or method */; + << ExpectedFunctionOrMethod; return; } @@ -2664,6 +2823,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_IBOutletCollection: HandleIBOutletCollection(D, Attr, S); break; case AttributeList::AT_address_space: + case AttributeList::AT_opencl_image_access: case AttributeList::AT_objc_gc: case AttributeList::AT_vector_size: case AttributeList::AT_neon_vector_type: @@ -2684,6 +2844,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_analyzer_noreturn: HandleAnalyzerNoReturnAttr (D, Attr, S); break; case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; + case AttributeList::AT_availability:HandleAvailabilityAttr(D, Attr, S); break; case AttributeList::AT_carries_dependency: HandleDependencyAttr (D, Attr, S); break; case AttributeList::AT_common: HandleCommonAttr (D, Attr, S); break; @@ -2736,6 +2897,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, HandleInitPriorityAttr(D, Attr, S); break; case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; + case AttributeList::AT_MsStruct: HandleMsStructAttr (D, Attr, S); break; case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break; case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; @@ -2752,6 +2914,9 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_objc_exception: HandleObjCExceptionAttr(D, Attr, S); break; + case AttributeList::AT_objc_method_family: + HandleObjCMethodFamilyAttr(D, Attr, S); + break; case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; @@ -2772,6 +2937,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_fastcall: case AttributeList::AT_thiscall: case AttributeList::AT_pascal: + case AttributeList::AT_pcs: HandleCallConvAttr(D, Attr, S); break; case AttributeList::AT_opencl_kernel_function: @@ -2837,6 +3003,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { NamedDecl *NewD = 0; if (FunctionDecl *FD = dyn_cast(ND)) { NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), + FD->getInnerLocStart(), FD->getLocation(), DeclarationName(II), FD->getType(), FD->getTypeSourceInfo()); if (FD->getQualifier()) { @@ -2845,7 +3012,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { } } else if (VarDecl *VD = dyn_cast(ND)) { NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), - VD->getLocation(), II, + VD->getInnerLocStart(), VD->getLocation(), II, VD->getType(), VD->getTypeSourceInfo(), VD->getStorageClass(), VD->getStorageClassAsWritten()); @@ -2986,14 +3153,14 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, // Destroy all the delayed diagnostics we're about to pop off. for (unsigned i = state.SavedStackSize, e = DD.StackSize; i != e; ++i) - DD.Stack[i].destroy(); + DD.Stack[i].Destroy(); DD.StackSize = state.SavedStackSize; } static bool isDeclDeprecated(Decl *D) { do { - if (D->hasAttr()) + if (D->isDeprecated()) return true; } while ((D = cast_or_null(D->getDeclContext()))); return false; @@ -3016,7 +3183,7 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message, SourceLocation Loc, - bool UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass) { // Delay if we're currently parsing a declaration. if (DelayedDiagnostics.shouldDelayDiagnostics()) { DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, Message)); @@ -3032,7 +3199,9 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message, else { if (!UnknownObjCClass) Diag(Loc, diag::warn_deprecated) << D->getDeclName(); - else + else { Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName(); + Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); + } } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index f483262a8cf5..27632a1a57c4 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -18,9 +18,11 @@ #include "clang/Sema/Lookup.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclVisitor.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" @@ -287,17 +289,37 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { ParmVarDecl *NewParam = New->getParamDecl(p); if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) { + + unsigned DiagDefaultParamID = + diag::err_param_default_argument_redefinition; + + // MSVC accepts that default parameters be redefined for member functions + // of template class. The new default parameter's value is ignored. + Invalid = true; + if (getLangOptions().Microsoft) { + CXXMethodDecl* MD = dyn_cast(New); + if (MD && MD->getParent()->getDescribedClassTemplate()) { + // Merge the old default argument into the new parameter. + NewParam->setHasInheritedDefaultArg(); + if (OldParam->hasUninstantiatedDefaultArg()) + NewParam->setUninstantiatedDefaultArg( + OldParam->getUninstantiatedDefaultArg()); + else + NewParam->setDefaultArg(OldParam->getInit()); + DiagDefaultParamID = diag::warn_param_default_argument_redefinition; + Invalid = false; + } + } + // FIXME: If we knew where the '=' was, we could easily provide a fix-it // hint here. Alternatively, we could walk the type-source information // for NewParam to find the last source location in the type... but it // isn't worth the effort right now. This is the kind of test case that // is hard to get right: - // int f(int); // void g(int (*fp)(int) = f); // void g(int (*fp)(int) = &f); - Diag(NewParam->getLocation(), - diag::err_param_default_argument_redefinition) + Diag(NewParam->getLocation(), DiagDefaultParamID) << NewParam->getDefaultArgRange(); // Look for the function declaration where the default argument was @@ -312,7 +334,6 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { Diag(OldParam->getLocation(), diag::note_previous_definition) << OldParam->getDefaultArgRange(); - Invalid = true; } else if (OldParam->hasDefaultArg()) { // Merge the old default argument into the new parameter. // It's important to use getInit() here; getDefaultArg() @@ -382,6 +403,48 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { return Invalid; } +/// \brief Merge the exception specifications of two variable declarations. +/// +/// This is called when there's a redeclaration of a VarDecl. The function +/// checks if the redeclaration might have an exception specification and +/// validates compatibility and merges the specs if necessary. +void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) { + // Shortcut if exceptions are disabled. + if (!getLangOptions().CXXExceptions) + return; + + assert(Context.hasSameType(New->getType(), Old->getType()) && + "Should only be called if types are otherwise the same."); + + QualType NewType = New->getType(); + QualType OldType = Old->getType(); + + // We're only interested in pointers and references to functions, as well + // as pointers to member functions. + if (const ReferenceType *R = NewType->getAs()) { + NewType = R->getPointeeType(); + OldType = OldType->getAs()->getPointeeType(); + } else if (const PointerType *P = NewType->getAs()) { + NewType = P->getPointeeType(); + OldType = OldType->getAs()->getPointeeType(); + } else if (const MemberPointerType *M = NewType->getAs()) { + NewType = M->getPointeeType(); + OldType = OldType->getAs()->getPointeeType(); + } + + if (!NewType->isFunctionProtoType()) + return; + + // There's lots of special cases for functions. For function pointers, system + // libraries are hopefully not as broken so that we don't need these + // workarounds. + if (CheckEquivalentExceptionSpec( + OldType->getAs(), Old->getLocation(), + NewType->getAs(), New->getLocation())) { + New->setInvalidDecl(); + } +} + /// CheckCXXDefaultArguments - Verify that the default arguments for a /// function declaration are well-formed according to C++ /// [dcl.fct.default]. @@ -520,10 +583,9 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, CXXRecordDecl * CXXBaseDecl = cast(BaseDecl); assert(CXXBaseDecl && "Base type is not a C++ type"); - // C++ [class.derived]p2: - // If a class is marked with the class-virt-specifier final and it appears - // as a base-type-specifier in a base-clause (10 class.derived), the program - // is ill-formed. + // C++ [class]p3: + // If a class is marked final and it appears as a base-type-specifier in + // base-clause, the program is ill-formed. if (CXXBaseDecl->hasAttr()) { Diag(BaseLoc, diag::err_class_marked_final_used_as_base) << CXXBaseDecl->getDeclName(); @@ -876,26 +938,6 @@ void Sema::CheckOverrideControl(const Decl *D) { << MD->getDeclName(); return; } - - // C++0x [class.derived]p8: - // In a class definition marked with the class-virt-specifier explicit, - // if a virtual member function that is neither implicitly-declared nor a - // destructor overrides a member function of a base class and it is not - // marked with the virt-specifier override, the program is ill-formed. - if (MD->getParent()->hasAttr() && !isa(MD) && - HasOverriddenMethods && !MD->hasAttr()) { - llvm::SmallVector - OverriddenMethods(MD->begin_overridden_methods(), - MD->end_overridden_methods()); - - Diag(MD->getLocation(), diag::err_function_overriding_without_override) - << MD->getDeclName() - << (unsigned)OverriddenMethods.size(); - - for (unsigned I = 0; I != OverriddenMethods.size(); ++I) - Diag(OverriddenMethods[I]->getLocation(), - diag::note_overridden_virtual_function); - } } /// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member @@ -1068,6 +1110,12 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MD->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context)); } + if (VS.getLastLocation().isValid()) { + // Update the end location of a method that has a virt-specifiers. + if (CXXMethodDecl *MD = dyn_cast_or_null(Member)) + MD->setRangeEnd(VS.getLastLocation()); + } + CheckOverrideControl(Member); assert((Name || isInstField) && "No identifier for non-field ?"); @@ -1225,10 +1273,9 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, if (!NotUnknownSpecialization) { // When the scope specifier can refer to a member of an unknown // specialization, we take it as a type name. - BaseType = CheckTypenameType(ETK_None, - (NestedNameSpecifier *)SS.getScopeRep(), - *MemberOrBase, SourceLocation(), - SS.getRange(), IdLoc); + BaseType = CheckTypenameType(ETK_None, SourceLocation(), + SS.getWithLocInContext(Context), + *MemberOrBase, IdLoc); if (BaseType.isNull()) return true; @@ -1356,7 +1403,7 @@ static bool InitExprContainsUninitializedFields(const Stmt *S, *L = ME->getMemberLoc(); return true; } - } else if (isa(S)) { + } else if (isa(S)) { // sizeof/alignof doesn't reference contents, do not warn. return false; } else if (const UnaryOperator *UOE = dyn_cast(S)) { @@ -1476,17 +1523,61 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, MemInitResult Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr **Args, unsigned NumArgs, + SourceLocation NameLoc, SourceLocation LParenLoc, SourceLocation RParenLoc, - CXXRecordDecl *ClassDecl, - SourceLocation EllipsisLoc) { + CXXRecordDecl *ClassDecl) { SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!LangOpts.CPlusPlus0x) return Diag(Loc, diag::err_delegation_0x_only) << TInfo->getTypeLoc().getLocalSourceRange(); - return Diag(Loc, diag::err_delegation_unimplemented) - << TInfo->getTypeLoc().getLocalSourceRange(); + // Initialize the object. + InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( + QualType(ClassDecl->getTypeForDecl(), 0)); + InitializationKind Kind = + InitializationKind::CreateDirect(NameLoc, LParenLoc, RParenLoc); + + InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); + + ExprResult DelegationInit = + InitSeq.Perform(*this, DelegationEntity, Kind, + MultiExprArg(*this, Args, NumArgs), 0); + if (DelegationInit.isInvalid()) + return true; + + CXXConstructExpr *ConExpr = cast(DelegationInit.get()); + CXXConstructorDecl *Constructor = ConExpr->getConstructor(); + assert(Constructor && "Delegating constructor with no target?"); + + CheckImplicitConversions(DelegationInit.get(), LParenLoc); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + DelegationInit = MaybeCreateExprWithCleanups(DelegationInit); + if (DelegationInit.isInvalid()) + return true; + + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the base + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) { + ExprResult Init + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, + NumArgs, RParenLoc)); + return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, + Constructor, Init.takeAs(), + RParenLoc); + } + + return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, Constructor, + DelegationInit.takeAs(), + RParenLoc); } MemInitResult @@ -1538,9 +1629,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (!Dependent) { if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), BaseType)) - return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, - LParenLoc, RParenLoc, ClassDecl, - EllipsisLoc); + return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, BaseLoc, + LParenLoc, RParenLoc, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, VirtualBaseSpec); @@ -1684,7 +1774,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); Expr *CopyCtorArg = - DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param, + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, Constructor->getLocation(), ParamType, VK_LValue, 0); @@ -1695,9 +1785,9 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, CXXCastPath BasePath; BasePath.push_back(BaseSpec); - SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, - CK_UncheckedDerivedToBase, - VK_LValue, &BasePath); + CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath).take(); InitializationKind InitKind = InitializationKind::CreateDirect(Constructor->getLocation(), @@ -1745,7 +1835,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); Expr *MemberExprBase = - DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param, + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, Loc, ParamType, VK_LValue, 0); // Build a reference to this field within the parameter. @@ -1783,7 +1873,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, IterationVarName = &SemaRef.Context.Idents.get(OS.str()); } VarDecl *IterationVar - = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, + = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc, IterationVarName, SizeType, SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None, SC_None); @@ -1978,6 +2068,30 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info, return false; } + +bool +Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, + CXXCtorInitializer *Initializer) { + Constructor->setNumCtorInitializers(1); + CXXCtorInitializer **initializer = + new (Context) CXXCtorInitializer*[1]; + memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*)); + Constructor->setCtorInitializers(initializer); + + // FIXME: This doesn't catch indirect loops yet + CXXConstructorDecl *Target = Initializer->getTargetConstructor(); + while (Target) { + if (Target == Constructor) { + Diag(Initializer->getSourceLocation(), diag::err_delegating_ctor_loop) + << Constructor; + return true; + } + Target = Target->getTargetConstructor(); + } + + return false; +} + bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, @@ -2340,10 +2454,23 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, if (CheckRedundantInit(*this, Init, Members[Field]) || CheckRedundantUnionInit(*this, Init, MemberUnions)) HadError = true; - } else { + } else if (Init->isBaseInitializer()) { void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0)); if (CheckRedundantInit(*this, Init, Members[Key])) HadError = true; + } else { + assert(Init->isDelegatingInitializer()); + // This must be the only initializer + if (i != 0 || NumMemInits > 1) { + Diag(MemInits[0]->getSourceLocation(), + diag::err_delegating_initializer_alone) + << MemInits[0]->getSourceRange(); + HadError = true; + // We will treat this as being the only initializer. + } + SetDelegatingInitializer(Constructor, *MemInits); + // Return immediately as the initializer is set. + return; } } @@ -2380,10 +2507,13 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, continue; CXXRecordDecl *FieldClassDecl = cast(RT->getDecl()); + if (FieldClassDecl->isInvalidDecl()) + continue; if (FieldClassDecl->hasTrivialDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl); + assert(Dtor && "No dtor found for FieldClassDecl!"); CheckDestructorAccess(Field->getLocation(), Dtor, PDiag(diag::err_access_dtor_field) << Field->getDeclName() @@ -2404,12 +2534,16 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, if (Base->isVirtual()) DirectVirtualBases.insert(RT); - // Ignore trivial destructors. CXXRecordDecl *BaseClassDecl = cast(RT->getDecl()); + // If our base class is invalid, we probably can't get its dtor anyway. + if (BaseClassDecl->isInvalidDecl()) + continue; + // Ignore trivial destructors. if (BaseClassDecl->hasTrivialDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); + assert(Dtor && "No dtor found for BaseClassDecl!"); // FIXME: caret should be on the start of the class name CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor, @@ -2431,12 +2565,16 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, if (DirectVirtualBases.count(RT)) continue; - // Ignore trivial destructors. CXXRecordDecl *BaseClassDecl = cast(RT->getDecl()); + // If our base class is invalid, we probably can't get its dtor anyway. + if (BaseClassDecl->isInvalidDecl()) + continue; + // Ignore trivial destructors. if (BaseClassDecl->hasTrivialDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); + assert(Dtor && "No dtor found for BaseClassDecl!"); CheckDestructorAccess(ClassDecl->getLocation(), Dtor, PDiag(diag::err_access_dtor_vbase) << VBase->getType()); @@ -2786,7 +2924,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { for (CXXRecordDecl::method_iterator M = Record->method_begin(), MEnd = Record->method_end(); M != MEnd; ++M) { - DiagnoseHiddenVirtualMethods(Record, *M); + if (!(*M)->isStatic()) + DiagnoseHiddenVirtualMethods(Record, *M); } } @@ -2801,12 +2940,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } /// \brief Data used with FindHiddenVirtualMethod -struct FindHiddenVirtualMethodData { - Sema *S; - CXXMethodDecl *Method; - llvm::SmallPtrSet OverridenAndUsingBaseMethods; - llvm::SmallVector OverloadedMethods; -}; +namespace { + struct FindHiddenVirtualMethodData { + Sema *S; + CXXMethodDecl *Method; + llvm::SmallPtrSet OverridenAndUsingBaseMethods; + llvm::SmallVector OverloadedMethods; + }; +} /// \brief Member lookup function that determines whether a given C++ /// method overloads virtual methods in a base class without overriding any, @@ -2917,53 +3058,101 @@ namespace { /// implicitly-declared special member functions. class ImplicitExceptionSpecification { ASTContext &Context; - bool AllowsAllExceptions; + // We order exception specifications thus: + // noexcept is the most restrictive, but is only used in C++0x. + // throw() comes next. + // Then a throw(collected exceptions) + // Finally no specification. + // throw(...) is used instead if any called function uses it. + ExceptionSpecificationType ComputedEST; llvm::SmallPtrSet ExceptionsSeen; llvm::SmallVector Exceptions; - + + void ClearExceptions() { + ExceptionsSeen.clear(); + Exceptions.clear(); + } + public: explicit ImplicitExceptionSpecification(ASTContext &Context) - : Context(Context), AllowsAllExceptions(false) { } - - /// \brief Whether the special member function should have any - /// exception specification at all. - bool hasExceptionSpecification() const { - return !AllowsAllExceptions; + : Context(Context), ComputedEST(EST_BasicNoexcept) { + if (!Context.getLangOptions().CPlusPlus0x) + ComputedEST = EST_DynamicNone; } - - /// \brief Whether the special member function should have a - /// throw(...) exception specification (a Microsoft extension). - bool hasAnyExceptionSpecification() const { - return false; + + /// \brief Get the computed exception specification type. + ExceptionSpecificationType getExceptionSpecType() const { + assert(ComputedEST != EST_ComputedNoexcept && + "noexcept(expr) should not be a possible result"); + return ComputedEST; } - + /// \brief The number of exceptions in the exception specification. unsigned size() const { return Exceptions.size(); } - + /// \brief The set of exceptions in the exception specification. const QualType *data() const { return Exceptions.data(); } - - /// \brief Note that + + /// \brief Integrate another called method into the collected data. void CalledDecl(CXXMethodDecl *Method) { - // If we already know that we allow all exceptions, do nothing. - if (AllowsAllExceptions || !Method) + // If we have an MSAny spec already, don't bother. + if (!Method || ComputedEST == EST_MSAny) return; - + const FunctionProtoType *Proto = Method->getType()->getAs(); - + + ExceptionSpecificationType EST = Proto->getExceptionSpecType(); + // If this function can throw any exceptions, make a note of that. - if (!Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec()) { - AllowsAllExceptions = true; - ExceptionsSeen.clear(); - Exceptions.clear(); + if (EST == EST_MSAny || EST == EST_None) { + ClearExceptions(); + ComputedEST = EST; return; } - + + // If this function has a basic noexcept, it doesn't affect the outcome. + if (EST == EST_BasicNoexcept) + return; + + // If we have a throw-all spec at this point, ignore the function. + if (ComputedEST == EST_None) + return; + + // If we're still at noexcept(true) and there's a nothrow() callee, + // change to that specification. + if (EST == EST_DynamicNone) { + if (ComputedEST == EST_BasicNoexcept) + ComputedEST = EST_DynamicNone; + return; + } + + // Check out noexcept specs. + if (EST == EST_ComputedNoexcept) { + FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(Context); + assert(NR != FunctionProtoType::NR_NoNoexcept && + "Must have noexcept result for EST_ComputedNoexcept."); + assert(NR != FunctionProtoType::NR_Dependent && + "Should not generate implicit declarations for dependent cases, " + "and don't know how to handle them anyway."); + + // noexcept(false) -> no spec on the new function + if (NR == FunctionProtoType::NR_Throw) { + ClearExceptions(); + ComputedEST = EST_None; + } + // noexcept(true) won't change anything either. + return; + } + + assert(EST == EST_Dynamic && "EST case not considered earlier."); + assert(ComputedEST != EST_None && + "Shouldn't collect exceptions when throw-all is guaranteed."); + ComputedEST = EST_Dynamic; // Record the exceptions in this function's exception specification. for (FunctionProtoType::exception_iterator E = Proto->exception_begin(), EEnd = Proto->exception_end(); - E != EEnd; ++E) + E != EEnd; ++E) if (ExceptionsSeen.insert(Context.getCanonicalType(*E))) Exceptions.push_back(*E); } @@ -3006,6 +3195,25 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { } } +void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) { + if (!D) + return; + + int NumParamList = D->getNumTemplateParameterLists(); + for (int i = 0; i < NumParamList; i++) { + TemplateParameterList* Params = D->getTemplateParameterList(i); + for (TemplateParameterList::iterator Param = Params->begin(), + ParamEnd = Params->end(); + Param != ParamEnd; ++Param) { + NamedDecl *Named = cast(*Param); + if (Named->getDeclName()) { + S->AddDecl(Named); + IdResolver.AddDecl(Named); + } + } + } +} + void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { if (!D) return; @@ -3256,9 +3464,9 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, // be used as the identifier in the declarator for a destructor // declaration. QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); - if (isa(DeclaratorType)) + if (const TypedefType *TT = DeclaratorType->getAs()) Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) - << DeclaratorType; + << DeclaratorType << isa(TT->getDecl()); // C++ [class.dtor]p2: // A destructor is used to destroy objects of its class type. A @@ -3488,14 +3696,16 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { /// definition. Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, SourceLocation InlineLoc, + SourceLocation NamespaceLoc, SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, AttributeList *AttrList) { - // anonymous namespace starts at its left brace + SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; + // For anonymous namespace, take the location of the left brace. + SourceLocation Loc = II ? IdentLoc : LBrace; NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, - (II ? IdentLoc : LBrace) , II); - Namespc->setLBracLoc(LBrace); + StartLoc, Loc, II); Namespc->setInline(InlineLoc.isValid()); Scope *DeclRegionScope = NamespcScope->getParent(); @@ -3654,7 +3864,7 @@ static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { NamespaceDecl *Namespc = dyn_cast_or_null(Dcl); assert(Namespc && "Invalid parameter, expected NamespaceDecl"); - Namespc->setRBracLoc(RBrace); + Namespc->setRBraceLoc(RBrace); PopDeclContext(); if (Namespc->hasAttr()) PopPragmaVisibility(); @@ -3677,7 +3887,7 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { // The "std" namespace has not yet been defined, so build one implicitly. StdNamespace = NamespaceDecl::Create(Context, Context.getTranslationUnitDecl(), - SourceLocation(), + SourceLocation(), SourceLocation(), &PP.getIdentifierTable().get("std")); getStdNamespace()->setImplicit(true); } @@ -3685,6 +3895,19 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { return getStdNamespace(); } +/// \brief Determine whether a using statement is in a context where it will be +/// apply in all contexts. +static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { + switch (CurContext->getDeclKind()) { + case Decl::TranslationUnit: + return true; + case Decl::LinkageSpec: + return IsUsingDirectiveInToplevelContext(CurContext->getParent()); + default: + return false; + } +} + Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, SourceLocation NamespcLoc, @@ -3769,6 +3992,12 @@ Decl *Sema::ActOnUsingDirective(Scope *S, UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc, SS.getWithLocInContext(Context), IdentLoc, Named, CommonAncestor); + + if (IsUsingDirectiveInToplevelContext(CurContext) && + !SourceMgr.isFromMainFile(SourceMgr.getInstantiationLoc(IdentLoc))) { + Diag(IdentLoc, diag::warn_using_directive_in_header); + } + PushUsingDirective(S, UDir); } else { Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); @@ -3870,8 +4099,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, return true; } - if (TypedefDecl *TD1 = dyn_cast(D1)) - if (TypedefDecl *TD2 = dyn_cast(D2)) { + if (TypedefNameDecl *TD1 = dyn_cast(D1)) + if (TypedefNameDecl *TD2 = dyn_cast(D2)) { SuppressRedeclaration = true; return Context.hasSameType(TD1->getUnderlyingType(), TD2->getUnderlyingType()); @@ -4470,6 +4699,61 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; } +Decl *Sema::ActOnAliasDeclaration(Scope *S, + AccessSpecifier AS, + SourceLocation UsingLoc, + UnqualifiedId &Name, + TypeResult Type) { + assert((S->getFlags() & Scope::DeclScope) && + "got alias-declaration outside of declaration scope"); + + if (Type.isInvalid()) + return 0; + + bool Invalid = false; + DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name); + TypeSourceInfo *TInfo = 0; + GetTypeFromParser(Type.get(), &TInfo); + + if (DiagnoseClassNameShadow(CurContext, NameInfo)) + return 0; + + if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo, + UPPC_DeclarationType)) + Invalid = true; + + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); + LookupName(Previous, S); + + // Warn about shadowing the name of a template parameter. + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + if (DiagnoseTemplateParameterShadow(Name.StartLocation, + Previous.getFoundDecl())) + Invalid = true; + Previous.clear(); + } + + assert(Name.Kind == UnqualifiedId::IK_Identifier && + "name in alias declaration must be an identifier"); + TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc, + Name.StartLocation, + Name.Identifier, TInfo); + + NewTD->setAccess(AS); + + if (Invalid) + NewTD->setInvalidDecl(); + + bool Redeclaration = false; + ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); + + if (!Redeclaration) + PushOnScopeChains(NewTD, S); + + return NewTD; +} + Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, SourceLocation AliasLoc, @@ -4609,7 +4893,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( // exception-specification. [...] ImplicitExceptionSpecification ExceptSpec(Context); - // Direct base-class destructors. + // Direct base-class constructors. for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), BEnd = ClassDecl->bases_end(); B != BEnd; ++B) { @@ -4625,8 +4909,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( ExceptSpec.CalledDecl(Constructor); } } - - // Virtual base-class destructors. + + // Virtual base-class constructors. for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), BEnd = ClassDecl->vbases_end(); B != BEnd; ++B) { @@ -4639,8 +4923,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( ExceptSpec.CalledDecl(Constructor); } } - - // Field destructors. + + // Field constructors. for (RecordDecl::field_iterator F = ClassDecl->field_begin(), FEnd = ClassDecl->field_end(); F != FEnd; ++F) { @@ -4657,19 +4941,19 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( } FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); - EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); EPI.NumExceptions = ExceptSpec.size(); EPI.Exceptions = ExceptSpec.data(); - + // Create the actual constructor declaration. CanQualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(ClassType); - DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); + DeclarationNameInfo NameInfo(Name, ClassLoc); CXXConstructorDecl *DefaultCon - = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo, + = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Context.getFunctionType(Context.VoidTy, 0, 0, EPI), /*TInfo=*/0, @@ -4714,6 +4998,10 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, Constructor->setUsed(); MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Constructor); + } } void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { @@ -4865,15 +5153,16 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { // user-writtern inline constructor [...] DeclarationNameInfo DNI(CreatedCtorName, UsingLoc); CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create( - Context, ClassDecl, DNI, QualType(NewCtorType, 0), /*TInfo=*/0, - BaseCtor->isExplicit(), /*Inline=*/true, + Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0), + /*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true, /*ImplicitlyDeclared=*/true); NewCtor->setAccess(BaseCtor->getAccess()); // Build up the parameter decls and add them. llvm::SmallVector ParamDecls; for (unsigned i = 0; i < params; ++i) { - ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor, UsingLoc, + ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor, + UsingLoc, UsingLoc, /*IdentifierInfo=*/0, BaseCtorType->getArgType(i), /*TInfo=*/0, SC_None, @@ -4931,24 +5220,24 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { ExceptSpec.CalledDecl( LookupDestructor(cast(RecordTy->getDecl()))); } - + // Create the actual destructor declaration. FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); - EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); EPI.NumExceptions = ExceptSpec.size(); EPI.Exceptions = ExceptSpec.data(); QualType Ty = Context.getFunctionType(Context.VoidTy, 0, 0, EPI); - + CanQualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(ClassType); - DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); + DeclarationNameInfo NameInfo(Name, ClassLoc); CXXDestructorDecl *Destructor - = CXXDestructorDecl::Create(Context, ClassDecl, NameInfo, Ty, 0, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true); + = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Ty, 0, + /*isInline=*/true, + /*isImplicitlyDeclared=*/true); Destructor->setAccess(AS_public); Destructor->setImplicit(); Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); @@ -4998,6 +5287,10 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, Destructor->setUsed(); MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Destructor); + } } /// \brief Builds a statement that copies the given entity from \p From to @@ -5133,7 +5426,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, OS << "__i" << Depth; IterationVarName = &S.Context.Idents.get(OS.str()); } - VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, + VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType, S.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None, SC_None); @@ -5328,30 +5621,30 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { ExceptSpec.CalledDecl(CopyAssign); } } - + // An implicitly-declared copy assignment operator is an inline public // member of its class. FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); - EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); EPI.NumExceptions = ExceptSpec.size(); EPI.Exceptions = ExceptSpec.data(); DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); - DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); CXXMethodDecl *CopyAssignment - = CXXMethodDecl::Create(Context, ClassDecl, NameInfo, + = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Context.getFunctionType(RetType, &ArgType, 1, EPI), /*TInfo=*/0, /*isStatic=*/false, /*StorageClassAsWritten=*/SC_None, - /*isInline=*/true); + /*isInline=*/true, + SourceLocation()); CopyAssignment->setAccess(AS_public); CopyAssignment->setImplicit(); CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, - ClassDecl->getLocation(), - /*Id=*/0, + ClassLoc, ClassLoc, /*Id=*/0, ArgType, /*TInfo=*/0, SC_None, SC_None, 0); @@ -5440,21 +5733,19 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Construct the "from" expression, which is an implicit cast to the // appropriately-qualified base type. Expr *From = OtherRef; - ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals), - CK_UncheckedDerivedToBase, - VK_LValue, &BasePath); + From = ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals), + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath).take(); // Dereference "this". ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This); // Implicitly cast "this" to the appropriately-qualified base type. - Expr *ToE = To.takeAs(); - ImpCastExprToType(ToE, - Context.getCVRQualifiedType(BaseType, - CopyAssignOperator->getTypeQualifiers()), - CK_UncheckedDerivedToBase, - VK_LValue, &BasePath); - To = Owned(ToE); + To = ImpCastExprToType(To.take(), + Context.getCVRQualifiedType(BaseType, + CopyAssignOperator->getTypeQualifiers()), + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath); // Build the copy. StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType, @@ -5659,6 +5950,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, /*isStmtExpr=*/false); assert(!Body.isInvalid() && "Compound statement creation cannot fail"); CopyAssignOperator->setBody(Body.takeAs()); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(CopyAssignOperator); + } } CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( @@ -5790,20 +6085,20 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( ExceptSpec.CalledDecl(CopyConstructor); } } - + // An implicitly-declared copy constructor is an inline public // member of its class. FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); - EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); EPI.NumExceptions = ExceptSpec.size(); EPI.Exceptions = ExceptSpec.data(); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType)); - DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); CXXConstructorDecl *CopyConstructor - = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo, + = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0, @@ -5818,7 +6113,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, - ClassDecl->getLocation(), + ClassLoc, ClassLoc, /*IdentifierInfo=*/0, ArgType, /*TInfo=*/0, SC_None, @@ -5859,6 +6154,10 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, } CopyConstructor->setUsed(); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(CopyConstructor); + } } ExprResult @@ -5903,6 +6202,13 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, unsigned NumExprs = ExprArgs.size(); Expr **Exprs = (Expr **)ExprArgs.release(); + for (specific_attr_iterator + i = Constructor->specific_attr_begin(), + e = Constructor->specific_attr_end(); i != e; ++i) { + const NonNullAttr *NonNull = *i; + CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc); + } + MarkDeclarationReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, Exprs, NumExprs, @@ -5932,20 +6238,29 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD, } void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { - CXXRecordDecl *ClassDecl = cast(Record->getDecl()); - if (!ClassDecl->isInvalidDecl() && !VD->isInvalidDecl() && - !ClassDecl->hasTrivialDestructor() && !ClassDecl->isDependentContext()) { - CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); - MarkDeclarationReferenced(VD->getLocation(), Destructor); - CheckDestructorAccess(VD->getLocation(), Destructor, - PDiag(diag::err_access_dtor_var) - << VD->getDeclName() - << VD->getType()); + if (VD->isInvalidDecl()) return; - // TODO: this should be re-enabled for static locals by !CXAAtExit - if (!VD->isInvalidDecl() && VD->hasGlobalStorage() && !VD->isStaticLocal()) - Diag(VD->getLocation(), diag::warn_global_destructor); - } + CXXRecordDecl *ClassDecl = cast(Record->getDecl()); + if (ClassDecl->isInvalidDecl()) return; + if (ClassDecl->hasTrivialDestructor()) return; + if (ClassDecl->isDependentContext()) return; + + CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); + MarkDeclarationReferenced(VD->getLocation(), Destructor); + CheckDestructorAccess(VD->getLocation(), Destructor, + PDiag(diag::err_access_dtor_var) + << VD->getDeclName() + << VD->getType()); + + if (!VD->hasGlobalStorage()) return; + + // Emit warning for non-trivial dtor in global scope (a real global, + // class-static, function-static). + Diag(VD->getLocation(), diag::warn_exit_time_destructor); + + // TODO: this should be re-enabled for static locals by !CXAAtExit + if (!VD->isStaticLocal()) + Diag(VD->getLocation(), diag::warn_global_destructor); } /// AddCXXDirectInitializerToDecl - This action is called immediately after @@ -5983,15 +6298,17 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl, } Expr *Init = Exprs.get()[0]; - QualType DeducedType; - if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) { + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) << VDecl->getDeclName() << VDecl->getType() << Init->getType() << Init->getSourceRange(); + if (!DeducedType) { RealDecl->setInvalidDecl(); return; } - VDecl->setType(DeducedType); + VDecl->setTypeSourceInfo(DeducedType); + VDecl->setType(DeducedType->getType()); // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. @@ -6523,8 +6840,7 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, // FIXME: Add all the various semantics of linkage specifications LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, - LangLoc, Language, - LBraceLoc.isValid()); + ExternLoc, LangLoc, Language); CurContext->addDecl(D); PushDeclContext(S, D); return D; @@ -6535,20 +6851,26 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, /// valid, it's the position of the closing '}' brace in a linkage /// specification that uses braces. Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, - Decl *LinkageSpec, - SourceLocation RBraceLoc) { - if (LinkageSpec) + Decl *LinkageSpec, + SourceLocation RBraceLoc) { + if (LinkageSpec) { + if (RBraceLoc.isValid()) { + LinkageSpecDecl* LSDecl = cast(LinkageSpec); + LSDecl->setRBraceLoc(RBraceLoc); + } PopDeclContext(); + } return LinkageSpec; } /// \brief Perform semantic analysis for the variable declaration that /// occurs within a C++ catch clause, returning the newly-created /// variable. -VarDecl *Sema::BuildExceptionDeclaration(Scope *S, +VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, - IdentifierInfo *Name, - SourceLocation Loc) { + SourceLocation StartLoc, + SourceLocation Loc, + IdentifierInfo *Name) { bool Invalid = false; QualType ExDeclType = TInfo->getType(); @@ -6608,19 +6930,15 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, Diag(Loc, diag::err_objc_object_catch); Invalid = true; } else if (T->isObjCObjectPointerType()) { - if (!getLangOptions().NeXTRuntime) { - Diag(Loc, diag::err_objc_pointer_cxx_catch_gnu); - Invalid = true; - } else if (!getLangOptions().ObjCNonFragileABI) { + if (!getLangOptions().ObjCNonFragileABI) { Diag(Loc, diag::err_objc_pointer_cxx_catch_fragile); Invalid = true; } } } - VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc, - Name, ExDeclType, TInfo, SC_None, - SC_None); + VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name, + ExDeclType, TInfo, SC_None, SC_None); ExDecl->setExceptionVariable(true); if (!Invalid) { @@ -6703,9 +7021,9 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { } VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo, - D.getIdentifier(), - D.getIdentifierLoc()); - + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getIdentifier()); if (Invalid) ExDecl->setInvalidDecl(); @@ -6719,21 +7037,23 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { return ExDecl; } -Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, +Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, Expr *AssertExpr, - Expr *AssertMessageExpr_) { + Expr *AssertMessageExpr_, + SourceLocation RParenLoc) { StringLiteral *AssertMessage = cast(AssertMessageExpr_); if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) { llvm::APSInt Value(32); if (!AssertExpr->isIntegerConstantExpr(Value, Context)) { - Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) << + Diag(StaticAssertLoc, + diag::err_static_assert_expression_is_not_constant) << AssertExpr->getSourceRange(); return 0; } if (Value == 0) { - Diag(AssertLoc, diag::err_static_assert_failed) + Diag(StaticAssertLoc, diag::err_static_assert_failed) << AssertMessage->getString() << AssertExpr->getSourceRange(); } } @@ -6741,8 +7061,8 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression)) return 0; - Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc, - AssertExpr, AssertMessage); + Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc, + AssertExpr, AssertMessage, RParenLoc); CurContext->addDecl(Decl); return Decl; @@ -6815,7 +7135,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); bool isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TempParamLists.size(); bool Invalid = false; if (TemplateParameterList *TemplateParams @@ -6825,16 +7144,16 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, /*friend*/ true, isExplicitSpecialization, Invalid)) { - --NumMatchedTemplateParamLists; - if (TemplateParams->size() > 0) { // This is a declaration of a class template. if (Invalid) return 0; - + return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, Attr, - TemplateParams, AS_public).take(); + TemplateParams, AS_public, + TempParamLists.size() - 1, + (TemplateParameterList**) TempParamLists.release()).take(); } else { // The "template<>" header is extraneous. Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) @@ -6848,7 +7167,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); bool isAllExplicitSpecializations = true; - for (unsigned I = 0; I != NumMatchedTemplateParamLists; ++I) { + for (unsigned I = TempParamLists.size(); I-- > 0; ) { if (TempParamLists.get()[I]->size()) { isAllExplicitSpecializations = false; break; @@ -6861,10 +7180,11 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, // about the template header and build an appropriate non-templated // friend. TODO: for source fidelity, remember the headers. if (isAllExplicitSpecializations) { + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTagTypeKind(Kind); - QualType T = CheckTypenameType(Keyword, SS.getScopeRep(), *Name, - TagLoc, SS.getRange(), NameLoc); + QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, + *Name, NameLoc); if (T.isNull()) return 0; @@ -6872,12 +7192,12 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, if (isa(T)) { DependentNameTypeLoc TL = cast(TSI->getTypeLoc()); TL.setKeywordLoc(TagLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(NameLoc); } else { ElaboratedTypeLoc TL = cast(TSI->getTypeLoc()); TL.setKeywordLoc(TagLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(QualifierLoc); cast(TL.getNamedTypeLoc()).setNameLoc(NameLoc); } @@ -6896,7 +7216,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); DependentNameTypeLoc TL = cast(TSI->getTypeLoc()); TL.setKeywordLoc(TagLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(NameLoc); FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, @@ -7359,10 +7679,14 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, /// /// \param InitRange the source range that covers the "0" initializer. bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { + SourceLocation EndLoc = InitRange.getEnd(); + if (EndLoc.isValid()) + Method->setRangeEnd(EndLoc); + if (Method->isVirtual() || Method->getParent()->isDependentContext()) { Method->setPure(); return false; - } + } if (!Method->isInvalidDecl()) Diag(Method->getLocation(), diag::err_non_virtual_pure) @@ -7379,7 +7703,7 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { /// class X. void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { // If there is no declaration, there was an error parsing it. - if (D == 0) return; + if (D == 0 || D->isInvalidDecl()) return; // We should only get called for declarations with scope specifiers, like: // int foo::bar; @@ -7391,7 +7715,7 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { /// initializer for the out-of-line declaration 'D'. void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { // If there is no declaration, there was an error parsing it. - if (D == 0) return; + if (D == 0 || D->isInvalidDecl()) return; assert(D->isOutOfLine()); ExitDeclaratorContext(S); @@ -7472,6 +7796,7 @@ bool Sema::DefineUsedVTables() { // the members of a class as "used", so we check the size each // time through the loop and prefer indices (with are stable) to // iterators (which are not). + bool DefinedAnything = false; for (unsigned I = 0; I != VTableUses.size(); ++I) { CXXRecordDecl *Class = VTableUses[I].first->getDefinition(); if (!Class) @@ -7524,6 +7849,7 @@ bool Sema::DefineUsedVTables() { // Mark all of the virtual members of this class as referenced, so // that we can build a vtable. Then, tell the AST consumer that a // vtable for this class is required. + DefinedAnything = true; MarkVirtualMembersReferenced(Loc, Class); CXXRecordDecl *Canonical = cast(Class->getCanonicalDecl()); Consumer.HandleVTable(Class, VTablesUsed[Canonical]); @@ -7537,7 +7863,7 @@ bool Sema::DefineUsedVTables() { } VTableUses.clear(); - return true; + return DefinedAnything; } void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index 652318f7204e..7b235bab5d9a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -28,7 +28,7 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S, NamedDecl *ND, SourceLocation ImplLoc, int select) { - if (ND && ND->getAttr()) { + if (ND && ND->isDeprecated()) { S.Diag(ImplLoc, diag::warn_deprecated_def) << select; if (select == 0) S.Diag(ND->getLocation(), diag::note_method_declared_at); @@ -174,7 +174,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (PrevDecl && SuperClassDecl == 0) { // The previous declaration was not a class decl. Check if we have a // typedef. If we do, get the underlying class type. - if (const TypedefDecl *TDecl = dyn_cast_or_null(PrevDecl)) { + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null(PrevDecl)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { if (NamedDecl *IDecl = T->getAs()->getInterface()) @@ -193,7 +194,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } } - if (!dyn_cast_or_null(PrevDecl)) { + if (!dyn_cast_or_null(PrevDecl)) { if (!SuperClassDecl) Diag(SuperLoc, diag::err_undef_superclass) << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); @@ -242,7 +243,8 @@ Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, // Check for class declaration NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, LookupOrdinaryName, ForRedeclaration); - if (const TypedefDecl *TDecl = dyn_cast_or_null(CDeclU)) { + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null(CDeclU)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { if (NamedDecl *IDecl = T->getAs()->getInterface()) { @@ -1242,7 +1244,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, // @class XCElementToggler; // // FIXME: Make an extension? - TypedefDecl *TDD = dyn_cast(PrevDecl); + TypedefNameDecl *TDD = dyn_cast(PrevDecl); if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; Diag(PrevDecl->getLocation(), diag::note_previous_definition); @@ -1369,15 +1371,14 @@ void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, PrevObjCMethod->setDefined(impl); // If a method is deprecated, push it in the global pool. // This is used for better diagnostics. - if (Method->getAttr()) { - if (!PrevObjCMethod->getAttr()) + if (Method->isDeprecated()) { + if (!PrevObjCMethod->isDeprecated()) List->Method = Method; } // If new method is unavailable, push it into global pool // unless previous one is deprecated. - if (Method->getAttr()) { - if (!PrevObjCMethod->getAttr() && - !PrevObjCMethod->getAttr()) + if (Method->isUnavailable()) { + if (PrevObjCMethod->getAvailability() < AR_Deprecated) List->Method = Method; } return; @@ -1475,7 +1476,7 @@ void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl, assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch"); QualType T1 = Context.getCanonicalType((*ParamI)->getType()); QualType T2 = Context.getCanonicalType((*PrevI)->getType()); - // If type of arguement of method in this class does not match its + // If type of argument of method in this class does not match its // respective argument type in the super class method, issue warning; if (!Context.typesAreCompatible(T1, T2)) { Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super) @@ -1535,7 +1536,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, SourceLocation L = ClassDecl->getLocation(); AtEnd.setBegin(L); AtEnd.setEnd(L); - Diag(L, diag::warn_missing_atend); + Diag(L, diag::err_missing_atend); } // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. @@ -1697,21 +1698,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, /// objective-c's type qualifier from the parser version of the same info. static Decl::ObjCDeclQualifier CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { - Decl::ObjCDeclQualifier ret = Decl::OBJC_TQ_None; - if (PQTVal & ObjCDeclSpec::DQ_In) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_In); - if (PQTVal & ObjCDeclSpec::DQ_Inout) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Inout); - if (PQTVal & ObjCDeclSpec::DQ_Out) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Out); - if (PQTVal & ObjCDeclSpec::DQ_Bycopy) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Bycopy); - if (PQTVal & ObjCDeclSpec::DQ_Byref) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Byref); - if (PQTVal & ObjCDeclSpec::DQ_Oneway) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Oneway); - - return ret; + return (Decl::ObjCDeclQualifier) (unsigned) PQTVal; } static inline @@ -1736,7 +1723,7 @@ Decl *Sema::ActOnMethodDeclaration( ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, - bool isVariadic) { + bool isVariadic, bool MethodDefinition) { // Make sure we can establish a context for the method. if (!ClassDecl) { Diag(MethodLoc, diag::error_missing_method_context); @@ -1789,25 +1776,24 @@ Decl *Sema::ActOnMethodDeclaration( if (R.isSingleResult()) { NamedDecl *PrevDecl = R.getFoundDecl(); if (S->isDeclScope(PrevDecl)) { - // FIXME. This should be an error; but will break projects. - Diag(ArgInfo[i].NameLoc, diag::warn_method_param_redefinition) + Diag(ArgInfo[i].NameLoc, + (MethodDefinition ? diag::warn_method_param_redefinition + : diag::warn_method_param_declaration)) << ArgInfo[i].Name; Diag(PrevDecl->getLocation(), diag::note_previous_declaration); } } - ParmVarDecl* Param - = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc, - ArgInfo[i].Name, ArgType, DI, - SC_None, SC_None, 0); + SourceLocation StartLoc = DI + ? DI->getTypeLoc().getBeginLoc() + : ArgInfo[i].NameLoc; - if (ArgType->isObjCObjectType()) { - Diag(ArgInfo[i].NameLoc, - diag::err_object_cannot_be_passed_returned_by_value) - << 1 << ArgType; - Param->setInvalidDecl(); - } + ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc, + ArgInfo[i].NameLoc, ArgInfo[i].Name, + ArgType, DI, SC_None, SC_None); + + Param->setObjCMethodScopeInfo(i); Param->setObjCDeclQualifier( CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier())); @@ -1888,16 +1874,9 @@ Decl *Sema::ActOnMethodDeclaration( Diag(PrevMethod->getLocation(), diag::note_previous_declaration); } - // If the interface declared this method, and it was deprecated there, - // mark it deprecated here. + // Merge information down from the interface declaration if we have one. if (InterfaceMD) - if (Attr *DA = InterfaceMD->getAttr()) { - StringLiteral *SE = StringLiteral::CreateEmpty(Context, 1); - ObjCMethod->addAttr(::new (Context) - DeprecatedAttr(DA->getLocation(), - Context, - SE->getString())); - } + mergeObjCMethodDecls(ObjCMethod, InterfaceMD); return ObjCMethod; } @@ -1935,7 +1914,9 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, for (unsigned i = 0; i < Ivars.size(); i++) { FieldDecl* ID = cast(Ivars[i]); RecordDecl *Record = dyn_cast(TagD); - Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(), + Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, + /*FIXME: StartL=*/ID->getLocation(), + ID->getLocation(), ID->getIdentifier(), ID->getType(), ID->getBitWidth()); Decls.push_back(FD); @@ -1953,17 +1934,17 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, } /// \brief Build a type-check a new Objective-C exception variable declaration. -VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, - QualType T, - IdentifierInfo *Name, - SourceLocation NameLoc, +VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, + SourceLocation StartLoc, + SourceLocation IdLoc, + IdentifierInfo *Id, bool Invalid) { // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage // duration shall not be qualified by an address-space qualifier." // Since all parameters have automatic store duration, they can not have // an address space. if (T.getAddressSpace() != 0) { - Diag(NameLoc, diag::err_arg_with_address_space); + Diag(IdLoc, diag::err_arg_with_address_space); Invalid = true; } @@ -1975,14 +1956,14 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, // Okay: we don't know what this type will instantiate to. } else if (!T->isObjCObjectPointerType()) { Invalid = true; - Diag(NameLoc ,diag::err_catch_param_not_objc_type); + Diag(IdLoc ,diag::err_catch_param_not_objc_type); } else if (T->isObjCQualifiedIdType()) { Invalid = true; - Diag(NameLoc, diag::err_illegal_qualifiers_on_catch_parm); + Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm); } - VarDecl *New = VarDecl::Create(Context, CurContext, NameLoc, Name, T, TInfo, - SC_None, SC_None); + VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id, + T, TInfo, SC_None, SC_None); New->setExceptionVariable(true); if (Invalid) @@ -2023,8 +2004,10 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { << Context.getTypeDeclType(OwnedDecl); } - VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, D.getIdentifier(), - D.getIdentifierLoc(), + VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getIdentifier(), D.isInvalidType()); // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp index 5d7993b1afba..f1033dc8c2ff 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp @@ -96,16 +96,24 @@ bool Sema::CheckDistantExceptionSpec(QualType T) { } bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { + OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator(); + bool IsOperatorNew = OO == OO_New || OO == OO_Array_New; bool MissingExceptionSpecification = false; bool MissingEmptyExceptionSpecification = false; - if (!CheckEquivalentExceptionSpec(PDiag(diag::err_mismatched_exception_spec), + unsigned DiagID = diag::err_mismatched_exception_spec; + if (getLangOptions().Microsoft) + DiagID = diag::warn_mismatched_exception_spec; + + if (!CheckEquivalentExceptionSpec(PDiag(DiagID), PDiag(diag::note_previous_declaration), Old->getType()->getAs(), Old->getLocation(), New->getType()->getAs(), New->getLocation(), &MissingExceptionSpecification, - &MissingEmptyExceptionSpecification)) + &MissingEmptyExceptionSpecification, + /*AllowNoexceptAllMatchWithNoSpec=*/true, + IsOperatorNew)) return false; // The failure was something other than an empty exception @@ -129,9 +137,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { Context.getSourceManager().isInSystemHeader(Old->getLocation())) && Old->isExternC()) { FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); - EPI.HasExceptionSpec = true; - EPI.HasAnyExceptionSpec = false; - EPI.NumExceptions = 0; + EPI.ExceptionSpecType = EST_DynamicNone; QualType NewType = Context.getFunctionType(NewProto->getResultType(), NewProto->arg_type_begin(), NewProto->getNumArgs(), @@ -145,10 +151,14 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { = Old->getType()->getAs(); FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); - EPI.HasExceptionSpec = OldProto->hasExceptionSpec(); - EPI.HasAnyExceptionSpec = OldProto->hasAnyExceptionSpec(); - EPI.NumExceptions = OldProto->getNumExceptions(); - EPI.Exceptions = OldProto->exception_begin(); + EPI.ExceptionSpecType = OldProto->getExceptionSpecType(); + if (EPI.ExceptionSpecType == EST_Dynamic) { + EPI.NumExceptions = OldProto->getNumExceptions(); + EPI.Exceptions = OldProto->exception_begin(); + } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + // FIXME: We can't just take the expression from the old prototype. It + // likely contains references to the old prototype's parameters. + } // Update the type of the function with the appropriate exception // specification. @@ -160,7 +170,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // If exceptions are disabled, suppress the warning about missing // exception specifications for new and delete operators. - if (!getLangOptions().Exceptions) { + if (!getLangOptions().CXXExceptions) { switch (New->getDeclName().getCXXOverloadedOperator()) { case OO_New: case OO_Array_New: @@ -178,30 +188,53 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // Warn about the lack of exception specification. llvm::SmallString<128> ExceptionSpecString; llvm::raw_svector_ostream OS(ExceptionSpecString); - OS << "throw("; - bool OnFirstException = true; - for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(), - EEnd = OldProto->exception_end(); - E != EEnd; - ++E) { - if (OnFirstException) - OnFirstException = false; - else - OS << ", "; - - OS << E->getAsString(Context.PrintingPolicy); + switch (OldProto->getExceptionSpecType()) { + case EST_DynamicNone: + OS << "throw()"; + break; + + case EST_Dynamic: { + OS << "throw("; + bool OnFirstException = true; + for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(), + EEnd = OldProto->exception_end(); + E != EEnd; + ++E) { + if (OnFirstException) + OnFirstException = false; + else + OS << ", "; + + OS << E->getAsString(Context.PrintingPolicy); + } + OS << ")"; + break; + } + + case EST_BasicNoexcept: + OS << "noexcept"; + break; + + case EST_ComputedNoexcept: + OS << "noexcept("; + OldProto->getNoexceptExpr()->printPretty(OS, Context, 0, + Context.PrintingPolicy); + OS << ")"; + break; + + default: + assert(false && "This spec type is compatible with none."); } - OS << ")"; OS.flush(); - SourceLocation AfterParenLoc; + SourceLocation FixItLoc; if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); if (const FunctionTypeLoc *FTLoc = dyn_cast(&TL)) - AfterParenLoc = PP.getLocForEndOfToken(FTLoc->getRParenLoc()); + FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd()); } - if (AfterParenLoc.isInvalid()) + if (FixItLoc.isInvalid()) Diag(New->getLocation(), diag::warn_missing_exception_specification) << New << OS.str(); else { @@ -209,7 +242,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // late-specified return types. Diag(New->getLocation(), diag::warn_missing_exception_specification) << New << OS.str() - << FixItHint::CreateInsertion(AfterParenLoc, " " + OS.str().str()); + << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); } if (!Old->getLocation().isInvalid()) @@ -218,7 +251,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { return false; } - Diag(New->getLocation(), diag::err_mismatched_exception_spec); + Diag(New->getLocation(), DiagID); Diag(Old->getLocation(), diag::note_previous_declaration); return true; } @@ -230,26 +263,29 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { bool Sema::CheckEquivalentExceptionSpec( const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc) { + unsigned DiagID = diag::err_mismatched_exception_spec; + if (getLangOptions().Microsoft) + DiagID = diag::warn_mismatched_exception_spec; return CheckEquivalentExceptionSpec( - PDiag(diag::err_mismatched_exception_spec), + PDiag(DiagID), PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc); } -/// CheckEquivalentExceptionSpec - Check if the two types have equivalent -/// exception specifications. Exception specifications are equivalent if -/// they allow exactly the same set of exception types. It does not matter how -/// that is achieved. See C++ [except.spec]p2. -bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, +/// CheckEquivalentExceptionSpec - Check if the two types have compatible +/// exception specifications. See C++ [except.spec]p3. +bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, - const FunctionProtoType *Old, + const FunctionProtoType *Old, SourceLocation OldLoc, - const FunctionProtoType *New, + const FunctionProtoType *New, SourceLocation NewLoc, bool *MissingExceptionSpecification, - bool *MissingEmptyExceptionSpecification) { + bool*MissingEmptyExceptionSpecification, + bool AllowNoexceptAllMatchWithNoSpec, + bool IsOperatorNew) { // Just completely ignore this under -fno-exceptions. - if (!getLangOptions().Exceptions) + if (!getLangOptions().CXXExceptions) return false; if (MissingExceptionSpecification) @@ -258,29 +294,133 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, if (MissingEmptyExceptionSpecification) *MissingEmptyExceptionSpecification = false; - bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec(); - bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec(); - if (getLangOptions().Microsoft) { - // Treat throw(whatever) as throw(...) to be compatible with MS headers. - if (New->hasExceptionSpec() && New->getNumExceptions() > 0) - NewAny = true; - if (Old->hasExceptionSpec() && Old->getNumExceptions() > 0) - OldAny = true; + // C++0x [except.spec]p3: Two exception-specifications are compatible if: + // - both are non-throwing, regardless of their form, + // - both have the form noexcept(constant-expression) and the constant- + // expressions are equivalent, + // - one exception-specification is a noexcept-specification allowing all + // exceptions and the other is of the form throw(type-id-list), or + // - both are dynamic-exception-specifications that have the same set of + // adjusted types. + // + // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is + // of the form throw(), noexcept, or noexcept(constant-expression) where the + // constant-expression yields true. + // + // CWG 1073 Proposed resolution: Strike the third bullet above. + // + // C++0x [except.spec]p4: If any declaration of a function has an exception- + // specifier that is not a noexcept-specification allowing all exceptions, + // all declarations [...] of that function shall have a compatible + // exception-specification. + // + // That last point basically means that noexcept(false) matches no spec. + // It's considered when AllowNoexceptAllMatchWithNoSpec is true. + + ExceptionSpecificationType OldEST = Old->getExceptionSpecType(); + ExceptionSpecificationType NewEST = New->getExceptionSpecType(); + + // Shortcut the case where both have no spec. + if (OldEST == EST_None && NewEST == EST_None) + return false; + + FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context); + FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context); + if (OldNR == FunctionProtoType::NR_BadNoexcept || + NewNR == FunctionProtoType::NR_BadNoexcept) + return false; + + // Dependent noexcept specifiers are compatible with each other, but nothing + // else. + // One noexcept is compatible with another if the argument is the same + if (OldNR == NewNR && + OldNR != FunctionProtoType::NR_NoNoexcept && + NewNR != FunctionProtoType::NR_NoNoexcept) + return false; + if (OldNR != NewNR && + OldNR != FunctionProtoType::NR_NoNoexcept && + NewNR != FunctionProtoType::NR_NoNoexcept) { + Diag(NewLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(OldLoc, NoteID); + return true; } - if (OldAny && NewAny) + // The MS extension throw(...) is compatible with itself. + if (OldEST == EST_MSAny && NewEST == EST_MSAny) return false; - if (OldAny || NewAny) { + + // It's also compatible with no spec. + if ((OldEST == EST_None && NewEST == EST_MSAny) || + (OldEST == EST_MSAny && NewEST == EST_None)) + return false; + + // It's also compatible with noexcept(false). + if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw) + return false; + if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw) + return false; + + // As described above, noexcept(false) matches no spec only for functions. + if (AllowNoexceptAllMatchWithNoSpec) { + if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw) + return false; + if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw) + return false; + } + + // Any non-throwing specifications are compatible. + bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow || + OldEST == EST_DynamicNone; + bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow || + NewEST == EST_DynamicNone; + if (OldNonThrowing && NewNonThrowing) + return false; + + // As a special compatibility feature, under C++0x we accept no spec and + // throw(std::bad_alloc) as equivalent for operator new and operator new[]. + // This is because the implicit declaration changed, but old code would break. + if (getLangOptions().CPlusPlus0x && IsOperatorNew) { + const FunctionProtoType *WithExceptions = 0; + if (OldEST == EST_None && NewEST == EST_Dynamic) + WithExceptions = New; + else if (OldEST == EST_Dynamic && NewEST == EST_None) + WithExceptions = Old; + if (WithExceptions && WithExceptions->getNumExceptions() == 1) { + // One has no spec, the other throw(something). If that something is + // std::bad_alloc, all conditions are met. + QualType Exception = *WithExceptions->exception_begin(); + if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) { + IdentifierInfo* Name = ExRecord->getIdentifier(); + if (Name && Name->getName() == "bad_alloc") { + // It's called bad_alloc, but is it in std? + DeclContext* DC = ExRecord->getDeclContext(); + DC = DC->getEnclosingNamespaceContext(); + if (NamespaceDecl* NS = dyn_cast(DC)) { + IdentifierInfo* NSName = NS->getIdentifier(); + DC = DC->getParent(); + if (NSName && NSName->getName() == "std" && + DC->getEnclosingNamespaceContext()->isTranslationUnit()) { + return false; + } + } + } + } + } + } + + // At this point, the only remaining valid case is two matching dynamic + // specifications. We return here unless both specifications are dynamic. + if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) { if (MissingExceptionSpecification && Old->hasExceptionSpec() && !New->hasExceptionSpec()) { // The old type has an exception specification of some sort, but // the new type does not. *MissingExceptionSpecification = true; - if (MissingEmptyExceptionSpecification && - !Old->hasAnyExceptionSpec() && Old->getNumExceptions() == 0) { - // The old type has a throw() exception specification and the - // new type has no exception specification, and the caller asked + if (MissingEmptyExceptionSpecification && OldNonThrowing) { + // The old type has a throw() or noexcept(true) exception specification + // and the new type has no exception specification, and the caller asked // to handle this itself. *MissingEmptyExceptionSpecification = true; } @@ -294,8 +434,11 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, return true; } + assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic && + "Exception compatibility logic error: non-dynamic spec slipped through."); + bool Success = true; - // Both have a definite exception spec. Collect the first set, then compare + // Both have a dynamic exception spec. Collect the first set, then compare // to the second. llvm::SmallPtrSet OldTypes, NewTypes; for (FunctionProtoType::exception_iterator I = Old->exception_begin(), @@ -331,7 +474,7 @@ bool Sema::CheckExceptionSpecSubset( const FunctionProtoType *Subset, SourceLocation SubLoc) { // Just auto-succeed under -fno-exceptions. - if (!getLangOptions().Exceptions) + if (!getLangOptions().CXXExceptions) return false; // FIXME: As usual, we could be more specific in our error messages, but @@ -340,19 +483,66 @@ bool Sema::CheckExceptionSpecSubset( if (!SubLoc.isValid()) SubLoc = SuperLoc; + ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType(); + // If superset contains everything, we're done. - if (!Superset->hasExceptionSpec() || Superset->hasAnyExceptionSpec()) + if (SuperEST == EST_None || SuperEST == EST_MSAny) return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); + // If there are dependent noexcept specs, assume everything is fine. Unlike + // with the equivalency check, this is safe in this case, because we don't + // want to merge declarations. Checks after instantiation will catch any + // omissions we make here. + // We also shortcut checking if a noexcept expression was bad. + + FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context); + if (SuperNR == FunctionProtoType::NR_BadNoexcept || + SuperNR == FunctionProtoType::NR_Dependent) + return false; + + // Another case of the superset containing everything. + if (SuperNR == FunctionProtoType::NR_Throw) + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); + + ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); + // It does not. If the subset contains everything, we've failed. - if (!Subset->hasExceptionSpec() || Subset->hasAnyExceptionSpec()) { + if (SubEST == EST_None || SubEST == EST_MSAny) { Diag(SubLoc, DiagID); if (NoteID.getDiagID() != 0) Diag(SuperLoc, NoteID); return true; } - // Neither contains everything. Do a proper comparison. + FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context); + if (SubNR == FunctionProtoType::NR_BadNoexcept || + SubNR == FunctionProtoType::NR_Dependent) + return false; + + // Another case of the subset containing everything. + if (SubNR == FunctionProtoType::NR_Throw) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + + // If the subset contains nothing, we're done. + if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow) + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); + + // Otherwise, if the superset contains nothing, we've failed. + if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + + assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic && + "Exception spec subset: non-dynamic case slipped through."); + + // Neither contains everything or nothing. Do a proper comparison. for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(), SubE = Subset->exception_end(); SubI != SubE; ++SubI) { // Take one type from the subset. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 415ab3f38d58..20b92b84203f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -16,6 +16,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -56,7 +57,7 @@ using namespace sema; /// referenced), false otherwise. /// bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, - bool UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass) { if (getLangOptions().CPlusPlus && isa(D)) { // If there were any diagnostics suppressed by template argument deduction, // emit them now. @@ -68,7 +69,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, Diag(Suppressed[I].first, Suppressed[I].second); // Clear out the list of suppressed diagnostics, so that we don't emit - // them again for this specialization. However, we don't remove this + // them again for this specialization. However, we don't obsolete this // entry from the table, because we want to avoid ever emitting these // diagnostics again. Suppressed.clear(); @@ -82,25 +83,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, return true; } - // See if the decl is deprecated. - if (const DeprecatedAttr *DA = D->getAttr()) - EmitDeprecationWarning(D, DA->getMessage(), Loc, UnknownObjCClass); - - // See if the decl is unavailable - if (const UnavailableAttr *UA = D->getAttr()) { - if (UA->getMessage().empty()) { - if (!UnknownObjCClass) - Diag(Loc, diag::err_unavailable) << D->getDeclName(); - else - Diag(Loc, diag::warn_unavailable_fwdclass_message) - << D->getDeclName(); - } - else - Diag(Loc, diag::err_unavailable_message) - << D->getDeclName() << UA->getMessage(); - Diag(D->getLocation(), diag::note_unavailable_here) << 0; - } - // See if this is a deleted function. if (FunctionDecl *FD = dyn_cast(D)) { if (FD->isDeleted()) { @@ -110,6 +92,32 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, } } + // See if this declaration is unavailable or deprecated. + std::string Message; + switch (D->getAvailability(&Message)) { + case AR_Available: + case AR_NotYetIntroduced: + break; + + case AR_Deprecated: + EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass); + break; + + case AR_Unavailable: + if (Message.empty()) { + if (!UnknownObjCClass) + Diag(Loc, diag::err_unavailable) << D->getDeclName(); + else + Diag(Loc, diag::warn_unavailable_fwdclass_message) + << D->getDeclName(); + } + else + Diag(Loc, diag::err_unavailable_message) + << D->getDeclName() << Message; + Diag(D->getLocation(), diag::note_unavailable_here) << 0; + break; + } + // Warn if this is used but marked unused. if (D->hasAttr()) Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName(); @@ -117,6 +125,23 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, return false; } +/// \brief Retrieve the message suffix that should be added to a +/// diagnostic complaining about the given function being deleted or +/// unavailable. +std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) { + // FIXME: C++0x implicitly-deleted special member functions could be + // detected here so that we could improve diagnostics to say, e.g., + // "base class 'A' had a deleted copy constructor". + if (FD->isDeleted()) + return std::string(); + + std::string Message; + if (FD->getAvailability(&Message)) + return ": " + Message; + + return std::string(); +} + /// DiagnoseSentinelCalls - This routine checks on method dispatch calls /// (and other functions in future), which have been declared with sentinel /// attribute. It warns if call does not have the sentinel argument. @@ -232,13 +257,13 @@ SourceRange Sema::getExprRange(ExprTy *E) const { //===----------------------------------------------------------------------===// /// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4). -void Sema::DefaultFunctionArrayConversion(Expr *&E) { +ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) { QualType Ty = E->getType(); assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type"); if (Ty->isFunctionType()) - ImpCastExprToType(E, Context.getPointerType(Ty), - CK_FunctionToPointerDecay); + E = ImpCastExprToType(E, Context.getPointerType(Ty), + CK_FunctionToPointerDecay).take(); else if (Ty->isArrayType()) { // In C90 mode, arrays only promote to pointers if the array expression is // an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has @@ -252,25 +277,48 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { // T" can be converted to an rvalue of type "pointer to T". // if (getLangOptions().C99 || getLangOptions().CPlusPlus || E->isLValue()) - ImpCastExprToType(E, Context.getArrayDecayedType(Ty), - CK_ArrayToPointerDecay); + E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty), + CK_ArrayToPointerDecay).take(); + } + return Owned(E); +} + +static void CheckForNullPointerDereference(Sema &S, Expr *E) { + // Check to see if we are dereferencing a null pointer. If so, + // and if not volatile-qualified, this is undefined behavior that the + // optimizer will delete, so warn about it. People sometimes try to use this + // to get a deterministic trap and are surprised by clang's behavior. This + // only handles the pattern "*null", which is a very syntactic check. + if (UnaryOperator *UO = dyn_cast(E->IgnoreParenCasts())) + if (UO->getOpcode() == UO_Deref && + UO->getSubExpr()->IgnoreParenCasts()-> + isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) && + !UO->getType().isVolatileQualified()) { + S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::warn_indirection_through_null) + << UO->getSubExpr()->getSourceRange()); + S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::note_indirection_through_null)); } } -void Sema::DefaultLvalueConversion(Expr *&E) { +ExprResult Sema::DefaultLvalueConversion(Expr *E) { // C++ [conv.lval]p1: // A glvalue of a non-function, non-array type T can be // converted to a prvalue. - if (!E->isGLValue()) return; + if (!E->isGLValue()) return Owned(E); QualType T = E->getType(); assert(!T.isNull() && "r-value conversion on typeless expression?"); // Create a load out of an ObjCProperty l-value, if necessary. if (E->getObjectKind() == OK_ObjCProperty) { - ConvertPropertyForRValue(E); + ExprResult Res = ConvertPropertyForRValue(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); if (!E->isGLValue()) - return; + return Owned(E); } // We don't want to throw lvalue-to-rvalue casts on top of @@ -279,7 +327,7 @@ void Sema::DefaultLvalueConversion(Expr *&E) { (E->getType() == Context.OverloadTy || T->isDependentType() || T->isRecordType())) - return; + return Owned(E); // The C standard is actually really unclear on this point, and // DR106 tells us what the result should be but not why. It's @@ -287,7 +335,9 @@ void Sema::DefaultLvalueConversion(Expr *&E) { // lvalue-to-rvalue at all. Note that expressions of unqualified // 'void' type are never l-values, but qualified void can be. if (T->isVoidType()) - return; + return Owned(E); + + CheckForNullPointerDereference(*this, E); // C++ [conv.lval]p1: // [...] If T is a non-class type, the type of the prvalue is the @@ -301,27 +351,34 @@ void Sema::DefaultLvalueConversion(Expr *&E) { if (T.hasQualifiers()) T = T.getUnqualifiedType(); - if (const ArraySubscriptExpr *ae = dyn_cast(E)) - CheckArrayAccess(ae); + CheckArrayAccess(E); - E = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, - E, 0, VK_RValue); + return Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, + E, 0, VK_RValue)); } -void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) { - DefaultFunctionArrayConversion(E); - DefaultLvalueConversion(E); +ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) { + ExprResult Res = DefaultFunctionArrayConversion(E); + if (Res.isInvalid()) + return ExprError(); + Res = DefaultLvalueConversion(Res.take()); + if (Res.isInvalid()) + return ExprError(); + return move(Res); } /// UsualUnaryConversions - Performs various conversions that are common to most /// operators (C99 6.3). The conversions of array and function types are -/// sometimes surpressed. For example, the array->pointer conversion doesn't +/// sometimes suppressed. For example, the array->pointer conversion doesn't /// apply if the array is an argument to the sizeof or address (&) operators. /// In these instances, this routine should *not* be called. -Expr *Sema::UsualUnaryConversions(Expr *&E) { +ExprResult Sema::UsualUnaryConversions(Expr *E) { // First, convert to an r-value. - DefaultFunctionArrayLvalueConversion(E); + ExprResult Res = DefaultFunctionArrayLvalueConversion(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); QualType Ty = E->getType(); assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); @@ -345,60 +402,66 @@ Expr *Sema::UsualUnaryConversions(Expr *&E) { QualType PTy = Context.isPromotableBitField(E); if (!PTy.isNull()) { - ImpCastExprToType(E, PTy, CK_IntegralCast); - return E; + E = ImpCastExprToType(E, PTy, CK_IntegralCast).take(); + return Owned(E); } if (Ty->isPromotableIntegerType()) { QualType PT = Context.getPromotedIntegerType(Ty); - ImpCastExprToType(E, PT, CK_IntegralCast); - return E; + E = ImpCastExprToType(E, PT, CK_IntegralCast).take(); + return Owned(E); } } - - return E; + return Owned(E); } /// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that /// do not have a prototype. Arguments that have type float are promoted to /// double. All other argument types are converted by UsualUnaryConversions(). -void Sema::DefaultArgumentPromotion(Expr *&Expr) { - QualType Ty = Expr->getType(); +ExprResult Sema::DefaultArgumentPromotion(Expr *E) { + QualType Ty = E->getType(); assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type"); - UsualUnaryConversions(Expr); + ExprResult Res = UsualUnaryConversions(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); // If this is a 'float' (CVR qualified or typedef) promote to double. if (Ty->isSpecificBuiltinType(BuiltinType::Float)) - return ImpCastExprToType(Expr, Context.DoubleTy, CK_FloatingCast); + E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take(); + + return Owned(E); } /// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but /// will warn if the resulting type is not a POD type, and rejects ObjC -/// interfaces passed by value. This returns true if the argument type is -/// completely illegal. -bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, +/// interfaces passed by value. +ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, FunctionDecl *FDecl) { - DefaultArgumentPromotion(Expr); + ExprResult ExprRes = DefaultArgumentPromotion(E); + if (ExprRes.isInvalid()) + return ExprError(); + E = ExprRes.take(); // __builtin_va_start takes the second argument as a "varargs" argument, but // it doesn't actually do anything with it. It doesn't need to be non-pod // etc. if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start) - return false; + return Owned(E); - if (Expr->getType()->isObjCObjectType() && - DiagRuntimeBehavior(Expr->getLocStart(), 0, + if (E->getType()->isObjCObjectType() && + DiagRuntimeBehavior(E->getLocStart(), 0, PDiag(diag::err_cannot_pass_objc_interface_to_vararg) - << Expr->getType() << CT)) - return true; + << E->getType() << CT)) + return ExprError(); - if (!Expr->getType()->isPODType() && - DiagRuntimeBehavior(Expr->getLocStart(), 0, + if (!E->getType()->isPODType() && + DiagRuntimeBehavior(E->getLocStart(), 0, PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) - << Expr->getType() << CT)) - return true; + << E->getType() << CT)) + return ExprError(); - return false; + return Owned(E); } /// UsualArithmeticConversions - Performs various conversions that are common to @@ -407,19 +470,24 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, /// responsible for emitting appropriate error diagnostics. /// FIXME: verify the conversion rules for "complex int" are consistent with /// GCC. -QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, +QualType Sema::UsualArithmeticConversions(ExprResult &lhsExpr, ExprResult &rhsExpr, bool isCompAssign) { - if (!isCompAssign) - UsualUnaryConversions(lhsExpr); + if (!isCompAssign) { + lhsExpr = UsualUnaryConversions(lhsExpr.take()); + if (lhsExpr.isInvalid()) + return QualType(); + } - UsualUnaryConversions(rhsExpr); + rhsExpr = UsualUnaryConversions(rhsExpr.take()); + if (rhsExpr.isInvalid()) + return QualType(); // For conversion purposes, we ignore any qualifiers. // For example, "const float" and "float" are equivalent. QualType lhs = - Context.getCanonicalType(lhsExpr->getType()).getUnqualifiedType(); + Context.getCanonicalType(lhsExpr.get()->getType()).getUnqualifiedType(); QualType rhs = - Context.getCanonicalType(rhsExpr->getType()).getUnqualifiedType(); + Context.getCanonicalType(rhsExpr.get()->getType()).getUnqualifiedType(); // If both types are identical, no conversion is needed. if (lhs == rhs) @@ -434,11 +502,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, QualType lhs_unpromoted = lhs; if (lhs->isPromotableIntegerType()) lhs = Context.getPromotedIntegerType(lhs); - QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr); + QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr.get()); if (!LHSBitfieldPromoteTy.isNull()) lhs = LHSBitfieldPromoteTy; if (lhs != lhs_unpromoted && !isCompAssign) - ImpCastExprToType(lhsExpr, lhs, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), lhs, CK_IntegralCast); // If both types are identical, no conversion is needed. if (lhs == rhs) @@ -455,11 +523,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (!RHSComplexFloat && !rhs->isRealFloatingType()) { if (rhs->isIntegerType()) { QualType fp = cast(lhs)->getElementType(); - ImpCastExprToType(rhsExpr, fp, CK_IntegralToFloating); - ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_IntegralToFloating); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingRealToComplex); } else { assert(rhs->isComplexIntegerType()); - ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexToFloatingComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralComplexToFloatingComplex); } return lhs; } @@ -469,11 +537,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // int -> float -> _Complex float if (lhs->isIntegerType()) { QualType fp = cast(rhs)->getElementType(); - ImpCastExprToType(lhsExpr, fp, CK_IntegralToFloating); - ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), fp, CK_IntegralToFloating); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingRealToComplex); } else { assert(lhs->isComplexIntegerType()); - ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexToFloatingComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralComplexToFloatingComplex); } } return rhs; @@ -495,13 +563,13 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (LHSComplexFloat && RHSComplexFloat) { if (order > 0) { // _Complex float -> _Complex double - ImpCastExprToType(rhsExpr, lhs, CK_FloatingComplexCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingComplexCast); return lhs; } else if (order < 0) { // _Complex float -> _Complex double if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_FloatingComplexCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingComplexCast); return rhs; } return lhs; @@ -513,8 +581,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (order > 0) { // LHS is wider // float -> _Complex double QualType fp = cast(lhs)->getElementType(); - ImpCastExprToType(rhsExpr, fp, CK_FloatingCast); - ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_FloatingCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingRealToComplex); return lhs; } @@ -522,11 +590,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, QualType result = (order == 0 ? lhs : Context.getComplexType(rhs)); // double -> _Complex double - ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingRealToComplex); // _Complex float -> _Complex double if (!isCompAssign && order < 0) - ImpCastExprToType(lhsExpr, result, CK_FloatingComplexCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingComplexCast); return result; } @@ -539,8 +607,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // float -> _Complex double if (!isCompAssign) { QualType fp = cast(rhs)->getElementType(); - ImpCastExprToType(lhsExpr, fp, CK_FloatingCast); - ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), fp, CK_FloatingCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingRealToComplex); } return rhs; } @@ -550,11 +618,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // double -> _Complex double if (!isCompAssign) - ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingRealToComplex); // _Complex float -> _Complex double if (order > 0) - ImpCastExprToType(rhsExpr, result, CK_FloatingComplexCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingComplexCast); return result; } @@ -568,13 +636,13 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (LHSFloat && RHSFloat) { int order = Context.getFloatingTypeOrder(lhs, rhs); if (order > 0) { - ImpCastExprToType(rhsExpr, lhs, CK_FloatingCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingCast); return lhs; } assert(order < 0 && "illegal float comparison"); if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_FloatingCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingCast); return rhs; } @@ -582,7 +650,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (LHSFloat) { if (rhs->isIntegerType()) { // Convert rhs to the lhs floating point type. - ImpCastExprToType(rhsExpr, lhs, CK_IntegralToFloating); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralToFloating); return lhs; } @@ -591,11 +659,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, QualType result = Context.getComplexType(lhs); // _Complex int -> _Complex float - ImpCastExprToType(rhsExpr, result, CK_IntegralComplexToFloatingComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_IntegralComplexToFloatingComplex); // float -> _Complex float if (!isCompAssign) - ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingRealToComplex); return result; } @@ -604,7 +672,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (lhs->isIntegerType()) { // Convert lhs to the rhs floating point type. if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralToFloating); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralToFloating); return rhs; } @@ -614,10 +682,10 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // _Complex int -> _Complex float if (!isCompAssign) - ImpCastExprToType(lhsExpr, result, CK_IntegralComplexToFloatingComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_IntegralComplexToFloatingComplex); // float -> _Complex float - ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingRealToComplex); return result; } @@ -633,21 +701,21 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, assert(order && "inequal types with equal element ordering"); if (order > 0) { // _Complex int -> _Complex long - ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralComplexCast); return lhs; } if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralComplexCast); return rhs; } else if (lhsComplexInt) { // int -> _Complex int - ImpCastExprToType(rhsExpr, lhs, CK_IntegralRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralRealToComplex); return lhs; } else if (rhsComplexInt) { // int -> _Complex int if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralRealToComplex); return rhs; } @@ -659,29 +727,29 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (lhsSigned == rhsSigned) { // Same signedness; use the higher-ranked type if (compare >= 0) { - ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast); return lhs; } else if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast); return rhs; } else if (compare != (lhsSigned ? 1 : -1)) { // The unsigned type has greater than or equal rank to the // signed type, so use the unsigned type if (rhsSigned) { - ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast); return lhs; } else if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast); return rhs; } else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) { // The two types are different widths; if we are here, that // means the signed type is larger than the unsigned type, so // use the signed type. if (lhsSigned) { - ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast); return lhs; } else if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast); return rhs; } else { // The signed type is higher-ranked than the unsigned type, @@ -690,9 +758,9 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // to the signed type. QualType result = Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs); - ImpCastExprToType(rhsExpr, result, CK_IntegralCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_IntegralCast); if (!isCompAssign) - ImpCastExprToType(lhsExpr, result, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_IntegralCast); return result; } } @@ -702,6 +770,163 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, //===----------------------------------------------------------------------===// +ExprResult +Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + MultiTypeArg types, + MultiExprArg exprs) { + unsigned NumAssocs = types.size(); + assert(NumAssocs == exprs.size()); + + ParsedType *ParsedTypes = types.release(); + Expr **Exprs = exprs.release(); + + TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs]; + for (unsigned i = 0; i < NumAssocs; ++i) { + if (ParsedTypes[i]) + (void) GetTypeFromParser(ParsedTypes[i], &Types[i]); + else + Types[i] = 0; + } + + ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + ControllingExpr, Types, Exprs, + NumAssocs); + delete [] Types; + return ER; +} + +ExprResult +Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + TypeSourceInfo **Types, + Expr **Exprs, + unsigned NumAssocs) { + bool TypeErrorFound = false, + IsResultDependent = ControllingExpr->isTypeDependent(), + ContainsUnexpandedParameterPack + = ControllingExpr->containsUnexpandedParameterPack(); + + for (unsigned i = 0; i < NumAssocs; ++i) { + if (Exprs[i]->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + + if (Types[i]) { + if (Types[i]->getType()->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + + if (Types[i]->getType()->isDependentType()) { + IsResultDependent = true; + } else { + // C1X 6.5.1.1p2 "The type name in a generic association shall specify a + // complete object type other than a variably modified type." + unsigned D = 0; + if (Types[i]->getType()->isIncompleteType()) + D = diag::err_assoc_type_incomplete; + else if (!Types[i]->getType()->isObjectType()) + D = diag::err_assoc_type_nonobject; + else if (Types[i]->getType()->isVariablyModifiedType()) + D = diag::err_assoc_type_variably_modified; + + if (D != 0) { + Diag(Types[i]->getTypeLoc().getBeginLoc(), D) + << Types[i]->getTypeLoc().getSourceRange() + << Types[i]->getType(); + TypeErrorFound = true; + } + + // C1X 6.5.1.1p2 "No two generic associations in the same generic + // selection shall specify compatible types." + for (unsigned j = i+1; j < NumAssocs; ++j) + if (Types[j] && !Types[j]->getType()->isDependentType() && + Context.typesAreCompatible(Types[i]->getType(), + Types[j]->getType())) { + Diag(Types[j]->getTypeLoc().getBeginLoc(), + diag::err_assoc_compatible_types) + << Types[j]->getTypeLoc().getSourceRange() + << Types[j]->getType() + << Types[i]->getType(); + Diag(Types[i]->getTypeLoc().getBeginLoc(), + diag::note_compat_assoc) + << Types[i]->getTypeLoc().getSourceRange() + << Types[i]->getType(); + TypeErrorFound = true; + } + } + } + } + if (TypeErrorFound) + return ExprError(); + + // If we determined that the generic selection is result-dependent, don't + // try to compute the result expression. + if (IsResultDependent) + return Owned(new (Context) GenericSelectionExpr( + Context, KeyLoc, ControllingExpr, + Types, Exprs, NumAssocs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack)); + + llvm::SmallVector CompatIndices; + unsigned DefaultIndex = -1U; + for (unsigned i = 0; i < NumAssocs; ++i) { + if (!Types[i]) + DefaultIndex = i; + else if (Context.typesAreCompatible(ControllingExpr->getType(), + Types[i]->getType())) + CompatIndices.push_back(i); + } + + // C1X 6.5.1.1p2 "The controlling expression of a generic selection shall have + // type compatible with at most one of the types named in its generic + // association list." + if (CompatIndices.size() > 1) { + // We strip parens here because the controlling expression is typically + // parenthesized in macro definitions. + ControllingExpr = ControllingExpr->IgnoreParens(); + Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match) + << ControllingExpr->getSourceRange() << ControllingExpr->getType() + << (unsigned) CompatIndices.size(); + for (llvm::SmallVector::iterator I = CompatIndices.begin(), + E = CompatIndices.end(); I != E; ++I) { + Diag(Types[*I]->getTypeLoc().getBeginLoc(), + diag::note_compat_assoc) + << Types[*I]->getTypeLoc().getSourceRange() + << Types[*I]->getType(); + } + return ExprError(); + } + + // C1X 6.5.1.1p2 "If a generic selection has no default generic association, + // its controlling expression shall have type compatible with exactly one of + // the types named in its generic association list." + if (DefaultIndex == -1U && CompatIndices.size() == 0) { + // We strip parens here because the controlling expression is typically + // parenthesized in macro definitions. + ControllingExpr = ControllingExpr->IgnoreParens(); + Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_no_match) + << ControllingExpr->getSourceRange() << ControllingExpr->getType(); + return ExprError(); + } + + // C1X 6.5.1.1p3 "If a generic selection has a generic association with a + // type name that is compatible with the type of the controlling expression, + // then the result expression of the generic selection is the expression + // in that generic association. Otherwise, the result expression of the + // generic selection is the expression in the default generic association." + unsigned ResultIndex = + CompatIndices.size() ? CompatIndices[0] : DefaultIndex; + + return Owned(new (Context) GenericSelectionExpr( + Context, KeyLoc, ControllingExpr, + Types, Exprs, NumAssocs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack, + ResultIndex)); +} + /// ActOnStringLiteral - The specified tokens were lexed as pasted string /// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string /// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from @@ -721,8 +946,10 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { StringTokLocs.push_back(StringToks[i].getLocation()); QualType StrTy = Context.CharTy; - if (Literal.AnyWide) StrTy = Context.getWCharType(); - if (Literal.Pascal) StrTy = Context.UnsignedCharTy; + if (Literal.AnyWide) + StrTy = Context.getWCharType(); + else if (Literal.Pascal) + StrTy = Context.UnsignedCharTy; // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings) @@ -738,7 +965,7 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { // Pass &StringTokLocs[0], StringTokLocs.size() to factory! return Owned(StringLiteral::Create(Context, Literal.GetString(), Literal.GetStringLength(), - Literal.AnyWide, StrTy, + Literal.AnyWide, Literal.Pascal, StrTy, &StringTokLocs[0], StringTokLocs.size())); } @@ -783,11 +1010,20 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, // diagnose this. if (!S.CurContext->isFunctionOrMethod()) return CR_NoCapture; - // This particular madness can happen in ill-formed default - // arguments; claim it's okay and let downstream code handle it. - if (isa(var) && - S.CurContext == var->getDeclContext()->getParent()) - return CR_NoCapture; + // Certain madnesses can happen with parameter declarations, which + // we want to ignore. + if (isa(var)) { + // - If the parameter still belongs to the translation unit, then + // we're actually just using one parameter in the declaration of + // the next. This is useful in e.g. VLAs. + if (isa(var->getDeclContext())) + return CR_NoCapture; + + // - This particular madness can happen in ill-formed default + // arguments; claim it's okay and let downstream code handle it. + if (S.CurContext == var->getDeclContext()->getParent()) + return CR_NoCapture; + } DeclarationName functionName; if (FunctionDecl *fn = dyn_cast(var->getDeclContext())) @@ -889,8 +1125,18 @@ static CaptureResult shouldCaptureValueReference(Sema &S, SourceLocation loc, // Build a copy expression. Expr *copyExpr = 0; - if (!byRef && S.getLangOptions().CPlusPlus && - !type->isDependentType() && type->isStructureOrClassType()) { + const RecordType *rtype; + if (!byRef && S.getLangOptions().CPlusPlus && !type->isDependentType() && + (rtype = type->getAs())) { + + // The capture logic needs the destructor, so make sure we mark it. + // Usually this is unnecessary because most local variables have + // their destructors marked at declaration time, but parameters are + // an exception because it's technically only the call site that + // actually requires the destructor. + if (isa(var)) + S.FinalizeVarWithDestructor(var, rtype); + // According to the blocks spec, the capture of a variable from // the stack requires a const copy constructor. This is not true // of the copy/move done to move a __block variable to the heap. @@ -974,8 +1220,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, MarkDeclarationReferenced(NameInfo.getLoc(), D); Expr *E = DeclRefExpr::Create(Context, - SS? (NestedNameSpecifier *)SS->getScopeRep() : 0, - SS? SS->getRange() : SourceRange(), + SS? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc(), D, NameInfo, Ty, VK); // Just in case we're building an illegal pointer-to-member. @@ -1261,12 +1507,24 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, return IMA_Error_StaticContext; } + CXXRecordDecl * + contextClass = cast(DC)->getParent()->getCanonicalDecl(); + + // [class.mfct.non-static]p3: + // ...is used in the body of a non-static member function of class X, + // if name lookup (3.4.1) resolves the name in the id-expression to a + // non-static non-type member of some class C [...] + // ...if C is not X or a base class of X, the class member access expression + // is ill-formed. + if (R.getNamingClass() && + contextClass != R.getNamingClass()->getCanonicalDecl() && + contextClass->isProvablyNotDerivedFrom(R.getNamingClass())) + return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + // If we can prove that the current context is unrelated to all the // declaring classes, it can't be an implicit member reference (in // which case it's an error if any of those members are selected). - if (IsProvablyNotDerivedFrom(SemaRef, - cast(DC)->getParent(), - Classes)) + if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); return (hasNonInstance ? IMA_Mixed : IMA_Instance); @@ -1350,10 +1608,13 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, TemplateArgumentListInfo TList; if (ULE->hasExplicitTemplateArgs()) ULE->copyTemplateArgumentsInto(TList); + + CXXScopeSpec SS; + SS.Adopt(ULE->getQualifierLoc()); CXXDependentScopeMemberExpr *DepExpr = CXXDependentScopeMemberExpr::Create( Context, DepThis, DepThisType, true, SourceLocation(), - ULE->getQualifier(), ULE->getQualifierRange(), NULL, + SS.getWithLocInContext(Context), NULL, R.getLookupNameInfo(), &TList); CallsUndergoingInstantiation.back()->setCallee(DepExpr); } else { @@ -1479,11 +1740,10 @@ bool Sema::canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property) { return true; } -static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef, - LookupResult &Lookup, - IdentifierInfo *II, - SourceLocation NameLoc) { - ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl(); +ObjCIvarDecl *Sema::SynthesizeProvisionalIvar(LookupResult &Lookup, + IdentifierInfo *II, + SourceLocation NameLoc) { + ObjCMethodDecl *CurMeth = getCurMethodDecl(); bool LookForIvars; if (Lookup.empty()) LookForIvars = true; @@ -1503,7 +1763,7 @@ static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef, if (!ClassImpDecl) return 0; bool DynamicImplSeen = false; - ObjCPropertyDecl *property = SemaRef.LookupPropertyDecl(IDecl, II); + ObjCPropertyDecl *property = LookupPropertyDecl(IDecl, II); if (!property) return 0; if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) { @@ -1515,9 +1775,9 @@ static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef, return 0; } if (!DynamicImplSeen) { - QualType PropType = SemaRef.Context.getCanonicalType(property->getType()); - ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(SemaRef.Context, ClassImpDecl, - NameLoc, + QualType PropType = Context.getCanonicalType(property->getType()); + ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, + NameLoc, NameLoc, II, PropType, /*Dinfo=*/0, ObjCIvarDecl::Private, (Expr *)0, true); @@ -1619,7 +1879,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S, // Synthesize ivars lazily. if (getLangOptions().ObjCDefaultSynthProperties && getLangOptions().ObjCNonFragileABI2) { - if (SynthesizeProvisionalIvar(*this, R, II, NameLoc)) { + if (SynthesizeProvisionalIvar(R, II, NameLoc)) { if (const ObjCPropertyDecl *Property = canSynthesizeProvisionalIvar(II)) { Diag(NameLoc, diag::warn_synthesized_ivar_access) << II; @@ -1850,13 +2110,35 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, if (SelfExpr.isInvalid()) return ExprError(); - Expr *SelfE = SelfExpr.take(); - DefaultLvalueConversion(SelfE); + SelfExpr = DefaultLvalueConversion(SelfExpr.take()); + if (SelfExpr.isInvalid()) + return ExprError(); MarkDeclarationReferenced(Loc, IV); + Expr *base = SelfExpr.take(); + base = base->IgnoreParenImpCasts(); + if (const DeclRefExpr *DE = dyn_cast(base)) { + const NamedDecl *ND = DE->getDecl(); + if (!isa(ND)) { + // relax the rule such that it is allowed to have a shadow 'self' + // where stand-alone ivar can be found in this 'self' object. + // This is to match gcc's behavior. + ObjCInterfaceDecl *selfIFace = 0; + if (const ObjCObjectPointerType *OPT = + base->getType()->getAsObjCInterfacePointerType()) + selfIFace = OPT->getInterfaceDecl(); + if (!selfIFace || + !selfIFace->lookupInstanceVariable(IV->getIdentifier())) { + Diag(Loc, diag::error_implicit_ivar_access) + << IV->getDeclName(); + Diag(ND->getLocation(), diag::note_declared_at); + return ExprError(); + } + } + } return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), Loc, - SelfE, true, true)); + SelfExpr.take(), true, true)); } } else if (CurMethod->isInstanceMethod()) { // We should warn if a local variable hides an ivar. @@ -1902,14 +2184,14 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, /// * Finally we cast from the declaring class to the "true" /// declaring class of the member. This conversion does not /// obey access control. -bool -Sema::PerformObjectMemberConversion(Expr *&From, +ExprResult +Sema::PerformObjectMemberConversion(Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, NamedDecl *Member) { CXXRecordDecl *RD = dyn_cast(Member->getDeclContext()); if (!RD) - return false; + return Owned(From); QualType DestRecordType; QualType DestType; @@ -1929,7 +2211,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, } } else if (CXXMethodDecl *Method = dyn_cast(Member)) { if (Method->isStatic()) - return false; + return Owned(From); DestType = Method->getThisType(Context); DestRecordType = DestType->getPointeeType(); @@ -1943,15 +2225,15 @@ Sema::PerformObjectMemberConversion(Expr *&From, } } else { // No conversion necessary. - return false; + return Owned(From); } if (DestType->isDependentType() || FromType->isDependentType()) - return false; + return Owned(From); // If the unqualified types are the same, no conversion is necessary. if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) - return false; + return Owned(From); SourceRange FromRange = From->getSourceRange(); SourceLocation FromLoc = FromRange.getBegin(); @@ -1990,12 +2272,12 @@ Sema::PerformObjectMemberConversion(Expr *&From, CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, QRecordType, FromLoc, FromRange, &BasePath)) - return true; + return ExprError(); if (PointerConversions) QType = Context.getPointerType(QType); - ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase, - VK, &BasePath); + From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase, + VK, &BasePath).take(); FromType = QType; FromRecordType = QRecordType; @@ -2003,7 +2285,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, // If the qualifier type was the same as the destination type, // we're done. if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) - return false; + return Owned(From); } } @@ -2026,13 +2308,13 @@ Sema::PerformObjectMemberConversion(Expr *&From, CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, URecordType, FromLoc, FromRange, &BasePath)) - return true; + return ExprError(); QualType UType = URecordType; if (PointerConversions) UType = Context.getPointerType(UType); - ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase, - VK, &BasePath); + From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase, + VK, &BasePath).take(); FromType = UType; FromRecordType = URecordType; } @@ -2046,11 +2328,10 @@ Sema::PerformObjectMemberConversion(Expr *&From, if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType, FromLoc, FromRange, &BasePath, IgnoreAccess)) - return true; + return ExprError(); - ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, - VK, &BasePath); - return false; + return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, + VK, &BasePath); } /// \brief Build a MemberExpr AST node. @@ -2061,14 +2342,7 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = 0) { - NestedNameSpecifier *Qualifier = 0; - SourceRange QualifierRange; - if (SS.isSet()) { - Qualifier = (NestedNameSpecifier *) SS.getScopeRep(); - QualifierRange = SS.getRange(); - } - - return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange, + return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty, VK, OK); } @@ -2123,10 +2397,12 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, } S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field); - if (S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), - FoundDecl, Field)) + ExprResult Base = + S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), + FoundDecl, Field); + if (Base.isInvalid()) return ExprError(); - return S.Owned(BuildMemberExpr(S.Context, BaseExpr, IsArrow, SS, + return S.Owned(BuildMemberExpr(S.Context, Base.take(), IsArrow, SS, Field, FoundDecl, MemberNameInfo, MemberType, VK, OK)); } @@ -2234,7 +2510,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, /// were not overloaded, and it doesn't promise that the declaration /// will in fact be used. static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { - if (isa(D)) { + if (isa(D)) { S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName(); return true; } @@ -2276,8 +2552,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), - (NestedNameSpecifier*) SS.getScopeRep(), - SS.getRange(), R.getLookupNameInfo(), + SS.getWithLocInContext(Context), + R.getLookupNameInfo(), NeedsADL, R.isOverloadedResult(), R.begin(), R.end()); @@ -2433,6 +2709,16 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, break; case Decl::Function: { + const FunctionType *fty = type->castAs(); + + // If we're referring to a function with an __unknown_anytype + // result type, make the entire expression __unknown_anytype. + if (fty->getResultType() == Context.UnknownAnyTy) { + type = Context.UnknownAnyTy; + valueKind = VK_RValue; + break; + } + // Functions are l-values in C++. if (getLangOptions().CPlusPlus) { valueKind = VK_LValue; @@ -2444,10 +2730,10 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // used for checking compatibility. Therefore, when referencing // the function, we pretend that we don't have the full function // type. - if (!cast(VD)->hasPrototype()) - if (const FunctionProtoType *proto = type->getAs()) - type = Context.getFunctionNoProtoType(proto->getResultType(), - proto->getExtInfo()); + if (!cast(VD)->hasPrototype() && + isa(fty)) + type = Context.getFunctionNoProtoType(fty->getResultType(), + fty->getExtInfo()); // Functions are r-values in C. valueKind = VK_RValue; @@ -2455,6 +2741,16 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, } case Decl::CXXMethod: + // If we're referring to a method with an __unknown_anytype + // result type, make the entire expression __unknown_anytype. + // This should only be possible with a type written directly. + if (const FunctionProtoType *proto = dyn_cast(VD->getType())) + if (proto->getResultType() == Context.UnknownAnyTy) { + type = Context.UnknownAnyTy; + valueKind = VK_RValue; + break; + } + // C++ methods are l-values if static, r-values if non-static. if (cast(VD)->isStatic()) { valueKind = VK_LValue; @@ -2478,8 +2774,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, return ExprError(); } -ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, - tok::TokenKind Kind) { +ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { PredefinedExpr::IdentType IT; switch (Kind) { @@ -2606,9 +2901,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) { bool isExact = (result == APFloat::opOK); Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation()); - if (getLangOptions().SinglePrecisionConstants && Ty == Context.DoubleTy) - ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast); - + if (Ty == Context.DoubleTy) { + if (getLangOptions().SinglePrecisionConstants) { + Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take(); + } else if (getLangOptions().OpenCL && !getOpenCLOptions().cl_khr_fp64) { + Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64); + Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take(); + } + } } else if (!Literal.isIntegerLiteral()) { return ExprError(); } else { @@ -2716,10 +3016,10 @@ ExprResult Sema::ActOnParenExpr(SourceLocation L, /// The UsualUnaryConversions() function is *not* called by this routine. /// See C99 6.3.2.1p[2-4] for more details. -bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, - SourceLocation OpLoc, - SourceRange ExprRange, - bool isSizeof) { +bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType exprType, + SourceLocation OpLoc, + SourceRange ExprRange, + UnaryExprOrTypeTrait ExprKind) { if (exprType->isDependentType()) return false; @@ -2730,30 +3030,47 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, if (const ReferenceType *Ref = exprType->getAs()) exprType = Ref->getPointeeType(); + // [OpenCL 1.1 6.11.12] "The vec_step built-in function takes a built-in + // scalar or vector data type argument..." + // Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic + // type (C99 6.2.5p18) or void. + if (ExprKind == UETT_VecStep) { + if (!(exprType->isArithmeticType() || exprType->isVoidType() || + exprType->isVectorType())) { + Diag(OpLoc, diag::err_vecstep_non_scalar_vector_type) + << exprType << ExprRange; + return true; + } + } + // C99 6.5.3.4p1: if (exprType->isFunctionType()) { // alignof(function) is allowed as an extension. - if (isSizeof) - Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange; + if (ExprKind == UETT_SizeOf) + Diag(OpLoc, diag::ext_sizeof_function_type) + << ExprRange; return false; } - // Allow sizeof(void)/alignof(void) as an extension. + // Allow sizeof(void)/alignof(void) as an extension. vec_step(void) is not + // an extension, as void is a built-in scalar type (OpenCL 1.1 6.1.1). if (exprType->isVoidType()) { - Diag(OpLoc, diag::ext_sizeof_void_type) - << (isSizeof ? "sizeof" : "__alignof") << ExprRange; + if (ExprKind != UETT_VecStep) + Diag(OpLoc, diag::ext_sizeof_void_type) + << ExprKind << ExprRange; return false; } if (RequireCompleteType(OpLoc, exprType, PDiag(diag::err_sizeof_alignof_incomplete_type) - << int(!isSizeof) << ExprRange)) + << ExprKind << ExprRange)) return true; // Reject sizeof(interface) and sizeof(interface) in 64-bit mode. if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) { Diag(OpLoc, diag::err_sizeof_nonfragile_interface) - << exprType << isSizeof << ExprRange; + << exprType << (ExprKind == UETT_SizeOf) + << ExprRange; return true; } @@ -2783,109 +3100,132 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E, SourceLocation OpLoc, if (isa(ME->getMemberDecl())) return false; - return S.CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false); + return S.CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange, + UETT_AlignOf); +} + +bool Sema::CheckVecStepExpr(Expr *E, SourceLocation OpLoc, + SourceRange ExprRange) { + E = E->IgnoreParens(); + + // Cannot know anything else if the expression is dependent. + if (E->isTypeDependent()) + return false; + + return CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange, + UETT_VecStep); } /// \brief Build a sizeof or alignof expression given a type operand. ExprResult -Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo, - SourceLocation OpLoc, - bool isSizeOf, SourceRange R) { +Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { if (!TInfo) return ExprError(); QualType T = TInfo->getType(); if (!T->isDependentType() && - CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf)) + CheckUnaryExprOrTypeTraitOperand(T, OpLoc, R, ExprKind)) return ExprError(); // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. - return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, TInfo, - Context.getSizeType(), OpLoc, - R.getEnd())); + return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, TInfo, + Context.getSizeType(), + OpLoc, R.getEnd())); } /// \brief Build a sizeof or alignof expression given an expression /// operand. ExprResult -Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, - bool isSizeOf, SourceRange R) { +Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { // Verify that the operand is valid. bool isInvalid = false; if (E->isTypeDependent()) { // Delay type-checking for type-dependent expressions. - } else if (!isSizeOf) { + } else if (ExprKind == UETT_AlignOf) { isInvalid = CheckAlignOfExpr(*this, E, OpLoc, R); + } else if (ExprKind == UETT_VecStep) { + isInvalid = CheckVecStepExpr(E, OpLoc, R); } else if (E->getBitField()) { // C99 6.5.3.4p1. Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0; isInvalid = true; } else if (E->getType()->isPlaceholderType()) { - ExprResult PE = CheckPlaceholderExpr(E, OpLoc); + ExprResult PE = CheckPlaceholderExpr(E); if (PE.isInvalid()) return ExprError(); - return CreateSizeOfAlignOfExpr(PE.take(), OpLoc, isSizeOf, R); + return CreateUnaryExprOrTypeTraitExpr(PE.take(), OpLoc, ExprKind, R); } else { - isInvalid = CheckSizeOfAlignOfOperand(E->getType(), OpLoc, R, true); + isInvalid = CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, R, + UETT_SizeOf); } if (isInvalid) return ExprError(); // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. - return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, E, - Context.getSizeType(), OpLoc, - R.getEnd())); + return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, E, + Context.getSizeType(), + OpLoc, R.getEnd())); } -/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and -/// the same for @c alignof and @c __alignof +/// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c +/// expr and the same for @c alignof and @c __alignof /// Note that the ArgRange is invalid if isType is false. ExprResult -Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, - void *TyOrEx, const SourceRange &ArgRange) { +Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, bool isType, + void *TyOrEx, const SourceRange &ArgRange) { // If error parsing type, ignore. if (TyOrEx == 0) return ExprError(); if (isType) { TypeSourceInfo *TInfo; (void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo); - return CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeof, ArgRange); + return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange); } Expr *ArgEx = (Expr *)TyOrEx; ExprResult Result - = CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange()); + = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind, + ArgEx->getSourceRange()); return move(Result); } -static QualType CheckRealImagOperand(Sema &S, Expr *&V, SourceLocation Loc, +static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc, bool isReal) { - if (V->isTypeDependent()) + if (V.get()->isTypeDependent()) return S.Context.DependentTy; // _Real and _Imag are only l-values for normal l-values. - if (V->getObjectKind() != OK_Ordinary) - S.DefaultLvalueConversion(V); + if (V.get()->getObjectKind() != OK_Ordinary) { + V = S.DefaultLvalueConversion(V.take()); + if (V.isInvalid()) + return QualType(); + } // These operators return the element type of a complex type. - if (const ComplexType *CT = V->getType()->getAs()) + if (const ComplexType *CT = V.get()->getType()->getAs()) return CT->getElementType(); // Otherwise they pass through real integer and floating point types here. - if (V->getType()->isArithmeticType()) - return V->getType(); + if (V.get()->getType()->isArithmeticType()) + return V.get()->getType(); // Test for placeholders. - ExprResult PR = S.CheckPlaceholderExpr(V, Loc); + ExprResult PR = S.CheckPlaceholderExpr(V.get()); if (PR.isInvalid()) return QualType(); - if (PR.take() != V) { - V = PR.take(); + if (PR.get() != V.get()) { + V = move(PR); return CheckRealImagOperand(S, V, Loc, isReal); } // Reject anything else. - S.Diag(Loc, diag::err_realimag_invalid_type) << V->getType() + S.Diag(Loc, diag::err_realimag_invalid_type) << V.get()->getType() << (isReal ? "__real" : "__imag"); return QualType(); } @@ -2955,9 +3295,16 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *RHSExp = Idx; // Perform default conversions. - if (!LHSExp->getType()->getAs()) - DefaultFunctionArrayLvalueConversion(LHSExp); - DefaultFunctionArrayLvalueConversion(RHSExp); + if (!LHSExp->getType()->getAs()) { + ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp); + if (Result.isInvalid()) + return ExprError(); + LHSExp = Result.take(); + } + ExprResult Result = DefaultFunctionArrayLvalueConversion(RHSExp); + if (Result.isInvalid()) + return ExprError(); + RHSExp = Result.take(); QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType(); ExprValueKind VK = VK_LValue; @@ -3010,8 +3357,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // force the promotion here. Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << LHSExp->getSourceRange(); - ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy), - CK_ArrayToPointerDecay); + LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy), + CK_ArrayToPointerDecay).take(); LHSTy = LHSExp->getType(); BaseExpr = LHSExp; @@ -3021,8 +3368,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // Same as previous, except for 123[f().a] case Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << RHSExp->getSourceRange(); - ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy), - CK_ArrayToPointerDecay); + RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy), + CK_ArrayToPointerDecay).take(); RHSTy = RHSExp->getType(); BaseExpr = RHSExp; @@ -3269,8 +3616,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, // must have pointer type, and the accessed type is the pointee. return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType, IsArrow, OpLoc, - SS.getScopeRep(), - SS.getRange(), + SS.getWithLocInContext(Context), FirstQualifierInScope, NameInfo, TemplateArgs)); } @@ -3441,10 +3787,15 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, // Explicit member accesses. } else { + ExprResult BaseResult = Owned(Base); ExprResult Result = - LookupMemberExpr(R, Base, IsArrow, OpLoc, + LookupMemberExpr(R, BaseResult, IsArrow, OpLoc, SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); + if (Result.isInvalid()) { Owned(Base); return ExprError(); @@ -3477,7 +3828,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } R.setBaseObjectType(BaseType); - NestedNameSpecifier *Qualifier = SS.getScopeRep(); const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); DeclarationName MemberName = MemberNameInfo.getName(); SourceLocation MemberLoc = MemberNameInfo.getLoc(); @@ -3522,7 +3872,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(), BaseExpr, BaseExprType, IsArrow, OpLoc, - Qualifier, SS.getRange(), + SS.getWithLocInContext(Context), MemberNameInfo, TemplateArgs, R.begin(), R.end()); @@ -3569,8 +3919,12 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // Perform a property load on the base regardless of whether we // actually need it for the declaration. - if (BaseExpr->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(BaseExpr); + if (BaseExpr->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(BaseExpr); + if (Result.isInvalid()) + return ExprError(); + BaseExpr = Result.take(); + } if (FieldDecl *FD = dyn_cast(MemberDecl)) return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, @@ -3591,12 +3945,20 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } if (CXXMethodDecl *MemberFn = dyn_cast(MemberDecl)) { + ExprValueKind valueKind; + QualType type; + if (MemberFn->isInstance()) { + valueKind = VK_RValue; + type = Context.BoundMemberTy; + } else { + valueKind = VK_LValue; + type = MemberFn->getType(); + } + MarkDeclarationReferenced(MemberLoc, MemberDecl); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, MemberFn, FoundDecl, MemberNameInfo, - MemberFn->getType(), - MemberFn->isInstance() ? VK_RValue : VK_LValue, - OK_Ordinary)); + type, valueKind, OK_Ordinary)); } assert(!isa(MemberDecl) && "member function not C++ method?"); @@ -3629,9 +3991,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, /// types would be profitable. The redefinition type is whatever /// this translation unit tried to typedef to id/Class; we store /// it to the side and then re-use it in places like this. -static bool ShouldTryAgainWithRedefinitionType(Sema &S, Expr *&base) { +static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) { const ObjCObjectPointerType *opty - = base->getType()->getAs(); + = base.get()->getType()->getAs(); if (!opty) return false; const ObjCObjectType *ty = opty->getObjectType(); @@ -3651,7 +4013,7 @@ static bool ShouldTryAgainWithRedefinitionType(Sema &S, Expr *&base) { if (opty && !opty->getObjectType()->getInterface() != 0) return false; - S.ImpCastExprToType(base, redef, CK_BitCast); + base = S.ImpCastExprToType(base.take(), redef, CK_BitCast); return true; } @@ -3666,17 +4028,22 @@ static bool ShouldTryAgainWithRedefinitionType(Sema &S, Expr *&base) { /// The ObjCImpDecl bit is a gross hack that will need to be properly /// fixed for ObjC++. ExprResult -Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, +Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, bool &IsArrow, SourceLocation OpLoc, CXXScopeSpec &SS, Decl *ObjCImpDecl, bool HasTemplateArgs) { - assert(BaseExpr && "no base expression"); + assert(BaseExpr.get() && "no base expression"); // Perform default conversions. - DefaultFunctionArrayConversion(BaseExpr); - if (IsArrow) DefaultLvalueConversion(BaseExpr); + BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); - QualType BaseType = BaseExpr->getType(); + if (IsArrow) { + BaseExpr = DefaultLvalueConversion(BaseExpr.take()); + if (BaseExpr.isInvalid()) + return ExprError(); + } + + QualType BaseType = BaseExpr.get()->getType(); assert(!BaseType->isDependentType()); DeclarationName MemberName = R.getLookupName(); @@ -3700,19 +4067,21 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // overloaded operator->, but that should have been dealt with // by now. Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr->getSourceRange() + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() << FixItHint::CreateReplacement(OpLoc, "."); IsArrow = false; + } else if (BaseType == Context.BoundMemberTy) { + goto fail; } else { Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) - << BaseType << BaseExpr->getSourceRange(); + << BaseType << BaseExpr.get()->getSourceRange(); return ExprError(); } } // Handle field access to simple records. if (const RecordType *RTy = BaseType->getAs()) { - if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(), + if (LookupMemberExprInRecord(*this, R, BaseExpr.get()->getSourceRange(), RTy, OpLoc, SS, HasTemplateArgs)) return ExprError(); @@ -3735,7 +4104,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // But we only actually find it this way on objects of type 'id', // apparently. if (OTy->isObjCId() && Member->isStr("isa")) - return Owned(new (Context) ObjCIsaExpr(BaseExpr, IsArrow, MemberLoc, + return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc, Context.getObjCClassType())); if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) @@ -3768,7 +4137,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) << IDecl->getDeclName() << MemberName - << BaseExpr->getSourceRange(); + << BaseExpr.get()->getSourceRange(); return ExprError(); } } @@ -3814,7 +4183,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, } return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), - MemberLoc, BaseExpr, + MemberLoc, BaseExpr.take(), IsArrow)); } @@ -3822,8 +4191,11 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, const ObjCObjectPointerType *OPT; if (!IsArrow && (OPT = BaseType->getAs())) { // This actually uses the base as an r-value. - DefaultLvalueConversion(BaseExpr); - assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr->getType())); + BaseExpr = DefaultLvalueConversion(BaseExpr.take()); + if (BaseExpr.isInvalid()) + return ExprError(); + + assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()->getType())); IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); @@ -3843,7 +4215,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, VK_LValue, OK_ObjCProperty, MemberLoc, - BaseExpr)); + BaseExpr.take())); } if (ObjCMethodDecl *OMD = dyn_cast(PMDecl)) { @@ -3867,11 +4239,12 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, PType, VK, OK, - MemberLoc, BaseExpr)); + MemberLoc, BaseExpr.take())); } } - - if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + // Use of id.member can only be for a property reference. Do not + // use the 'id' redefinition in this case. + if (IsArrow && ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl, HasTemplateArgs); @@ -3937,7 +4310,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // FIXME: we must check that the setter has property type. return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, PType, VK, OK, - MemberLoc, BaseExpr)); + MemberLoc, BaseExpr.take())); } if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) @@ -3949,7 +4322,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, } // Normal property access. - return HandleExprPropertyRefExpr(OPT, BaseExpr, MemberName, MemberLoc, + return HandleExprPropertyRefExpr(OPT, BaseExpr.get(), MemberName, MemberLoc, SourceLocation(), QualType(), false); } @@ -3957,13 +4330,13 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (BaseType->isExtVectorType()) { // FIXME: this expr should store IsArrow. IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); - ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr->getValueKind()); + ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind()); QualType ret = CheckExtVectorComponent(*this, BaseType, VK, OpLoc, Member, MemberLoc); if (ret.isNull()) return ExprError(); - return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr, + return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr.take(), *Member, MemberLoc)); } @@ -3972,7 +4345,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) && !Context.ObjCSelRedefinitionType->isObjCSelType()) { - ImpCastExprToType(BaseExpr, Context.ObjCSelRedefinitionType, CK_BitCast); + BaseExpr = ImpCastExprToType(BaseExpr.take(), Context.ObjCSelRedefinitionType, + CK_BitCast); return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl, HasTemplateArgs); } @@ -3991,7 +4365,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (!IsArrow && Ptr->getPointeeType()->isRecordType() && MemberName.getNameKind() != DeclarationName::CXXDestructorName) { Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr->getSourceRange() + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() << FixItHint::CreateReplacement(OpLoc, "->"); // Recurse as an -> access. @@ -4006,11 +4380,11 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, bool TryCall = false; bool Overloaded = false; UnresolvedSet<8> AllOverloads; - if (const OverloadExpr *Overloads = dyn_cast(BaseExpr)) { + if (const OverloadExpr *Overloads = dyn_cast(BaseExpr.get())) { AllOverloads.append(Overloads->decls_begin(), Overloads->decls_end()); TryCall = true; Overloaded = true; - } else if (DeclRefExpr *DeclRef = dyn_cast(BaseExpr)) { + } else if (DeclRefExpr *DeclRef = dyn_cast(BaseExpr.get())) { if (FunctionDecl* Fun = dyn_cast(DeclRef->getDecl())) { AllOverloads.addDecl(Fun); TryCall = true; @@ -4024,22 +4398,25 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, bool HasViableZeroArgOverload = false; for (OverloadExpr::decls_iterator it = AllOverloads.begin(), DeclsEnd = AllOverloads.end(); it != DeclsEnd; ++it) { - const FunctionDecl *OverloadDecl = cast(*it); - QualType ResultTy = OverloadDecl->getResultType(); - if ((!IsArrow && ResultTy->isRecordType()) || - (IsArrow && ResultTy->isPointerType() && - ResultTy->getPointeeType()->isRecordType())) { - ViableOverloads.addDecl(*it); - if (OverloadDecl->getMinRequiredArguments() == 0) { - HasViableZeroArgOverload = true; + // Our overload set may include TemplateDecls, which we'll ignore for the + // purposes of determining whether we can issue a '()' fixit. + if (const FunctionDecl *OverloadDecl = dyn_cast(*it)) { + QualType ResultTy = OverloadDecl->getResultType(); + if ((!IsArrow && ResultTy->isRecordType()) || + (IsArrow && ResultTy->isPointerType() && + ResultTy->getPointeeType()->isRecordType())) { + ViableOverloads.addDecl(*it); + if (OverloadDecl->getMinRequiredArguments() == 0) { + HasViableZeroArgOverload = true; + } } } } if (!HasViableZeroArgOverload || ViableOverloads.size() != 1) { - Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call) - << 1 << 0 - << BaseExpr->getSourceRange(); + Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) + << (AllOverloads.size() > 1) << 0 + << BaseExpr.get()->getSourceRange(); int ViableOverloadCount = ViableOverloads.size(); int I; for (I = 0; I < ViableOverloadCount; ++I) { @@ -4052,7 +4429,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, diag::note_member_ref_possible_intended_overload); } if (I != ViableOverloadCount) { - Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates) + Diag(BaseExpr.get()->getExprLoc(), diag::note_ovl_too_many_candidates) << int(ViableOverloadCount - I); } return ExprError(); @@ -4068,6 +4445,16 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, } } else if ((Fun = BaseType->getAs())) { TryCall = true; + } else if (BaseType == Context.BoundMemberTy) { + // Look for the bound-member type. If it's still overloaded, + // give up, although we probably should have fallen into the + // OverloadExpr case above if we actually have an overloaded + // bound member. + QualType fnType = Expr::findBoundMemberType(BaseExpr.get()); + if (!fnType.isNull()) { + TryCall = true; + Fun = fnType->castAs(); + } } if (TryCall) { @@ -4088,24 +4475,24 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // can emit a fixit and carry on pretending that BaseExpr was actually a // CallExpr. SourceLocation ParenInsertionLoc = - PP.getLocForEndOfToken(BaseExpr->getLocEnd()); - Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call) + PP.getLocForEndOfToken(BaseExpr.get()->getLocEnd()); + Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) << int(Overloaded) << 1 - << BaseExpr->getSourceRange() + << BaseExpr.get()->getSourceRange() << FixItHint::CreateInsertion(ParenInsertionLoc, "()"); - ExprResult NewBase = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc, + ExprResult NewBase = ActOnCallExpr(0, BaseExpr.take(), ParenInsertionLoc, MultiExprArg(*this, 0, 0), ParenInsertionLoc); if (NewBase.isInvalid()) return ExprError(); - BaseExpr = NewBase.takeAs(); - DefaultFunctionArrayConversion(BaseExpr); + BaseExpr = NewBase; + BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl, HasTemplateArgs); } Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union) - << BaseType << BaseExpr->getSourceRange(); + << BaseType << BaseExpr.get()->getSourceRange(); return ExprError(); } @@ -4167,8 +4554,12 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, NameInfo, TemplateArgs); } else { LookupResult R(*this, NameInfo, LookupMemberName); - Result = LookupMemberExpr(R, Base, IsArrow, OpLoc, + ExprResult BaseResult = Owned(Base); + Result = LookupMemberExpr(R, BaseResult, IsArrow, OpLoc, SS, ObjCImpDecl, TemplateArgs != 0); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); if (Result.isInvalid()) { Owned(Base); @@ -4313,6 +4704,13 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, << NumArgsInProto << NumArgs << Fn->getSourceRange() << SourceRange(Args[NumArgsInProto]->getLocStart(), Args[NumArgs-1]->getLocEnd()); + + // Emit the location of the prototype. + if (FDecl && !FDecl->getBuiltinID()) + Diag(FDecl->getLocStart(), + diag::note_typecheck_call_too_many_args) + << FDecl; + // This deletes the extra arguments. Call->setNumArgs(Context, NumArgsInProto); return true; @@ -4394,16 +4792,37 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, // If this is a variadic call, handle args passed through "...". if (CallType != VariadicDoesNotApply) { - // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = ArgIx; i != NumArgs; ++i) { - Expr *Arg = Args[i]; - Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType, FDecl); - AllArgs.push_back(Arg); + + // Assume that extern "C" functions with variadic arguments that + // return __unknown_anytype aren't *really* variadic. + if (Proto->getResultType() == Context.UnknownAnyTy && + FDecl && FDecl->isExternC()) { + for (unsigned i = ArgIx; i != NumArgs; ++i) { + ExprResult arg; + if (isa(Args[i]->IgnoreParens())) + arg = DefaultFunctionArrayLvalueConversion(Args[i]); + else + arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl); + Invalid |= arg.isInvalid(); + AllArgs.push_back(arg.take()); + } + + // Otherwise do argument promotion, (C99 6.5.2.2p7). + } else { + for (unsigned i = ArgIx; i != NumArgs; ++i) { + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl); + Invalid |= Arg.isInvalid(); + AllArgs.push_back(Arg.take()); + } } } return Invalid; } +/// Given a function expression of unknown-any type, try to rebuild it +/// to have a function type. +static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn); + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. @@ -4464,94 +4883,39 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, RParenLoc)); - Expr *NakedFn = Fn->IgnoreParens(); - - // Determine whether this is a call to an unresolved member function. - if (UnresolvedMemberExpr *MemE = dyn_cast(NakedFn)) { - // If lookup was unresolved but not dependent (i.e. didn't find - // an unresolved using declaration), it has to be an overloaded - // function set, which means it must contain either multiple - // declarations (all methods or method templates) or a single - // method template. - assert((MemE->getNumDecls() > 1) || - isa( - (*MemE->decls_begin())->getUnderlyingDecl())); - (void)MemE; + if (Fn->getType() == Context.UnknownAnyTy) { + ExprResult result = rebuildUnknownAnyFunction(*this, Fn); + if (result.isInvalid()) return ExprError(); + Fn = result.take(); + } + if (Fn->getType() == Context.BoundMemberTy) { return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, RParenLoc); } + } - // Determine whether this is a call to a member function. - if (MemberExpr *MemExpr = dyn_cast(NakedFn)) { - NamedDecl *MemDecl = MemExpr->getMemberDecl(); - if (isa(MemDecl)) + // Check for overloaded calls. This can happen even in C due to extensions. + if (Fn->getType() == Context.OverloadTy) { + OverloadExpr::FindResult find = OverloadExpr::find(Fn); + + // We aren't supposed to apply this logic if there's an '&' involved. + if (!find.IsAddressOfOperand) { + OverloadExpr *ovl = find.Expression; + if (isa(ovl)) { + UnresolvedLookupExpr *ULE = cast(ovl); + return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig); + } else { return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, RParenLoc); - } - - // Determine whether this is a call to a pointer-to-member function. - if (BinaryOperator *BO = dyn_cast(NakedFn)) { - if (BO->getOpcode() == BO_PtrMemD || - BO->getOpcode() == BO_PtrMemI) { - if (const FunctionProtoType *FPT - = BO->getType()->getAs()) { - QualType ResultTy = FPT->getCallResultType(Context); - ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType()); - - // Check that the object type isn't more qualified than the - // member function we're calling. - Qualifiers FuncQuals = Qualifiers::fromCVRMask(FPT->getTypeQuals()); - Qualifiers ObjectQuals - = BO->getOpcode() == BO_PtrMemD - ? BO->getLHS()->getType().getQualifiers() - : BO->getLHS()->getType()->getAs() - ->getPointeeType().getQualifiers(); - - Qualifiers Difference = ObjectQuals - FuncQuals; - Difference.removeObjCGCAttr(); - Difference.removeAddressSpace(); - if (Difference) { - std::string QualsString = Difference.getAsString(); - Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals) - << BO->getType().getUnqualifiedType() - << QualsString - << (QualsString.find(' ') == std::string::npos? 1 : 2); - } - - CXXMemberCallExpr *TheCall - = new (Context) CXXMemberCallExpr(Context, Fn, Args, - NumArgs, ResultTy, VK, - RParenLoc); - - if (CheckCallReturnType(FPT->getResultType(), - BO->getRHS()->getSourceRange().getBegin(), - TheCall, 0)) - return ExprError(); - - if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs, - RParenLoc)) - return ExprError(); - - return MaybeBindToTemporary(TheCall); - } - return ExprError(Diag(Fn->getLocStart(), - diag::err_typecheck_call_not_function) - << Fn->getType() << Fn->getSourceRange()); } } } // If we're directly calling a function, get the appropriate declaration. - // Also, in C++, keep track of whether we should perform argument-dependent - // lookup and whether there were any explicitly-specified template arguments. Expr *NakedFn = Fn->IgnoreParens(); - if (isa(NakedFn)) { - UnresolvedLookupExpr *ULE = cast(NakedFn); - return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, - RParenLoc, ExecConfig); - } NamedDecl *NDecl = 0; if (UnaryOperator *UnOp = dyn_cast(NakedFn)) @@ -4560,6 +4924,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, if (isa(NakedFn)) NDecl = cast(NakedFn)->getDecl(); + else if (isa(NakedFn)) + NDecl = cast(NakedFn)->getMemberDecl(); return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc, ExecConfig); @@ -4595,7 +4961,10 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, FunctionDecl *FDecl = dyn_cast_or_null(NDecl); // Promote the function operand. - UsualUnaryConversions(Fn); + ExprResult Result = UsualUnaryConversions(Fn); + if (Result.isInvalid()) + return ExprError(); + Fn = Result.take(); // Make the call expr early, before semantic checks. This guarantees cleanup // of arguments and function on error. @@ -4621,6 +4990,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) return CheckBuiltinFunctionCall(BuiltinID, TheCall); + retry: const FunctionType *FuncT; if (const PointerType *PT = Fn->getType()->getAs()) { // C99 6.5.2.2p1 - "The expression that denotes the called function shall @@ -4633,6 +5003,15 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, Fn->getType()->getAs()) { FuncT = BPT->getPointeeType()->castAs(); } else { + // Handle calls to expressions of unknown-any type. + if (Fn->getType() == Context.UnknownAnyTy) { + ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn); + if (rewrite.isInvalid()) return ExprError(); + Fn = rewrite.take(); + TheCall->setCallee(Fn); + goto retry; + } + return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) << Fn->getType() << Fn->getSourceRange()); } @@ -4703,7 +5082,12 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, Arg = ArgE.takeAs(); } else { - DefaultArgumentPromotion(Arg); + ExprResult ArgE = DefaultArgumentPromotion(Arg); + + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs(); } if (RequireCompleteType(Arg->getSourceRange().getBegin(), @@ -4819,12 +5203,12 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, /// Prepares for a scalar cast, performing all the necessary stages /// except the final cast and returning the kind required. -static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { +static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { // Both Src and Dest are scalar types, i.e. arithmetic or pointer. // Also, callers should have filtered out the invalid cases with // pointers. Everything else should be possible. - QualType SrcTy = Src->getType(); + QualType SrcTy = Src.get()->getType(); if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy)) return CK_NoOp; @@ -4854,7 +5238,7 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { case Type::STK_Integral: switch (DestTy->getScalarTypeKind()) { case Type::STK_Pointer: - if (Src->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) + if (Src.get()->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) return CK_NullToPointer; return CK_IntegralToPointer; case Type::STK_Bool: @@ -4864,12 +5248,12 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { case Type::STK_Floating: return CK_IntegralToFloating; case Type::STK_IntegralComplex: - S.ImpCastExprToType(Src, DestTy->getAs()->getElementType(), - CK_IntegralCast); + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs()->getElementType(), + CK_IntegralCast); return CK_IntegralRealToComplex; case Type::STK_FloatingComplex: - S.ImpCastExprToType(Src, DestTy->getAs()->getElementType(), - CK_IntegralToFloating); + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs()->getElementType(), + CK_IntegralToFloating); return CK_FloatingRealToComplex; case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); @@ -4885,12 +5269,12 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { case Type::STK_Integral: return CK_FloatingToIntegral; case Type::STK_FloatingComplex: - S.ImpCastExprToType(Src, DestTy->getAs()->getElementType(), - CK_FloatingCast); + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs()->getElementType(), + CK_FloatingCast); return CK_FloatingRealToComplex; case Type::STK_IntegralComplex: - S.ImpCastExprToType(Src, DestTy->getAs()->getElementType(), - CK_FloatingToIntegral); + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs()->getElementType(), + CK_FloatingToIntegral); return CK_IntegralRealToComplex; case Type::STK_Pointer: llvm_unreachable("valid float->pointer cast?"); @@ -4909,14 +5293,14 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { QualType ET = SrcTy->getAs()->getElementType(); if (S.Context.hasSameType(ET, DestTy)) return CK_FloatingComplexToReal; - S.ImpCastExprToType(Src, ET, CK_FloatingComplexToReal); + Src = S.ImpCastExprToType(Src.take(), ET, CK_FloatingComplexToReal); return CK_FloatingCast; } case Type::STK_Bool: return CK_FloatingComplexToBoolean; case Type::STK_Integral: - S.ImpCastExprToType(Src, SrcTy->getAs()->getElementType(), - CK_FloatingComplexToReal); + Src = S.ImpCastExprToType(Src.take(), SrcTy->getAs()->getElementType(), + CK_FloatingComplexToReal); return CK_FloatingToIntegral; case Type::STK_Pointer: llvm_unreachable("valid complex float->pointer cast?"); @@ -4935,14 +5319,14 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { QualType ET = SrcTy->getAs()->getElementType(); if (S.Context.hasSameType(ET, DestTy)) return CK_IntegralComplexToReal; - S.ImpCastExprToType(Src, ET, CK_IntegralComplexToReal); + Src = S.ImpCastExprToType(Src.take(), ET, CK_IntegralComplexToReal); return CK_IntegralCast; } case Type::STK_Bool: return CK_IntegralComplexToBoolean; case Type::STK_Floating: - S.ImpCastExprToType(Src, SrcTy->getAs()->getElementType(), - CK_IntegralComplexToReal); + Src = S.ImpCastExprToType(Src.take(), SrcTy->getAs()->getElementType(), + CK_IntegralComplexToReal); return CK_IntegralToFloating; case Type::STK_Pointer: llvm_unreachable("valid complex int->pointer cast?"); @@ -4957,15 +5341,20 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { } /// CheckCastTypes - Check type constraints for casting between types. -bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, - Expr *&castExpr, CastKind& Kind, ExprValueKind &VK, - CXXCastPath &BasePath, bool FunctionalStyle) { +ExprResult Sema::CheckCastTypes(SourceRange TyR, QualType castType, + Expr *castExpr, CastKind& Kind, ExprValueKind &VK, + CXXCastPath &BasePath, bool FunctionalStyle) { + if (castExpr->getType() == Context.UnknownAnyTy) + return checkUnknownAnyCast(TyR, castType, castExpr, Kind, VK, BasePath); + if (getLangOptions().CPlusPlus) return CXXCheckCStyleCast(SourceRange(TyR.getBegin(), castExpr->getLocEnd()), castType, VK, castExpr, Kind, BasePath, FunctionalStyle); + assert(!castExpr->getType()->isPlaceholderType()); + // We only support r-value casts in C. VK = VK_RValue; @@ -4973,18 +5362,24 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, // type needs to be scalar. if (castType->isVoidType()) { // We don't necessarily do lvalue-to-rvalue conversions on this. - IgnoredValueConversions(castExpr); + ExprResult castExprRes = IgnoredValueConversions(castExpr); + if (castExprRes.isInvalid()) + return ExprError(); + castExpr = castExprRes.take(); // Cast to void allows any expr type. Kind = CK_ToVoid; - return false; + return Owned(castExpr); } - DefaultFunctionArrayLvalueConversion(castExpr); + ExprResult castExprRes = DefaultFunctionArrayLvalueConversion(castExpr); + if (castExprRes.isInvalid()) + return ExprError(); + castExpr = castExprRes.take(); if (RequireCompleteType(TyR.getBegin(), castType, diag::err_typecheck_cast_to_incomplete)) - return true; + return ExprError(); if (!castType->isScalarType() && !castType->isVectorType()) { if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) && @@ -4994,7 +5389,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar) << castType << castExpr->getSourceRange(); Kind = CK_NoOp; - return false; + return Owned(castExpr); } if (castType->isUnionType()) { @@ -5011,16 +5406,19 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, break; } } - if (Field == FieldEnd) - return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type) + if (Field == FieldEnd) { + Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type) << castExpr->getType() << castExpr->getSourceRange(); + return ExprError(); + } Kind = CK_ToUnion; - return false; + return Owned(castExpr); } // Reject any other conversions to non-scalar types. - return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar) + Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar) << castType << castExpr->getSourceRange(); + return ExprError(); } // The type we're casting to is known to be a scalar or vector. @@ -5028,49 +5426,73 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, // Require the operand to be a scalar or vector. if (!castExpr->getType()->isScalarType() && !castExpr->getType()->isVectorType()) { - return Diag(castExpr->getLocStart(), + Diag(castExpr->getLocStart(), diag::err_typecheck_expect_scalar_operand) << castExpr->getType() << castExpr->getSourceRange(); + return ExprError(); } if (castType->isExtVectorType()) return CheckExtVectorCast(TyR, castType, castExpr, Kind); - if (castType->isVectorType()) - return CheckVectorCast(TyR, castType, castExpr->getType(), Kind); - if (castExpr->getType()->isVectorType()) - return CheckVectorCast(TyR, castExpr->getType(), castType, Kind); + if (castType->isVectorType()) { + if (castType->getAs()->getVectorKind() == + VectorType::AltiVecVector && + (castExpr->getType()->isIntegerType() || + castExpr->getType()->isFloatingType())) { + Kind = CK_VectorSplat; + return Owned(castExpr); + } else if (CheckVectorCast(TyR, castType, castExpr->getType(), Kind)) { + return ExprError(); + } else + return Owned(castExpr); + } + if (castExpr->getType()->isVectorType()) { + if (CheckVectorCast(TyR, castExpr->getType(), castType, Kind)) + return ExprError(); + else + return Owned(castExpr); + } // The source and target types are both scalars, i.e. // - arithmetic types (fundamental, enum, and complex) // - all kinds of pointers // Note that member pointers were filtered out with C++, above. - if (isa(castExpr)) - return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr); + if (isa(castExpr)) { + Diag(castExpr->getLocStart(), diag::err_cast_selector_expr); + return ExprError(); + } // If either type is a pointer, the other type has to be either an // integer or a pointer. if (!castType->isArithmeticType()) { QualType castExprType = castExpr->getType(); if (!castExprType->isIntegralType(Context) && - castExprType->isArithmeticType()) - return Diag(castExpr->getLocStart(), - diag::err_cast_pointer_from_non_pointer_int) + castExprType->isArithmeticType()) { + Diag(castExpr->getLocStart(), + diag::err_cast_pointer_from_non_pointer_int) << castExprType << castExpr->getSourceRange(); + return ExprError(); + } } else if (!castExpr->getType()->isArithmeticType()) { - if (!castType->isIntegralType(Context) && castType->isArithmeticType()) - return Diag(castExpr->getLocStart(), - diag::err_cast_pointer_to_non_pointer_int) + if (!castType->isIntegralType(Context) && castType->isArithmeticType()) { + Diag(castExpr->getLocStart(), diag::err_cast_pointer_to_non_pointer_int) << castType << castExpr->getSourceRange(); + return ExprError(); + } } - Kind = PrepareScalarCast(*this, castExpr, castType); + castExprRes = Owned(castExpr); + Kind = PrepareScalarCast(*this, castExprRes, castType); + if (castExprRes.isInvalid()) + return ExprError(); + castExpr = castExprRes.take(); if (Kind == CK_BitCast) CheckCastAlign(castExpr, castType, TyR); - return false; + return Owned(castExpr); } bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, @@ -5093,8 +5515,8 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, return false; } -bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, - CastKind &Kind) { +ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, + Expr *CastExpr, CastKind &Kind) { assert(DestTy->isExtVectorType() && "Not an extended vector type!"); QualType SrcTy = CastExpr->getType(); @@ -5102,11 +5524,13 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, // If SrcTy is a VectorType, the total size must match to explicitly cast to // an ExtVectorType. if (SrcTy->isVectorType()) { - if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) - return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) + if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) { + Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) << DestTy << SrcTy << R; + return ExprError(); + } Kind = CK_BitCast; - return false; + return Owned(CastExpr); } // All non-pointer scalars can be cast to ExtVector type. The appropriate @@ -5118,11 +5542,14 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, << DestTy << SrcTy << R; QualType DestElemTy = DestTy->getAs()->getElementType(); - ImpCastExprToType(CastExpr, DestElemTy, - PrepareScalarCast(*this, CastExpr, DestElemTy)); + ExprResult CastExprRes = Owned(CastExpr); + CastKind CK = PrepareScalarCast(*this, CastExprRes, DestElemTy); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = ImpCastExprToType(CastExprRes.take(), DestElemTy, CK).take(); Kind = CK_VectorSplat; - return false; + return Owned(CastExpr); } ExprResult @@ -5150,12 +5577,15 @@ Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, CastKind Kind = CK_Invalid; ExprValueKind VK = VK_RValue; CXXCastPath BasePath; - if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr, - Kind, VK, BasePath)) + ExprResult CastResult = + CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr, + Kind, VK, BasePath); + if (CastResult.isInvalid()) return ExprError(); + castExpr = CastResult.take(); return Owned(CStyleCastExpr::Create(Context, - Ty->getType().getNonLValueExprType(Context), + Ty->getType().getNonLValueExprType(Context), VK, Kind, castExpr, &BasePath, Ty, LParenLoc, RParenLoc)); } @@ -5185,9 +5615,9 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, TypeSourceInfo *TInfo) { ParenListExpr *PE = cast(Op); QualType Ty = TInfo->getType(); - bool isAltiVecLiteral = false; + bool isVectorLiteral = false; - // Check for an altivec literal, + // Check for an altivec or OpenCL literal, // i.e. all the elements are integer constants. if (getLangOptions().AltiVec && Ty->isVectorType()) { if (PE->getNumExprs() == 0) { @@ -5196,18 +5626,45 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, } if (PE->getNumExprs() == 1) { if (!PE->getExpr(0)->getType()->isVectorType()) - isAltiVecLiteral = true; + isVectorLiteral = true; } else - isAltiVecLiteral = true; + isVectorLiteral = true; } - // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')' + // If this is a vector initializer, '(' type ')' '(' init, ..., init ')' // then handle it as such. - if (isAltiVecLiteral) { + if (isVectorLiteral) { llvm::SmallVector initExprs; - for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) - initExprs.push_back(PE->getExpr(i)); + // '(...)' form of vector initialization in AltiVec: the number of + // initializers must be one or must match the size of the vector. + // If a single value is specified in the initializer then it will be + // replicated to all the components of the vector + if (Ty->getAs()->getVectorKind() == + VectorType::AltiVecVector) { + unsigned numElems = Ty->getAs()->getNumElements(); + // The number of initializers must be one or must match the size of the + // vector. If a single value is specified in the initializer then it will + // be replicated to all the components of the vector + if (PE->getNumExprs() == 1) { + QualType ElemTy = Ty->getAs()->getElementType(); + ExprResult Literal = Owned(PE->getExpr(0)); + Literal = ImpCastExprToType(Literal.take(), ElemTy, + PrepareScalarCast(*this, Literal, ElemTy)); + return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take()); + } + else if (PE->getNumExprs() < numElems) { + Diag(PE->getExprLoc(), + diag::err_incorrect_number_of_vector_initializers); + return ExprError(); + } + else + for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) + initExprs.push_back(PE->getExpr(i)); + } + else + for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) + initExprs.push_back(PE->getExpr(i)); // FIXME: This means that pretty-printing the final AST will produce curly // braces instead of the original commas. @@ -5265,11 +5722,8 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHS, Expr *RHS, // In this case, check to make sure that we got here from a "NULL" // string in the source code. NullExpr = NullExpr->IgnoreParenImpCasts(); - SourceManager& SM = Context.getSourceManager(); - SourceLocation Loc = SM.getInstantiationLoc(NullExpr->getExprLoc()); - unsigned Len = - Lexer::MeasureTokenLength(Loc, SM, Context.getLangOptions()); - if (Len != 4 || memcmp(SM.getCharacterData(Loc), "NULL", 4)) + SourceLocation loc = NullExpr->getExprLoc(); + if (!findMacroSpelling(loc, "NULL")) return false; } @@ -5283,23 +5737,17 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHS, Expr *RHS, /// Note that lhs is not null here, even if this is the gnu "x ?: y" extension. /// In that case, lhs = cond. /// C99 6.5.15 -QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, +QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc) { - // If both LHS and RHS are overloaded functions, try to resolve them. - if (Context.hasSameType(LHS->getType(), RHS->getType()) && - LHS->getType()->isSpecificBuiltinType(BuiltinType::Overload)) { - ExprResult LHSResult = CheckPlaceholderExpr(LHS, QuestionLoc); - if (LHSResult.isInvalid()) - return QualType(); - ExprResult RHSResult = CheckPlaceholderExpr(RHS, QuestionLoc); - if (RHSResult.isInvalid()) - return QualType(); + ExprResult lhsResult = CheckPlaceholderExpr(LHS.get()); + if (!lhsResult.isUsable()) return QualType(); + LHS = move(lhsResult); - LHS = LHSResult.take(); - RHS = RHSResult.take(); - } + ExprResult rhsResult = CheckPlaceholderExpr(RHS.get()); + if (!rhsResult.isUsable()) return QualType(); + RHS = move(rhsResult); // C++ is sufficiently different to merit its own checker. if (getLangOptions().CPlusPlus) @@ -5308,12 +5756,19 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, VK = VK_RValue; OK = OK_Ordinary; - UsualUnaryConversions(Cond); - UsualUnaryConversions(LHS); - UsualUnaryConversions(RHS); - QualType CondTy = Cond->getType(); - QualType LHSTy = LHS->getType(); - QualType RHSTy = RHS->getType(); + Cond = UsualUnaryConversions(Cond.take()); + if (Cond.isInvalid()) + return QualType(); + LHS = UsualUnaryConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + RHS = UsualUnaryConversions(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + + QualType CondTy = Cond.get()->getType(); + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); // first, check the condition. if (!CondTy->isScalarType()) { // C99 6.5.15p2 @@ -5321,14 +5776,14 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // Throw an error if its not either. if (getLangOptions().OpenCL) { if (!CondTy->isVectorType()) { - Diag(Cond->getLocStart(), + Diag(Cond.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar_or_vector) << CondTy; return QualType(); } } else { - Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar) + Diag(Cond.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) << CondTy; return QualType(); } @@ -5344,25 +5799,27 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (getLangOptions().OpenCL && CondTy->isVectorType()) { // Both operands should be of scalar type. if (!LHSTy->isScalarType()) { - Diag(LHS->getLocStart(), diag::err_typecheck_cond_expect_scalar) + Diag(LHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) << CondTy; return QualType(); } if (!RHSTy->isScalarType()) { - Diag(RHS->getLocStart(), diag::err_typecheck_cond_expect_scalar) + Diag(RHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) << CondTy; return QualType(); } // Implicity convert these scalars to the type of the condition. - ImpCastExprToType(LHS, CondTy, CK_IntegralCast); - ImpCastExprToType(RHS, CondTy, CK_IntegralCast); + LHS = ImpCastExprToType(LHS.take(), CondTy, CK_IntegralCast); + RHS = ImpCastExprToType(RHS.take(), CondTy, CK_IntegralCast); } // If both operands have arithmetic type, do the usual arithmetic conversions // to find a common type: C99 6.5.15p3,5. if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) { UsualArithmeticConversions(LHS, RHS); - return LHS->getType(); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + return LHS.get()->getType(); } // If both operands are the same structure or union type, the result is that @@ -5380,32 +5837,34 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // The following || allows only one side to be void (a GCC-ism). if (LHSTy->isVoidType() || RHSTy->isVoidType()) { if (!LHSTy->isVoidType()) - Diag(RHS->getLocStart(), diag::ext_typecheck_cond_one_void) - << RHS->getSourceRange(); + Diag(RHS.get()->getLocStart(), diag::ext_typecheck_cond_one_void) + << RHS.get()->getSourceRange(); if (!RHSTy->isVoidType()) - Diag(LHS->getLocStart(), diag::ext_typecheck_cond_one_void) - << LHS->getSourceRange(); - ImpCastExprToType(LHS, Context.VoidTy, CK_ToVoid); - ImpCastExprToType(RHS, Context.VoidTy, CK_ToVoid); + Diag(LHS.get()->getLocStart(), diag::ext_typecheck_cond_one_void) + << LHS.get()->getSourceRange(); + LHS = ImpCastExprToType(LHS.take(), Context.VoidTy, CK_ToVoid); + RHS = ImpCastExprToType(RHS.take(), Context.VoidTy, CK_ToVoid); return Context.VoidTy; } // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has // the type of the other operand." if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) && - RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + RHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { // promote the null to a pointer. - ImpCastExprToType(RHS, LHSTy, CK_NullToPointer); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_NullToPointer); return LHSTy; } if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) && - LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(LHS, RHSTy, CK_NullToPointer); + LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_NullToPointer); return RHSTy; } // All objective-c pointer type analysis is done here. QualType compositeType = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); if (!compositeType.isNull()) return compositeType; @@ -5415,12 +5874,12 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) { if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) { QualType destType = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, destType, CK_BitCast); - ImpCastExprToType(RHS, destType, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); return destType; } Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } // We have 2 block pointer types. @@ -5435,18 +5894,18 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), rhptee.getUnqualifiedType())) { Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); // In this situation, we assume void* type. No especially good // reason, but this is what gcc does, and we do have to pick // to get a consistent AST. QualType incompatTy = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, incompatTy, CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); return incompatTy; } // The block pointer types are compatible. - ImpCastExprToType(LHS, LHSTy, CK_BitCast); - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } @@ -5463,9 +5922,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(LHS, destType, CK_NoOp); + LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(RHS, destType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); return destType; } if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) { @@ -5473,9 +5932,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(RHS, destType, CK_NoOp); + RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(LHS, destType, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); return destType; } @@ -5486,13 +5945,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), rhptee.getUnqualifiedType())) { Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); // In this situation, we assume void* type. No especially good // reason, but this is what gcc does, and we do have to pick // to get a consistent AST. QualType incompatTy = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, incompatTy, CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); return incompatTy; } // The pointer types are compatible. @@ -5502,8 +5961,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // type. // FIXME: Need to calculate the composite type. // FIXME: Need to add qualifiers - ImpCastExprToType(LHS, LHSTy, CK_BitCast); - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } @@ -5511,69 +5970,69 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // null pointers have been filtered out by this point. if (RHSTy->isPointerType() && LHSTy->isIntegerType()) { Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); - ImpCastExprToType(LHS, RHSTy, CK_IntegralToPointer); + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_IntegralToPointer); return RHSTy; } if (LHSTy->isPointerType() && RHSTy->isIntegerType()) { Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); - ImpCastExprToType(RHS, LHSTy, CK_IntegralToPointer); + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_IntegralToPointer); return LHSTy; } // Emit a better diagnostic if one of the expressions is a null pointer // constant and the other is not a pointer type. In this case, the user most // likely forgot to take the address of the other expression. - if (DiagnoseConditionalForNull(LHS, RHS, QuestionLoc)) + if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) return QualType(); // Otherwise, the operands are not compatible. Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } /// FindCompositeObjCPointerType - Helper method to find composite type of /// two objective-c pointer types of the two input expressions. -QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, +QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, SourceLocation QuestionLoc) { - QualType LHSTy = LHS->getType(); - QualType RHSTy = RHS->getType(); + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); // Handle things like Class and struct objc_class*. Here we case the result // to the pseudo-builtin, because that will be implicitly cast back to the // redefinition type if an attempt is made to access its fields. if (LHSTy->isObjCClassType() && (Context.hasSameType(RHSTy, Context.ObjCClassRedefinitionType))) { - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } if (RHSTy->isObjCClassType() && (Context.hasSameType(LHSTy, Context.ObjCClassRedefinitionType))) { - ImpCastExprToType(LHS, RHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); return RHSTy; } // And the same for struct objc_object* / id if (LHSTy->isObjCIdType() && (Context.hasSameType(RHSTy, Context.ObjCIdRedefinitionType))) { - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } if (RHSTy->isObjCIdType() && (Context.hasSameType(LHSTy, Context.ObjCIdRedefinitionType))) { - ImpCastExprToType(LHS, RHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); return RHSTy; } // And the same for struct objc_selector* / SEL if (Context.isObjCSelType(LHSTy) && (Context.hasSameType(RHSTy, Context.ObjCSelRedefinitionType))) { - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } if (Context.isObjCSelType(RHSTy) && (Context.hasSameType(LHSTy, Context.ObjCSelRedefinitionType))) { - ImpCastExprToType(LHS, RHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); return RHSTy; } // Check constraints for Objective-C object pointers types. @@ -5620,15 +6079,15 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, else { Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) << LHSTy << RHSTy - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); QualType incompatTy = Context.getObjCIdType(); - ImpCastExprToType(LHS, incompatTy, CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); return incompatTy; } // The object pointer types are compatible. - ImpCastExprToType(LHS, compositeType, CK_BitCast); - ImpCastExprToType(RHS, compositeType, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), compositeType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), compositeType, CK_BitCast); return compositeType; } // Check Objective-C object pointer types and 'void *' @@ -5639,9 +6098,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(LHS, destType, CK_NoOp); + LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(RHS, destType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); return destType; } if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { @@ -5651,9 +6110,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(RHS, destType, CK_NoOp); + RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(LHS, destType, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); return destType; } return QualType(); @@ -5681,7 +6140,10 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, && commonExpr->isOrdinaryOrBitFieldObject() && RHSExpr->isOrdinaryOrBitFieldObject() && Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) { - UsualUnaryConversions(commonExpr); + ExprResult commonRes = UsualUnaryConversions(commonExpr); + if (commonRes.isInvalid()) + return ExprError(); + commonExpr = commonRes.take(); } opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(), @@ -5693,19 +6155,21 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; - QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr, + ExprResult Cond = Owned(CondExpr), LHS = Owned(LHSExpr), RHS = Owned(RHSExpr); + QualType result = CheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc); - if (result.isNull()) + if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() || + RHS.isInvalid()) return ExprError(); if (!commonExpr) - return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc, - LHSExpr, ColonLoc, - RHSExpr, result, VK, OK)); + return Owned(new (Context) ConditionalOperator(Cond.take(), QuestionLoc, + LHS.take(), ColonLoc, + RHS.take(), result, VK, OK)); return Owned(new (Context) - BinaryConditionalOperator(commonExpr, opaqueValue, CondExpr, LHSExpr, - RHSExpr, QuestionLoc, ColonLoc, result, VK, OK)); + BinaryConditionalOperator(commonExpr, opaqueValue, Cond.take(), LHS.take(), + RHS.take(), QuestionLoc, ColonLoc, result, VK, OK)); } // checkPointerTypesForAssignment - This is a very tricky routine (despite @@ -5736,6 +6200,12 @@ checkPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) { if (lhq.getAddressSpace() != rhq.getAddressSpace()) ConvTy = Sema::IncompatiblePointerDiscardsQualifiers; + // It's okay to add or remove GC qualifiers when converting to + // and from void*. + else if (lhq.withoutObjCGCAttr().compatiblyIncludes(rhq.withoutObjCGCAttr()) + && (lhptee->isVoidType() || rhptee->isVoidType())) + ; // keep old + // For GCC compatibility, other qualifier mismatches are treated // as still compatible in C. else ConvTy = Sema::CompatiblePointerDiscardsQualifiers; @@ -5885,7 +6355,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc, // adds casts to this they'll be wasted, but fortunately that doesn't // usually happen on valid code. OpaqueValueExpr rhs(Loc, rhsType, VK_RValue); - Expr *rhsPtr = &rhs; + ExprResult rhsPtr = &rhs; CastKind K = CK_Invalid; return CheckAssignmentConstraints(lhsType, rhsPtr, K); @@ -5909,9 +6379,9 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc, /// /// Sets 'Kind' for any result kind except Incompatible. Sema::AssignConvertType -Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, +Sema::CheckAssignmentConstraints(QualType lhsType, ExprResult &rhs, CastKind &Kind) { - QualType rhsType = rhs->getType(); + QualType rhsType = rhs.get()->getType(); // Get canonical types. We're not formatting these types, just comparing // them. @@ -5950,7 +6420,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, QualType elType = cast(lhsType)->getElementType(); if (elType != rhsType) { Kind = PrepareScalarCast(*this, rhs, elType); - ImpCastExprToType(rhs, elType, Kind); + rhs = ImpCastExprToType(rhs.take(), elType, Kind); } Kind = CK_VectorSplat; return Compatible; @@ -6151,10 +6621,11 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, /// \brief Constructs a transparent union from an expression that is /// used to initialize the transparent union. -static void ConstructTransparentUnion(ASTContext &C, Expr *&E, +static void ConstructTransparentUnion(Sema &S, ASTContext &C, ExprResult &EResult, QualType UnionType, FieldDecl *Field) { // Build an initializer list that designates the appropriate member // of the transparent union. + Expr *E = EResult.take(); InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(), &E, 1, SourceLocation()); @@ -6164,13 +6635,14 @@ static void ConstructTransparentUnion(ASTContext &C, Expr *&E, // Build a compound literal constructing a value of the transparent // union type from this initializer list. TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType); - E = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType, - VK_RValue, Initializer, false); + EResult = S.Owned( + new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType, + VK_RValue, Initializer, false)); } Sema::AssignConvertType -Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { - QualType FromType = rExpr->getType(); +Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, ExprResult &rExpr) { + QualType FromType = rExpr.get()->getType(); // If the ArgType is a Union type, we want to handle a potential // transparent_union GCC extension. @@ -6191,25 +6663,23 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { // 2) null pointer constant if (FromType->isPointerType()) if (FromType->getAs()->getPointeeType()->isVoidType()) { - ImpCastExprToType(rExpr, it->getType(), CK_BitCast); + rExpr = ImpCastExprToType(rExpr.take(), it->getType(), CK_BitCast); InitField = *it; break; } - if (rExpr->isNullPointerConstant(Context, + if (rExpr.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(rExpr, it->getType(), CK_NullToPointer); + rExpr = ImpCastExprToType(rExpr.take(), it->getType(), CK_NullToPointer); InitField = *it; break; } } - Expr *rhs = rExpr; CastKind Kind = CK_Invalid; - if (CheckAssignmentConstraints(it->getType(), rhs, Kind) + if (CheckAssignmentConstraints(it->getType(), rExpr, Kind) == Compatible) { - ImpCastExprToType(rhs, it->getType(), Kind); - rExpr = rhs; + rExpr = ImpCastExprToType(rExpr.take(), it->getType(), Kind); InitField = *it; break; } @@ -6218,20 +6688,23 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { if (!InitField) return Incompatible; - ConstructTransparentUnion(Context, rExpr, ArgType, InitField); + ConstructTransparentUnion(*this, Context, rExpr, ArgType, InitField); return Compatible; } Sema::AssignConvertType -Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { +Sema::CheckSingleAssignmentConstraints(QualType lhsType, ExprResult &rExpr) { if (getLangOptions().CPlusPlus) { if (!lhsType->isRecordType()) { // C++ 5.17p3: If the left operand is not of class type, the // expression is implicitly converted (C++ 4) to the // cv-unqualified type of the left operand. - if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType(), - AA_Assigning)) + ExprResult Res = PerformImplicitConversion(rExpr.get(), + lhsType.getUnqualifiedType(), + AA_Assigning); + if (Res.isInvalid()) return Incompatible; + rExpr = move(Res); return Compatible; } @@ -6244,9 +6717,9 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { if ((lhsType->isPointerType() || lhsType->isObjCObjectPointerType() || lhsType->isBlockPointerType()) - && rExpr->isNullPointerConstant(Context, + && rExpr.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(rExpr, lhsType, CK_NullToPointer); + rExpr = ImpCastExprToType(rExpr.take(), lhsType, CK_NullToPointer); return Compatible; } @@ -6256,8 +6729,11 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // expressions that suppress this implicit conversion (&, sizeof). // // Suppress this for references: C++ 8.5.3p5. - if (!lhsType->isReferenceType()) - DefaultFunctionArrayLvalueConversion(rExpr); + if (!lhsType->isReferenceType()) { + rExpr = DefaultFunctionArrayLvalueConversion(rExpr.take()); + if (rExpr.isInvalid()) + return Incompatible; + } CastKind Kind = CK_Invalid; Sema::AssignConvertType result = @@ -6269,25 +6745,25 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // so that we can use references in built-in functions even in C. // The getNonReferenceType() call makes sure that the resulting expression // does not have reference type. - if (result != Incompatible && rExpr->getType() != lhsType) - ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context), Kind); + if (result != Incompatible && rExpr.get()->getType() != lhsType) + rExpr = ImpCastExprToType(rExpr.take(), lhsType.getNonLValueExprType(Context), Kind); return result; } -QualType Sema::InvalidOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { +QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &lex, ExprResult &rex) { Diag(Loc, diag::err_typecheck_invalid_operands) - << lex->getType() << rex->getType() - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } -QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { +QualType Sema::CheckVectorOperands(SourceLocation Loc, ExprResult &lex, ExprResult &rex) { // For conversion purposes, we ignore any qualifiers. // For example, "const float" and "float" are equivalent. QualType lhsType = - Context.getCanonicalType(lex->getType()).getUnqualifiedType(); + Context.getCanonicalType(lex.get()->getType()).getUnqualifiedType(); QualType rhsType = - Context.getCanonicalType(rex->getType()).getUnqualifiedType(); + Context.getCanonicalType(rex.get()->getType()).getUnqualifiedType(); // If the vector types are identical, return. if (lhsType == rhsType) @@ -6301,17 +6777,17 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { if (LV->getElementType() == RV->getElementType() && LV->getNumElements() == RV->getNumElements()) { if (lhsType->isExtVectorType()) { - ImpCastExprToType(rex, lhsType, CK_BitCast); + rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); return lhsType; } - ImpCastExprToType(lex, rhsType, CK_BitCast); + lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast); return rhsType; } else if (Context.getTypeSize(lhsType) ==Context.getTypeSize(rhsType)){ // If we are allowing lax vector conversions, and LHS and RHS are both // vectors, the total size only needs to be the same. This is a // bitcast; no bits are changed but the result type is different. - ImpCastExprToType(rex, lhsType, CK_BitCast); + rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); return lhsType; } } @@ -6321,7 +6797,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { // Handle the case of equivalent AltiVec and GCC vector types if (lhsType->isVectorType() && rhsType->isVectorType() && Context.areCompatibleVectorTypes(lhsType, rhsType)) { - ImpCastExprToType(lex, rhsType, CK_BitCast); + lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast); return rhsType; } @@ -6340,9 +6816,9 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) { int order = Context.getIntegerTypeOrder(EltTy, rhsType); if (order > 0) - ImpCastExprToType(rex, EltTy, CK_IntegralCast); + rex = ImpCastExprToType(rex.take(), EltTy, CK_IntegralCast); if (order >= 0) { - ImpCastExprToType(rex, lhsType, CK_VectorSplat); + rex = ImpCastExprToType(rex.take(), lhsType, CK_VectorSplat); if (swapped) std::swap(rex, lex); return lhsType; } @@ -6351,9 +6827,9 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { rhsType->isRealFloatingType()) { int order = Context.getFloatingTypeOrder(EltTy, rhsType); if (order > 0) - ImpCastExprToType(rex, EltTy, CK_FloatingCast); + rex = ImpCastExprToType(rex.take(), EltTy, CK_FloatingCast); if (order >= 0) { - ImpCastExprToType(rex, lhsType, CK_VectorSplat); + rex = ImpCastExprToType(rex.take(), lhsType, CK_VectorSplat); if (swapped) std::swap(rex, lex); return lhsType; } @@ -6362,72 +6838,78 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { // Vectors of different size or scalar and non-ext-vector are errors. Diag(Loc, diag::err_typecheck_vector_not_convertable) - << lex->getType() << rex->getType() - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } QualType Sema::CheckMultiplyDivideOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign, bool isDiv) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) + ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign, bool isDiv) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) return CheckVectorOperands(Loc, lex, rex); QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); - if (!lex->getType()->isArithmeticType() || - !rex->getType()->isArithmeticType()) + if (!lex.get()->getType()->isArithmeticType() || + !rex.get()->getType()->isArithmeticType()) return InvalidOperands(Loc, lex, rex); // Check for division by zero. if (isDiv && - rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) - DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_division_by_zero) - << rex->getSourceRange()); + rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(Loc, rex.get(), PDiag(diag::warn_division_by_zero) + << rex.get()->getSourceRange()); return compType; } QualType Sema::CheckRemainderOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { - if (lex->getType()->hasIntegerRepresentation() && - rex->getType()->hasIntegerRepresentation()) + ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { + if (lex.get()->getType()->hasIntegerRepresentation() && + rex.get()->getType()->hasIntegerRepresentation()) return CheckVectorOperands(Loc, lex, rex); return InvalidOperands(Loc, lex, rex); } QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); - if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType()) + if (!lex.get()->getType()->isIntegerType() || !rex.get()->getType()->isIntegerType()) return InvalidOperands(Loc, lex, rex); // Check for remainder by zero. - if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) - DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_remainder_by_zero) - << rex->getSourceRange()); + if (rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(Loc, rex.get(), PDiag(diag::warn_remainder_by_zero) + << rex.get()->getSourceRange()); return compType; } QualType Sema::CheckAdditionOperands( // C99 6.5.6 - Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { + ExprResult &lex, ExprResult &rex, SourceLocation Loc, QualType* CompLHSTy) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { QualType compType = CheckVectorOperands(Loc, lex, rex); if (CompLHSTy) *CompLHSTy = compType; return compType; } QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); // handle the common case first (both operands are arithmetic). - if (lex->getType()->isArithmeticType() && - rex->getType()->isArithmeticType()) { + if (lex.get()->getType()->isArithmeticType() && + rex.get()->getType()->isArithmeticType()) { if (CompLHSTy) *CompLHSTy = compType; return compType; } // Put any potential pointer into PExp - Expr* PExp = lex, *IExp = rex; + Expr* PExp = lex.get(), *IExp = rex.get(); if (IExp->getType()->isAnyPointerType()) std::swap(PExp, IExp); @@ -6440,23 +6922,23 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 if (PointeeTy->isVoidType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_void_type) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } // GNU extension: arithmetic on pointer to void Diag(Loc, diag::ext_gnu_void_ptr) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } else if (PointeeTy->isFunctionType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_function_type) - << lex->getType() << lex->getSourceRange(); + << lex.get()->getType() << lex.get()->getSourceRange(); return QualType(); } // GNU extension: arithmetic on pointer to function Diag(Loc, diag::ext_gnu_ptr_func_arith) - << lex->getType() << lex->getSourceRange(); + << lex.get()->getType() << lex.get()->getSourceRange(); } else { // Check if we require a complete type. if (((PExp->getType()->isPointerType() && @@ -6476,9 +6958,9 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 } if (CompLHSTy) { - QualType LHSTy = Context.isPromotableBitField(lex); + QualType LHSTy = Context.isPromotableBitField(lex.get()); if (LHSTy.isNull()) { - LHSTy = lex->getType(); + LHSTy = lex.get()->getType(); if (LHSTy->isPromotableIntegerType()) LHSTy = Context.getPromotedIntegerType(LHSTy); } @@ -6492,28 +6974,30 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 } // C99 6.5.6 -QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, +QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, QualType* CompLHSTy) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { QualType compType = CheckVectorOperands(Loc, lex, rex); if (CompLHSTy) *CompLHSTy = compType; return compType; } QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); // Enforce type constraints: C99 6.5.6p3. // Handle the common case first (both operands are arithmetic). - if (lex->getType()->isArithmeticType() - && rex->getType()->isArithmeticType()) { + if (lex.get()->getType()->isArithmeticType() && + rex.get()->getType()->isArithmeticType()) { if (CompLHSTy) *CompLHSTy = compType; return compType; } // Either ptr - int or ptr - ptr. - if (lex->getType()->isAnyPointerType()) { - QualType lpointee = lex->getType()->getPointeeType(); + if (lex.get()->getType()->isAnyPointerType()) { + QualType lpointee = lex.get()->getType()->getPointeeType(); // The LHS must be an completely-defined object type. @@ -6522,7 +7006,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, if (lpointee->isVoidType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_void_type) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } @@ -6531,42 +7015,42 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, } else if (lpointee->isFunctionType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_function_type) - << lex->getType() << lex->getSourceRange(); + << lex.get()->getType() << lex.get()->getSourceRange(); return QualType(); } // GNU C extension: arithmetic on pointer to function - ComplainAboutFunc = lex; + ComplainAboutFunc = lex.get(); } else if (!lpointee->isDependentType() && RequireCompleteType(Loc, lpointee, PDiag(diag::err_typecheck_sub_ptr_object) - << lex->getSourceRange() - << lex->getType())) + << lex.get()->getSourceRange() + << lex.get()->getType())) return QualType(); // Diagnose bad cases where we step over interface counts. if (lpointee->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(Loc, diag::err_arithmetic_nonfragile_interface) - << lpointee << lex->getSourceRange(); + << lpointee << lex.get()->getSourceRange(); return QualType(); } // The result type of a pointer-int computation is the pointer type. - if (rex->getType()->isIntegerType()) { + if (rex.get()->getType()->isIntegerType()) { if (ComplainAboutVoid) Diag(Loc, diag::ext_gnu_void_ptr) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); if (ComplainAboutFunc) Diag(Loc, diag::ext_gnu_ptr_func_arith) << ComplainAboutFunc->getType() << ComplainAboutFunc->getSourceRange(); - if (CompLHSTy) *CompLHSTy = lex->getType(); - return lex->getType(); + if (CompLHSTy) *CompLHSTy = lex.get()->getType(); + return lex.get()->getType(); } // Handle pointer-pointer subtractions. - if (const PointerType *RHSPTy = rex->getType()->getAs()) { + if (const PointerType *RHSPTy = rex.get()->getType()->getAs()) { QualType rpointee = RHSPTy->getPointeeType(); // RHS must be a completely-type object type. @@ -6574,7 +7058,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, if (rpointee->isVoidType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_void_type) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } @@ -6582,26 +7066,26 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, } else if (rpointee->isFunctionType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_function_type) - << rex->getType() << rex->getSourceRange(); + << rex.get()->getType() << rex.get()->getSourceRange(); return QualType(); } // GNU extension: arithmetic on pointer to function if (!ComplainAboutFunc) - ComplainAboutFunc = rex; + ComplainAboutFunc = rex.get(); } else if (!rpointee->isDependentType() && RequireCompleteType(Loc, rpointee, PDiag(diag::err_typecheck_sub_ptr_object) - << rex->getSourceRange() - << rex->getType())) + << rex.get()->getSourceRange() + << rex.get()->getType())) return QualType(); if (getLangOptions().CPlusPlus) { // Pointee types must be the same: C++ [expr.add] if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) { Diag(Loc, diag::err_typecheck_sub_ptr_compatible) - << lex->getType() << rex->getType() - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } } else { @@ -6610,21 +7094,21 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, Context.getCanonicalType(lpointee).getUnqualifiedType(), Context.getCanonicalType(rpointee).getUnqualifiedType())) { Diag(Loc, diag::err_typecheck_sub_ptr_compatible) - << lex->getType() << rex->getType() - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } } if (ComplainAboutVoid) Diag(Loc, diag::ext_gnu_void_ptr) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); if (ComplainAboutFunc) Diag(Loc, diag::ext_gnu_ptr_func_arith) << ComplainAboutFunc->getType() << ComplainAboutFunc->getSourceRange(); - if (CompLHSTy) *CompLHSTy = lex->getType(); + if (CompLHSTy) *CompLHSTy = lex.get()->getType(); return Context.getPointerDiffType(); } } @@ -6638,22 +7122,26 @@ static bool isScopedEnumerationType(QualType T) { return false; } -static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex, +static void DiagnoseBadShiftValues(Sema& S, ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned Opc, QualType LHSTy) { llvm::APSInt Right; // Check right/shifter operand - if (rex->isValueDependent() || !rex->isIntegerConstantExpr(Right, S.Context)) + if (rex.get()->isValueDependent() || !rex.get()->isIntegerConstantExpr(Right, S.Context)) return; if (Right.isNegative()) { - S.Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange(); + S.DiagRuntimeBehavior(Loc, rex.get(), + S.PDiag(diag::warn_shift_negative) + << rex.get()->getSourceRange()); return; } llvm::APInt LeftBits(Right.getBitWidth(), - S.Context.getTypeSize(lex->getType())); + S.Context.getTypeSize(lex.get()->getType())); if (Right.uge(LeftBits)) { - S.Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange(); + S.DiagRuntimeBehavior(Loc, rex.get(), + S.PDiag(diag::warn_shift_gt_typewidth) + << rex.get()->getSourceRange()); return; } if (Opc != BO_Shl) @@ -6664,7 +7152,7 @@ static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex, // integers have defined behavior modulo one more than the maximum value // representable in the result type, so never warn for those. llvm::APSInt Left; - if (lex->isValueDependent() || !lex->isIntegerConstantExpr(Left, S.Context) || + if (lex.get()->isValueDependent() || !lex.get()->isIntegerConstantExpr(Left, S.Context) || LHSTy->hasUnsignedIntegerRepresentation()) return; llvm::APInt ResultBits = @@ -6681,32 +7169,32 @@ static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex, if (LeftBits == ResultBits - 1) { S.Diag(Loc, diag::warn_shift_result_overrides_sign_bit) << Result.toString(10) << LHSTy - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return; } S.Diag(Loc, diag::warn_shift_result_gt_typewidth) << Result.toString(10) << Result.getMinSignedBits() << LHSTy - << Left.getBitWidth() << lex->getSourceRange() << rex->getSourceRange(); + << Left.getBitWidth() << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } // C99 6.5.7 -QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, +QualType Sema::CheckShiftOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned Opc, bool isCompAssign) { // C99 6.5.7p2: Each of the operands shall have integer type. - if (!lex->getType()->hasIntegerRepresentation() || - !rex->getType()->hasIntegerRepresentation()) + if (!lex.get()->getType()->hasIntegerRepresentation() || + !rex.get()->getType()->hasIntegerRepresentation()) return InvalidOperands(Loc, lex, rex); // C++0x: Don't allow scoped enums. FIXME: Use something better than // hasIntegerRepresentation() above instead of this. - if (isScopedEnumerationType(lex->getType()) || - isScopedEnumerationType(rex->getType())) { + if (isScopedEnumerationType(lex.get()->getType()) || + isScopedEnumerationType(rex.get()->getType())) { return InvalidOperands(Loc, lex, rex); } // Vector shifts promote their scalar inputs to vector type. - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) return CheckVectorOperands(Loc, lex, rex); // Shifts don't perform usual arithmetic conversions, they just do integer @@ -6714,13 +7202,17 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, // For the LHS, do usual unary conversions, but then reset them away // if this is a compound assignment. - Expr *old_lex = lex; - UsualUnaryConversions(lex); - QualType LHSTy = lex->getType(); + ExprResult old_lex = lex; + lex = UsualUnaryConversions(lex.take()); + if (lex.isInvalid()) + return QualType(); + QualType LHSTy = lex.get()->getType(); if (isCompAssign) lex = old_lex; // The RHS is simpler. - UsualUnaryConversions(rex); + rex = UsualUnaryConversions(rex.take()); + if (rex.isInvalid()) + return QualType(); // Sanity-check shift operands DiagnoseBadShiftValues(*this, lex, rex, Loc, Opc, LHSTy); @@ -6740,22 +7232,24 @@ static bool IsWithinTemplateSpecialization(Decl *D) { } // C99 6.5.8, C++ [expr.rel] -QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, +QualType Sema::CheckCompareOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned OpaqueOpc, bool isRelational) { BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc; // Handle vector comparisons separately. - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) return CheckVectorCompareOperands(lex, rex, Loc, isRelational); - QualType lType = lex->getType(); - QualType rType = rex->getType(); - - Expr *LHSStripped = lex->IgnoreParenImpCasts(); - Expr *RHSStripped = rex->IgnoreParenImpCasts(); + QualType lType = lex.get()->getType(); + QualType rType = rex.get()->getType(); + + Expr *LHSStripped = lex.get()->IgnoreParenImpCasts(); + Expr *RHSStripped = rex.get()->IgnoreParenImpCasts(); QualType LHSStrippedType = LHSStripped->getType(); QualType RHSStrippedType = RHSStripped->getType(); + + // Two different enums will raise a warning when compared. if (const EnumType *LHSEnumType = LHSStrippedType->getAs()) { if (const EnumType *RHSEnumType = RHSStrippedType->getAs()) { @@ -6764,15 +7258,15 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, !Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) { Diag(Loc, diag::warn_comparison_of_mixed_enum_types) << LHSStrippedType << RHSStrippedType - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } } } if (!lType->hasFloatingRepresentation() && !(lType->isBlockPointerType() && isRelational) && - !lex->getLocStart().isMacroID() && - !rex->getLocStart().isMacroID()) { + !lex.get()->getLocStart().isMacroID() && + !rex.get()->getLocStart().isMacroID()) { // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. @@ -6828,13 +7322,13 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if ((isa(LHSStripped) || isa(LHSStripped)) && !RHSStripped->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - literalString = lex; + literalString = lex.get(); literalStringStripped = LHSStripped; } else if ((isa(RHSStripped) || isa(RHSStripped)) && !LHSStripped->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - literalString = rex; + literalString = rex.get(); literalStringStripped = RHSStripped; } @@ -6858,15 +7352,23 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } // C99 6.5.8p3 / C99 6.5.9p4 - if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType()) + if (lex.get()->getType()->isArithmeticType() && rex.get()->getType()->isArithmeticType()) { UsualArithmeticConversions(lex, rex); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); + } else { - UsualUnaryConversions(lex); - UsualUnaryConversions(rex); + lex = UsualUnaryConversions(lex.take()); + if (lex.isInvalid()) + return QualType(); + + rex = UsualUnaryConversions(rex.take()); + if (rex.isInvalid()) + return QualType(); } - lType = lex->getType(); - rType = rex->getType(); + lType = lex.get()->getType(); + rType = rex.get()->getType(); // The result of comparisons is 'bool' in C++, 'int' in C. QualType ResultTy = Context.getLogicalOperationType(); @@ -6877,15 +7379,15 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } else { // Check for comparisons of floating point operands using != and ==. if (lType->hasFloatingRepresentation()) - CheckFloatComparison(Loc,lex,rex); + CheckFloatComparison(Loc, lex.get(), rex.get()); if (lType->isArithmeticType() && rType->isArithmeticType()) return ResultTy; } - bool LHSIsNull = lex->isNullPointerConstant(Context, + bool LHSIsNull = lex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); - bool RHSIsNull = rex->isNullPointerConstant(Context, + bool RHSIsNull = rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); // All of the following pointer-related warnings are GCC extensions, except @@ -6911,12 +7413,12 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, isSFINAEContext()? diag::err_typecheck_comparison_of_fptr_to_void : diag::ext_typecheck_comparison_of_fptr_to_void) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); if (isSFINAEContext()) return QualType(); - ImpCastExprToType(rex, lType, CK_BitCast); + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } } @@ -6934,17 +7436,17 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, isSFINAEContext()? 0 : &NonStandardCompositeType); if (T.isNull()) { Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } else if (NonStandardCompositeType) { Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard) << lType << rType << T - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(lex, T, CK_BitCast); - ImpCastExprToType(rex, T, CK_BitCast); + lex = ImpCastExprToType(lex.take(), T, CK_BitCast); + rex = ImpCastExprToType(rex.take(), T, CK_BitCast); return ResultTy; } // C99 6.5.9p2 and C99 6.5.8p2 @@ -6953,7 +7455,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, // Valid unless a relational comparison of function pointers if (isRelational && LCanPointeeTy->isFunctionType()) { Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } } else if (!isRelational && (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { @@ -6961,15 +7463,19 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) && !LHSIsNull && !RHSIsNull) { Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } } else { // Invalid Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + if (LCanPointeeTy != RCanPointeeTy) { + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); } - if (LCanPointeeTy != RCanPointeeTy) - ImpCastExprToType(rex, lType, CK_BitCast); return ResultTy; } @@ -6983,7 +7489,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (RHSIsNull && ((lType->isPointerType() || lType->isNullPtrType()) || (!isRelational && lType->isMemberPointerType()))) { - ImpCastExprToType(rex, lType, + rex = ImpCastExprToType(rex.take(), lType, lType->isMemberPointerType() ? CK_NullToMemberPointer : CK_NullToPointer); @@ -6992,7 +7498,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (LHSIsNull && ((rType->isPointerType() || rType->isNullPtrType()) || (!isRelational && rType->isMemberPointerType()))) { - ImpCastExprToType(lex, rType, + lex = ImpCastExprToType(lex.take(), rType, rType->isMemberPointerType() ? CK_NullToMemberPointer : CK_NullToPointer); @@ -7017,19 +7523,25 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, isSFINAEContext()? 0 : &NonStandardCompositeType); if (T.isNull()) { Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } else if (NonStandardCompositeType) { Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard) << lType << rType << T - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(lex, T, CK_BitCast); - ImpCastExprToType(rex, T, CK_BitCast); + lex = ImpCastExprToType(lex.take(), T, CK_BitCast); + rex = ImpCastExprToType(rex.take(), T, CK_BitCast); return ResultTy; } + + // Handle scoped enumeration types specifically, since they don't promote + // to integers. + if (lex.get()->getType()->isEnumeralType() && + Context.hasSameUnqualifiedType(lex.get()->getType(), rex.get()->getType())) + return ResultTy; } // Handle block pointer types. @@ -7040,49 +7552,57 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (!LHSIsNull && !RHSIsNull && !Context.typesAreCompatible(lpointee, rpointee)) { Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(rex, lType, CK_BitCast); + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } + // Allow block pointers to be compared with null pointer constants. if (!isRelational && ((lType->isBlockPointerType() && rType->isPointerType()) || (lType->isPointerType() && rType->isBlockPointerType()))) { if (!LHSIsNull && !RHSIsNull) { - if (!((rType->isPointerType() && rType->getAs() + if (!((rType->isPointerType() && rType->castAs() ->getPointeeType()->isVoidType()) - || (lType->isPointerType() && lType->getAs() + || (lType->isPointerType() && lType->castAs() ->getPointeeType()->isVoidType()))) Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(rex, lType, CK_BitCast); + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } - if ((lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType())) { - if (lType->isPointerType() || rType->isPointerType()) { - const PointerType *LPT = lType->getAs(); - const PointerType *RPT = rType->getAs(); - bool LPtrToVoid = LPT ? - Context.getCanonicalType(LPT->getPointeeType())->isVoidType() : false; - bool RPtrToVoid = RPT ? - Context.getCanonicalType(RPT->getPointeeType())->isVoidType() : false; + if (lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType()) { + const PointerType *LPT = lType->getAs(); + const PointerType *RPT = rType->getAs(); + if (LPT || RPT) { + bool LPtrToVoid = LPT ? LPT->getPointeeType()->isVoidType() : false; + bool RPtrToVoid = RPT ? RPT->getPointeeType()->isVoidType() : false; if (!LPtrToVoid && !RPtrToVoid && !Context.typesAreCompatible(lType, rType)) { Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(rex, lType, CK_BitCast); + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) { if (!Context.areComparableObjCPointerTypes(lType, rType)) Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - ImpCastExprToType(rex, lType, CK_BitCast); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } } @@ -7104,16 +7624,16 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (DiagID) { Diag(Loc, DiagID) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); if (isError) return QualType(); } if (lType->isIntegerType()) - ImpCastExprToType(lex, rType, + lex = ImpCastExprToType(lex.take(), rType, LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); else - ImpCastExprToType(rex, lType, + rex = ImpCastExprToType(rex.take(), lType, RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); return ResultTy; } @@ -7121,14 +7641,15 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, // Handle block pointers. if (!isRelational && RHSIsNull && lType->isBlockPointerType() && rType->isIntegerType()) { - ImpCastExprToType(rex, lType, CK_NullToPointer); + rex = ImpCastExprToType(rex.take(), lType, CK_NullToPointer); return ResultTy; } if (!isRelational && LHSIsNull && lType->isIntegerType() && rType->isBlockPointerType()) { - ImpCastExprToType(lex, rType, CK_NullToPointer); + lex = ImpCastExprToType(lex.take(), rType, CK_NullToPointer); return ResultTy; } + return InvalidOperands(Loc, lex, rex); } @@ -7136,7 +7657,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, /// operates on extended vector types. Instead of producing an IntTy result, /// like a scalar comparison, a vector comparison produces a vector of integer /// types. -QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, +QualType Sema::CheckVectorCompareOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isRelational) { // Check to make sure we're operating on vectors of the same type and width, @@ -7145,20 +7666,20 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, if (vType.isNull()) return vType; + QualType lType = lex.get()->getType(); + QualType rType = rex.get()->getType(); + // If AltiVec, the comparison results in a numeric type, i.e. // bool for C++, int for C - if (getLangOptions().AltiVec) + if (vType->getAs()->getVectorKind() == VectorType::AltiVecVector) return Context.getLogicalOperationType(); - QualType lType = lex->getType(); - QualType rType = rex->getType(); - // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. if (!lType->hasFloatingRepresentation()) { - if (DeclRefExpr* DRL = dyn_cast(lex->IgnoreParens())) - if (DeclRefExpr* DRR = dyn_cast(rex->IgnoreParens())) + if (DeclRefExpr* DRL = dyn_cast(lex.get()->IgnoreParens())) + if (DeclRefExpr* DRR = dyn_cast(rex.get()->IgnoreParens())) if (DRL->getDecl() == DRR->getDecl()) DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) @@ -7170,7 +7691,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, // Check for comparisons of floating point operands using != and ==. if (!isRelational && lType->hasFloatingRepresentation()) { assert (rType->hasFloatingRepresentation()); - CheckFloatComparison(Loc,lex,rex); + CheckFloatComparison(Loc, lex.get(), rex.get()); } // Return the type for the comparison, which is the same as vector type for @@ -7192,51 +7713,61 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, } inline QualType Sema::CheckBitwiseOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { - if (lex->getType()->hasIntegerRepresentation() && - rex->getType()->hasIntegerRepresentation()) + ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { + if (lex.get()->getType()->hasIntegerRepresentation() && + rex.get()->getType()->hasIntegerRepresentation()) return CheckVectorOperands(Loc, lex, rex); return InvalidOperands(Loc, lex, rex); } - QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); + ExprResult lexResult = Owned(lex), rexResult = Owned(rex); + QualType compType = UsualArithmeticConversions(lexResult, rexResult, isCompAssign); + if (lexResult.isInvalid() || rexResult.isInvalid()) + return QualType(); + lex = lexResult.take(); + rex = rexResult.take(); - if (lex->getType()->isIntegralOrUnscopedEnumerationType() && - rex->getType()->isIntegralOrUnscopedEnumerationType()) + if (lex.get()->getType()->isIntegralOrUnscopedEnumerationType() && + rex.get()->getType()->isIntegralOrUnscopedEnumerationType()) return compType; return InvalidOperands(Loc, lex, rex); } inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] - Expr *&lex, Expr *&rex, SourceLocation Loc, unsigned Opc) { + ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned Opc) { // Diagnose cases where the user write a logical and/or but probably meant a // bitwise one. We do this when the LHS is a non-bool integer and the RHS // is a constant. - if (lex->getType()->isIntegerType() && !lex->getType()->isBooleanType() && - rex->getType()->isIntegerType() && !rex->isValueDependent() && + if (lex.get()->getType()->isIntegerType() && !lex.get()->getType()->isBooleanType() && + rex.get()->getType()->isIntegerType() && !rex.get()->isValueDependent() && // Don't warn in macros. !Loc.isMacroID()) { // If the RHS can be constant folded, and if it constant folds to something // that isn't 0 or 1 (which indicate a potential logical operation that // happened to fold to true/false) then warn. Expr::EvalResult Result; - if (rex->Evaluate(Result, Context) && !Result.HasSideEffects && + if (rex.get()->Evaluate(Result, Context) && !Result.HasSideEffects && Result.Val.getInt() != 0 && Result.Val.getInt() != 1) { Diag(Loc, diag::warn_logical_instead_of_bitwise) - << rex->getSourceRange() + << rex.get()->getSourceRange() << (Opc == BO_LAnd ? "&&" : "||") << (Opc == BO_LAnd ? "&" : "|"); } } if (!Context.getLangOptions().CPlusPlus) { - UsualUnaryConversions(lex); - UsualUnaryConversions(rex); + lex = UsualUnaryConversions(lex.take()); + if (lex.isInvalid()) + return QualType(); - if (!lex->getType()->isScalarType() || !rex->getType()->isScalarType()) + rex = UsualUnaryConversions(rex.take()); + if (rex.isInvalid()) + return QualType(); + + if (!lex.get()->getType()->isScalarType() || !rex.get()->getType()->isScalarType()) return InvalidOperands(Loc, lex, rex); return Context.IntTy; @@ -7248,9 +7779,15 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] // C++ [expr.log.and]p1 // C++ [expr.log.or]p1 // The operands are both contextually converted to type bool. - if (PerformContextuallyConvertToBool(lex) || - PerformContextuallyConvertToBool(rex)) + ExprResult lexRes = PerformContextuallyConvertToBool(lex.get()); + if (lexRes.isInvalid()) return InvalidOperands(Loc, lex, rex); + lex = move(lexRes); + + ExprResult rexRes = PerformContextuallyConvertToBool(rex.get()); + if (rexRes.isInvalid()) + return InvalidOperands(Loc, lex, rex); + rex = move(rexRes); // C++ [expr.log.and]p2 // C++ [expr.log.or]p2 @@ -7281,6 +7818,35 @@ static bool IsReadonlyProperty(Expr *E, Sema &S) { return false; } +static bool IsConstProperty(Expr *E, Sema &S) { + if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) { + const ObjCPropertyRefExpr* PropExpr = cast(E); + if (PropExpr->isImplicitProperty()) return false; + + ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); + QualType T = PDecl->getType(); + if (T->isReferenceType()) + T = T->getAs()->getPointeeType(); + CanQualType CT = S.Context.getCanonicalType(T); + return CT.isConstQualified(); + } + return false; +} + +static bool IsReadonlyMessage(Expr *E, Sema &S) { + if (E->getStmtClass() != Expr::MemberExprClass) + return false; + const MemberExpr *ME = cast(E); + NamedDecl *Member = ME->getMemberDecl(); + if (isa(Member)) { + Expr *Base = ME->getBase()->IgnoreParenImpCasts(); + if (Base->getStmtClass() != Expr::ObjCMessageExprClass) + return false; + return cast(Base)->getMethodDecl() != 0; + } + return false; +} + /// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not, /// emit an error and return true. If so, return false. static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { @@ -7289,6 +7855,10 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { &Loc); if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S)) IsLV = Expr::MLV_ReadonlyProperty; + else if (Expr::MLV_ConstQualified && IsConstProperty(E, S)) + IsLV = Expr::MLV_Valid; + else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S)) + IsLV = Expr::MLV_InvalidMessageExpression; if (IsLV == Expr::MLV_Valid) return false; @@ -7331,6 +7901,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { case Expr::MLV_NoSetterProperty: Diag = diag::error_nosetter_property_assignment; break; + case Expr::MLV_InvalidMessageExpression: + Diag = diag::error_readonly_message_assignment; + break; case Expr::MLV_SubObjCPropertySetting: Diag = diag::error_no_subobject_property_setting; break; @@ -7349,7 +7922,7 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { // C99 6.5.16.1 -QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, +QualType Sema::CheckAssignmentOperands(Expr *LHS, ExprResult &RHS, SourceLocation Loc, QualType CompoundType) { // Verify that LHS is a modifiable lvalue, and emit error if not. @@ -7357,14 +7930,21 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, return QualType(); QualType LHSType = LHS->getType(); - QualType RHSType = CompoundType.isNull() ? RHS->getType() : CompoundType; + QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() : CompoundType; AssignConvertType ConvTy; if (CompoundType.isNull()) { QualType LHSTy(LHSType); // Simple assignment "x = y". - if (LHS->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForLValue(LHS, RHS, LHSTy); + if (LHS->getObjectKind() == OK_ObjCProperty) { + ExprResult LHSResult = Owned(LHS); + ConvertPropertyForLValue(LHSResult, RHS, LHSTy); + if (LHSResult.isInvalid()) + return QualType(); + LHS = LHSResult.take(); + } ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); + if (RHS.isInvalid()) + return QualType(); // Special case of NSObject attributes on c-style pointer types. if (ConvTy == IncompatiblePointer && ((Context.isObjCNSObjectType(LHSType) && @@ -7382,7 +7962,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, // If the RHS is a unary plus or minus, check to see if they = and + are // right next to each other. If so, the user may have typo'd "x =+ 4" // instead of "x += 4". - Expr *RHSCheck = RHS; + Expr *RHSCheck = RHS.get(); if (ImplicitCastExpr *ICE = dyn_cast(RHSCheck)) RHSCheck = ICE->getSubExpr(); if (UnaryOperator *UO = dyn_cast(RHSCheck)) { @@ -7406,32 +7986,12 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, } if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType, - RHS, AA_Assigning)) + RHS.get(), AA_Assigning)) return QualType(); - - // Check to see if the destination operand is a dereferenced null pointer. If - // so, and if not volatile-qualified, this is undefined behavior that the - // optimizer will delete, so warn about it. People sometimes try to use this - // to get a deterministic trap and are surprised by clang's behavior. This - // only handles the pattern "*null = whatever", which is a very syntactic - // check. - if (UnaryOperator *UO = dyn_cast(LHS->IgnoreParenCasts())) - if (UO->getOpcode() == UO_Deref && - UO->getSubExpr()->IgnoreParenCasts()-> - isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) && - !UO->getType().isVolatileQualified()) { - DiagRuntimeBehavior(UO->getOperatorLoc(), UO, - PDiag(diag::warn_indirection_through_null) - << UO->getSubExpr()->getSourceRange()); - DiagRuntimeBehavior(UO->getOperatorLoc(), UO, - PDiag(diag::note_indirection_through_null)); - } - + CheckForNullPointerDereference(*this, LHS); // Check for trivial buffer overflows. - if (const ArraySubscriptExpr *ae - = dyn_cast(LHS->IgnoreParenCasts())) - CheckArrayAccess(ae); + CheckArrayAccess(LHS->IgnoreParenCasts()); // C99 6.5.16p3: The type of an assignment expression is the type of the // left operand unless the left operand has qualified type, in which case @@ -7445,34 +8005,34 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, } // C99 6.5.17 -static QualType CheckCommaOperands(Sema &S, Expr *&LHS, Expr *&RHS, +static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS, SourceLocation Loc) { - S.DiagnoseUnusedExprResult(LHS); + S.DiagnoseUnusedExprResult(LHS.get()); - ExprResult LHSResult = S.CheckPlaceholderExpr(LHS, Loc); - if (LHSResult.isInvalid()) + LHS = S.CheckPlaceholderExpr(LHS.take()); + RHS = S.CheckPlaceholderExpr(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); - ExprResult RHSResult = S.CheckPlaceholderExpr(RHS, Loc); - if (RHSResult.isInvalid()) - return QualType(); - RHS = RHSResult.take(); - // C's comma performs lvalue conversion (C99 6.3.2.1) on both its // operands, but not unary promotions. // C++'s comma does not do any conversions at all (C++ [expr.comma]p1). // So we treat the LHS as a ignored value, and in C++ we allow the // containing site to determine what should be done with the RHS. - S.IgnoredValueConversions(LHS); + LHS = S.IgnoredValueConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); if (!S.getLangOptions().CPlusPlus) { - S.DefaultFunctionArrayLvalueConversion(RHS); - if (!RHS->getType()->isVoidType()) - S.RequireCompleteType(Loc, RHS->getType(), diag::err_incomplete_type); + RHS = S.DefaultFunctionArrayLvalueConversion(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + if (!RHS.get()->getType()->isVoidType()) + S.RequireCompleteType(Loc, RHS.get()->getType(), diag::err_incomplete_type); } - return RHS->getType(); + return RHS.get()->getType(); } /// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine @@ -7535,7 +8095,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, S.Diag(OpLoc, diag::ext_integer_increment_complex) << ResType << Op->getSourceRange(); } else if (ResType->isPlaceholderType()) { - ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc); + ExprResult PR = S.CheckPlaceholderExpr(Op); if (PR.isInvalid()) return QualType(); return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc, isInc, isPrefix); @@ -7562,7 +8122,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, } } -void Sema::ConvertPropertyForRValue(Expr *&E) { +ExprResult Sema::ConvertPropertyForRValue(Expr *E) { assert(E->getValueKind() == VK_LValue && E->getObjectKind() == OK_ObjCProperty); const ObjCPropertyRefExpr *PRE = E->getObjCProperty(); @@ -7586,28 +8146,30 @@ void Sema::ConvertPropertyForRValue(Expr *&E) { ExprResult Result = MaybeBindToTemporary(E); if (!Result.isInvalid()) E = Result.take(); + + return Owned(E); } -void Sema::ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType &LHSTy) { - assert(LHS->getValueKind() == VK_LValue && - LHS->getObjectKind() == OK_ObjCProperty); - const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty(); +void Sema::ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS, QualType &LHSTy) { + assert(LHS.get()->getValueKind() == VK_LValue && + LHS.get()->getObjectKind() == OK_ObjCProperty); + const ObjCPropertyRefExpr *PropRef = LHS.get()->getObjCProperty(); - if (PRE->isImplicitProperty()) { + if (PropRef->isImplicitProperty()) { // If using property-dot syntax notation for assignment, and there is a // setter, RHS expression is being passed to the setter argument. So, // type conversion (and comparison) is RHS to setter's argument type. - if (const ObjCMethodDecl *SetterMD = PRE->getImplicitPropertySetter()) { + if (const ObjCMethodDecl *SetterMD = PropRef->getImplicitPropertySetter()) { ObjCMethodDecl::param_iterator P = SetterMD->param_begin(); LHSTy = (*P)->getType(); // Otherwise, if the getter returns an l-value, just call that. } else { - QualType Result = PRE->getImplicitPropertyGetter()->getResultType(); + QualType Result = PropRef->getImplicitPropertyGetter()->getResultType(); ExprValueKind VK = Expr::getValueKindForType(Result); if (VK == VK_LValue) { - LHS = ImplicitCastExpr::Create(Context, LHS->getType(), - CK_GetObjCProperty, LHS, 0, VK); + LHS = ImplicitCastExpr::Create(Context, LHS.get()->getType(), + CK_GetObjCProperty, LHS.take(), 0, VK); return; } } @@ -7616,11 +8178,9 @@ void Sema::ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType &LHSTy) { if (getLangOptions().CPlusPlus && LHSTy->isRecordType()) { InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, LHSTy); - Expr *Arg = RHS; - ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), - Owned(Arg)); + ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), RHS); if (!ArgE.isInvalid()) - RHS = ArgE.takeAs(); + RHS = ArgE; } } @@ -7695,10 +8255,15 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, return S.Context.DependentTy; if (OrigOp->getType() == S.Context.OverloadTy) return S.Context.OverloadTy; + if (OrigOp->getType() == S.Context.UnknownAnyTy) + return S.Context.UnknownAnyTy; + if (OrigOp->getType() == S.Context.BoundMemberTy) { + S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp->getSourceRange(); + return QualType(); + } - ExprResult PR = S.CheckPlaceholderExpr(OrigOp, OpLoc); - if (PR.isInvalid()) return QualType(); - OrigOp = PR.take(); + assert(!OrigOp->getType()->isPlaceholderType()); // Make sure to ignore parentheses in subsequent checks Expr *op = OrigOp->IgnoreParens(); @@ -7717,7 +8282,7 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, ValueDecl *dcl = getPrimaryDecl(op); Expr::LValueClassification lval = op->ClassifyLValue(S.Context); - if (lval == Expr::LV_ClassTemporary) { + if (lval == Expr::LV_ClassTemporary) { bool sfinae = S.isSFINAEContext(); S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary : diag::ext_typecheck_addrof_class_temporary) @@ -7833,7 +8398,10 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, if (Op->isTypeDependent()) return S.Context.DependentTy; - S.UsualUnaryConversions(Op); + ExprResult ConvResult = S.UsualUnaryConversions(Op); + if (ConvResult.isInvalid()) + return QualType(); + Op = ConvResult.take(); QualType OpTy = Op->getType(); QualType Result; @@ -7847,7 +8415,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, OpTy->getAs()) Result = OPT->getPointeeType(); else { - ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc); + ExprResult PR = S.CheckPlaceholderExpr(Op); if (PR.isInvalid()) return QualType(); if (PR.take() != Op) return CheckIndirectionOperand(S, PR.take(), VK, OpLoc); @@ -7970,7 +8538,8 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *lhs, Expr *rhs, /// built-in operations; ActOnBinOp handles overloaded operators. ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, - Expr *lhs, Expr *rhs) { + Expr *lhsExpr, Expr *rhsExpr) { + ExprResult lhs = Owned(lhsExpr), rhs = Owned(rhsExpr); QualType ResultTy; // Result type of the binary operator. // The following two variables are used for compound assignment operators QualType CompLHSTy; // Type of LHS after promotions for computation @@ -7978,16 +8547,33 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; + // Check if a 'foo' involved in a binary op, identifies a single + // function unambiguously (i.e. an lvalue ala 13.4) + // But since an assignment can trigger target based overload, exclude it in + // our blind search. i.e: + // template void f(); template void f(U); + // f == 0; // resolve f blindly + // void (*p)(int); p = f; // resolve f using target + if (Opc != BO_Assign) { + ExprResult resolvedLHS = CheckPlaceholderExpr(lhs.get()); + if (!resolvedLHS.isUsable()) return ExprError(); + lhs = move(resolvedLHS); + + ExprResult resolvedRHS = CheckPlaceholderExpr(rhs.get()); + if (!resolvedRHS.isUsable()) return ExprError(); + rhs = move(resolvedRHS); + } + switch (Opc) { case BO_Assign: - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType()); + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, QualType()); if (getLangOptions().CPlusPlus && - lhs->getObjectKind() != OK_ObjCProperty) { - VK = lhs->getValueKind(); - OK = lhs->getObjectKind(); + lhs.get()->getObjectKind() != OK_ObjCProperty) { + VK = lhs.get()->getValueKind(); + OK = lhs.get()->getObjectKind(); } if (!ResultTy.isNull()) - DiagnoseSelfAssignment(*this, lhs, rhs, OpLoc); + DiagnoseSelfAssignment(*this, lhs.get(), rhs.get(), OpLoc); break; case BO_PtrMemD: case BO_PtrMemI: @@ -8036,60 +8622,59 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true, Opc == BO_DivAssign); CompLHSTy = CompResultTy; - if (!CompResultTy.isNull()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); break; case BO_RemAssign: CompResultTy = CheckRemainderOperands(lhs, rhs, OpLoc, true); CompLHSTy = CompResultTy; - if (!CompResultTy.isNull()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); break; case BO_AddAssign: CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy); - if (!CompResultTy.isNull()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); break; case BO_SubAssign: CompResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc, &CompLHSTy); - if (!CompResultTy.isNull()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); break; case BO_ShlAssign: case BO_ShrAssign: CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc, true); CompLHSTy = CompResultTy; - if (!CompResultTy.isNull()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); break; case BO_AndAssign: case BO_XorAssign: case BO_OrAssign: CompResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true); CompLHSTy = CompResultTy; - if (!CompResultTy.isNull()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); break; case BO_Comma: ResultTy = CheckCommaOperands(*this, lhs, rhs, OpLoc); - if (getLangOptions().CPlusPlus) { - VK = rhs->getValueKind(); - OK = rhs->getObjectKind(); + if (getLangOptions().CPlusPlus && !rhs.isInvalid()) { + VK = rhs.get()->getValueKind(); + OK = rhs.get()->getObjectKind(); } break; } - if (ResultTy.isNull()) + if (ResultTy.isNull() || lhs.isInvalid() || rhs.isInvalid()) return ExprError(); if (CompResultTy.isNull()) - return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy, - VK, OK, OpLoc)); - - if (getLangOptions().CPlusPlus && lhs->getObjectKind() != OK_ObjCProperty) { + return Owned(new (Context) BinaryOperator(lhs.take(), rhs.take(), Opc, + ResultTy, VK, OK, OpLoc)); + if (getLangOptions().CPlusPlus && lhs.get()->getObjectKind() != OK_ObjCProperty) { VK = VK_LValue; - OK = lhs->getObjectKind(); + OK = lhs.get()->getObjectKind(); } - return Owned(new (Context) CompoundAssignOperator(lhs, rhs, Opc, ResultTy, - VK, OK, CompLHSTy, + return Owned(new (Context) CompoundAssignOperator(lhs.take(), rhs.take(), Opc, + ResultTy, VK, OK, CompLHSTy, CompResultTy, OpLoc)); } @@ -8161,23 +8746,23 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, Self.PDiag(diag::warn_precedence_bitwise_rel) << SourceRange(lhs->getLocStart(), OpLoc) << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc), - Self.PDiag(diag::note_precedence_bitwise_first) - << BinOp::getOpcodeStr(Opc), - SourceRange(cast(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()), Self.PDiag(diag::note_precedence_bitwise_silence) << BinOp::getOpcodeStr(lhsopc), - lhs->getSourceRange()); + lhs->getSourceRange(), + Self.PDiag(diag::note_precedence_bitwise_first) + << BinOp::getOpcodeStr(Opc), + SourceRange(cast(lhs)->getRHS()->getLocStart(), rhs->getLocEnd())); else if (BinOp::isComparisonOp(rhsopc)) SuggestParentheses(Self, OpLoc, Self.PDiag(diag::warn_precedence_bitwise_rel) << SourceRange(OpLoc, rhs->getLocEnd()) << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc), + Self.PDiag(diag::note_precedence_bitwise_silence) + << BinOp::getOpcodeStr(rhsopc), + rhs->getSourceRange(), Self.PDiag(diag::note_precedence_bitwise_first) << BinOp::getOpcodeStr(Opc), - SourceRange(lhs->getLocEnd(), cast(rhs)->getLHS()->getLocStart()), - Self.PDiag(diag::note_precedence_bitwise_silence) - << BinOp::getOpcodeStr(rhsopc), - rhs->getSourceRange()); + SourceRange(lhs->getLocEnd(), cast(rhs)->getLHS()->getLocStart())); } /// \brief It accepts a '&&' expr that is inside a '||' one. @@ -8185,14 +8770,13 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, /// in parentheses. static void EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc, - Expr *E) { - assert(isa(E) && - cast(E)->getOpcode() == BO_LAnd); - SuggestParentheses(Self, OpLoc, + BinaryOperator *Bop) { + assert(Bop->getOpcode() == BO_LAnd); + SuggestParentheses(Self, Bop->getOperatorLoc(), Self.PDiag(diag::warn_logical_and_in_logical_or) - << E->getSourceRange(), + << Bop->getSourceRange() << OpLoc, Self.PDiag(diag::note_logical_and_in_logical_or_silence), - E->getSourceRange(), + Bop->getSourceRange(), Self.PDiag(0), SourceRange()); } @@ -8316,7 +8900,8 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, - Expr *Input) { + Expr *InputExpr) { + ExprResult Input = Owned(InputExpr); ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; QualType resultType; @@ -8325,23 +8910,28 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, case UO_PreDec: case UO_PostInc: case UO_PostDec: - resultType = CheckIncrementDecrementOperand(*this, Input, VK, OpLoc, + resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OpLoc, Opc == UO_PreInc || Opc == UO_PostInc, Opc == UO_PreInc || Opc == UO_PreDec); break; case UO_AddrOf: - resultType = CheckAddressOfOperand(*this, Input, OpLoc); + resultType = CheckAddressOfOperand(*this, Input.get(), OpLoc); break; - case UO_Deref: - DefaultFunctionArrayLvalueConversion(Input); - resultType = CheckIndirectionOperand(*this, Input, VK, OpLoc); + case UO_Deref: { + ExprResult resolved = CheckPlaceholderExpr(Input.get()); + if (!resolved.isUsable()) return ExprError(); + Input = move(resolved); + Input = DefaultFunctionArrayLvalueConversion(Input.take()); + resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc); break; + } case UO_Plus: case UO_Minus: - UsualUnaryConversions(Input); - resultType = Input->getType(); + Input = UsualUnaryConversions(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); if (resultType->isDependentType()) break; if (resultType->isArithmeticType() || // C99 6.5.3.3p1 @@ -8355,49 +8945,59 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, resultType->isPointerType()) break; else if (resultType->isPlaceholderType()) { - ExprResult PR = CheckPlaceholderExpr(Input, OpLoc); - if (PR.isInvalid()) return ExprError(); - return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take()); + Input = CheckPlaceholderExpr(Input.take()); + if (Input.isInvalid()) return ExprError(); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); } return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input->getSourceRange()); + << resultType << Input.get()->getSourceRange()); + case UO_Not: // bitwise complement - UsualUnaryConversions(Input); - resultType = Input->getType(); + Input = UsualUnaryConversions(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); if (resultType->isDependentType()) break; // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. if (resultType->isComplexType() || resultType->isComplexIntegerType()) // C99 does not support '~' for complex conjugation. Diag(OpLoc, diag::ext_integer_complement_complex) - << resultType << Input->getSourceRange(); + << resultType << Input.get()->getSourceRange(); else if (resultType->hasIntegerRepresentation()) break; else if (resultType->isPlaceholderType()) { - ExprResult PR = CheckPlaceholderExpr(Input, OpLoc); - if (PR.isInvalid()) return ExprError(); - return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take()); + Input = CheckPlaceholderExpr(Input.take()); + if (Input.isInvalid()) return ExprError(); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); } else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input->getSourceRange()); + << resultType << Input.get()->getSourceRange()); } break; + case UO_LNot: // logical negation // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). - DefaultFunctionArrayLvalueConversion(Input); - resultType = Input->getType(); + Input = DefaultFunctionArrayLvalueConversion(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); if (resultType->isDependentType()) break; - if (resultType->isScalarType()) { // C99 6.5.3.3p1 - // ok, fallthrough + if (resultType->isScalarType()) { + // C99 6.5.3.3p1: ok, fallthrough; + if (Context.getLangOptions().CPlusPlus) { + // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: + // operand contextually converted to bool. + Input = ImpCastExprToType(Input.take(), Context.BoolTy, + ScalarTypeToBooleanCastKind(resultType)); + } } else if (resultType->isPlaceholderType()) { - ExprResult PR = CheckPlaceholderExpr(Input, OpLoc); - if (PR.isInvalid()) return ExprError(); - return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take()); + Input = CheckPlaceholderExpr(Input.take()); + if (Input.isInvalid()) return ExprError(); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); } else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input->getSourceRange()); + << resultType << Input.get()->getSourceRange()); } // LNot always has type int. C99 6.5.3.3p5. @@ -8408,20 +9008,21 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, case UO_Imag: resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); // _Real and _Imag map ordinary l-values into ordinary l-values. - if (Input->getValueKind() != VK_RValue && - Input->getObjectKind() == OK_Ordinary) - VK = Input->getValueKind(); + if (Input.isInvalid()) return ExprError(); + if (Input.get()->getValueKind() != VK_RValue && + Input.get()->getObjectKind() == OK_Ordinary) + VK = Input.get()->getValueKind(); break; case UO_Extension: - resultType = Input->getType(); - VK = Input->getValueKind(); - OK = Input->getObjectKind(); + resultType = Input.get()->getType(); + VK = Input.get()->getValueKind(); + OK = Input.get()->getObjectKind(); break; } - if (resultType.isNull()) + if (resultType.isNull() || Input.isInvalid()) return ExprError(); - return Owned(new (Context) UnaryOperator(Input, Opc, resultType, + return Owned(new (Context) UnaryOperator(Input.take(), Opc, resultType, VK, OK, OpLoc)); } @@ -8488,26 +9089,28 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, LastLabelStmt = Label; LastStmt = Label->getSubStmt(); } - if (Expr *LastExpr = dyn_cast(LastStmt)) { + if (Expr *LastE = dyn_cast(LastStmt)) { // Do function/array conversion on the last expression, but not // lvalue-to-rvalue. However, initialize an unqualified type. - DefaultFunctionArrayConversion(LastExpr); - Ty = LastExpr->getType().getUnqualifiedType(); + ExprResult LastExpr = DefaultFunctionArrayConversion(LastE); + if (LastExpr.isInvalid()) + return ExprError(); + Ty = LastExpr.get()->getType().getUnqualifiedType(); - if (!Ty->isDependentType() && !LastExpr->isTypeDependent()) { - ExprResult Res = PerformCopyInitialization( + if (!Ty->isDependentType() && !LastExpr.get()->isTypeDependent()) { + LastExpr = PerformCopyInitialization( InitializedEntity::InitializeResult(LPLoc, Ty, false), SourceLocation(), - Owned(LastExpr)); - if (Res.isInvalid()) + LastExpr); + if (LastExpr.isInvalid()) return ExprError(); - if ((LastExpr = Res.takeAs())) { + if (LastExpr.get() != 0) { if (!LastLabelStmt) - Compound->setLastStmt(LastExpr); + Compound->setLastStmt(LastExpr.take()); else - LastLabelStmt->setSubStmt(LastExpr); + LastLabelStmt->setSubStmt(LastExpr.take()); StmtExprMayBindToTemp = true; } } @@ -8779,8 +9382,8 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { // Check whether that explicit signature was synthesized by // GetTypeForDeclarator. If so, don't save that as part of the // written signature. - if (ExplicitSignature.getLParenLoc() == - ExplicitSignature.getRParenLoc()) { + if (ExplicitSignature.getLocalRangeBegin() == + ExplicitSignature.getLocalRangeEnd()) { // This would be much cheaper if we stored TypeLocs instead of // TypeSourceInfos. TypeLoc Result = ExplicitSignature.getResultLoc(); @@ -8942,7 +9545,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, // If we don't have a function type, just build one from nothing. } else { FunctionProtoType::ExtProtoInfo EPI; - EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, 0, CC_Default); + EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, false, 0, CC_Default); BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); } @@ -8984,7 +9587,10 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, // a pointer for va_arg. VaListType = Context.getArrayDecayedType(VaListType); // Make sure the input expression also decays appropriately. - UsualUnaryConversions(E); + ExprResult Result = UsualUnaryConversions(E); + if (Result.isInvalid()) + return ExprError(); + E = Result.take(); } else { // Otherwise, the va_list argument must be an l-value because // it is modified by va_arg. @@ -9260,6 +9866,8 @@ Sema::PopExpressionEvaluationContext() { void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { assert(D && "No declaration?"); + D->setReferenced(); + if (D->isUsed(false)) return; @@ -9393,6 +10001,9 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (MSInfo->getPointOfInstantiation().isInvalid() && MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) { MSInfo->setPointOfInstantiation(Loc); + // This is a modification of an existing AST node. Notify listeners. + if (ASTMutationListener *L = getASTMutationListener()) + L->StaticDataMemberInstantiated(Var); PendingInstantiations.push_back(std::make_pair(Var, Loc)); } } @@ -9624,10 +10235,13 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { return; } + Diag(Loc, diagnostic) << E->getSourceRange(); + SourceLocation Open = E->getSourceRange().getBegin(); SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd()); - - Diag(Loc, diagnostic) << E->getSourceRange(); + Diag(Loc, diag::note_condition_assign_silence) + << FixItHint::CreateInsertion(Open, "(") + << FixItHint::CreateInsertion(Close, ")"); if (IsOrAssign) Diag(Loc, diag::note_condition_or_assign_to_comparison) @@ -9635,10 +10249,6 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { else Diag(Loc, diag::note_condition_assign_to_comparison) << FixItHint::CreateReplacement(Loc, "=="); - - Diag(Loc, diag::note_condition_assign_silence) - << FixItHint::CreateInsertion(Open, "(") - << FixItHint::CreateInsertion(Close, ")"); } /// \brief Redundant parentheses over an equality comparison can indicate @@ -9648,6 +10258,9 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *parenE) { SourceLocation parenLoc = parenE->getLocStart(); if (parenLoc.isInvalid() || parenLoc.isMacroID()) return; + // Don't warn for dependent expressions. + if (parenE->isTypeDependent()) + return; Expr *E = parenE->IgnoreParens(); @@ -9658,68 +10271,467 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *parenE) { SourceLocation Loc = opE->getOperatorLoc(); Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange(); - Diag(Loc, diag::note_equality_comparison_to_assign) - << FixItHint::CreateReplacement(Loc, "="); Diag(Loc, diag::note_equality_comparison_silence) << FixItHint::CreateRemoval(parenE->getSourceRange().getBegin()) << FixItHint::CreateRemoval(parenE->getSourceRange().getEnd()); + Diag(Loc, diag::note_equality_comparison_to_assign) + << FixItHint::CreateReplacement(Loc, "="); } } -bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) { +ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) { DiagnoseAssignmentAsCondition(E); if (ParenExpr *parenE = dyn_cast(E)) DiagnoseEqualityWithExtraParens(parenE); - if (!E->isTypeDependent()) { - if (E->isBoundMemberFunction(Context)) - return Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << E->getSourceRange(); + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + if (!E->isTypeDependent()) { if (getLangOptions().CPlusPlus) return CheckCXXBooleanCondition(E); // C++ 6.4p4 - DefaultFunctionArrayLvalueConversion(E); + ExprResult ERes = DefaultFunctionArrayLvalueConversion(E); + if (ERes.isInvalid()) + return ExprError(); + E = ERes.take(); QualType T = E->getType(); - if (!T->isScalarType()) // C99 6.8.4.1p1 - return Diag(Loc, diag::err_typecheck_statement_requires_scalar) - << T << E->getSourceRange(); + if (!T->isScalarType()) { // C99 6.8.4.1p1 + Diag(Loc, diag::err_typecheck_statement_requires_scalar) + << T << E->getSourceRange(); + return ExprError(); + } } - return false; + return Owned(E); } ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, Expr *Sub) { if (!Sub) return ExprError(); - - if (CheckBooleanCondition(Sub, Loc)) + + return CheckBooleanCondition(Sub, Loc); +} + +namespace { + /// A visitor for rebuilding a call to an __unknown_any expression + /// to have an appropriate type. + struct RebuildUnknownAnyFunction + : StmtVisitor { + + Sema &S; + + RebuildUnknownAnyFunction(Sema &S) : S(S) {} + + ExprResult VisitStmt(Stmt *S) { + llvm_unreachable("unexpected statement!"); + return ExprError(); + } + + ExprResult VisitExpr(Expr *expr) { + S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_call) + << expr->getSourceRange(); + return ExprError(); + } + + /// Rebuild an expression which simply semantically wraps another + /// expression which it shares the type and value kind of. + template ExprResult rebuildSugarExpr(T *expr) { + ExprResult subResult = Visit(expr->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + + Expr *subExpr = subResult.take(); + expr->setSubExpr(subExpr); + expr->setType(subExpr->getType()); + expr->setValueKind(subExpr->getValueKind()); + assert(expr->getObjectKind() == OK_Ordinary); + return expr; + } + + ExprResult VisitParenExpr(ParenExpr *paren) { + return rebuildSugarExpr(paren); + } + + ExprResult VisitUnaryExtension(UnaryOperator *op) { + return rebuildSugarExpr(op); + } + + ExprResult VisitUnaryAddrOf(UnaryOperator *op) { + ExprResult subResult = Visit(op->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + + Expr *subExpr = subResult.take(); + op->setSubExpr(subExpr); + op->setType(S.Context.getPointerType(subExpr->getType())); + assert(op->getValueKind() == VK_RValue); + assert(op->getObjectKind() == OK_Ordinary); + return op; + } + + ExprResult resolveDecl(Expr *expr, ValueDecl *decl) { + if (!isa(decl)) return VisitExpr(expr); + + expr->setType(decl->getType()); + + assert(expr->getValueKind() == VK_RValue); + if (S.getLangOptions().CPlusPlus && + !(isa(decl) && + cast(decl)->isInstance())) + expr->setValueKind(VK_LValue); + + return expr; + } + + ExprResult VisitMemberExpr(MemberExpr *mem) { + return resolveDecl(mem, mem->getMemberDecl()); + } + + ExprResult VisitDeclRefExpr(DeclRefExpr *ref) { + return resolveDecl(ref, ref->getDecl()); + } + }; +} + +/// Given a function expression of unknown-any type, try to rebuild it +/// to have a function type. +static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn) { + ExprResult result = RebuildUnknownAnyFunction(S).Visit(fn); + if (result.isInvalid()) return ExprError(); + return S.DefaultFunctionArrayConversion(result.take()); +} + +namespace { + /// A visitor for rebuilding an expression of type __unknown_anytype + /// into one which resolves the type directly on the referring + /// expression. Strict preservation of the original source + /// structure is not a goal. + struct RebuildUnknownAnyExpr + : StmtVisitor { + + Sema &S; + + /// The current destination type. + QualType DestType; + + RebuildUnknownAnyExpr(Sema &S, QualType castType) + : S(S), DestType(castType) {} + + ExprResult VisitStmt(Stmt *S) { + llvm_unreachable("unexpected statement!"); + return ExprError(); + } + + ExprResult VisitExpr(Expr *expr) { + S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_expr) + << expr->getSourceRange(); + return ExprError(); + } + + ExprResult VisitCallExpr(CallExpr *call); + ExprResult VisitObjCMessageExpr(ObjCMessageExpr *message); + + /// Rebuild an expression which simply semantically wraps another + /// expression which it shares the type and value kind of. + template ExprResult rebuildSugarExpr(T *expr) { + ExprResult subResult = Visit(expr->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + Expr *subExpr = subResult.take(); + expr->setSubExpr(subExpr); + expr->setType(subExpr->getType()); + expr->setValueKind(subExpr->getValueKind()); + assert(expr->getObjectKind() == OK_Ordinary); + return expr; + } + + ExprResult VisitParenExpr(ParenExpr *paren) { + return rebuildSugarExpr(paren); + } + + ExprResult VisitUnaryExtension(UnaryOperator *op) { + return rebuildSugarExpr(op); + } + + ExprResult VisitUnaryAddrOf(UnaryOperator *op) { + const PointerType *ptr = DestType->getAs(); + if (!ptr) { + S.Diag(op->getOperatorLoc(), diag::err_unknown_any_addrof) + << op->getSourceRange(); + return ExprError(); + } + assert(op->getValueKind() == VK_RValue); + assert(op->getObjectKind() == OK_Ordinary); + op->setType(DestType); + + // Build the sub-expression as if it were an object of the pointee type. + DestType = ptr->getPointeeType(); + ExprResult subResult = Visit(op->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + op->setSubExpr(subResult.take()); + return op; + } + + ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice); + + ExprResult resolveDecl(Expr *expr, ValueDecl *decl); + + ExprResult VisitMemberExpr(MemberExpr *mem) { + return resolveDecl(mem, mem->getMemberDecl()); + } + + ExprResult VisitDeclRefExpr(DeclRefExpr *ref) { + return resolveDecl(ref, ref->getDecl()); + } + }; +} + +/// Rebuilds a call expression which yielded __unknown_anytype. +ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *call) { + Expr *callee = call->getCallee(); + + enum FnKind { + FK_MemberFunction, + FK_FunctionPointer, + FK_BlockPointer + }; + + FnKind kind; + QualType type = callee->getType(); + if (type == S.Context.BoundMemberTy) { + assert(isa(call) || isa(call)); + kind = FK_MemberFunction; + type = Expr::findBoundMemberType(callee); + } else if (const PointerType *ptr = type->getAs()) { + type = ptr->getPointeeType(); + kind = FK_FunctionPointer; + } else { + type = type->castAs()->getPointeeType(); + kind = FK_BlockPointer; + } + const FunctionType *fnType = type->castAs(); + + // Verify that this is a legal result type of a function. + if (DestType->isArrayType() || DestType->isFunctionType()) { + unsigned diagID = diag::err_func_returning_array_function; + if (kind == FK_BlockPointer) + diagID = diag::err_block_returning_array_function; + + S.Diag(call->getExprLoc(), diagID) + << DestType->isFunctionType() << DestType; return ExprError(); - - return Owned(Sub); + } + + // Otherwise, go ahead and set DestType as the call's result. + call->setType(DestType.getNonLValueExprType(S.Context)); + call->setValueKind(Expr::getValueKindForType(DestType)); + assert(call->getObjectKind() == OK_Ordinary); + + // Rebuild the function type, replacing the result type with DestType. + if (const FunctionProtoType *proto = dyn_cast(fnType)) + DestType = S.Context.getFunctionType(DestType, + proto->arg_type_begin(), + proto->getNumArgs(), + proto->getExtProtoInfo()); + else + DestType = S.Context.getFunctionNoProtoType(DestType, + fnType->getExtInfo()); + + // Rebuild the appropriate pointer-to-function type. + switch (kind) { + case FK_MemberFunction: + // Nothing to do. + break; + + case FK_FunctionPointer: + DestType = S.Context.getPointerType(DestType); + break; + + case FK_BlockPointer: + DestType = S.Context.getBlockPointerType(DestType); + break; + } + + // Finally, we can recurse. + ExprResult calleeResult = Visit(callee); + if (!calleeResult.isUsable()) return ExprError(); + call->setCallee(calleeResult.take()); + + // Bind a temporary if necessary. + return S.MaybeBindToTemporary(call); +} + +ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *msg) { + ObjCMethodDecl *method = msg->getMethodDecl(); + assert(method && "__unknown_anytype message without result type?"); + + // Verify that this is a legal result type of a call. + if (DestType->isArrayType() || DestType->isFunctionType()) { + S.Diag(msg->getExprLoc(), diag::err_func_returning_array_function) + << DestType->isFunctionType() << DestType; + return ExprError(); + } + + assert(method->getResultType() == S.Context.UnknownAnyTy); + method->setResultType(DestType); + + // Change the type of the message. + msg->setType(DestType.getNonReferenceType()); + msg->setValueKind(Expr::getValueKindForType(DestType)); + + return S.MaybeBindToTemporary(msg); +} + +ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *ice) { + // The only case we should ever see here is a function-to-pointer decay. + assert(ice->getCastKind() == CK_FunctionToPointerDecay); + assert(ice->getValueKind() == VK_RValue); + assert(ice->getObjectKind() == OK_Ordinary); + + ice->setType(DestType); + + // Rebuild the sub-expression as the pointee (function) type. + DestType = DestType->castAs()->getPointeeType(); + + ExprResult result = Visit(ice->getSubExpr()); + if (!result.isUsable()) return ExprError(); + + ice->setSubExpr(result.take()); + return S.Owned(ice); +} + +ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, ValueDecl *decl) { + ExprValueKind valueKind = VK_LValue; + QualType type = DestType; + + // We know how to make this work for certain kinds of decls: + + // - functions + if (FunctionDecl *fn = dyn_cast(decl)) { + // This is true because FunctionDecls must always have function + // type, so we can't be resolving the entire thing at once. + assert(type->isFunctionType()); + + if (CXXMethodDecl *method = dyn_cast(fn)) + if (method->isInstance()) { + valueKind = VK_RValue; + type = S.Context.BoundMemberTy; + } + + // Function references aren't l-values in C. + if (!S.getLangOptions().CPlusPlus) + valueKind = VK_RValue; + + // - variables + } else if (isa(decl)) { + if (const ReferenceType *refTy = type->getAs()) { + type = refTy->getPointeeType(); + } else if (type->isFunctionType()) { + S.Diag(expr->getExprLoc(), diag::err_unknown_any_var_function_type) + << decl << expr->getSourceRange(); + return ExprError(); + } + + // - nothing else + } else { + S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_decl) + << decl << expr->getSourceRange(); + return ExprError(); + } + + decl->setType(DestType); + expr->setType(type); + expr->setValueKind(valueKind); + return S.Owned(expr); +} + +/// Check a cast of an unknown-any type. We intentionally only +/// trigger this for C-style casts. +ExprResult Sema::checkUnknownAnyCast(SourceRange typeRange, QualType castType, + Expr *castExpr, CastKind &castKind, + ExprValueKind &VK, CXXCastPath &path) { + // Rewrite the casted expression from scratch. + ExprResult result = RebuildUnknownAnyExpr(*this, castType).Visit(castExpr); + if (!result.isUsable()) return ExprError(); + + castExpr = result.take(); + VK = castExpr->getValueKind(); + castKind = CK_NoOp; + + return castExpr; +} + +static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *e) { + Expr *orig = e; + unsigned diagID = diag::err_uncasted_use_of_unknown_any; + while (true) { + e = e->IgnoreParenImpCasts(); + if (CallExpr *call = dyn_cast(e)) { + e = call->getCallee(); + diagID = diag::err_uncasted_call_of_unknown_any; + } else { + break; + } + } + + SourceLocation loc; + NamedDecl *d; + if (DeclRefExpr *ref = dyn_cast(e)) { + loc = ref->getLocation(); + d = ref->getDecl(); + } else if (MemberExpr *mem = dyn_cast(e)) { + loc = mem->getMemberLoc(); + d = mem->getMemberDecl(); + } else if (ObjCMessageExpr *msg = dyn_cast(e)) { + diagID = diag::err_uncasted_call_of_unknown_any; + loc = msg->getSelectorLoc(); + d = msg->getMethodDecl(); + assert(d && "unknown method returning __unknown_any?"); + } else { + S.Diag(e->getExprLoc(), diag::err_unsupported_unknown_any_expr) + << e->getSourceRange(); + return ExprError(); + } + + S.Diag(loc, diagID) << d << orig->getSourceRange(); + + // Never recoverable. + return ExprError(); } /// Check for operands with placeholder types and complain if found. /// Returns true if there was an error and no recovery was possible. -ExprResult Sema::CheckPlaceholderExpr(Expr *E, SourceLocation Loc) { - const BuiltinType *BT = E->getType()->getAs(); - if (!BT || !BT->isPlaceholderType()) return Owned(E); +ExprResult Sema::CheckPlaceholderExpr(Expr *E) { + // Placeholder types are always *exactly* the appropriate builtin type. + QualType type = E->getType(); - // If this is overload, check for a single overload. - assert(BT->getKind() == BuiltinType::Overload); + // Overloaded expressions. + if (type == Context.OverloadTy) + return ResolveAndFixSingleFunctionTemplateSpecialization(E, false, true, + E->getSourceRange(), + QualType(), + diag::err_ovl_unresolvable); - if (FunctionDecl *Specialization - = ResolveSingleFunctionTemplateSpecialization(E)) { - // The access doesn't really matter in this case. - DeclAccessPair Found = DeclAccessPair::make(Specialization, - Specialization->getAccess()); - E = FixOverloadedFunctionReference(E, Found, Specialization); - if (!E) return ExprError(); - return Owned(E); - } + // Bound member functions. + if (type == Context.BoundMemberTy) { + Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) + << E->getSourceRange(); + return ExprError(); + } - Diag(Loc, diag::err_ovl_unresolvable) << E->getSourceRange(); - return ExprError(); + // Expressions of unknown type. + if (type == Context.UnknownAnyTy) + return diagnoseUnknownAnyExpr(*this, E); + + assert(!type->isPlaceholderType()); + return Owned(E); +} + +bool Sema::CheckCaseExpression(Expr *expr) { + if (expr->isTypeDependent()) + return true; + if (expr->isValueDependent() || expr->isIntegerConstantExpr(Context)) + return expr->getType()->isIntegralOrEnumerationType(); + return false; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index 6dd7aabaa1f0..7f1bf596a237 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; using namespace sema; @@ -138,10 +139,11 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, LookInScope = true; } + TypeDecl *NonMatchingTypeDecl = 0; LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName); for (unsigned Step = 0; Step != 2; ++Step) { // Look for the name first in the computed lookup context (if we - // have one) and, if that fails to find a match, in the sope (if + // have one) and, if that fails to find a match, in the scope (if // we're allowed to look there). Found.clear(); if (Step == 0 && LookupCtx) @@ -164,6 +166,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, return ParsedType::make(T); } + + if (!SearchType.isNull()) + NonMatchingTypeDecl = Type; } // If the name that we found is a class template name, and it is @@ -236,24 +241,22 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, if (isDependent) { // We didn't find our type, but that's okay: it's dependent // anyway. - NestedNameSpecifier *NNS = 0; - SourceRange Range; - if (SS.isSet()) { - NNS = (NestedNameSpecifier *)SS.getScopeRep(); - Range = SourceRange(SS.getRange().getBegin(), NameLoc); - } else { - NNS = NestedNameSpecifier::Create(Context, &II); - Range = SourceRange(NameLoc); - } - - QualType T = CheckTypenameType(ETK_None, NNS, II, - SourceLocation(), - Range, NameLoc); + + // FIXME: What if we have no nested-name-specifier? + QualType T = CheckTypenameType(ETK_None, SourceLocation(), + SS.getWithLocInContext(Context), + II, NameLoc); return ParsedType::make(T); } - if (ObjectTypePtr) - Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type) + if (NonMatchingTypeDecl) { + QualType T = Context.getTypeDeclType(NonMatchingTypeDecl); + Diag(NameLoc, diag::err_destructor_expr_type_mismatch) + << T << SearchType; + Diag(NonMatchingTypeDecl->getLocation(), diag::note_destructor_type_here) + << T; + } else if (ObjectTypePtr) + Diag(NameLoc, diag::err_ident_in_dtor_not_a_type) << &II; else Diag(NameLoc, diag::err_destructor_class_name); @@ -321,7 +324,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals); if (!Context.hasSameType(T, UnqualT)) { T = UnqualT; - ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E)); + E = ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E)).take(); } } @@ -341,7 +344,7 @@ ExprResult Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, bool isType, void *TyOrExpr, SourceLocation RParenLoc) { // Find the std::type_info type. - if (!StdNamespace) + if (!getStdNamespace()) return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); if (!CXXTypeInfoDecl) { @@ -477,17 +480,21 @@ Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { ExprResult Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) { // Don't report an error if 'throw' is used in system headers. - if (!getLangOptions().Exceptions && + if (!getLangOptions().CXXExceptions && !getSourceManager().isInSystemHeader(OpLoc)) Diag(OpLoc, diag::err_exceptions_disabled) << "throw"; - if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex)) - return ExprError(); + if (Ex && !Ex->isTypeDependent()) { + ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex); + if (ExRes.isInvalid()) + return ExprError(); + Ex = ExRes.take(); + } return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc)); } /// CheckCXXThrowOperand - Validate the operand of a throw. -bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { +ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E) { // C++ [except.throw]p3: // A throw-expression initializes a temporary object, called the exception // object, the type of which is determined by removing any top-level @@ -495,10 +502,13 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { // the type from "array of T" or "function returning T" to "pointer to T" // or "pointer to function returning T", [...] if (E->getType().hasQualifiers()) - ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp, - CastCategory(E)); + E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp, + CastCategory(E)).take(); - DefaultFunctionArrayConversion(E); + ExprResult Res = DefaultFunctionArrayConversion(E); + if (Res.isInvalid()) + return ExprError(); + E = Res.take(); // If the type of the exception would be an incomplete type or a pointer // to an incomplete type other than (cv) void the program is ill-formed. @@ -513,12 +523,12 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { PDiag(isPointer ? diag::err_throw_incomplete_ptr : diag::err_throw_incomplete) << E->getSourceRange())) - return true; + return ExprError(); if (RequireNonAbstractType(ThrowLoc, E->getType(), PDiag(diag::err_throw_abstract_type) << E->getSourceRange())) - return true; + return ExprError(); } // Initialize the exception result. This implicitly weeds out @@ -529,16 +539,16 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { InitializedEntity Entity = InitializedEntity::InitializeException(ThrowLoc, E->getType(), /*NRVO=*/false); - ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable, - QualType(), E); + Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable, + QualType(), E); if (Res.isInvalid()) - return true; - E = Res.takeAs(); + return ExprError(); + E = Res.take(); // If the exception has class type, we need additional handling. const RecordType *RecordTy = Ty->getAs(); if (!RecordTy) - return false; + return Owned(E); CXXRecordDecl *RD = cast(RecordTy->getDecl()); // If we are throwing a polymorphic class type or pointer thereof, @@ -547,21 +557,21 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { // If a pointer is thrown, the referenced object will not be destroyed. if (isPointer) - return false; + return Owned(E); // If the class has a non-trivial destructor, we must be able to call it. if (RD->hasTrivialDestructor()) - return false; + return Owned(E); CXXDestructorDecl *Destructor = const_cast(LookupDestructor(RD)); if (!Destructor) - return false; + return Owned(E); MarkDeclarationReferenced(E->getExprLoc(), Destructor); CheckDestructorAccess(E->getExprLoc(), Destructor, PDiag(diag::err_access_dtor_exception) << Ty); - return false; + return Owned(E); } CXXMethodDecl *Sema::tryCaptureCXXThis() { @@ -666,10 +676,13 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, CastKind Kind = CK_Invalid; ExprValueKind VK = VK_RValue; CXXCastPath BasePath; - if (CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0], - Kind, VK, BasePath, - /*FunctionalStyle=*/true)) + ExprResult CastExpr = + CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0], + Kind, VK, BasePath, + /*FunctionalStyle=*/true); + if (CastExpr.isInvalid()) return ExprError(); + Exprs[0] = CastExpr.take(); exprs.release(); @@ -846,16 +859,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, diag::err_auto_new_ctor_multiple_expressions) << AllocType << TypeRange); } - QualType DeducedType; - if (!DeduceAutoType(AllocType, ConstructorArgs.get()[0], DeducedType)) + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType)) return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) << AllocType << ConstructorArgs.get()[0]->getType() << TypeRange << ConstructorArgs.get()[0]->getSourceRange()); + if (!DeducedType) + return ExprError(); - AllocType = DeducedType; - AllocTypeInfo = Context.getTrivialTypeSourceInfo(AllocType, StartLoc); + AllocTypeInfo = DeducedType; + AllocType = AllocTypeInfo->getType(); } // Per C++0x [expr.new]p5, the type being constructed may be a @@ -935,8 +950,8 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } } - ImpCastExprToType(ArraySize, Context.getSizeType(), - CK_IntegralCast); + ArraySize = ImpCastExprToType(ArraySize, Context.getSizeType(), + CK_IntegralCast).take(); } FunctionDecl *OperatorNew = 0; @@ -1090,7 +1105,10 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, else if (AllocType->isVariablyModifiedType()) return Diag(Loc, diag::err_variably_modified_new_type) << AllocType; - + else if (unsigned AddressSpace = AllocType.getAddressSpace()) + return Diag(Loc, diag::err_address_space_qualified_new) + << AllocType.getUnqualifiedType() << AddressSpace; + return false; } @@ -1384,16 +1402,16 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); return true; - case OR_Deleted: + case OR_Deleted: { Diag(StartLoc, diag::err_ovl_deleted_call) << Best->Function->isDeleted() << Name - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Range; Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); return true; } + } assert(false && "Unreachable, bad result from BestViableFunction"); return true; } @@ -1402,11 +1420,18 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, /// DeclareGlobalNewDelete - Declare the global forms of operator new and /// delete. These are: /// @code +/// // C++03: /// void* operator new(std::size_t) throw(std::bad_alloc); /// void* operator new[](std::size_t) throw(std::bad_alloc); /// void operator delete(void *) throw(); /// void operator delete[](void *) throw(); +/// // C++0x: +/// void* operator new(std::size_t); +/// void* operator new[](std::size_t); +/// void operator delete(void *); +/// void operator delete[](void *); /// @endcode +/// C++0x operator delete is implicitly noexcept. /// Note that the placement and nothrow forms of new are *not* implicitly /// declared. Their use requires including \. void Sema::DeclareGlobalNewDelete() { @@ -1418,10 +1443,16 @@ void Sema::DeclareGlobalNewDelete() { // implicitly declared in global scope in each translation unit of a // program // + // C++03: // void* operator new(std::size_t) throw(std::bad_alloc); // void* operator new[](std::size_t) throw(std::bad_alloc); // void operator delete(void*) throw(); // void operator delete[](void*) throw(); + // C++0x: + // void* operator new(std::size_t); + // void* operator new[](std::size_t); + // void operator delete(void*); + // void operator delete[](void*); // // These implicit declarations introduce only the function names operator // new, operator new[], operator delete, operator delete[]. @@ -1430,14 +1461,16 @@ void Sema::DeclareGlobalNewDelete() { // "std" or "bad_alloc" as necessary to form the exception specification. // However, we do not make these implicit declarations visible to name // lookup. - if (!StdBadAlloc) { + // Note that the C++0x versions of operator delete are deallocation functions, + // and thus are implicitly noexcept. + if (!StdBadAlloc && !getLangOptions().CPlusPlus0x) { // The "std::bad_alloc" class has not yet been declared, so build it // implicitly. StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, getOrCreateStdNamespace(), - SourceLocation(), + SourceLocation(), SourceLocation(), &PP.getIdentifierTable().get("bad_alloc"), - SourceLocation(), 0); + 0); getStdBadAlloc()->setImplicit(true); } @@ -1493,21 +1526,27 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, bool HasBadAllocExceptionSpec = (Name.getCXXOverloadedOperator() == OO_New || Name.getCXXOverloadedOperator() == OO_Array_New); - if (HasBadAllocExceptionSpec) { + if (HasBadAllocExceptionSpec && !getLangOptions().CPlusPlus0x) { assert(StdBadAlloc && "Must have std::bad_alloc declared"); BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); } FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = true; if (HasBadAllocExceptionSpec) { - EPI.NumExceptions = 1; - EPI.Exceptions = &BadAllocType; + if (!getLangOptions().CPlusPlus0x) { + EPI.ExceptionSpecType = EST_Dynamic; + EPI.NumExceptions = 1; + EPI.Exceptions = &BadAllocType; + } + } else { + EPI.ExceptionSpecType = getLangOptions().CPlusPlus0x ? + EST_BasicNoexcept : EST_DynamicNone; } QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI); FunctionDecl *Alloc = - FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name, + FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), + SourceLocation(), Name, FnType, /*TInfo=*/0, SC_None, SC_None, false, true); Alloc->setImplicit(); @@ -1516,9 +1555,9 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), - 0, Argument, /*TInfo=*/0, - SC_None, - SC_None, 0); + SourceLocation(), 0, + Argument, /*TInfo=*/0, + SC_None, SC_None, 0); Alloc->setParams(&Param, 1); // FIXME: Also add this declaration to the IdentifierResolver, but @@ -1608,19 +1647,20 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, /// @code delete [] ptr; @endcode ExprResult Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, - bool ArrayForm, Expr *Ex) { + bool ArrayForm, Expr *ExE) { // C++ [expr.delete]p1: // The operand shall have a pointer type, or a class type having a single // conversion function to a pointer type. The result has type void. // // DR599 amends "pointer type" to "pointer to object type" in both cases. + ExprResult Ex = Owned(ExE); FunctionDecl *OperatorDelete = 0; bool ArrayFormAsWritten = ArrayForm; bool UsualArrayDeleteWantsSize = false; - if (!Ex->isTypeDependent()) { - QualType Type = Ex->getType(); + if (!Ex.get()->isTypeDependent()) { + QualType Type = Ex.get()->getType(); if (const RecordType *Record = Type->getAs()) { if (RequireCompleteType(StartLoc, Type, @@ -1652,15 +1692,18 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // We have a single conversion to a pointer-to-object type. Perform // that conversion. // TODO: don't redo the conversion calculation. - if (!PerformImplicitConversion(Ex, + ExprResult Res = + PerformImplicitConversion(Ex.get(), ObjectPtrConversions.front()->getConversionType(), - AA_Converting)) { - Type = Ex->getType(); + AA_Converting); + if (Res.isUsable()) { + Ex = move(Res); + Type = Ex.get()->getType(); } } else if (ObjectPtrConversions.size() > 1) { Diag(StartLoc, diag::err_ambiguous_delete_operand) - << Type << Ex->getSourceRange(); + << Type << Ex.get()->getSourceRange(); for (unsigned i= 0; i < ObjectPtrConversions.size(); i++) NoteOverloadCandidate(ObjectPtrConversions[i]); return ExprError(); @@ -1669,7 +1712,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (!Type->isPointerType()) return ExprError(Diag(StartLoc, diag::err_delete_operand) - << Type << Ex->getSourceRange()); + << Type << Ex.get()->getSourceRange()); QualType Pointee = Type->getAs()->getPointeeType(); if (Pointee->isVoidType() && !isSFINAEContext()) { @@ -1677,27 +1720,30 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // effectively bans deletion of "void*". However, most compilers support // this, so we treat it as a warning unless we're in a SFINAE context. Diag(StartLoc, diag::ext_delete_void_ptr_operand) - << Type << Ex->getSourceRange(); + << Type << Ex.get()->getSourceRange(); } else if (Pointee->isFunctionType() || Pointee->isVoidType()) return ExprError(Diag(StartLoc, diag::err_delete_operand) - << Type << Ex->getSourceRange()); + << Type << Ex.get()->getSourceRange()); else if (!Pointee->isDependentType() && RequireCompleteType(StartLoc, Pointee, PDiag(diag::warn_delete_incomplete) - << Ex->getSourceRange())) + << Ex.get()->getSourceRange())) return ExprError(); - + else if (unsigned AddressSpace = Pointee.getAddressSpace()) + return Diag(Ex.get()->getLocStart(), + diag::err_address_space_qualified_delete) + << Pointee.getUnqualifiedType() << AddressSpace; // C++ [expr.delete]p2: // [Note: a pointer to a const type can be the operand of a // delete-expression; it is not necessary to cast away the constness // (5.2.11) of the pointer expression before it is used as the operand // of the delete-expression. ] - ImpCastExprToType(Ex, Context.getPointerType(Context.VoidTy), + Ex = ImpCastExprToType(Ex.take(), Context.getPointerType(Context.VoidTy), CK_NoOp); if (Pointee->isArrayType() && !ArrayForm) { Diag(StartLoc, diag::warn_delete_array_type) - << Type << Ex->getSourceRange() + << Type << Ex.get()->getSourceRange() << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]"); ArrayForm = true; } @@ -1740,8 +1786,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // Look for a global declaration. DeclareGlobalNewDelete(); DeclContext *TUDecl = Context.getTranslationUnitDecl(); + Expr *Arg = Ex.get(); if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName, - &Ex, 1, TUDecl, /*AllowMissing=*/false, + &Arg, 1, TUDecl, /*AllowMissing=*/false, OperatorDelete)) return ExprError(); } @@ -1752,7 +1799,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (const RecordType *RT = PointeeElem->getAs()) { CXXRecordDecl *RD = cast(RT->getDecl()); if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) { - CheckDestructorAccess(Ex->getExprLoc(), Dtor, + CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor, PDiag(diag::err_access_dtor) << PointeeElem); } } @@ -1762,7 +1809,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, ArrayFormAsWritten, UsualArrayDeleteWantsSize, - OperatorDelete, Ex, StartLoc)); + OperatorDelete, Ex.take(), StartLoc)); } /// \brief Check the use of the given variable as a C++ condition in an if, @@ -1783,18 +1830,23 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, diag::err_invalid_use_of_array_type) << ConditionVar->getSourceRange()); - Expr *Condition = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar, + ExprResult Condition = + Owned(DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), + ConditionVar, ConditionVar->getLocation(), ConditionVar->getType().getNonReferenceType(), - VK_LValue); - if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc)) - return ExprError(); + VK_LValue)); + if (ConvertToBoolean) { + Condition = CheckBooleanCondition(Condition.take(), StmtLoc); + if (Condition.isInvalid()) + return ExprError(); + } - return Owned(Condition); + return move(Condition); } /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. -bool Sema::CheckCXXBooleanCondition(Expr *&CondExpr) { +ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr) { // C++ 6.4p4: // The value of a condition that is an initialized declaration in a statement // other than a switch statement is the value of the declared variable @@ -1880,20 +1932,22 @@ static ExprResult BuildCXXCastArgument(Sema &S, /// PerformImplicitConversion - Perform an implicit conversion of the /// expression From to the type ToType using the pre-computed implicit -/// conversion sequence ICS. Returns true if there was an error, false -/// otherwise. The expression From is replaced with the converted +/// conversion sequence ICS. Returns the converted /// expression. Action is the kind of conversion we're performing, /// used in the error message. -bool -Sema::PerformImplicitConversion(Expr *&From, QualType ToType, +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, bool CStyle) { switch (ICS.getKind()) { - case ImplicitConversionSequence::StandardConversion: - if (PerformImplicitConversion(From, ToType, ICS.Standard, Action, - CStyle)) - return true; + case ImplicitConversionSequence::StandardConversion: { + ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard, + Action, CStyle); + if (Res.isInvalid()) + return ExprError(); + From = Res.take(); break; + } case ImplicitConversionSequence::UserDefinedConversion: { @@ -1920,10 +1974,13 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } // Watch out for elipsis conversion. if (!ICS.UserDefined.EllipsisConversion) { - if (PerformImplicitConversion(From, BeforeToType, - ICS.UserDefined.Before, AA_Converting, - CStyle)) - return true; + ExprResult Res = + PerformImplicitConversion(From, BeforeToType, + ICS.UserDefined.Before, AA_Converting, + CStyle); + if (Res.isInvalid()) + return ExprError(); + From = Res.take(); } ExprResult CastArg @@ -1935,9 +1992,9 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, From); if (CastArg.isInvalid()) - return true; + return ExprError(); - From = CastArg.takeAs(); + From = CastArg.take(); return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, AA_Converting, CStyle); @@ -1947,28 +2004,27 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(), PDiag(diag::err_typecheck_ambiguous_condition) << From->getSourceRange()); - return true; + return ExprError(); case ImplicitConversionSequence::EllipsisConversion: assert(false && "Cannot perform an ellipsis conversion"); - return false; + return Owned(From); case ImplicitConversionSequence::BadConversion: - return true; + return ExprError(); } // Everything went well. - return false; + return Owned(From); } /// PerformImplicitConversion - Perform an implicit conversion of the /// expression From to the type ToType by following the standard -/// conversion sequence SCS. Returns true if there was an error, false -/// otherwise. The expression From is replaced with the converted +/// conversion sequence SCS. Returns the converted /// expression. Flavor is the context in which we're performing this /// conversion, for use in error messages. -bool -Sema::PerformImplicitConversion(Expr *&From, QualType ToType, +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, const StandardConversionSequence& SCS, AssignmentAction Action, bool CStyle) { // Overall FIXME: we are recomputing too many types here and doing far too @@ -1986,32 +2042,20 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, MultiExprArg(*this, &From, 1), /*FIXME:ConstructLoc*/SourceLocation(), ConstructorArgs)) - return true; - ExprResult FromResult = - BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), - ToType, SCS.CopyConstructor, - move_arg(ConstructorArgs), - /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete, - SourceRange()); - if (FromResult.isInvalid()) - return true; - From = FromResult.takeAs(); - return false; + return ExprError(); + return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), + ToType, SCS.CopyConstructor, + move_arg(ConstructorArgs), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); } - ExprResult FromResult = - BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), - ToType, SCS.CopyConstructor, - MultiExprArg(*this, &From, 1), - /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete, - SourceRange()); - - if (FromResult.isInvalid()) - return true; - - From = FromResult.takeAs(); - return false; + return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), + ToType, SCS.CopyConstructor, + MultiExprArg(*this, &From, 1), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); } // Resolve overloaded function references. @@ -2020,10 +2064,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true, Found); if (!Fn) - return true; + return ExprError(); if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) - return true; + return ExprError(); From = FixOverloadedFunctionReference(From, Found, Fn); FromType = From->getType(); @@ -2038,13 +2082,15 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, case ICK_Lvalue_To_Rvalue: // Should this get its own ICK? if (From->getObjectKind() == OK_ObjCProperty) { - ConvertPropertyForRValue(From); + ExprResult FromRes = ConvertPropertyForRValue(From); + if (FromRes.isInvalid()) + return ExprError(); + From = FromRes.take(); if (!From->isGLValue()) break; } // Check for trivial buffer overflows. - if (const ArraySubscriptExpr *AE = dyn_cast(From)) - CheckArrayAccess(AE); + CheckArrayAccess(From); FromType = FromType.getUnqualifiedType(); From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue, @@ -2053,12 +2099,12 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, case ICK_Array_To_Pointer: FromType = Context.getArrayDecayedType(FromType); - ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay); + From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay).take(); break; case ICK_Function_To_Pointer: FromType = Context.getPointerType(FromType); - ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay); + From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay).take(); break; default: @@ -2072,7 +2118,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // If both sides are functions (or pointers/references to them), there could // be incompatible exception declarations. if (CheckExceptionSpecCompatibility(From, ToType)) - return true; + return ExprError(); // Nothing else to do. break; @@ -2080,19 +2126,19 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // If both sides are functions (or pointers/references to them), there could // be incompatible exception declarations. if (CheckExceptionSpecCompatibility(From, ToType)) - return true; + return ExprError(); - ImpCastExprToType(From, ToType, CK_NoOp); + From = ImpCastExprToType(From, ToType, CK_NoOp).take(); break; case ICK_Integral_Promotion: case ICK_Integral_Conversion: - ImpCastExprToType(From, ToType, CK_IntegralCast); + From = ImpCastExprToType(From, ToType, CK_IntegralCast).take(); break; case ICK_Floating_Promotion: case ICK_Floating_Conversion: - ImpCastExprToType(From, ToType, CK_FloatingCast); + From = ImpCastExprToType(From, ToType, CK_FloatingCast).take(); break; case ICK_Complex_Promotion: @@ -2110,35 +2156,41 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } else { CK = CK_IntegralComplexCast; } - ImpCastExprToType(From, ToType, CK); + From = ImpCastExprToType(From, ToType, CK).take(); break; } case ICK_Floating_Integral: if (ToType->isRealFloatingType()) - ImpCastExprToType(From, ToType, CK_IntegralToFloating); + From = ImpCastExprToType(From, ToType, CK_IntegralToFloating).take(); else - ImpCastExprToType(From, ToType, CK_FloatingToIntegral); + From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral).take(); break; case ICK_Compatible_Conversion: - ImpCastExprToType(From, ToType, CK_NoOp); + From = ImpCastExprToType(From, ToType, CK_NoOp).take(); break; case ICK_Pointer_Conversion: { if (SCS.IncompatibleObjC && Action != AA_Casting) { // Diagnose incompatible Objective-C conversions - Diag(From->getSourceRange().getBegin(), - diag::ext_typecheck_convert_incompatible_pointer) - << From->getType() << ToType << Action - << From->getSourceRange(); + if (Action == AA_Initializing) + Diag(From->getSourceRange().getBegin(), + diag::ext_typecheck_convert_incompatible_pointer) + << ToType << From->getType() << Action + << From->getSourceRange(); + else + Diag(From->getSourceRange().getBegin(), + diag::ext_typecheck_convert_incompatible_pointer) + << From->getType() << ToType << Action + << From->getSourceRange(); } CastKind Kind = CK_Invalid; CXXCastPath BasePath; if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle)) - return true; - ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath); + return ExprError(); + From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath).take(); break; } @@ -2146,27 +2198,17 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, CastKind Kind = CK_Invalid; CXXCastPath BasePath; if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, CStyle)) - return true; + return ExprError(); if (CheckExceptionSpecCompatibility(From, ToType)) - return true; - ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath); + return ExprError(); + From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath).take(); break; } - case ICK_Boolean_Conversion: { - CastKind Kind = CK_Invalid; - switch (FromType->getScalarTypeKind()) { - case Type::STK_Pointer: Kind = CK_PointerToBoolean; break; - case Type::STK_MemberPointer: Kind = CK_MemberPointerToBoolean; break; - case Type::STK_Bool: llvm_unreachable("bool -> bool conversion?"); - case Type::STK_Integral: Kind = CK_IntegralToBoolean; break; - case Type::STK_Floating: Kind = CK_FloatingToBoolean; break; - case Type::STK_IntegralComplex: Kind = CK_IntegralComplexToBoolean; break; - case Type::STK_FloatingComplex: Kind = CK_FloatingComplexToBoolean; break; - } - ImpCastExprToType(From, Context.BoolTy, Kind); + case ICK_Boolean_Conversion: + From = ImpCastExprToType(From, Context.BoolTy, + ScalarTypeToBooleanCastKind(FromType)).take(); break; - } case ICK_Derived_To_Base: { CXXCastPath BasePath; @@ -2176,20 +2218,20 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, From->getSourceRange(), &BasePath, CStyle)) - return true; + return ExprError(); - ImpCastExprToType(From, ToType.getNonReferenceType(), + From = ImpCastExprToType(From, ToType.getNonReferenceType(), CK_DerivedToBase, CastCategory(From), - &BasePath); + &BasePath).take(); break; } case ICK_Vector_Conversion: - ImpCastExprToType(From, ToType, CK_BitCast); + From = ImpCastExprToType(From, ToType, CK_BitCast).take(); break; case ICK_Vector_Splat: - ImpCastExprToType(From, ToType, CK_VectorSplat); + From = ImpCastExprToType(From, ToType, CK_VectorSplat).take(); break; case ICK_Complex_Real: @@ -2202,17 +2244,17 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, if (Context.hasSameUnqualifiedType(ElType, From->getType())) { // do nothing } else if (From->getType()->isRealFloatingType()) { - ImpCastExprToType(From, ElType, - isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral); + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral).take(); } else { assert(From->getType()->isIntegerType()); - ImpCastExprToType(From, ElType, - isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast); + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast).take(); } // y -> _Complex y - ImpCastExprToType(From, ToType, + From = ImpCastExprToType(From, ToType, isFloatingComplex ? CK_FloatingRealToComplex - : CK_IntegralRealToComplex); + : CK_IntegralRealToComplex).take(); // Case 2. _Complex x -> y } else { @@ -2223,29 +2265,43 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, bool isFloatingComplex = ElType->isRealFloatingType(); // _Complex x -> x - ImpCastExprToType(From, ElType, + From = ImpCastExprToType(From, ElType, isFloatingComplex ? CK_FloatingComplexToReal - : CK_IntegralComplexToReal); + : CK_IntegralComplexToReal).take(); // x -> y if (Context.hasSameUnqualifiedType(ElType, ToType)) { // do nothing } else if (ToType->isRealFloatingType()) { - ImpCastExprToType(From, ToType, - isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating); + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating).take(); } else { assert(ToType->isIntegerType()); - ImpCastExprToType(From, ToType, - isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast); + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast).take(); } } break; case ICK_Block_Pointer_Conversion: { - ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast, VK_RValue); + From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast, + VK_RValue).take(); break; } + case ICK_TransparentUnionConversion: { + ExprResult FromRes = Owned(From); + Sema::AssignConvertType ConvTy = + CheckTransparentUnionArgumentConstraints(ToType, FromRes); + if (FromRes.isInvalid()) + return ExprError(); + From = FromRes.take(); + assert ((ConvTy == Sema::Compatible) && + "Improper transparent union conversion"); + (void)ConvTy; + break; + } + case ICK_Lvalue_To_Rvalue: case ICK_Array_To_Pointer: case ICK_Function_To_Pointer: @@ -2265,10 +2321,11 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // target type isn't a reference. ExprValueKind VK = ToType->isReferenceType() ? CastCategory(From) : VK_RValue; - ImpCastExprToType(From, ToType.getNonLValueExprType(Context), - CK_NoOp, VK); + From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), + CK_NoOp, VK).take(); - if (SCS.DeprecatedStringLiteralToCharPtr) + if (SCS.DeprecatedStringLiteralToCharPtr && + !getLangOptions().WritableStrings) Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion) << ToType.getNonReferenceType(); @@ -2280,7 +2337,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; } - return false; + return Owned(From); } ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT, @@ -2295,41 +2352,197 @@ ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT, return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen); } -static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, - SourceLocation KeyLoc) { - // FIXME: For many of these traits, we need a complete type before we can - // check these properties. - assert(!T->isDependentType() && - "Cannot evaluate traits for dependent types."); +/// \brief Check the completeness of a type in a unary type trait. +/// +/// If the particular type trait requires a complete type, tries to complete +/// it. If completing the type fails, a diagnostic is emitted and false +/// returned. If completing the type succeeds or no completion was required, +/// returns true. +static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, + UnaryTypeTrait UTT, + SourceLocation Loc, + QualType ArgTy) { + // C++0x [meta.unary.prop]p3: + // For all of the class templates X declared in this Clause, instantiating + // that template with a template argument that is a class template + // specialization may result in the implicit instantiation of the template + // argument if and only if the semantics of X require that the argument + // must be a complete type. + // We apply this rule to all the type trait expressions used to implement + // these class templates. We also try to follow any GCC documented behavior + // in these expressions to ensure portability of standard libraries. + switch (UTT) { + // is_complete_type somewhat obviously cannot require a complete type. + case UTT_IsCompleteType: + // Fall-through + + // These traits are modeled on the type predicates in C++0x + // [meta.unary.cat] and [meta.unary.comp]. They are not specified as + // requiring a complete type, as whether or not they return true cannot be + // impacted by the completeness of the type. + case UTT_IsVoid: + case UTT_IsIntegral: + case UTT_IsFloatingPoint: + case UTT_IsArray: + case UTT_IsPointer: + case UTT_IsLvalueReference: + case UTT_IsRvalueReference: + case UTT_IsMemberFunctionPointer: + case UTT_IsMemberObjectPointer: + case UTT_IsEnum: + case UTT_IsUnion: + case UTT_IsClass: + case UTT_IsFunction: + case UTT_IsReference: + case UTT_IsArithmetic: + case UTT_IsFundamental: + case UTT_IsObject: + case UTT_IsScalar: + case UTT_IsCompound: + case UTT_IsMemberPointer: + // Fall-through + + // These traits are modeled on type predicates in C++0x [meta.unary.prop] + // which requires some of its traits to have the complete type. However, + // the completeness of the type cannot impact these traits' semantics, and + // so they don't require it. This matches the comments on these traits in + // Table 49. + case UTT_IsConst: + case UTT_IsVolatile: + case UTT_IsSigned: + case UTT_IsUnsigned: + return true; + + // C++0x [meta.unary.prop] Table 49 requires the following traits to be + // applied to a complete type. + case UTT_IsTrivial: + case UTT_IsStandardLayout: + case UTT_IsPOD: + case UTT_IsLiteral: + case UTT_IsEmpty: + case UTT_IsPolymorphic: + case UTT_IsAbstract: + // Fall-through + + // These trait expressions are designed to help implement predicates in + // [meta.unary.prop] despite not being named the same. They are specified + // by both GCC and the Embarcadero C++ compiler, and require the complete + // type due to the overarching C++0x type predicates being implemented + // requiring the complete type. + case UTT_HasNothrowAssign: + case UTT_HasNothrowConstructor: + case UTT_HasNothrowCopy: + case UTT_HasTrivialAssign: + case UTT_HasTrivialConstructor: + case UTT_HasTrivialCopy: + case UTT_HasTrivialDestructor: + case UTT_HasVirtualDestructor: + // Arrays of unknown bound are expressly allowed. + QualType ElTy = ArgTy; + if (ArgTy->isIncompleteArrayType()) + ElTy = S.Context.getAsArrayType(ArgTy)->getElementType(); + + // The void type is expressly allowed. + if (ElTy->isVoidType()) + return true; + + return !S.RequireCompleteType( + Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr); + } + llvm_unreachable("Type trait not handled by switch"); +} + +static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, + SourceLocation KeyLoc, QualType T) { + assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); + ASTContext &C = Self.Context; switch(UTT) { - default: assert(false && "Unknown type trait or not implemented"); - case UTT_IsPOD: return T->isPODType(); - case UTT_IsLiteral: return T->isLiteralType(); - case UTT_IsClass: // Fallthrough + // Type trait expressions corresponding to the primary type category + // predicates in C++0x [meta.unary.cat]. + case UTT_IsVoid: + return T->isVoidType(); + case UTT_IsIntegral: + return T->isIntegralType(C); + case UTT_IsFloatingPoint: + return T->isFloatingType(); + case UTT_IsArray: + return T->isArrayType(); + case UTT_IsPointer: + return T->isPointerType(); + case UTT_IsLvalueReference: + return T->isLValueReferenceType(); + case UTT_IsRvalueReference: + return T->isRValueReferenceType(); + case UTT_IsMemberFunctionPointer: + return T->isMemberFunctionPointerType(); + case UTT_IsMemberObjectPointer: + return T->isMemberDataPointerType(); + case UTT_IsEnum: + return T->isEnumeralType(); case UTT_IsUnion: - if (const RecordType *Record = T->getAs()) { - bool Union = Record->getDecl()->isUnion(); - return UTT == UTT_IsUnion ? Union : !Union; - } + return T->isUnionType(); + case UTT_IsClass: + return T->isClassType() || T->isStructureType(); + case UTT_IsFunction: + return T->isFunctionType(); + + // Type trait expressions which correspond to the convenient composition + // predicates in C++0x [meta.unary.comp]. + case UTT_IsReference: + return T->isReferenceType(); + case UTT_IsArithmetic: + return T->isArithmeticType() && !T->isEnumeralType(); + case UTT_IsFundamental: + return T->isFundamentalType(); + case UTT_IsObject: + return T->isObjectType(); + case UTT_IsScalar: + return T->isScalarType(); + case UTT_IsCompound: + return T->isCompoundType(); + case UTT_IsMemberPointer: + return T->isMemberPointerType(); + + // Type trait expressions which correspond to the type property predicates + // in C++0x [meta.unary.prop]. + case UTT_IsConst: + return T.isConstQualified(); + case UTT_IsVolatile: + return T.isVolatileQualified(); + case UTT_IsTrivial: + return T->isTrivialType(); + case UTT_IsStandardLayout: + return T->isStandardLayoutType(); + case UTT_IsPOD: + return T->isPODType(); + case UTT_IsLiteral: + return T->isLiteralType(); + case UTT_IsEmpty: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return !RD->isUnion() && RD->isEmpty(); return false; - case UTT_IsEnum: return T->isEnumeralType(); case UTT_IsPolymorphic: - if (const RecordType *Record = T->getAs()) { - // Type traits are only parsed in C++, so we've got CXXRecords. - return cast(Record->getDecl())->isPolymorphic(); - } + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->isPolymorphic(); return false; case UTT_IsAbstract: - if (const RecordType *RT = T->getAs()) - return cast(RT->getDecl())->isAbstract(); - return false; - case UTT_IsEmpty: - if (const RecordType *Record = T->getAs()) { - return !Record->getDecl()->isUnion() - && cast(Record->getDecl())->isEmpty(); - } + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->isAbstract(); return false; + case UTT_IsSigned: + return T->isSignedIntegerType(); + case UTT_IsUnsigned: + return T->isUnsignedIntegerType(); + + // Type trait expressions which query classes regarding their construction, + // destruction, and copying. Rather than being based directly on the + // related type predicates in the standard, they are specified by both + // GCC[1] and the Embarcadero C++ compiler[2], and Clang implements those + // specifications. + // + // 1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html + // 2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index case UTT_HasTrivialConstructor: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: // If __is_pod (type) is true then the trait is true, else if type is @@ -2418,7 +2631,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, FoundAssign = true; const FunctionProtoType *CPT = Operator->getType()->getAs(); - if (!CPT->hasEmptyExceptionSpec()) { + if (!CPT->isNothrow(Self.Context)) { AllNoThrow = false; break; } @@ -2458,9 +2671,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, FoundConstructor = true; const FunctionProtoType *CPT = Constructor->getType()->getAs(); - // TODO: check whether evaluating default arguments can throw. + // FIXME: check whether evaluating default arguments can throw. // For now, we'll be conservative and assume that they can throw. - if (!CPT->hasEmptyExceptionSpec() || CPT->getNumArgs() > 1) { + if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) { AllNoThrow = false; break; } @@ -2495,7 +2708,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, = Constructor->getType()->getAs(); // TODO: check whether evaluating default arguments can throw. // For now, we'll be conservative and assume that they can throw. - return CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0; + return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0; } } } @@ -2510,7 +2723,17 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, return Destructor->isVirtual(); } return false; + + // These type trait expressions are modeled on the specifications for the + // Embarcadero C++0x type trait functions: + // http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index + case UTT_IsCompleteType: + // http://docwiki.embarcadero.com/RADStudio/XE/en/Is_complete_type_(typename_T_): + // Returns True if and only if T is a complete type at the point of the + // function call. + return !T->isIncompleteType(); } + llvm_unreachable("Type trait not covered by switch"); } ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT, @@ -2518,23 +2741,12 @@ ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT, TypeSourceInfo *TSInfo, SourceLocation RParen) { QualType T = TSInfo->getType(); - - // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html - // all traits except __is_class, __is_enum and __is_union require a the type - // to be complete, an array of unknown bound, or void. - if (UTT != UTT_IsClass && UTT != UTT_IsEnum && UTT != UTT_IsUnion) { - QualType E = T; - if (T->isIncompleteArrayType()) - E = Context.getAsArrayType(T)->getElementType(); - if (!T->isVoidType() && - RequireCompleteType(KWLoc, E, - diag::err_incomplete_type_used_in_type_trait_expr)) - return ExprError(); - } + if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T)) + return ExprError(); bool Value = false; if (!T->isDependentType()) - Value = EvaluateUnaryTypeTrait(*this, UTT, T, KWLoc); + Value = EvaluateUnaryTypeTrait(*this, UTT, KWLoc, T); return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value, RParen, Context.BoolTy)); @@ -2561,8 +2773,8 @@ ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT, static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, QualType LhsT, QualType RhsT, SourceLocation KeyLoc) { - assert((!LhsT->isDependentType() || RhsT->isDependentType()) && - "Cannot evaluate traits for dependent types."); + assert(!LhsT->isDependentType() && !RhsT->isDependentType() && + "Cannot evaluate traits of dependent types"); switch(BTT) { case BTT_IsBaseOf: { @@ -2594,11 +2806,12 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, return cast(rhsRecord->getDecl()) ->isDerivedFrom(cast(lhsRecord->getDecl())); } - + case BTT_IsSame: + return Self.Context.hasSameType(LhsT, RhsT); case BTT_TypeCompatible: return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(), RhsT.getUnqualifiedType()); - + case BTT_IsConvertible: case BTT_IsConvertibleTo: { // C++0x [meta.rel]p4: // Given the following function prototype: @@ -2673,6 +2886,8 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, QualType ResultType; switch (BTT) { case BTT_IsBaseOf: ResultType = Context.BoolTy; break; + case BTT_IsConvertible: ResultType = Context.BoolTy; break; + case BTT_IsSame: ResultType = Context.BoolTy; break; case BTT_TypeCompatible: ResultType = Context.IntTy; break; case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break; } @@ -2682,7 +2897,138 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, ResultType)); } -QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, +ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + ParsedType Ty, + Expr* DimExpr, + SourceLocation RParen) { + TypeSourceInfo *TSInfo; + QualType T = GetTypeFromParser(Ty, &TSInfo); + if (!TSInfo) + TSInfo = Context.getTrivialTypeSourceInfo(T); + + return BuildArrayTypeTrait(ATT, KWLoc, TSInfo, DimExpr, RParen); +} + +static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, + QualType T, Expr *DimExpr, + SourceLocation KeyLoc) { + assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); + + switch(ATT) { + case ATT_ArrayRank: + if (T->isArrayType()) { + unsigned Dim = 0; + while (const ArrayType *AT = Self.Context.getAsArrayType(T)) { + ++Dim; + T = AT->getElementType(); + } + return Dim; + } + return 0; + + case ATT_ArrayExtent: { + llvm::APSInt Value; + uint64_t Dim; + if (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) { + if (Value < llvm::APSInt(Value.getBitWidth(), Value.isUnsigned())) { + Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << + DimExpr->getSourceRange(); + return false; + } + Dim = Value.getLimitedValue(); + } else { + Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << + DimExpr->getSourceRange(); + return false; + } + + if (T->isArrayType()) { + unsigned D = 0; + bool Matched = false; + while (const ArrayType *AT = Self.Context.getAsArrayType(T)) { + if (Dim == D) { + Matched = true; + break; + } + ++D; + T = AT->getElementType(); + } + + if (Matched && T->isArrayType()) { + if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T)) + return CAT->getSize().getLimitedValue(); + } + } + return 0; + } + } + llvm_unreachable("Unknown type trait or not implemented"); +} + +ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + TypeSourceInfo *TSInfo, + Expr* DimExpr, + SourceLocation RParen) { + QualType T = TSInfo->getType(); + + // FIXME: This should likely be tracked as an APInt to remove any host + // assumptions about the width of size_t on the target. + uint64_t Value = 0; + if (!T->isDependentType()) + Value = EvaluateArrayTypeTrait(*this, ATT, T, DimExpr, KWLoc); + + // While the specification for these traits from the Embarcadero C++ + // compiler's documentation says the return type is 'unsigned int', Clang + // returns 'size_t'. On Windows, the primary platform for the Embarcadero + // compiler, there is no difference. On several other platforms this is an + // important distinction. + return Owned(new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value, + DimExpr, RParen, + Context.getSizeType())); +} + +ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen) { + // If error parsing the expression, ignore. + if (!Queried) + return ExprError(); + + ExprResult Result = BuildExpressionTrait(ET, KWLoc, Queried, RParen); + + return move(Result); +} + +static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) { + switch (ET) { + case ET_IsLValueExpr: return E->isLValue(); + case ET_IsRValueExpr: return E->isRValue(); + } + llvm_unreachable("Expression trait not covered by switch"); +} + +ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen) { + if (Queried->isTypeDependent()) { + // Delay type-checking for type-dependent expressions. + } else if (Queried->getType()->isPlaceholderType()) { + ExprResult PE = CheckPlaceholderExpr(Queried); + if (PE.isInvalid()) return ExprError(); + return BuildExpressionTrait(ET, KWLoc, PE.take(), RParen); + } + + bool Value = EvaluateExpressionTrait(ET, Queried); + + return Owned(new (Context) ExpressionTraitExpr(KWLoc, ET, Queried, Value, + RParen, Context.BoolTy)); +} + +QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex, ExprValueKind &VK, SourceLocation Loc, bool isIndirect) { @@ -2691,11 +3037,11 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, // The binary operator .* [p3: ->*] binds its second operand, which shall // be of type "pointer to member of T" (where T is a completely-defined // class type) [...] - QualType RType = rex->getType(); + QualType RType = rex.get()->getType(); const MemberPointerType *MemPtr = RType->getAs(); if (!MemPtr) { Diag(Loc, diag::err_bad_memptr_rhs) - << OpSpelling << RType << rex->getSourceRange(); + << OpSpelling << RType << rex.get()->getSourceRange(); return QualType(); } @@ -2711,7 +3057,7 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, // [...] to its first operand, which shall be of class T or of a class of // which T is an unambiguous and accessible base class. [p3: a pointer to // such a class] - QualType LType = lex->getType(); + QualType LType = lex.get()->getType(); if (isIndirect) { if (const PointerType *Ptr = LType->getAs()) LType = Ptr->getPointeeType(); @@ -2736,20 +3082,20 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, if (!IsDerivedFrom(LType, Class, Paths) || Paths.isAmbiguous(Context.getCanonicalType(Class))) { Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling - << (int)isIndirect << lex->getType(); + << (int)isIndirect << lex.get()->getType(); return QualType(); } // Cast LHS to type of use. QualType UseType = isIndirect ? Context.getPointerType(Class) : Class; ExprValueKind VK = - isIndirect ? VK_RValue : CastCategory(lex); + isIndirect ? VK_RValue : CastCategory(lex.get()); CXXCastPath BasePath; BuildBasePathArray(Paths, BasePath); - ImpCastExprToType(lex, UseType, CK_DerivedToBase, VK, &BasePath); + lex = ImpCastExprToType(lex.take(), UseType, CK_DerivedToBase, VK, &BasePath); } - if (isa(rex->IgnoreParens())) { + if (isa(rex.get()->IgnoreParens())) { // Diagnose use of pointer-to-member type which when used as // the functional cast in a pointer-to-member expression. Diag(Loc, diag::err_pointer_to_member_type) << isIndirect; @@ -2761,13 +3107,6 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, // second operand. // The cv qualifiers are the union of those in the pointer and the left side, // in accordance with 5.5p5 and 5.2.5. - // FIXME: This returns a dereferenced member function pointer as a normal - // function type. However, the only operation valid on such functions is - // calling them. There's also a GCC extension to get a function pointer to the - // thing, which is another complication, because this type - unlike the type - // that is the result of this expression - takes the class as the first - // argument. - // We probably need a "MemberFunctionClosureType" or something like that. QualType Result = MemPtr->getPointeeType(); Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers()); @@ -2784,15 +3123,15 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, break; case RQ_LValue: - if (!isIndirect && !lex->Classify(Context).isLValue()) + if (!isIndirect && !lex.get()->Classify(Context).isLValue()) Diag(Loc, diag::err_pointer_to_member_oper_value_classify) - << RType << 1 << lex->getSourceRange(); + << RType << 1 << lex.get()->getSourceRange(); break; case RQ_RValue: - if (isIndirect || !lex->Classify(Context).isRValue()) + if (isIndirect || !lex.get()->Classify(Context).isRValue()) Diag(Loc, diag::err_pointer_to_member_oper_value_classify) - << RType << 0 << lex->getSourceRange(); + << RType << 0 << lex.get()->getSourceRange(); break; } } @@ -2804,12 +3143,14 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, // operand is a pointer to a member function is a prvalue. The // result of an ->* expression is an lvalue if its second operand // is a pointer to data member and a prvalue otherwise. - if (Result->isFunctionType()) + if (Result->isFunctionType()) { VK = VK_RValue; - else if (isIndirect) + return Context.BoundMemberTy; + } else if (isIndirect) { VK = VK_LValue; - else - VK = lex->getValueKind(); + } else { + VK = lex.get()->getValueKind(); + } return Result; } @@ -2910,43 +3251,52 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, /// This is part of the parameter validation for the ? operator. If either /// value operand is a class type, overload resolution is used to find a /// conversion to a common type. -static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS, +static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS, SourceLocation QuestionLoc) { - Expr *Args[2] = { LHS, RHS }; + Expr *Args[2] = { LHS.get(), RHS.get() }; OverloadCandidateSet CandidateSet(QuestionLoc); Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args, 2, CandidateSet); OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) { - case OR_Success: + case OR_Success: { // We found a match. Perform the conversions on the arguments and move on. - if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], Sema::AA_Converting) || - Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], Sema::AA_Converting)) + ExprResult LHSRes = + Self.PerformImplicitConversion(LHS.get(), Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], Sema::AA_Converting); + if (LHSRes.isInvalid()) break; + LHS = move(LHSRes); + + ExprResult RHSRes = + Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], Sema::AA_Converting); + if (RHSRes.isInvalid()) + break; + RHS = move(RHSRes); if (Best->Function) Self.MarkDeclarationReferenced(QuestionLoc, Best->Function); return false; - + } + case OR_No_Viable_Function: // Emit a better diagnostic if one of the expressions is a null pointer // constant and the other is a pointer type. In this case, the user most // likely forgot to take the address of the other expression. - if (Self.DiagnoseConditionalForNull(LHS, RHS, QuestionLoc)) + if (Self.DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) return true; Self.Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHS->getType() << RHS->getType() - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return true; case OR_Ambiguous: Self.Diag(QuestionLoc, diag::err_conditional_ambiguous_ovl) - << LHS->getType() << RHS->getType() - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); // FIXME: Print the possible common types by printing the return types of // the viable candidates. break; @@ -2960,16 +3310,17 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS, /// \brief Perform an "extended" implicit conversion as returned by /// TryClassUnification. -static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) { +static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) { InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); - InitializationKind Kind = InitializationKind::CreateCopy(E->getLocStart(), + InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(), SourceLocation()); - InitializationSequence InitSeq(Self, Entity, Kind, &E, 1); - ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&E, 1)); + Expr *Arg = E.take(); + InitializationSequence InitSeq(Self, Entity, Kind, &Arg, 1); + ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&Arg, 1)); if (Result.isInvalid()) return true; - E = Result.takeAs(); + E = Result; return false; } @@ -2977,7 +3328,7 @@ static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) { /// /// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y /// extension. In this case, LHS == Cond. (But they're not aliases.) -QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, +QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc) { // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++ @@ -2985,9 +3336,11 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // C++0x 5.16p1 // The first expression is contextually converted to bool. - if (!Cond->isTypeDependent()) { - if (CheckCXXBooleanCondition(Cond)) + if (!Cond.get()->isTypeDependent()) { + ExprResult CondRes = CheckCXXBooleanCondition(Cond.take()); + if (CondRes.isInvalid()) return QualType(); + Cond = move(CondRes); } // Assume r-value. @@ -2995,28 +3348,30 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, OK = OK_Ordinary; // Either of the arguments dependent? - if (LHS->isTypeDependent() || RHS->isTypeDependent()) + if (LHS.get()->isTypeDependent() || RHS.get()->isTypeDependent()) return Context.DependentTy; // C++0x 5.16p2 // If either the second or the third operand has type (cv) void, ... - QualType LTy = LHS->getType(); - QualType RTy = RHS->getType(); + QualType LTy = LHS.get()->getType(); + QualType RTy = RHS.get()->getType(); bool LVoid = LTy->isVoidType(); bool RVoid = RTy->isVoidType(); if (LVoid || RVoid) { // ... then the [l2r] conversions are performed on the second and third // operands ... - DefaultFunctionArrayLvalueConversion(LHS); - DefaultFunctionArrayLvalueConversion(RHS); - LTy = LHS->getType(); - RTy = RHS->getType(); + LHS = DefaultFunctionArrayLvalueConversion(LHS.take()); + RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + LTy = LHS.get()->getType(); + RTy = RHS.get()->getType(); // ... and one of the following shall hold: // -- The second or the third operand (but not both) is a throw- // expression; the result is of the type of the other and is an rvalue. - bool LThrow = isa(LHS); - bool RThrow = isa(RHS); + bool LThrow = isa(LHS.get()); + bool RThrow = isa(RHS.get()); if (LThrow && !RThrow) return RTy; if (RThrow && !LThrow) @@ -3030,7 +3385,7 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // Neither holds, error. Diag(QuestionLoc, diag::err_conditional_void_nonvoid) << (LVoid ? RTy : LTy) << (LVoid ? 0 : 1) - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } @@ -3046,15 +3401,15 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // These return true if a single direction is already ambiguous. QualType L2RType, R2LType; bool HaveL2R, HaveR2L; - if (TryClassUnification(*this, LHS, RHS, QuestionLoc, HaveL2R, L2RType)) + if (TryClassUnification(*this, LHS.get(), RHS.get(), QuestionLoc, HaveL2R, L2RType)) return QualType(); - if (TryClassUnification(*this, RHS, LHS, QuestionLoc, HaveR2L, R2LType)) + if (TryClassUnification(*this, RHS.get(), LHS.get(), QuestionLoc, HaveR2L, R2LType)) return QualType(); // If both can be converted, [...] the program is ill-formed. if (HaveL2R && HaveR2L) { Diag(QuestionLoc, diag::err_conditional_ambiguous) - << LTy << RTy << LHS->getSourceRange() << RHS->getSourceRange(); + << LTy << RTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } @@ -3062,13 +3417,13 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // the chosen operand and the converted operands are used in place of the // original operands for the remainder of this section. if (HaveL2R) { - if (ConvertForConditional(*this, LHS, L2RType)) + if (ConvertForConditional(*this, LHS, L2RType) || LHS.isInvalid()) return QualType(); - LTy = LHS->getType(); + LTy = LHS.get()->getType(); } else if (HaveR2L) { - if (ConvertForConditional(*this, RHS, R2LType)) + if (ConvertForConditional(*this, RHS, R2LType) || RHS.isInvalid()) return QualType(); - RTy = RHS->getType(); + RTy = RHS.get()->getType(); } } @@ -3081,13 +3436,13 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // l-values. bool Same = Context.hasSameType(LTy, RTy); if (Same && - LHS->isGLValue() && - LHS->getValueKind() == RHS->getValueKind() && - LHS->isOrdinaryOrBitFieldObject() && - RHS->isOrdinaryOrBitFieldObject()) { - VK = LHS->getValueKind(); - if (LHS->getObjectKind() == OK_BitField || - RHS->getObjectKind() == OK_BitField) + LHS.get()->isGLValue() && + LHS.get()->getValueKind() == RHS.get()->getValueKind() && + LHS.get()->isOrdinaryOrBitFieldObject() && + RHS.get()->isOrdinaryOrBitFieldObject()) { + VK = LHS.get()->getValueKind(); + if (LHS.get()->getObjectKind() == OK_BitField || + RHS.get()->getObjectKind() == OK_BitField) OK = OK_BitField; return LTy; } @@ -3106,10 +3461,12 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // C++0x 5.16p6 // LValue-to-rvalue, array-to-pointer, and function-to-pointer standard // conversions are performed on the second and third operands. - DefaultFunctionArrayLvalueConversion(LHS); - DefaultFunctionArrayLvalueConversion(RHS); - LTy = LHS->getType(); - RTy = RHS->getType(); + LHS = DefaultFunctionArrayLvalueConversion(LHS.take()); + RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + LTy = LHS.get()->getType(); + RTy = RHS.get()->getType(); // After those conversions, one of the following shall hold: // -- The second and third operands have the same type; the result @@ -3123,18 +3480,18 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy); ExprResult LHSCopy = PerformCopyInitialization(Entity, SourceLocation(), - Owned(LHS)); + LHS); if (LHSCopy.isInvalid()) return QualType(); ExprResult RHSCopy = PerformCopyInitialization(Entity, SourceLocation(), - Owned(RHS)); + RHS); if (RHSCopy.isInvalid()) return QualType(); - LHS = LHSCopy.takeAs(); - RHS = RHSCopy.takeAs(); + LHS = LHSCopy; + RHS = RHSCopy; } return LTy; @@ -3149,7 +3506,9 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // common type, and the result is of that type. if (LTy->isArithmeticType() && RTy->isArithmeticType()) { UsualArithmeticConversions(LHS, RHS); - return LHS->getType(); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + return LHS.get()->getType(); } // -- The second and third operands have pointer type, or one has pointer @@ -3170,7 +3529,7 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands_nonstandard) << LTy << RTy << Composite - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return Composite; } @@ -3181,12 +3540,12 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return Composite; // Check if we are using a null with a non-pointer type. - if (DiagnoseConditionalForNull(LHS, RHS, QuestionLoc)) + if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) return QualType(); Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHS->getType() << RHS->getType() - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } @@ -3224,16 +3583,16 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, // the type of the other operand. if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { if (T2->isMemberPointerType()) - ImpCastExprToType(E1, T2, CK_NullToMemberPointer); + E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).take(); else - ImpCastExprToType(E1, T2, CK_NullToPointer); + E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take(); return T2; } if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { if (T1->isMemberPointerType()) - ImpCastExprToType(E2, T1, CK_NullToMemberPointer); + E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).take(); else - ImpCastExprToType(E2, T1, CK_NullToPointer); + E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take(); return T1; } @@ -3763,7 +4122,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(TemplateId->Template, + TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, @@ -3811,7 +4171,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(TemplateId->Template, + TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, @@ -3834,24 +4195,25 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, Destructed, HasTrailingLParen); } -ExprResult Sema::BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, +ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, CXXMethodDecl *Method) { - if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0, - FoundDecl, Method)) + ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0, + FoundDecl, Method); + if (Exp.isInvalid()) return true; MemberExpr *ME = - new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method, + new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method, SourceLocation(), Method->getType(), VK_RValue, OK_Ordinary); QualType ResultType = Method->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultType); ResultType = ResultType.getNonLValueExprType(Context); - MarkDeclarationReferenced(Exp->getLocStart(), Method); + MarkDeclarationReferenced(Exp.get()->getLocStart(), Method); CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK, - Exp->getLocEnd()); + Exp.get()->getLocEnd()); return CE; } @@ -3869,46 +4231,62 @@ ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation, /// Perform the conversions required for an expression used in a /// context that ignores the result. -void Sema::IgnoredValueConversions(Expr *&E) { +ExprResult Sema::IgnoredValueConversions(Expr *E) { // C99 6.3.2.1: // [Except in specific positions,] an lvalue that does not have // array type is converted to the value stored in the // designated object (and is no longer an lvalue). - if (E->isRValue()) return; + if (E->isRValue()) return Owned(E); // We always want to do this on ObjC property references. if (E->getObjectKind() == OK_ObjCProperty) { - ConvertPropertyForRValue(E); - if (E->isRValue()) return; + ExprResult Res = ConvertPropertyForRValue(E); + if (Res.isInvalid()) return Owned(E); + E = Res.take(); + if (E->isRValue()) return Owned(E); } // Otherwise, this rule does not apply in C++, at least not for the moment. - if (getLangOptions().CPlusPlus) return; + if (getLangOptions().CPlusPlus) return Owned(E); // GCC seems to also exclude expressions of incomplete enum type. if (const EnumType *T = E->getType()->getAs()) { if (!T->getDecl()->isComplete()) { // FIXME: stupid workaround for a codegen bug! - ImpCastExprToType(E, Context.VoidTy, CK_ToVoid); - return; + E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).take(); + return Owned(E); } } - DefaultFunctionArrayLvalueConversion(E); + ExprResult Res = DefaultFunctionArrayLvalueConversion(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); + if (!E->getType()->isVoidType()) RequireCompleteType(E->getExprLoc(), E->getType(), diag::err_incomplete_type); + return Owned(E); } -ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) { - if (!FullExpr) +ExprResult Sema::ActOnFinishFullExpr(Expr *FE) { + ExprResult FullExpr = Owned(FE); + + if (!FullExpr.get()) return ExprError(); - if (DiagnoseUnexpandedParameterPack(FullExpr)) + if (DiagnoseUnexpandedParameterPack(FullExpr.get())) return ExprError(); - IgnoredValueConversions(FullExpr); - CheckImplicitConversions(FullExpr); + FullExpr = CheckPlaceholderExpr(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + + FullExpr = IgnoredValueConversions(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + + CheckImplicitConversions(FullExpr.get()); return MaybeCreateExprWithCleanups(FullExpr); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index 4d03b068ca85..2a262f093922 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -62,7 +62,8 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, // Create the aggregate string with the appropriate content and location // information. - S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), false, + S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), + /*Wide=*/false, /*Pascal=*/false, Context.getPointerType(Context.CharTy), &StrLocs[0], StrLocs.size()); } @@ -246,7 +247,10 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, if (Args[i]->isTypeDependent()) continue; - DefaultArgumentPromotion(Args[i]); + ExprResult Result = DefaultArgumentPromotion(Args[i]); + if (Result.isInvalid()) + return true; + Args[i] = Result.take(); } unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found : @@ -305,7 +309,9 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, if (Args[i]->isTypeDependent()) continue; - IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + IsError |= Arg.isInvalid(); + Args[i] = Arg.take(); } } else { // Check for extra arguments to non-variadic methods. @@ -318,12 +324,24 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Args[NumArgs-1]->getLocEnd()); } } + // diagnose nonnull arguments. + for (specific_attr_iterator + i = Method->specific_attr_begin(), + e = Method->specific_attr_end(); i != e; ++i) { + CheckNonNullArguments(*i, Args, lbrac); + } DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs); return IsError; } bool Sema::isSelfExpr(Expr *RExpr) { + // 'self' is objc 'self' in an objc method only. + DeclContext *DC = CurContext; + while (isa(DC)) + DC = DC->getParent(); + if (DC && !isa(DC)) + return false; if (ImplicitCastExpr *ICE = dyn_cast(RExpr)) if (ICE->getCastKind() == CK_LValueToRValue) RExpr = ICE->getSubExpr(); @@ -381,6 +399,23 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, return Method; } +/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier +/// list of a qualified objective pointer type. +ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, + const ObjCObjectPointerType *OPT, + bool Instance) +{ + ObjCMethodDecl *MD = 0; + for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) { + ObjCProtocolDecl *PROTO = (*I); + if ((MD = PROTO->lookupMethod(Sel, Instance))) { + return MD; + } + } + return 0; +} + /// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an /// objective C interface. This is a property reference expression. ExprResult Sema:: @@ -391,6 +426,13 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, bool Super) { const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); ObjCInterfaceDecl *IFace = IFaceT->getDecl(); + + if (MemberName.getNameKind() != DeclarationName::Identifier) { + Diag(MemberLoc, diag::err_invalid_property_name) + << MemberName << QualType(OPT, 0); + return ExprError(); + } + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); if (IFace->isForwardDecl()) { @@ -405,6 +447,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); QualType ResTy = PD->getType(); + ResTy = ResTy.getNonLValueExprType(Context); Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) @@ -448,6 +491,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); + + // May be founf in property's qualified list. + if (!Getter) + Getter = LookupMethodInQualifiedType(Sel, OPT, true); // If this reference is in an @implementation, check for 'private' methods. if (!Getter) @@ -467,6 +514,11 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, SelectorTable::constructSetterName(PP.getIdentifierTable(), PP.getSelectorTable(), Member); ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); + + // May be founf in property's qualified list. + if (!Setter) + Setter = LookupMethodInQualifiedType(SetterSel, OPT, true); + if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. @@ -475,7 +527,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // Look through local category implementations associated with the class. if (!Setter) Setter = IFace->getCategoryInstanceMethod(SetterSel); - + if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); @@ -868,7 +920,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, return ExprError(); } assert(Class && "We don't know which class we're messaging?"); - + (void)DiagnoseUseOfDecl(Class, Loc); // Find the method we are messaging. if (!Method) { if (Class->isForwardDecl()) { @@ -1007,7 +1059,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. - DefaultFunctionArrayLvalueConversion(Receiver); + ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver); + if (Result.isInvalid()) + return ExprError(); + Receiver = Result.take(); ReceiverType = Receiver->getType(); } @@ -1026,39 +1081,53 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } else if (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()) { // Handle messages to Class. - if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { - if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { - // First check the public methods in the class interface. - Method = ClassDecl->lookupClassMethod(Sel); - - if (!Method) - Method = LookupPrivateClassMethod(Sel, ClassDecl); - - // FIXME: if we still haven't found a method, we need to look in - // protocols (if we have qualifiers). + // We allow sending a message to a qualified Class ("Class"), which + // is ok as long as one of the protocols implements the selector (if not, warn). + if (const ObjCObjectPointerType *QClassTy + = ReceiverType->getAsObjCQualifiedClassType()) { + // Search protocols for class methods. + Method = LookupMethodInQualifiedType(Sel, QClassTy, false); + if (!Method) { + Method = LookupMethodInQualifiedType(Sel, QClassTy, true); + // warn if instance method found for a Class message. + if (Method) { + Diag(Loc, diag::warn_instance_method_on_class_found) + << Method->getSelector() << Sel; + Diag(Method->getLocation(), diag::note_method_declared_at); + } } - if (Method && DiagnoseUseOfDecl(Method, Loc)) - return ExprError(); - } - if (!Method) { - // If not messaging 'self', look for any factory method named 'Sel'. - if (!Receiver || !isSelfExpr(Receiver)) { - Method = LookupFactoryMethodInGlobalPool(Sel, + } else { + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { + // First check the public methods in the class interface. + Method = ClassDecl->lookupClassMethod(Sel); + + if (!Method) + Method = LookupPrivateClassMethod(Sel, ClassDecl); + } + if (Method && DiagnoseUseOfDecl(Method, Loc)) + return ExprError(); + } + if (!Method) { + // If not messaging 'self', look for any factory method named 'Sel'. + if (!Receiver || !isSelfExpr(Receiver)) { + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc), + true); + if (!Method) { + // If no class (factory) method was found, check if an _instance_ + // method of the same name exists in the root class only. + Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc), - true); - if (!Method) { - // If no class (factory) method was found, check if an _instance_ - // method of the same name exists in the root class only. - Method = LookupInstanceMethodInGlobalPool(Sel, - SourceRange(LBracLoc, RBracLoc), - true); - if (Method) - if (const ObjCInterfaceDecl *ID = - dyn_cast(Method->getDeclContext())) { - if (ID->getSuperClass()) - Diag(Loc, diag::warn_root_inst_method_not_found) - << Sel << SourceRange(LBracLoc, RBracLoc); - } + true); + if (Method) + if (const ObjCInterfaceDecl *ID = + dyn_cast(Method->getDeclContext())) { + if (ID->getSuperClass()) + Diag(Loc, diag::warn_root_inst_method_not_found) + << Sel << SourceRange(LBracLoc, RBracLoc); + } + } } } } @@ -1070,15 +1139,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (const ObjCObjectPointerType *QIdTy = ReceiverType->getAsObjCQualifiedIdType()) { // Search protocols for instance methods. - for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), - E = QIdTy->qual_end(); I != E; ++I) { - ObjCProtocolDecl *PDecl = *I; - if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) - break; - // Since we aren't supporting "Class", look for a class method. - if (PDecl && (Method = PDecl->lookupClassMethod(Sel))) - break; - } + Method = LookupMethodInQualifiedType(Sel, QIdTy, true); + if (!Method) + Method = LookupMethodInQualifiedType(Sel, QIdTy, false); } else if (const ObjCObjectPointerType *OCIType = ReceiverType->getAsObjCInterfacePointerType()) { // We allow sending a message to a pointer to an interface (an object). @@ -1088,15 +1151,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // The idea is to add class info to MethodPool. Method = ClassDecl->lookupInstanceMethod(Sel); - if (!Method) { + if (!Method) // Search protocol qualifiers. - for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(), - E = OCIType->qual_end(); QI != E; ++QI) { - if ((Method = (*QI)->lookupInstanceMethod(Sel))) - break; - } - } - bool forwardClass = false; + Method = LookupMethodInQualifiedType(Sel, OCIType, true); + + const ObjCInterfaceDecl *forwardClass = 0; if (!Method) { // If we have implementations in scope, check "private" methods. Method = LookupPrivateInstanceMethod(Sel, ClassDecl); @@ -1108,7 +1167,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (OCIType->qual_empty()) { Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc)); - forwardClass = OCIType->getInterfaceDecl()->isForwardDecl(); + if (OCIType->getInterfaceDecl()->isForwardDecl()) + forwardClass = OCIType->getInterfaceDecl(); if (Method && !forwardClass) Diag(Loc, diag::warn_maynot_respond) << OCIType->getInterfaceDecl()->getIdentifier() << Sel; @@ -1125,37 +1185,42 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, << ReceiverType << Receiver->getSourceRange(); if (ReceiverType->isPointerType()) - ImpCastExprToType(Receiver, Context.getObjCIdType(), - CK_BitCast); + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + CK_BitCast).take(); else { // TODO: specialized warning on null receivers? bool IsNull = Receiver->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); - ImpCastExprToType(Receiver, Context.getObjCIdType(), - IsNull ? CK_NullToPointer : CK_IntegralToPointer); + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + IsNull ? CK_NullToPointer : CK_IntegralToPointer).take(); } ReceiverType = Receiver->getType(); } - else if (getLangOptions().CPlusPlus && - !PerformContextuallyConvertToObjCId(Receiver)) { - if (ImplicitCastExpr *ICE = dyn_cast(Receiver)) { - Receiver = ICE->getSubExpr(); - ReceiverType = Receiver->getType(); + else { + ExprResult ReceiverRes; + if (getLangOptions().CPlusPlus) + ReceiverRes = PerformContextuallyConvertToObjCId(Receiver); + if (ReceiverRes.isUsable()) { + Receiver = ReceiverRes.take(); + if (ImplicitCastExpr *ICE = dyn_cast(Receiver)) { + Receiver = ICE->getSubExpr(); + ReceiverType = Receiver->getType(); + } + return BuildInstanceMessage(Receiver, + ReceiverType, + SuperLoc, + Sel, + Method, + LBracLoc, + SelectorLoc, + RBracLoc, + move(ArgsIn)); + } else { + // Reject other random receiver types (e.g. structs). + Diag(Loc, diag::err_bad_receiver_type) + << ReceiverType << Receiver->getSourceRange(); + return ExprError(); } - return BuildInstanceMessage(Receiver, - ReceiverType, - SuperLoc, - Sel, - Method, - LBracLoc, - SelectorLoc, - RBracLoc, - move(ArgsIn)); - } else { - // Reject other random receiver types (e.g. structs). - Diag(Loc, diag::err_bad_receiver_type) - << ReceiverType << Receiver->getSourceRange(); - return ExprError(); } } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index 5882da0eab46..ca3fd6dfcb45 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -92,13 +92,31 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, const ConstantArrayType *CAT = cast(AT); - // C99 6.7.8p14. We have an array of character type with known size. However, + // We have an array of character type with known size. However, // the size may be smaller or larger than the string we are initializing. // FIXME: Avoid truncation for 64-bit length strings. - if (StrLength-1 > CAT->getSize().getZExtValue()) - S.Diag(Str->getSourceRange().getBegin(), - diag::warn_initializer_string_for_char_array_too_long) - << Str->getSourceRange(); + if (S.getLangOptions().CPlusPlus) { + if (StringLiteral *SL = dyn_cast(Str)) { + // For Pascal strings it's OK to strip off the terminating null character, + // so the example below is valid: + // + // unsigned char a[2] = "\pa"; + if (SL->isPascal()) + StrLength--; + } + + // [dcl.init.string]p2 + if (StrLength > CAT->getSize().getZExtValue()) + S.Diag(Str->getSourceRange().getBegin(), + diag::err_initializer_string_for_char_array_too_long) + << Str->getSourceRange(); + } else { + // C99 6.7.8p14. + if (StrLength-1 > CAT->getSize().getZExtValue()) + S.Diag(Str->getSourceRange().getBegin(), + diag::warn_initializer_string_for_char_array_too_long) + << Str->getSourceRange(); + } // Set the type to the actual size that we are initializing. If we have // something like: @@ -386,15 +404,29 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, if (hadError) { // Do nothing } else if (Init < NumInits) { - ILE->setInit(Init, ElementInit.takeAs()); - } else if (InitSeq.getKind() + // For arrays, just set the expression used for value-initialization + // of the "holes" in the array. + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) + ILE->setArrayFiller(ElementInit.takeAs()); + else + ILE->setInit(Init, ElementInit.takeAs()); + } else { + // For arrays, just set the expression used for value-initialization + // of the rest of elements and exit. + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) { + ILE->setArrayFiller(ElementInit.takeAs()); + return; + } + + if (InitSeq.getKind() == InitializationSequence::ConstructorInitialization) { - // Value-initialization requires a constructor call, so - // extend the initializer list to include the constructor - // call and make a note that we'll need to take another pass - // through the initializer list. - ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs()); - RequiresSecondPass = true; + // Value-initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs()); + RequiresSecondPass = true; + } } } else if (InitListExpr *InnerILE = dyn_cast(ILE->getInit(Init))) @@ -713,15 +745,23 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // compatible structure or union type. In the latter case, the // initial value of the object, including unnamed members, is // that of the expression. + ExprResult ExprRes = SemaRef.Owned(expr); if ((ElemType->isRecordType() || ElemType->isVectorType()) && - SemaRef.CheckSingleAssignmentConstraints(ElemType, expr) + SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes) == Sema::Compatible) { - SemaRef.DefaultFunctionArrayLvalueConversion(expr); - UpdateStructuredListElement(StructuredList, StructuredIndex, expr); + if (ExprRes.isInvalid()) + hadError = true; + else { + ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.take()); + if (ExprRes.isInvalid()) + hadError = true; + } + UpdateStructuredListElement(StructuredList, StructuredIndex, + ExprRes.takeAs()); ++Index; return; } - + ExprRes.release(); // Fall through for subaggregate initialization } @@ -1755,11 +1795,15 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, // Pre-allocate storage for the structured initializer list. unsigned NumElements = 0; unsigned NumInits = 0; - if (!StructuredList) + bool GotNumInits = false; + if (!StructuredList) { NumInits = IList->getNumInits(); - else if (Index < IList->getNumInits()) { - if (InitListExpr *SubList = dyn_cast(IList->getInit(Index))) + GotNumInits = true; + } else if (Index < IList->getNumInits()) { + if (InitListExpr *SubList = dyn_cast(IList->getInit(Index))) { NumInits = SubList->getNumInits(); + GotNumInits = true; + } } if (const ArrayType *AType @@ -1768,7 +1812,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, NumElements = CAType->getSize().getZExtValue(); // Simple heuristic so that we don't allocate a very large // initializer with many empty entries at the end. - if (NumInits && NumElements > NumInits) + if (GotNumInits && NumElements > NumInits) NumElements = 0; } } else if (const VectorType *VType = CurrentObjectType->getAs()) @@ -1936,6 +1980,9 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, Loc, GNUSyntax, Init.takeAs()); if (getLangOptions().CPlusPlus) + Diag(DIE->getLocStart(), diag::ext_designated_init_cxx) + << DIE->getSourceRange(); + else if (!getLangOptions().C99) Diag(DIE->getLocStart(), diag::ext_designated_init) << DIE->getSourceRange(); @@ -1998,6 +2045,7 @@ DeclarationName InitializedEntity::getName() const { case EK_New: case EK_Temporary: case EK_Base: + case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_BlockElement: @@ -2020,6 +2068,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const { case EK_New: case EK_Temporary: case EK_Base: + case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_BlockElement: @@ -2042,6 +2091,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_New: case EK_Temporary: case EK_Base: + case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_BlockElement: @@ -2101,6 +2151,7 @@ bool InitializationSequence::isAmbiguous() const { case FK_ReferenceInitDropsQualifiers: case FK_ReferenceInitFailed: case FK_ConversionFailed: + case FK_ConversionFromPropertyFailed: case FK_TooManyInitsForScalar: case FK_ReferenceBindingToInitList: case FK_InitListBadDestinationType: @@ -3126,8 +3177,14 @@ InitializationSequence::InitializationSequence(Sema &S, } for (unsigned I = 0; I != NumArgs; ++I) - if (Args[I]->getObjectKind() == OK_ObjCProperty) - S.ConvertPropertyForRValue(Args[I]); + if (Args[I]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = S.ConvertPropertyForRValue(Args[I]); + if (Result.isInvalid()) { + SetFailed(FK_ConversionFromPropertyFailed); + return; + } + Args[I] = Result.take(); + } QualType SourceType; Expr *Initializer = 0; @@ -3289,6 +3346,7 @@ getAssignmentAction(const InitializedEntity &Entity) { case InitializedEntity::EK_New: case InitializedEntity::EK_Exception: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: return Sema::AA_Initializing; case InitializedEntity::EK_Parameter: @@ -3325,6 +3383,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_New: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_BlockElement: @@ -3346,6 +3405,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_Result: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_BlockElement: return false; @@ -3430,6 +3490,7 @@ static ExprResult CopyObject(Sema &S, case InitializedEntity::EK_Temporary: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_BlockElement: Loc = CurInitExpr->getLocStart(); @@ -3686,14 +3747,15 @@ InitializationSequence::Perform(Sema &S, case SK_ObjCObjectConversion: case SK_ArrayInit: { assert(Args.size() == 1); - Expr *CurInitExpr = Args.get()[0]; - if (!CurInitExpr) return ExprError(); + CurInit = Args.get()[0]; + if (!CurInit.get()) return ExprError(); // Read from a property when initializing something with it. - if (CurInitExpr->getObjectKind() == OK_ObjCProperty) - S.ConvertPropertyForRValue(CurInitExpr); - - CurInit = ExprResult(CurInitExpr); + if (CurInit.get()->getObjectKind() == OK_ObjCProperty) { + CurInit = S.ConvertPropertyForRValue(CurInit.take()); + if (CurInit.isInvalid()) + return ExprError(); + } break; } @@ -3710,14 +3772,13 @@ InitializationSequence::Perform(Sema &S, if (CurInit.isInvalid()) return ExprError(); - Expr *CurInitExpr = CurInit.get(); - QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType(); + QualType SourceType = CurInit.get() ? CurInit.get()->getType() : QualType(); switch (Step->Kind) { case SK_ResolveAddressOfOverloadedFunction: // Overload resolution determined which function invoke; update the // initializer to reflect that choice. - S.CheckAddressOfMemberAccess(CurInitExpr, Step->Function.FoundDecl); + S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl); S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation()); CurInit = S.FixOverloadedFunctionReference(move(CurInit), Step->Function.FoundDecl, @@ -3735,8 +3796,8 @@ InitializationSequence::Perform(Sema &S, // Casts to inaccessible base classes are allowed with C-style casts. bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast(); if (S.CheckDerivedToBaseConversion(SourceType, Step->Type, - CurInitExpr->getLocStart(), - CurInitExpr->getSourceRange(), + CurInit.get()->getLocStart(), + CurInit.get()->getSourceRange(), &BasePath, IgnoreBaseAccess)) return ExprError(); @@ -3745,7 +3806,7 @@ InitializationSequence::Perform(Sema &S, if (const PointerType *Pointer = T->getAs()) T = Pointer->getPointeeType(); if (const RecordType *RecordTy = T->getAs()) - S.MarkVTableUsed(CurInitExpr->getLocStart(), + S.MarkVTableUsed(CurInit.get()->getLocStart(), cast(RecordTy->getDecl())); } @@ -3764,21 +3825,21 @@ InitializationSequence::Perform(Sema &S, } case SK_BindReference: - if (FieldDecl *BitField = CurInitExpr->getBitField()) { + if (FieldDecl *BitField = CurInit.get()->getBitField()) { // References cannot bind to bit fields (C++ [dcl.init.ref]p5). S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield) << Entity.getType().isVolatileQualified() << BitField->getDeclName() - << CurInitExpr->getSourceRange(); + << CurInit.get()->getSourceRange(); S.Diag(BitField->getLocation(), diag::note_bitfield_decl); return ExprError(); } - if (CurInitExpr->refersToVectorElement()) { + if (CurInit.get()->refersToVectorElement()) { // References cannot bind to vector elements. S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element) << Entity.getType().isVolatileQualified() - << CurInitExpr->getSourceRange(); + << CurInit.get()->getSourceRange(); PrintInitLocationNote(S, Entity); return ExprError(); } @@ -3786,7 +3847,7 @@ InitializationSequence::Perform(Sema &S, // Reference binding does not have any corresponding ASTs. // Check exception specifications - if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) + if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); break; @@ -3795,7 +3856,7 @@ InitializationSequence::Perform(Sema &S, // Reference binding does not have any corresponding ASTs. // Check exception specifications - if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) + if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); break; @@ -3817,13 +3878,14 @@ InitializationSequence::Perform(Sema &S, if (CXXConstructorDecl *Constructor = dyn_cast(Fn)) { // Build a call to the selected constructor. ASTOwningVector ConstructorArgs(S); - SourceLocation Loc = CurInitExpr->getLocStart(); + SourceLocation Loc = CurInit.get()->getLocStart(); CurInit.release(); // Ownership transferred into MultiExprArg, below. // Determine the arguments required to actually perform the constructor // call. + Expr *Arg = CurInit.get(); if (S.CompleteConstructorCall(Constructor, - MultiExprArg(&CurInitExpr, 1), + MultiExprArg(&Arg, 1), Loc, ConstructorArgs)) return ExprError(); @@ -3851,23 +3913,22 @@ InitializationSequence::Perform(Sema &S, // Build a call to the conversion function. CXXConversionDecl *Conversion = cast(Fn); IsLvalue = Conversion->getResultType()->isLValueReferenceType(); - S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr, 0, + S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0, FoundFn); S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()); // FIXME: Should we move this initialization into a separate // derived-to-base conversion? I believe the answer is "no", because // we don't want to turn off access control here for c-style casts. - if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0, - FoundFn, Conversion)) + ExprResult CurInitExprRes = + S.PerformObjectArgumentInitialization(CurInit.take(), /*Qualifier=*/0, + FoundFn, Conversion); + if(CurInitExprRes.isInvalid()) return ExprError(); - - // Do a little dance to make sure that CurInit has the proper - // pointer. - CurInit.release(); + CurInit = move(CurInitExprRes); // Build the actual call to the conversion function. - CurInit = S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn, Conversion); + CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion); if (CurInit.isInvalid() || !CurInit.get()) return ExprError(); @@ -3881,23 +3942,21 @@ InitializationSequence::Perform(Sema &S, if (RequiresCopy || shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); else if (CreatedObject && shouldDestroyTemporary(Entity)) { - CurInitExpr = static_cast(CurInit.get()); - QualType T = CurInitExpr->getType(); + QualType T = CurInit.get()->getType(); if (const RecordType *Record = T->getAs()) { CXXDestructorDecl *Destructor = S.LookupDestructor(cast(Record->getDecl())); - S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor, + S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); - S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor); - S.DiagnoseUseOfDecl(Destructor, CurInitExpr->getLocStart()); + S.MarkDeclarationReferenced(CurInit.get()->getLocStart(), Destructor); + S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart()); } } - CurInitExpr = CurInit.takeAs(); // FIXME: xvalues CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, - CurInitExpr->getType(), - CastKind, CurInitExpr, 0, + CurInit.get()->getType(), + CastKind, CurInit.get(), 0, IsLvalue ? VK_LValue : VK_RValue)); if (RequiresCopy) @@ -3917,25 +3976,23 @@ InitializationSequence::Perform(Sema &S, (Step->Kind == SK_QualificationConversionXValue ? VK_XValue : VK_RValue); - S.ImpCastExprToType(CurInitExpr, Step->Type, CK_NoOp, VK); - CurInit.release(); - CurInit = S.Owned(CurInitExpr); + CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_NoOp, VK); break; } case SK_ConversionSequence: { - if (S.PerformImplicitConversion(CurInitExpr, Step->Type, *Step->ICS, - getAssignmentAction(Entity), - Kind.isCStyleOrFunctionalCast())) + ExprResult CurInitExprRes = + S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS, + getAssignmentAction(Entity), + Kind.isCStyleOrFunctionalCast()); + if (CurInitExprRes.isInvalid()) return ExprError(); - - CurInit.release(); - CurInit = S.Owned(CurInitExpr); + CurInit = move(CurInitExprRes); break; } case SK_ListInitialization: { - InitListExpr *InitList = cast(CurInitExpr); + InitListExpr *InitList = cast(CurInit.get()); QualType Ty = Step->Type; if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty)) return ExprError(); @@ -4004,6 +4061,9 @@ InitializationSequence::Perform(Sema &S, CXXConstructExpr::CK_VirtualBase : CXXConstructExpr::CK_NonVirtualBase; } + if (Entity.getKind() == InitializedEntity::EK_Delegating) { + ConstructKind = CXXConstructExpr::CK_Delegating; + } // Only get the parenthesis range if it is a direct construction. SourceRange parenRange = @@ -4068,54 +4128,57 @@ InitializationSequence::Perform(Sema &S, } case SK_CAssignment: { - QualType SourceType = CurInitExpr->getType(); + QualType SourceType = CurInit.get()->getType(); + ExprResult Result = move(CurInit); Sema::AssignConvertType ConvTy = - S.CheckSingleAssignmentConstraints(Step->Type, CurInitExpr); + S.CheckSingleAssignmentConstraints(Step->Type, Result); + if (Result.isInvalid()) + return ExprError(); + CurInit = move(Result); // If this is a call, allow conversion to a transparent union. + ExprResult CurInitExprRes = move(CurInit); if (ConvTy != Sema::Compatible && Entity.getKind() == InitializedEntity::EK_Parameter && - S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExpr) + S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes) == Sema::Compatible) ConvTy = Sema::Compatible; + if (CurInitExprRes.isInvalid()) + return ExprError(); + CurInit = move(CurInitExprRes); bool Complained; if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), Step->Type, SourceType, - CurInitExpr, + CurInit.get(), getAssignmentAction(Entity), &Complained)) { PrintInitLocationNote(S, Entity); return ExprError(); } else if (Complained) PrintInitLocationNote(S, Entity); - - CurInit.release(); - CurInit = S.Owned(CurInitExpr); break; } case SK_StringInit: { QualType Ty = Step->Type; - CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, + CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty, S.Context.getAsArrayType(Ty), S); break; } case SK_ObjCObjectConversion: - S.ImpCastExprToType(CurInitExpr, Step->Type, + CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_ObjCObjectLValueCast, - S.CastCategory(CurInitExpr)); - CurInit.release(); - CurInit = S.Owned(CurInitExpr); + S.CastCategory(CurInit.get())); break; case SK_ArrayInit: // Okay: we checked everything before creating this step. Note that // this is a GNU extension. S.Diag(Kind.getLocation(), diag::ext_array_init_copy) - << Step->Type << CurInitExpr->getType() - << CurInitExpr->getSourceRange(); + << Step->Type << CurInit.get()->getType() + << CurInit.get()->getSourceRange(); // If the destination type is an incomplete array type, update the // type accordingly. @@ -4123,7 +4186,7 @@ InitializationSequence::Perform(Sema &S, if (const IncompleteArrayType *IncompleteDest = S.Context.getAsIncompleteArrayType(Step->Type)) { if (const ConstantArrayType *ConstantSource - = S.Context.getAsConstantArrayType(CurInitExpr->getType())) { + = S.Context.getAsConstantArrayType(CurInit.get()->getType())) { *ResultType = S.Context.getConstantArrayType( IncompleteDest->getElementType(), ConstantSource->getSize(), @@ -4283,6 +4346,11 @@ bool InitializationSequence::Diagnose(Sema &S, << Args[0]->getSourceRange(); break; } + + case FK_ConversionFromPropertyFailed: + // No-op. This error has already been reported. + break; + case FK_TooManyInitsForScalar: { SourceRange R; @@ -4482,6 +4550,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const { OS << "conversion failed"; break; + case FK_ConversionFromPropertyFailed: + OS << "conversion from property failed"; + break; + case FK_TooManyInitsForScalar: OS << "too many initializers for scalar"; break; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 3deb4034c538..309c7712d4cc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -686,8 +686,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { // FIXME: Calling convention! FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo(); EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default); - EPI.HasExceptionSpec = false; - EPI.HasAnyExceptionSpec = false; + EPI.ExceptionSpecType = EST_None; EPI.NumExceptions = 0; QualType ExpectedType = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), @@ -1130,8 +1129,8 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // If we didn't find a use of this identifier, and if the identifier // corresponds to a compiler builtin, create the decl object for the builtin // now, injecting it into translation unit scope, and return it. - if (AllowBuiltinCreation) - return LookupBuiltin(*this, R); + if (AllowBuiltinCreation && LookupBuiltin(*this, R)) + return true; // If we didn't find a use of this identifier, the ExternalSource // may be able to handle the situation. @@ -1964,10 +1963,13 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { case Type::Complex: break; - // These are ignored by ADL. + // If T is an Objective-C object or interface type, or a pointer to an + // object or interface type, the associated namespace is the global + // namespace. case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: + Result.Namespaces.insert(Result.S.Context.getTranslationUnitDecl()); break; } @@ -2203,7 +2205,8 @@ void ADLResult::insert(NamedDecl *New) { void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - ADLResult &Result) { + ADLResult &Result, + bool StdNamespaceIsAssociated) { // Find all of the associated namespaces and classes based on the // arguments we have. AssociatedNamespaceSet AssociatedNamespaces; @@ -2211,6 +2214,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, FindAssociatedClassesAndNamespaces(Args, NumArgs, AssociatedNamespaces, AssociatedClasses); + if (StdNamespaceIsAssociated && StdNamespace) + AssociatedNamespaces.insert(getStdNamespace()); QualType T1, T2; if (Operator) { @@ -2766,30 +2771,35 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, } /// LookupOrCreateLabel - Do a name lookup of a label with the specified name. -/// If isLocalLabel is true, then this is a definition of an __label__ label -/// name, otherwise it is a normal label definition or use. +/// If GnuLabelLoc is a valid source location, then this is a definition +/// of an __label__ label name, otherwise it is a normal label definition +/// or use. LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, - bool isLocalLabel) { + SourceLocation GnuLabelLoc) { // Do a lookup to see if we have a label with this name already. NamedDecl *Res = 0; - - // Local label definitions always shadow existing labels. - if (!isLocalLabel) - Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration); - - // If we found a label, check to see if it is in the same context as us. When - // in a Block, we don't want to reuse a label in an enclosing function. + + if (GnuLabelLoc.isValid()) { + // Local label definitions always shadow existing labels. + Res = LabelDecl::Create(Context, CurContext, Loc, II, GnuLabelLoc); + Scope *S = CurScope; + PushOnScopeChains(Res, S, true); + return cast(Res); + } + + // Not a GNU local label. + Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration); + // If we found a label, check to see if it is in the same context as us. + // When in a Block, we don't want to reuse a label in an enclosing function. if (Res && Res->getDeclContext() != CurContext) Res = 0; - if (Res == 0) { // If not forward referenced or defined already, create the backing decl. Res = LabelDecl::Create(Context, CurContext, Loc, II); - Scope *S = isLocalLabel ? CurScope : CurScope->getFnParent(); + Scope *S = CurScope->getFnParent(); assert(S && "Not in a function?"); PushOnScopeChains(Res, S, true); } - return cast(Res); } @@ -2853,8 +2863,6 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, } void TypoCorrectionConsumer::FoundName(llvm::StringRef Name) { - using namespace std; - // Use a simple length-based heuristic to determine the minimum possible // edit distance. If the minimum isn't good enough, bail out early. unsigned MinED = abs((int)Name.size() - (int)Typo.size()); @@ -2863,7 +2871,8 @@ void TypoCorrectionConsumer::FoundName(llvm::StringRef Name) { // Compute an upper bound on the allowable edit distance, so that the // edit-distance algorithm can short-circuit. - unsigned UpperBound = min(unsigned((Typo.size() + 2) / 3), BestEditDistance); + unsigned UpperBound = + std::min(unsigned((Typo.size() + 2) / 3), BestEditDistance); // Compute the edit distance between the typo and the name of this // entity. If this edit distance is not worse than the best edit diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp index b086ca751406..6c4469cef9ef 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp @@ -45,11 +45,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, !(Attributes & ObjCDeclSpec::DQ_PR_copy))); TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); - QualType T = TSI->getType(); - if (T->isReferenceType()) { - Diag(AtLoc, diag::error_reference_property); - return 0; - } + // Proceed with constructing the ObjCPropertDecls. ObjCContainerDecl *ClassDecl = cast(ClassCategory); @@ -404,12 +400,16 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (!PropertyIvar) PropertyIvar = PropertyId; QualType PropType = Context.getCanonicalType(property->getType()); + QualType PropertyIvarType = PropType; + if (PropType->isReferenceType()) + PropertyIvarType = cast(PropType)->getPointeeType(); // Check that this is a previously declared 'ivar' in 'IDecl' interface ObjCInterfaceDecl *ClassDeclared; Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); if (!Ivar) { - Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc, - PropertyIvar, PropType, /*Dinfo=*/0, + Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, + PropertyLoc, PropertyLoc, PropertyIvar, + PropertyIvarType, /*Dinfo=*/0, ObjCIvarDecl::Private, (Expr *)0, true); ClassImpDecl->addDecl(Ivar); @@ -432,19 +432,19 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, QualType IvarType = Context.getCanonicalType(Ivar->getType()); // Check that type of property and its ivar are type compatible. - if (PropType != IvarType) { + if (PropertyIvarType != IvarType) { bool compat = false; - if (isa(PropType) + if (isa(PropertyIvarType) && isa(IvarType)) compat = Context.canAssignObjCInterfaces( - PropType->getAs(), + PropertyIvarType->getAs(), IvarType->getAs()); else { SourceLocation Loc = PropertyIvarLoc; if (Loc.isInvalid()) Loc = PropertyLoc; - compat = (CheckAssignmentConstraints(Loc, PropType, IvarType) + compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType) == Compatible); } if (!compat) { @@ -459,7 +459,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // FIXME! Rules for properties are somewhat different that those // for assignments. Use a new routine to consolidate all cases; // specifically for property redeclarations as well as for ivars. - QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType(); + QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); if (lhsType != rhsType && lhsType->isArithmeticType()) { @@ -538,7 +538,10 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, SelfExpr, true, true); ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); ParmVarDecl *Param = (*P); - Expr *rhs = new (Context) DeclRefExpr(Param, Param->getType(), + QualType T = Param->getType(); + if (T->isReferenceType()) + T = T->getAs()->getPointeeType(); + Expr *rhs = new (Context) DeclRefExpr(Param, T, VK_LValue, SourceLocation()); ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), BO_Assign, lhs, rhs); @@ -682,7 +685,7 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, /// ComparePropertiesInBaseAndSuper - This routine compares property /// declarations in base and its super class, if any, and issues -/// diagnostics in a variety of inconsistant situations. +/// diagnostics in a variety of inconsistent situations. /// void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) { ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); @@ -1137,10 +1140,14 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, ObjCPropertyDecl *Property) { // Should we just clone all attributes over? - if (DeprecatedAttr *A = Property->getAttr()) - PropertyMethod->addAttr(A->clone(S.Context)); - if (UnavailableAttr *A = Property->getAttr()) - PropertyMethod->addAttr(A->clone(S.Context)); + for (Decl::attr_iterator A = Property->attr_begin(), + AEnd = Property->attr_end(); + A != AEnd; ++A) { + if (isa(*A) || + isa(*A) || + isa(*A)) + PropertyMethod->addAttr((*A)->clone(S.Context)); + } } /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods @@ -1235,7 +1242,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, // Invent the arguments for the setter. We don't bother making a // nice name for the argument. - ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, Loc, + ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, + Loc, Loc, property->getIdentifier(), property->getType(), /*TInfo=*/0, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 8d03285ee443..3f3ed0e1f902 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -36,18 +36,26 @@ using namespace sema; /// A convenience routine for creating a decayed reference to a /// function. -static Expr * +static ExprResult CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, SourceLocation Loc = SourceLocation()) { - Expr *E = new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc); - S.DefaultFunctionArrayConversion(E); - return E; + ExprResult E = S.Owned(new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc)); + E = S.DefaultFunctionArrayConversion(E.take()); + if (E.isInvalid()) + return ExprError(); + return move(E); } static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, bool InOverloadResolution, StandardConversionSequence &SCS, bool CStyle); + +static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From, + QualType &ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle); static OverloadingResult IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, UserDefinedConversionSequence& User, @@ -128,7 +136,9 @@ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) { ICR_Conversion, ICR_Conversion, ICR_Conversion, - ICR_Complex_Real_Conversion + ICR_Complex_Real_Conversion, + ICR_Conversion, + ICR_Conversion }; return Rank[(int)Kind]; } @@ -157,7 +167,9 @@ const char* GetImplicitConversionName(ImplicitConversionKind Kind) { "Derived-to-base conversion", "Vector conversion", "Vector splat", - "Complex-real conversion" + "Complex-real conversion", + "Block Pointer conversion", + "Transparent Union Conversion" }; return Name[Kind]; } @@ -228,7 +240,7 @@ isPointerConversionToVoidPointer(ASTContext& Context) const { if (First == ICK_Array_To_Pointer) FromType = Context.getArrayDecayedType(FromType); - if (Second == ICK_Pointer_Conversion && FromType->isPointerType()) + if (Second == ICK_Pointer_Conversion && FromType->isAnyPointerType()) if (const PointerType* ToPtrType = ToType->getAs()) return ToPtrType->getPointeeType()->isVoidType(); @@ -876,20 +888,19 @@ bool Sema::TryImplicitConversion(InitializationSequence &Sequence, } /// PerformImplicitConversion - Perform an implicit conversion of the -/// expression From to the type ToType. Returns true if there was an -/// error, false otherwise. The expression From is replaced with the +/// expression From to the type ToType. Returns the /// converted expression. Flavor is the kind of conversion we're /// performing, used in the error message. If @p AllowExplicit, /// explicit user-defined conversions are permitted. -bool -Sema::PerformImplicitConversion(Expr *&From, QualType ToType, +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, bool AllowExplicit) { ImplicitConversionSequence ICS; return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS); } -bool -Sema::PerformImplicitConversion(Expr *&From, QualType ToType, +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, bool AllowExplicit, ImplicitConversionSequence& ICS) { ICS = clang::TryImplicitConversion(*this, From, ToType, @@ -1048,27 +1059,33 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // otherwise, only a boolean conversion is standard if (!ToType->isBooleanType()) return false; - - } - - if (CXXMethodDecl *Method = dyn_cast(Fn)) { - if (!Method->isStatic()) { - const Type *ClassType - = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); - FromType = S.Context.getMemberPointerType(FromType, ClassType); - } } - // If the "from" expression takes the address of the overloaded - // function, update the type of the resulting expression accordingly. - if (FromType->getAs()) - if (UnaryOperator *UnOp = dyn_cast(From->IgnoreParens())) - if (UnOp->getOpcode() == UO_AddrOf) - FromType = S.Context.getPointerType(FromType); + // Check if the "from" expression is taking the address of an overloaded + // function and recompute the FromType accordingly. Take advantage of the + // fact that non-static member functions *must* have such an address-of + // expression. + CXXMethodDecl *Method = dyn_cast(Fn); + if (Method && !Method->isStatic()) { + assert(isa(From->IgnoreParens()) && + "Non-unary operator on non-static member address"); + assert(cast(From->IgnoreParens())->getOpcode() + == UO_AddrOf && + "Non-address-of operator on non-static member address"); + const Type *ClassType + = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); + FromType = S.Context.getMemberPointerType(FromType, ClassType); + } else if (isa(From->IgnoreParens())) { + assert(cast(From->IgnoreParens())->getOpcode() == + UO_AddrOf && + "Non-address-of operator for overloaded function expression"); + FromType = S.Context.getPointerType(FromType); + } // Check that we've computed the proper type after overload resolution. - assert(S.Context.hasSameType(FromType, - S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); + assert(S.Context.hasSameType( + FromType, + S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); } else { return false; } @@ -1188,6 +1205,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Pointer conversions (C++ 4.10). SCS.Second = ICK_Pointer_Conversion; SCS.IncompatibleObjC = IncompatibleObjC; + FromType = FromType.getUnqualifiedType(); } else if (S.IsMemberPointerConversion(From, FromType, ToType, InOverloadResolution, FromType)) { // Pointer to member conversions (4.11). @@ -1203,6 +1221,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, } else if (IsNoReturnConversion(S.Context, FromType, ToType, FromType)) { // Treat a conversion that strips "noreturn" as an identity conversion. SCS.Second = ICK_NoReturn_Adjustment; + } else if (IsTransparentUnionStandardConversion(S, From, ToType, + InOverloadResolution, + SCS, CStyle)) { + SCS.Second = ICK_TransparentUnionConversion; + FromType = ToType; } else { // No second conversion required. SCS.Second = ICK_Identity; @@ -1244,6 +1267,30 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, return true; } + +static bool +IsTransparentUnionStandardConversion(Sema &S, Expr* From, + QualType &ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle) { + + const RecordType *UT = ToType->getAsUnionType(); + if (!UT || !UT->getDecl()->hasAttr()) + return false; + // The field to initialize within the transparent union. + RecordDecl *UD = UT->getDecl(); + // It's compatible if the expression matches any of the fields. + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); + it != itend; ++it) { + if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS, CStyle)) { + ToType = it->getType(); + return true; + } + } + return false; +} /// IsIntegralPromotion - Determines whether the conversion from the /// expression From (whose potentially-adjusted type is FromType) to @@ -1615,8 +1662,30 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, return true; } + if (FromPointeeType->isVectorType() && ToPointeeType->isVectorType() && + Context.areCompatibleVectorTypes(FromPointeeType, ToPointeeType)) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + return false; } + +/// \brief Adopt the given qualifiers for the given type. +static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ + Qualifiers TQs = T.getQualifiers(); + + // Check whether qualifiers already match. + if (TQs == Qs) + return T; + + if (Qs.compatiblyIncludes(TQs)) + return Context.getQualifiedType(T, Qs); + + return Context.getQualifiedType(T.getUnqualifiedType(), Qs); +} /// isObjCPointerConversion - Determines whether this is an /// Objective-C pointer conversion. Subroutine of IsPointerConversion, @@ -1627,6 +1696,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, if (!getLangOptions().ObjC1) return false; + // The set of qualifiers on the type we're converting from. + Qualifiers FromQualifiers = FromType.getQualifiers(); + // First, we handle all conversions on ObjC object pointer types. const ObjCObjectPointerType* ToObjCPtr = ToType->getAs(); @@ -1640,10 +1712,11 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, FromObjCPtr->getPointeeType())) return false; + // Check for compatible // Objective C++: We're able to convert between "id" or "Class" and a // pointer to any interface (in both directions). if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) { - ConvertedType = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); return true; } // Conversions with Objective-C's id<...>. @@ -1651,7 +1724,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ToObjCPtr->isObjCQualifiedIdType()) && Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType, /*compare=*/false)) { - ConvertedType = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); return true; } // Objective C++: We're able to convert from a pointer to an @@ -1666,6 +1739,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, ToObjCPtr->getPointeeType(), ToType, Context); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); return true; } @@ -1677,6 +1751,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, ToObjCPtr->getPointeeType(), ToType, Context); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); return true; } } @@ -1689,7 +1764,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, // Objective C++: We're able to convert from a pointer to any object // to a block pointer type. if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) { - ConvertedType = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); return true; } ToPointeeType = ToBlockPtr->getPointeeType(); @@ -1698,7 +1773,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) { // Objective C++: We're able to convert from a block pointer type to a // pointer to any object. - ConvertedType = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); return true; } else @@ -1721,6 +1796,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, // We always complain about this conversion. IncompatibleObjC = true; ConvertedType = Context.getPointerType(ConvertedType); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); return true; } // Allow conversion of pointee being objective-c pointer to another one; @@ -1730,6 +1806,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, IncompatibleObjC)) { ConvertedType = Context.getPointerType(ConvertedType); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); return true; } @@ -1790,7 +1867,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, if (HasObjCConversion) { // We had an Objective-C conversion. Allow this pointer // conversion, but complain about it. - ConvertedType = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); IncompatibleObjC = true; return true; } @@ -1936,11 +2013,12 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, Kind = CK_BitCast; - if (CXXBoolLiteralExpr* LitBool - = dyn_cast(From->IgnoreParens())) - if (!IsCStyleOrFunctionalCast && LitBool->getValue() == false) - Diag(LitBool->getExprLoc(), diag::warn_init_pointer_from_false) - << ToType; + if (!IsCStyleOrFunctionalCast && + Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy) && + From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(From->getExprLoc(), From, + PDiag(diag::warn_impcast_bool_to_null_pointer) + << ToType << From->getSourceRange()); if (const PointerType *FromPtrType = FromType->getAs()) if (const PointerType *ToPtrType = ToType->getAs()) { @@ -2116,21 +2194,24 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, // unwrap. UnwrappedAnyPointer = true; + Qualifiers FromQuals = FromType.getQualifiers(); + Qualifiers ToQuals = ToType.getQualifiers(); + // -- for every j > 0, if const is in cv 1,j then const is in cv // 2,j, and similarly for volatile. - if (!CStyle && !ToType.isAtLeastAsQualifiedAs(FromType)) + if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals)) return false; // -- if the cv 1,j and cv 2,j are different, then const is in // every cv for 0 < k < j. - if (!CStyle && FromType.getCVRQualifiers() != ToType.getCVRQualifiers() + if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers() && !PreviousToQualsIncludeConst) return false; // Keep track of whether all prior cv-qualifiers in the "to" type // include const. PreviousToQualsIncludeConst - = PreviousToQualsIncludeConst && ToType.isConstQualified(); + = PreviousToQualsIncludeConst && ToQuals.hasConst(); } // We are left with FromType and ToType being the pointee types @@ -2175,7 +2256,11 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, S.IsDerivedFrom(From->getType(), ToType))) ConstructorsOnly = true; - if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag())) { + S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag()); + // RequireCompleteType may have returned true due to some invalid decl + // during template instantiation, but ToType may be complete enough now + // to try to recover. + if (ToType->isIncompleteType()) { // We're not going to find any constructors. } else if (CXXRecordDecl *ToRecordDecl = dyn_cast(ToRecordType->getDecl())) { @@ -2546,7 +2631,8 @@ CompareStandardConversionSequences(Sema &S, if (ImplicitConversionSequence::CompareKind DerivedCK = CompareDerivedToBaseConversions(S, SCS1, SCS2)) return DerivedCK; - } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) { + } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid && + !S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) { // Both conversion sequences are conversions to void // pointers. Compare the source types to determine if there's an // inheritance relationship in their sources. @@ -2560,10 +2646,8 @@ CompareStandardConversionSequences(Sema &S, if (SCS2.First == ICK_Array_To_Pointer) FromType2 = S.Context.getArrayDecayedType(FromType2); - QualType FromPointee1 - = FromType1->getAs()->getPointeeType().getUnqualifiedType(); - QualType FromPointee2 - = FromType2->getAs()->getPointeeType().getUnqualifiedType(); + QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType(); + QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType(); if (S.IsDerivedFrom(FromPointee2, FromPointee1)) return ImplicitConversionSequence::Better; @@ -2572,13 +2656,19 @@ CompareStandardConversionSequences(Sema &S, // Objective-C++: If one interface is more specific than the // other, it is the better one. - const ObjCObjectType* FromIface1 = FromPointee1->getAs(); - const ObjCObjectType* FromIface2 = FromPointee2->getAs(); - if (FromIface1 && FromIface1) { - if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1)) - return ImplicitConversionSequence::Better; - else if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2)) - return ImplicitConversionSequence::Worse; + const ObjCObjectPointerType* FromObjCPtr1 + = FromType1->getAs(); + const ObjCObjectPointerType* FromObjCPtr2 + = FromType2->getAs(); + if (FromObjCPtr1 && FromObjCPtr2) { + bool AssignLeft = S.Context.canAssignObjCInterfaces(FromObjCPtr1, + FromObjCPtr2); + bool AssignRight = S.Context.canAssignObjCInterfaces(FromObjCPtr2, + FromObjCPtr1); + if (AssignLeft != AssignRight) { + return AssignLeft? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } } } @@ -2981,7 +3071,12 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, // overload resolution, cases for which cv1 is greater // cv-qualification than cv2 are identified as // reference-compatible with added qualification (see 13.3.3.2). - if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers()) + // + // Note that we also require equivalence of Objective-C GC and address-space + // qualifiers when performing these computations, so that e.g., an int in + // address space 1 is not reference-compatible with an int in address + // space 2. + if (T1Quals == T2Quals) return Ref_Compatible; else if (T1.isMoreQualifiedThan(T2)) return Ref_Compatible_With_Added_Qualification; @@ -3480,8 +3575,8 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, /// PerformObjectArgumentInitialization - Perform initialization of /// the implicit object parameter for the given Method with the given /// expression. -bool -Sema::PerformObjectArgumentInitialization(Expr *&From, +ExprResult +Sema::PerformObjectArgumentInitialization(Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, CXXMethodDecl *Method) { @@ -3517,7 +3612,7 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, << From->getSourceRange(); Diag(Method->getLocation(), diag::note_previous_decl) << Method->getDeclName(); - return true; + return ExprError(); } } @@ -3526,13 +3621,18 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); } - if (ICS.Standard.Second == ICK_Derived_To_Base) - return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method); + if (ICS.Standard.Second == ICK_Derived_To_Base) { + ExprResult FromRes = + PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method); + if (FromRes.isInvalid()) + return ExprError(); + From = FromRes.take(); + } if (!Context.hasSameType(From->getType(), DestType)) - ImpCastExprToType(From, DestType, CK_NoOp, - From->getType()->isPointerType() ? VK_RValue : VK_LValue); - return false; + From = ImpCastExprToType(From, DestType, CK_NoOp, + From->getType()->isPointerType() ? VK_RValue : VK_LValue).take(); + return Owned(From); } /// TryContextuallyConvertToBool - Attempt to contextually convert the @@ -3550,16 +3650,16 @@ TryContextuallyConvertToBool(Sema &S, Expr *From) { /// PerformContextuallyConvertToBool - Perform a contextual conversion /// of the expression From to bool (C++0x [conv]p3). -bool Sema::PerformContextuallyConvertToBool(Expr *&From) { +ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) { ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From); if (!ICS.isBad()) return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting); if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) - return Diag(From->getSourceRange().getBegin(), - diag::err_typecheck_bool_condition) + return Diag(From->getSourceRange().getBegin(), + diag::err_typecheck_bool_condition) << From->getType() << From->getSourceRange(); - return true; + return ExprError(); } /// TryContextuallyConvertToObjCId - Attempt to contextually convert the @@ -3577,12 +3677,12 @@ TryContextuallyConvertToObjCId(Sema &S, Expr *From) { /// PerformContextuallyConvertToObjCId - Perform a contextual conversion /// of the expression From to 'id'. -bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) { +ExprResult Sema::PerformContextuallyConvertToObjCId(Expr *From) { QualType Ty = Context.getObjCIdType(); ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(*this, From); if (!ICS.isBad()) return PerformImplicitConversion(From, Ty, ICS, AA_Converting); - return true; + return ExprError(); } /// \brief Attempt to convert the given expression to an integral or @@ -4061,7 +4161,7 @@ void Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, Expr **Args, unsigned NumArgs, @@ -4114,7 +4214,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, void Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { @@ -6090,9 +6190,10 @@ void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, - bool PartialOverloading) { + bool PartialOverloading, + bool StdNamespaceIsAssociated) { ADLResult Fns; // FIXME: This approach for uniquing ADL results (and removing @@ -6103,7 +6204,8 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, // we supposed to consider on ADL candidates, anyway? // FIXME: Pass in the explicit template arguments? - ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns); + ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns, + StdNamespaceIsAssociated); // Erase all of the candidates we already knew about. for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), @@ -6282,8 +6384,7 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, // Best is the best viable function. if (Best->Function && - (Best->Function->isDeleted() || - Best->Function->getAttr())) + (Best->Function->isDeleted() || Best->Function->isUnavailable())) return OR_Deleted; return OR_Success; @@ -6473,6 +6574,17 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { return; } + if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy + << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr() + << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); assert(CVR && "unexpected qualifiers mismatch"); @@ -6735,7 +6847,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, FunctionDecl *Fn = Cand->Function; // Note deleted candidates, but only if they're viable. - if (Cand->Viable && (Fn->isDeleted() || Fn->hasAttr())) { + if (Cand->Viable && (Fn->isDeleted() || Fn->isUnavailable())) { std::string FnDesc; OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); @@ -7134,8 +7246,23 @@ class AddressOfFunctionResolver if (!TargetFunctionType->isFunctionType()) { if (OvlExpr->hasExplicitTemplateArgs()) { DeclAccessPair dap; - if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( + if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( OvlExpr, false, &dap) ) { + + if (CXXMethodDecl *Method = dyn_cast(Fn)) { + if (!Method->isStatic()) { + // If the target type is a non-function type and the function + // found is a non-static member function, pretend as if that was + // the target, it's the only possible type to end up with. + TargetTypeIsNonStaticMemberFunction = true; + + // And skip adding the function if its not in the proper form. + // We'll diagnose this due to an empty set of functions. + if (!OvlExprInfo.HasFormOfMemberPointer) + return; + } + } + Matches.push_back(std::make_pair(dap,Fn)); } } @@ -7419,32 +7546,29 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetTyp /// template, where that template-id refers to a single template whose template /// arguments are either provided by the template-id or have defaults, /// as described in C++0x [temp.arg.explicit]p3. -FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, - bool Complain, - DeclAccessPair* FoundResult) { +FunctionDecl * +Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, + bool Complain, + DeclAccessPair *FoundResult) { // C++ [over.over]p1: // [...] [Note: any redundant set of parentheses surrounding the // overloaded function name is ignored (5.1). ] // C++ [over.over]p1: // [...] The overloaded function name can be preceded by the & // operator. - if (From->getType() != Context.OverloadTy) - return 0; - - OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression; // If we didn't actually find any template-ids, we're done. - if (!OvlExpr->hasExplicitTemplateArgs()) + if (!ovl->hasExplicitTemplateArgs()) return 0; TemplateArgumentListInfo ExplicitTemplateArgs; - OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); + ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); // Look through all of the overloaded functions, searching for one // whose type matches exactly. FunctionDecl *Matched = 0; - for (UnresolvedSetIterator I = OvlExpr->decls_begin(), - E = OvlExpr->decls_end(); I != E; ++I) { + for (UnresolvedSetIterator I = ovl->decls_begin(), + E = ovl->decls_end(); I != E; ++I) { // C++0x [temp.arg.explicit]p3: // [...] In contexts where deduction is done and fails, or in contexts // where deduction is not done, if a template argument list is @@ -7461,7 +7585,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); + TemplateDeductionInfo Info(Context, ovl->getNameLoc()); if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info)) { @@ -7470,30 +7594,98 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, continue; } + assert(Specialization && "no specialization and no error?"); + // Multiple matches; we can't resolve to a single declaration. if (Matched) { - if (FoundResult) - *FoundResult = DeclAccessPair(); - if (Complain) { - Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous) - << OvlExpr->getName(); - NoteAllOverloadCandidates(OvlExpr); + Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous) + << ovl->getName(); + NoteAllOverloadCandidates(ovl); } return 0; - } + } - if ((Matched = Specialization) && FoundResult) - *FoundResult = I.getPair(); + Matched = Specialization; + if (FoundResult) *FoundResult = I.getPair(); } return Matched; } + + + +// Resolve and fix an overloaded expression that +// can be resolved because it identifies a single function +// template specialization +// Last three arguments should only be supplied if Complain = true +ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization( + Expr *SrcExpr, bool doFunctionPointerConverion, bool complain, + const SourceRange& OpRangeForComplaining, + QualType DestTypeForComplaining, + unsigned DiagIDForComplaining) { + assert(SrcExpr->getType() == Context.OverloadTy); + + OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr); + + DeclAccessPair found; + ExprResult SingleFunctionExpression; + if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( + ovl.Expression, /*complain*/ false, &found)) { + if (DiagnoseUseOfDecl(fn, SrcExpr->getSourceRange().getBegin())) + return ExprError(); + + // It is only correct to resolve to an instance method if we're + // resolving a form that's permitted to be a pointer to member. + // Otherwise we'll end up making a bound member expression, which + // is illegal in all the contexts we resolve like this. + if (!ovl.HasFormOfMemberPointer && + isa(fn) && + cast(fn)->isInstance()) { + if (complain) { + Diag(ovl.Expression->getExprLoc(), + diag::err_invalid_use_of_bound_member_func) + << ovl.Expression->getSourceRange(); + // TODO: I believe we only end up here if there's a mix of + // static and non-static candidates (otherwise the expression + // would have 'bound member' type, not 'overload' type). + // Ideally we would note which candidate was chosen and why + // the static candidates were rejected. + } + + return ExprError(); + } + + // Fix the expresion to refer to 'fn'. + SingleFunctionExpression = + Owned(FixOverloadedFunctionReference(SrcExpr, found, fn)); + + // If desired, do function-to-pointer decay. + if (doFunctionPointerConverion) + SingleFunctionExpression = + DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take()); + } + + if (!SingleFunctionExpression.isUsable()) { + if (complain) { + Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining) + << ovl.Expression->getName() + << DestTypeForComplaining + << OpRangeForComplaining + << ovl.Expression->getQualifierLoc().getSourceRange(); + NoteAllOverloadCandidates(SrcExpr); + } + return ExprError(); + } + + return SingleFunctionExpression; +} + /// \brief Add a single candidate to the overload set. static void AddOverloadedCallCandidate(Sema &S, DeclAccessPair FoundDecl, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading) { @@ -7559,7 +7751,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, // It would be nice to avoid this copy. TemplateArgumentListInfo TABuffer; - const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + TemplateArgumentListInfo *ExplicitTemplateArgs = 0; if (ULE->hasExplicitTemplateArgs()) { ULE->copyTemplateArgumentsInto(TABuffer); ExplicitTemplateArgs = &TABuffer; @@ -7576,7 +7768,8 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, Args, NumArgs, ExplicitTemplateArgs, CandidateSet, - PartialOverloading); + PartialOverloading, + ULE->isStdAssociatedNamespace()); } /// Attempts to recover from a call where no functions were found. @@ -7590,9 +7783,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, SourceLocation RParenLoc) { CXXScopeSpec SS; - if (ULE->getQualifier()) - SS.MakeTrivial(SemaRef.Context, - ULE->getQualifier(), ULE->getQualifierRange()); + SS.Adopt(ULE->getQualifierLoc()); TemplateArgumentListInfo TABuffer; const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; @@ -7657,7 +7848,9 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, // We don't perform ADL in C. assert(getLangOptions().CPlusPlus && "ADL enabled in C"); - } + } else + assert(!ULE->isStdAssociatedNamespace() && + "std is associated namespace but not doing ADL"); #endif OverloadCandidateSet CandidateSet(Fn->getExprLoc()); @@ -7704,8 +7897,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call) << Best->Function->isDeleted() << ULE->getName() - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Fn->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); } @@ -7749,8 +7941,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // TODO: provide better source location info. DeclarationNameInfo OpNameInfo(OpName, OpLoc); - if (Input->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Input); + if (Input->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Input); + if (Result.isInvalid()) + return ExprError(); + Input = Result.take(); + } Expr *Args[2] = { Input, 0 }; unsigned NumArgs = 1; @@ -7776,11 +7972,11 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, NamingClass, - 0, SourceRange(), OpNameInfo, + NestedNameSpecifierLoc(), OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, - &Args[0], NumArgs, + &Args[0], NumArgs, Context.DependentTy, VK_RValue, OpLoc)); @@ -7821,9 +8017,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl); - if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, - Best->FoundDecl, Method)) + ExprResult InputRes = + PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, + Best->FoundDecl, Method); + if (InputRes.isInvalid()) return ExprError(); + Input = InputRes.take(); } else { // Convert the arguments. ExprResult InputInit @@ -7845,11 +8044,13 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl); + if (FnExpr.isInvalid()) + return ExprError(); Args[0] = Input; CallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, + new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), Args, NumArgs, ResultTy, VK, OpLoc); if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, @@ -7861,39 +8062,40 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - if (PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing)) - return ExprError(); - - break; - } - } - - case OR_No_Viable_Function: - // No viable function; fall through to handling this as a - // built-in operator, which will produce an error message for us. + ExprResult InputRes = + PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (InputRes.isInvalid()) + return ExprError(); + Input = InputRes.take(); break; - - case OR_Ambiguous: - Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) - << UnaryOperator::getOpcodeStr(Opc) - << Input->getType() - << Input->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, - Args, NumArgs, - UnaryOperator::getOpcodeStr(Opc), OpLoc); - return ExprError(); - - case OR_Deleted: - Diag(OpLoc, diag::err_ovl_deleted_oper) - << Best->Function->isDeleted() - << UnaryOperator::getOpcodeStr(Opc) - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) - << Input->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); - return ExprError(); } + } + + case OR_No_Viable_Function: + // No viable function; fall through to handling this as a + // built-in operator, which will produce an error message for us. + break; + + case OR_Ambiguous: + Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) + << UnaryOperator::getOpcodeStr(Opc) + << Input->getType() + << Input->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + Args, NumArgs, + UnaryOperator::getOpcodeStr(Opc), OpLoc); + return ExprError(); + + case OR_Deleted: + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << UnaryOperator::getOpcodeStr(Opc) + << getDeletedOrUnavailableSuffix(Best->Function) + << Input->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + return ExprError(); + } // Either we found no viable overloaded operator or we matched a // built-in operator. In either case, fall through to trying to @@ -7956,8 +8158,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // TODO: provide better source location info in DNLoc component. DeclarationNameInfo OpNameInfo(OpName, OpLoc); UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, NamingClass, 0, SourceRange(), - OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), + = UnresolvedLookupExpr::Create(Context, NamingClass, + NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, 2, @@ -7967,8 +8170,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, } // Always do property rvalue conversions on the RHS. - if (Args[1]->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Args[1]); + if (Args[1]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Args[1]); + if (Result.isInvalid()) + return ExprError(); + Args[1] = Result.take(); + } // The LHS is more complicated. if (Args[0]->getObjectKind() == OK_ObjCProperty) { @@ -7996,7 +8203,10 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); } - ConvertPropertyForRValue(Args[0]); + ExprResult Result = ConvertPropertyForRValue(Args[0]); + if (Result.isInvalid()) + return ExprError(); + Args[0] = Result.take(); } // If this is the assignment operator, we only perform overload resolution @@ -8057,10 +8267,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Arg1.isInvalid()) return ExprError(); - if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, - Best->FoundDecl, Method)) + ExprResult Arg0 = + PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Best->FoundDecl, Method); + if (Arg0.isInvalid()) return ExprError(); - + Args[0] = Arg0.takeAs(); Args[1] = RHS = Arg1.takeAs(); } else { // Convert the arguments. @@ -8090,10 +8302,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc); + if (FnExpr.isInvalid()) + return ExprError(); CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, + new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), Args, 2, ResultTy, VK, OpLoc); if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, @@ -8105,12 +8319,19 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing) || - PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], AA_Passing)) + ExprResult ArgsRes0 = + PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (ArgsRes0.isInvalid()) return ExprError(); + Args[0] = ArgsRes0.take(); + ExprResult ArgsRes1 = + PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], AA_Passing); + if (ArgsRes1.isInvalid()) + return ExprError(); + Args[1] = ArgsRes1.take(); break; } } @@ -8158,8 +8379,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << BinaryOperator::getOpcodeStr(Opc) - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2); return ExprError(); @@ -8187,7 +8407,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, NamingClass, - 0, SourceRange(), OpNameInfo, + NestedNameSpecifierLoc(), OpNameInfo, /*ADL*/ true, /*Overloaded*/ false, UnresolvedSetIterator(), UnresolvedSetIterator()); @@ -8200,10 +8420,18 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, RLoc)); } - if (Args[0]->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Args[0]); - if (Args[1]->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Args[1]); + if (Args[0]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Args[0]); + if (Result.isInvalid()) + return ExprError(); + Args[0] = Result.take(); + } + if (Args[1]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Args[1]); + if (Result.isInvalid()) + return ExprError(); + Args[1] = Result.take(); + } // Build an empty overload set. OverloadCandidateSet CandidateSet(LLoc); @@ -8234,9 +8462,12 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Convert the arguments. CXXMethodDecl *Method = cast(FnDecl); - if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, - Best->FoundDecl, Method)) + ExprResult Arg0 = + PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Best->FoundDecl, Method); + if (Arg0.isInvalid()) return ExprError(); + Args[0] = Arg0.take(); // Convert the arguments. ExprResult InputInit @@ -8256,11 +8487,13 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc); + if (FnExpr.isInvalid()) + return ExprError(); CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Subscript, - FnExpr, Args, 2, + FnExpr.take(), Args, 2, ResultTy, VK, RLoc); if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall, @@ -8272,11 +8505,19 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing) || - PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], AA_Passing)) + ExprResult ArgsRes0 = + PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (ArgsRes0.isInvalid()) return ExprError(); + Args[0] = ArgsRes0.take(); + + ExprResult ArgsRes1 = + PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], AA_Passing); + if (ArgsRes1.isInvalid()) + return ExprError(); + Args[1] = ArgsRes1.take(); break; } @@ -8308,8 +8549,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, case OR_Deleted: Diag(LLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << "[]" - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, "[]", LLoc); @@ -8325,16 +8565,66 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, /// function (and includes the object parameter), Args/NumArgs are the /// arguments to the function call (not including the object /// parameter). The caller needs to validate that the member -/// expression refers to a member function or an overloaded member -/// function. +/// expression refers to a non-static member function or an overloaded +/// member function. ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc) { + assert(MemExprE->getType() == Context.BoundMemberTy || + MemExprE->getType() == Context.OverloadTy); + // Dig out the member expression. This holds both the object // argument and the member function we're referring to. Expr *NakedMemExpr = MemExprE->IgnoreParens(); + // Determine whether this is a call to a pointer-to-member function. + if (BinaryOperator *op = dyn_cast(NakedMemExpr)) { + assert(op->getType() == Context.BoundMemberTy); + assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI); + + QualType fnType = + op->getRHS()->getType()->castAs()->getPointeeType(); + + const FunctionProtoType *proto = fnType->castAs(); + QualType resultType = proto->getCallResultType(Context); + ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType()); + + // Check that the object type isn't more qualified than the + // member function we're calling. + Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals()); + + QualType objectType = op->getLHS()->getType(); + if (op->getOpcode() == BO_PtrMemI) + objectType = objectType->castAs()->getPointeeType(); + Qualifiers objectQuals = objectType.getQualifiers(); + + Qualifiers difference = objectQuals - funcQuals; + difference.removeObjCGCAttr(); + difference.removeAddressSpace(); + if (difference) { + std::string qualsString = difference.getAsString(); + Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals) + << fnType.getUnqualifiedType() + << qualsString + << (qualsString.find(' ') == std::string::npos ? 1 : 2); + } + + CXXMemberCallExpr *call + = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, + resultType, valueKind, RParenLoc); + + if (CheckCallReturnType(proto->getResultType(), + op->getRHS()->getSourceRange().getBegin(), + call, 0)) + return ExprError(); + + if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc)) + return ExprError(); + + return MaybeBindToTemporary(call); + } + MemberExpr *MemExpr; CXXMethodDecl *Method = 0; DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public); @@ -8427,8 +8717,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call) << Best->Function->isDeleted() << DeclName - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << MemExprE->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); // FIXME: Leaking incoming expressions! @@ -8464,12 +8753,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Convert the object argument (for a non-static member function call). // We only need to do this if there was actually an overload; otherwise // it was done at lookup. - Expr *ObjectArg = MemExpr->getBase(); - if (!Method->isStatic() && - PerformObjectArgumentInitialization(ObjectArg, Qualifier, - FoundDecl, Method)) - return ExprError(); - MemExpr->setBase(ObjectArg); + if (!Method->isStatic()) { + ExprResult ObjectArg = + PerformObjectArgumentInitialization(MemExpr->getBase(), Qualifier, + FoundDecl, Method); + if (ObjectArg.isInvalid()) + return ExprError(); + MemExpr->setBase(ObjectArg.take()); + } // Convert the rest of the arguments const FunctionProtoType *Proto = @@ -8489,15 +8780,19 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, /// overloaded function call operator (@c operator()) or performing a /// user-defined conversion on the object argument. ExprResult -Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, +Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc) { - if (Object->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Object); + ExprResult Object = Owned(Obj); + if (Object.get()->getObjectKind() == OK_ObjCProperty) { + Object = ConvertPropertyForRValue(Object.take()); + if (Object.isInvalid()) + return ExprError(); + } - assert(Object->getType()->isRecordType() && "Requires object type argument"); - const RecordType *Record = Object->getType()->getAs(); + assert(Object.get()->getType()->isRecordType() && "Requires object type argument"); + const RecordType *Record = Object.get()->getType()->getAs(); // C++ [over.call.object]p1: // If the primary-expression E in the function call syntax @@ -8509,9 +8804,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, OverloadCandidateSet CandidateSet(LParenLoc); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); - if (RequireCompleteType(LParenLoc, Object->getType(), + if (RequireCompleteType(LParenLoc, Object.get()->getType(), PDiag(diag::err_incomplete_object_call) - << Object->getSourceRange())) + << Object.get()->getSourceRange())) return true; LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName); @@ -8520,8 +8815,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) { - AddMethodCandidate(Oper.getPair(), Object->getType(), - Object->Classify(Context), Args, NumArgs, CandidateSet, + AddMethodCandidate(Oper.getPair(), Object.get()->getType(), + Object.get()->Classify(Context), Args, NumArgs, CandidateSet, /*SuppressUserConversions=*/ false); } @@ -8566,12 +8861,12 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, if (const FunctionProtoType *Proto = ConvType->getAs()) AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto, - Object, Args, NumArgs, CandidateSet); + Object.get(), Args, NumArgs, CandidateSet); } // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(*this, Object->getLocStart(), + switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(), Best)) { case OR_Success: // Overload resolution succeeded; we'll build the appropriate call @@ -8580,31 +8875,30 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, case OR_No_Viable_Function: if (CandidateSet.empty()) - Diag(Object->getSourceRange().getBegin(), diag::err_ovl_no_oper) - << Object->getType() << /*call*/ 1 - << Object->getSourceRange(); + Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_no_oper) + << Object.get()->getType() << /*call*/ 1 + << Object.get()->getSourceRange(); else - Diag(Object->getSourceRange().getBegin(), + Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_no_viable_object_call) - << Object->getType() << Object->getSourceRange(); + << Object.get()->getType() << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); break; case OR_Ambiguous: - Diag(Object->getSourceRange().getBegin(), + Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_ambiguous_object_call) - << Object->getType() << Object->getSourceRange(); + << Object.get()->getType() << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); break; case OR_Deleted: - Diag(Object->getSourceRange().getBegin(), + Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_deleted_object_call) << Best->Function->isDeleted() - << Object->getType() - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) - << Object->getSourceRange(); + << Object.get()->getType() + << getDeletedOrUnavailableSuffix(Best->Function) + << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); break; } @@ -8619,7 +8913,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, = cast( Best->Conversions[0].UserDefined.ConversionFunction); - CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl); + CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); // We selected one of the surrogate functions that converts the @@ -8628,7 +8922,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Create an implicit member expr to refer to the conversion operator. // and then call it. - ExprResult Call = BuildCXXMemberCallExpr(Object, Best->FoundDecl, Conv); + ExprResult Call = BuildCXXMemberCallExpr(Object.get(), Best->FoundDecl, Conv); if (Call.isInvalid()) return ExprError(); @@ -8637,7 +8931,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, } MarkDeclarationReferenced(LParenLoc, Best->Function); - CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl); + CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); // We found an overloaded operator(). Build a CXXOperatorCallExpr @@ -8660,11 +8954,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, } else { MethodArgs = new Expr*[NumArgs + 1]; } - MethodArgs[0] = Object; + MethodArgs[0] = Object.get(); for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) MethodArgs[ArgIdx + 1] = Args[ArgIdx]; - Expr *NewFn = CreateFunctionRefExpr(*this, Method); + ExprResult NewFn = CreateFunctionRefExpr(*this, Method); + if (NewFn.isInvalid()) + return true; // Once we've built TheCall, all of the expressions are properly // owned. @@ -8673,7 +8969,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, ResultTy = ResultTy.getNonLValueExprType(Context); CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn, + new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(), MethodArgs, NumArgs + 1, ResultTy, VK, RParenLoc); delete [] MethodArgs; @@ -8692,10 +8988,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, bool IsError = false; // Initialize the implicit object parameter. - IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0, - Best->FoundDecl, Method); - TheCall->setArg(0, Object); - + ExprResult ObjRes = + PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/0, + Best->FoundDecl, Method); + if (ObjRes.isInvalid()) + IsError = true; + else + Object = move(ObjRes); + TheCall->setArg(0, Object.take()); // Check the argument types. for (unsigned i = 0; i != NumArgsToCheck; i++) { @@ -8731,9 +9031,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, if (Proto->isVariadic()) { // Promote the arguments (C99 6.5.2.2p7). for (unsigned i = NumArgsInProto; i != NumArgs; i++) { - Expr *Arg = Args[i]; - IsError |= DefaultVariadicArgumentPromotion(Arg, VariadicMethod, 0); - TheCall->setArg(i + 1, Arg); + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + IsError |= Arg.isInvalid(); + TheCall->setArg(i + 1, Arg.take()); } } @@ -8753,8 +9053,12 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { assert(Base->getType()->isRecordType() && "left-hand side must have class type"); - if (Base->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Base); + if (Base->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Base); + if (Result.isInvalid()) + return ExprError(); + Base = Result.take(); + } SourceLocation Loc = Base->getExprLoc(); @@ -8811,8 +9115,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << "->" - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Base->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1); return ExprError(); @@ -8824,24 +9127,30 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { // Convert the object parameter. CXXMethodDecl *Method = cast(Best->Function); - if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, - Best->FoundDecl, Method)) + ExprResult BaseResult = + PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, + Best->FoundDecl, Method); + if (BaseResult.isInvalid()) return ExprError(); + Base = BaseResult.take(); // Build the operator call. - Expr *FnExpr = CreateFunctionRefExpr(*this, Method); + ExprResult FnExpr = CreateFunctionRefExpr(*this, Method); + if (FnExpr.isInvalid()) + return ExprError(); QualType ResultTy = Method->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultTy); ResultTy = ResultTy.getNonLValueExprType(Context); CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, + new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(), &Base, 1, ResultTy, VK, OpLoc); if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, Method)) return ExprError(); - return Owned(TheCall); + + return MaybeBindToTemporary(TheCall); } /// FixOverloadedFunctionReference - E is an expression that refers to @@ -8930,12 +9239,12 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, } return DeclRefExpr::Create(Context, - ULE->getQualifier(), - ULE->getQualifierRange(), + ULE->getQualifierLoc(), Fn, ULE->getNameLoc(), Fn->getType(), VK_LValue, + Found.getDecl(), TemplateArgs); } @@ -8954,17 +9263,17 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (MemExpr->isImplicitAccess()) { if (cast(Fn)->isStatic()) { return DeclRefExpr::Create(Context, - MemExpr->getQualifier(), - MemExpr->getQualifierRange(), + MemExpr->getQualifierLoc(), Fn, MemExpr->getMemberLoc(), Fn->getType(), VK_LValue, + Found.getDecl(), TemplateArgs); } else { SourceLocation Loc = MemExpr->getMemberLoc(); if (MemExpr->getQualifier()) - Loc = MemExpr->getQualifierRange().getBegin(); + Loc = MemExpr->getQualifierLoc().getBeginLoc(); Base = new (Context) CXXThisExpr(Loc, MemExpr->getBaseType(), /*isImplicit=*/true); @@ -8972,18 +9281,24 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, } else Base = MemExpr->getBase(); + ExprValueKind valueKind; + QualType type; + if (cast(Fn)->isStatic()) { + valueKind = VK_LValue; + type = Fn->getType(); + } else { + valueKind = VK_RValue; + type = Context.BoundMemberTy; + } + return MemberExpr::Create(Context, Base, MemExpr->isArrow(), - MemExpr->getQualifier(), - MemExpr->getQualifierRange(), + MemExpr->getQualifierLoc(), Fn, Found, MemExpr->getMemberNameInfo(), TemplateArgs, - Fn->getType(), - cast(Fn)->isStatic() - ? VK_LValue : VK_RValue, - OK_Ordinary); + type, valueKind, OK_Ordinary); } llvm_unreachable("Invalid reference to overloaded function"); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 89957e60deca..65cea7a69d61 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -45,8 +46,9 @@ StmtResult Sema::ActOnExprStmt(FullExprArg expr) { } -StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, bool LeadingEmptyMacro) { - return Owned(new (Context) NullStmt(SemiLoc, LeadingEmptyMacro)); +StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, + SourceLocation LeadingEmptyMacroLoc) { + return Owned(new (Context) NullStmt(SemiLoc, LeadingEmptyMacroLoc)); } StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc, @@ -76,12 +78,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (!E) return; - if (E->isBoundMemberFunction(Context)) { - Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << E->getSourceRange(); - return; - } - SourceLocation Loc; SourceRange R1, R2; if (!E->isUnusedResultAWarning(Loc, R1, R2, Context)) @@ -245,11 +241,10 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, } // Otherwise, things are good. Fill in the declaration and return it. - TheDecl->setLocation(IdentLoc); - LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); TheDecl->setStmt(LS); - TheDecl->setLocation(IdentLoc); + if (!TheDecl->isGnuLocal()) + TheDecl->setLocation(IdentLoc); return Owned(LS); } @@ -470,7 +465,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, GetTypeBeforeIntegralPromotion(CondExpr); // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. - UsualUnaryConversions(CondExpr); + ExprResult CondResult = UsualUnaryConversions(CondExpr); + if (CondResult.isInvalid()) + return StmtError(); + CondExpr = CondResult.take(); QualType CondType = CondExpr->getType(); SS->setCond(CondExpr); @@ -556,7 +554,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If the LHS is not the same type as the condition, insert an implicit // cast. - ImpCastExprToType(Lo, CondType, CK_IntegralCast); + Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take(); CS->setLHS(Lo); // If this is a case range, remember it in CaseRanges, otherwise CaseVals. @@ -635,7 +633,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If the LHS is not the same type as the condition, insert an implicit // cast. - ImpCastExprToType(Hi, CondType, CK_IntegralCast); + Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take(); CR->setRHS(Hi); // If the low value is bigger than the high value, the case is empty. @@ -869,11 +867,13 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, Expr *Cond, SourceLocation CondRParen) { assert(Cond && "ActOnDoStmt(): missing expression"); - if (CheckBooleanCondition(Cond, DoLoc)) + ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc); + if (CondResult.isInvalid() || CondResult.isInvalid()) return StmtError(); + Cond = CondResult.take(); CheckImplicitConversions(Cond, DoLoc); - ExprResult CondResult = MaybeCreateExprWithCleanups(Cond); + CondResult = MaybeCreateExprWithCleanups(Cond); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); @@ -974,7 +974,10 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, << FirstType << First->getSourceRange(); } if (Second && !Second->isTypeDependent()) { - DefaultFunctionArrayLvalueConversion(Second); + ExprResult Result = DefaultFunctionArrayLvalueConversion(Second); + if (Result.isInvalid()) + return StmtError(); + Second = Result.take(); QualType SecondType = Second->getType(); if (!SecondType->isObjCObjectPointerType()) Diag(ForLoc, diag::err_collection_expr_type) @@ -992,7 +995,8 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, Selector CSelector = Context.Selectors.getSelector(3, &KeyIdents[0]); if (ObjCInterfaceDecl *IDecl = OPT->getInterfaceDecl()) { if (!IDecl->isForwardDecl() && - !IDecl->lookupInstanceMethod(CSelector)) { + !IDecl->lookupInstanceMethod(CSelector) && + !LookupMethodInQualifiedType(CSelector, OPT, true)) { // Must further look into private implementation methods. if (!LookupPrivateInstanceMethod(CSelector, IDecl)) Diag(ForLoc, diag::warn_collection_expr_type) @@ -1005,6 +1009,389 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, ForLoc, RParenLoc)); } +namespace { + +enum BeginEndFunction { + BEF_begin, + BEF_end +}; + +/// Build a variable declaration for a for-range statement. +static VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, + QualType Type, const char *Name) { + DeclContext *DC = SemaRef.CurContext; + IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); + TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); + VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, + TInfo, SC_Auto, SC_None); + Decl->setImplicit(); + return Decl; +} + +/// Finish building a variable declaration for a for-range statement. +/// \return true if an error occurs. +static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, + SourceLocation Loc, int diag) { + // Deduce the type for the iterator variable now rather than leaving it to + // AddInitializerToDecl, so we can produce a more suitable diagnostic. + TypeSourceInfo *InitTSI = 0; + if (Init->getType()->isVoidType() || + !SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI)) + SemaRef.Diag(Loc, diag) << Init->getType(); + if (!InitTSI) { + Decl->setInvalidDecl(); + return true; + } + Decl->setTypeSourceInfo(InitTSI); + Decl->setType(InitTSI->getType()); + + SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false, + /*TypeMayContainAuto=*/false); + SemaRef.FinalizeDeclaration(Decl); + SemaRef.CurContext->addHiddenDecl(Decl); + return false; +} + +/// Produce a note indicating which begin/end function was implicitly called +/// by a C++0x for-range statement. This is often not obvious from the code, +/// nor from the diagnostics produced when analysing the implicit expressions +/// required in a for-range statement. +void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, + BeginEndFunction BEF) { + CallExpr *CE = dyn_cast(E); + if (!CE) + return; + FunctionDecl *D = dyn_cast(CE->getCalleeDecl()); + if (!D) + return; + SourceLocation Loc = D->getLocation(); + + std::string Description; + bool IsTemplate = false; + if (FunctionTemplateDecl *FunTmpl = D->getPrimaryTemplate()) { + Description = SemaRef.getTemplateArgumentBindingsText( + FunTmpl->getTemplateParameters(), *D->getTemplateSpecializationArgs()); + IsTemplate = true; + } + + SemaRef.Diag(Loc, diag::note_for_range_begin_end) + << BEF << IsTemplate << Description << E->getType(); +} + +/// Build a call to 'begin' or 'end' for a C++0x for-range statement. If the +/// given LookupResult is non-empty, it is assumed to describe a member which +/// will be invoked. Otherwise, the function will be found via argument +/// dependent lookup. +static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, + SourceLocation Loc, + VarDecl *Decl, + BeginEndFunction BEF, + const DeclarationNameInfo &NameInfo, + LookupResult &MemberLookup, + Expr *Range) { + ExprResult CallExpr; + if (!MemberLookup.empty()) { + ExprResult MemberRef = + SemaRef.BuildMemberReferenceExpr(Range, Range->getType(), Loc, + /*IsPtr=*/false, CXXScopeSpec(), + /*Qualifier=*/0, MemberLookup, + /*TemplateArgs=*/0); + if (MemberRef.isInvalid()) + return ExprError(); + CallExpr = SemaRef.ActOnCallExpr(S, MemberRef.get(), Loc, MultiExprArg(), + Loc, 0); + if (CallExpr.isInvalid()) + return ExprError(); + } else { + UnresolvedSet<0> FoundNames; + // C++0x [stmt.ranged]p1: For the purposes of this name lookup, namespace + // std is an associated namespace. + UnresolvedLookupExpr *Fn = + UnresolvedLookupExpr::Create(SemaRef.Context, /*NamingClass=*/0, + NestedNameSpecifierLoc(), NameInfo, + /*NeedsADL=*/true, /*Overloaded=*/false, + FoundNames.begin(), FoundNames.end(), + /*LookInStdNamespace=*/true); + CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc, + 0); + if (CallExpr.isInvalid()) { + SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type) + << Range->getType(); + return ExprError(); + } + } + if (FinishForRangeVarDecl(SemaRef, Decl, CallExpr.get(), Loc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(SemaRef, CallExpr.get(), BEF); + return ExprError(); + } + return CallExpr; +} + +} + +/// ActOnCXXForRangeStmt - Check and build a C++0x for-range statement. +/// +/// C++0x [stmt.ranged]: +/// A range-based for statement is equivalent to +/// +/// { +/// auto && __range = range-init; +/// for ( auto __begin = begin-expr, +/// __end = end-expr; +/// __begin != __end; +/// ++__begin ) { +/// for-range-declaration = *__begin; +/// statement +/// } +/// } +/// +/// The body of the loop is not available yet, since it cannot be analysed until +/// we have determined the type of the for-range-declaration. +StmtResult +Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, SourceLocation LParenLoc, + Stmt *First, SourceLocation ColonLoc, Expr *Range, + SourceLocation RParenLoc) { + if (!First || !Range) + return StmtError(); + + DeclStmt *DS = dyn_cast(First); + assert(DS && "first part of for range not a decl stmt"); + + if (!DS->isSingleDecl()) { + Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range); + return StmtError(); + } + if (DS->getSingleDecl()->isInvalidDecl()) + return StmtError(); + + if (DiagnoseUnexpandedParameterPack(Range, UPPC_Expression)) + return StmtError(); + + // Build auto && __range = range-init + SourceLocation RangeLoc = Range->getLocStart(); + VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc, + Context.getAutoRRefDeductType(), + "__range"); + if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc, + diag::err_for_range_deduction_failure)) + return StmtError(); + + // Claim the type doesn't contain auto: we've already done the checking. + DeclGroupPtrTy RangeGroup = + BuildDeclaratorGroup((Decl**)&RangeVar, 1, /*TypeMayContainAuto=*/false); + StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc); + if (RangeDecl.isInvalid()) + return StmtError(); + + return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(), + /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS, + RParenLoc); +} + +/// BuildCXXForRangeStmt - Build or instantiate a C++0x for-range statement. +StmtResult +Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, + Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond, + Expr *Inc, Stmt *LoopVarDecl, + SourceLocation RParenLoc) { + Scope *S = getCurScope(); + + DeclStmt *RangeDS = cast(RangeDecl); + VarDecl *RangeVar = cast(RangeDS->getSingleDecl()); + QualType RangeVarType = RangeVar->getType(); + + DeclStmt *LoopVarDS = cast(LoopVarDecl); + VarDecl *LoopVar = cast(LoopVarDS->getSingleDecl()); + + StmtResult BeginEndDecl = BeginEnd; + ExprResult NotEqExpr = Cond, IncrExpr = Inc; + + if (!BeginEndDecl.get() && !RangeVarType->isDependentType()) { + SourceLocation RangeLoc = RangeVar->getLocation(); + + ExprResult RangeRef = BuildDeclRefExpr(RangeVar, + RangeVarType.getNonReferenceType(), + VK_LValue, ColonLoc); + if (RangeRef.isInvalid()) + return StmtError(); + + QualType AutoType = Context.getAutoDeductType(); + Expr *Range = RangeVar->getInit(); + if (!Range) + return StmtError(); + QualType RangeType = Range->getType(); + + if (RequireCompleteType(RangeLoc, RangeType, + PDiag(diag::err_for_range_incomplete_type))) + return StmtError(); + + // Build auto __begin = begin-expr, __end = end-expr. + VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, + "__begin"); + VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, + "__end"); + + // Build begin-expr and end-expr and attach to __begin and __end variables. + ExprResult BeginExpr, EndExpr; + if (const ArrayType *UnqAT = RangeType->getAsArrayTypeUnsafe()) { + // - if _RangeT is an array type, begin-expr and end-expr are __range and + // __range + __bound, respectively, where __bound is the array bound. If + // _RangeT is an array of unknown size or an array of incomplete type, + // the program is ill-formed; + + // begin-expr is __range. + BeginExpr = RangeRef; + if (FinishForRangeVarDecl(*this, BeginVar, RangeRef.get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return StmtError(); + } + + // Find the array bound. + ExprResult BoundExpr; + if (const ConstantArrayType *CAT = dyn_cast(UnqAT)) + BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(), + Context.IntTy, RangeLoc)); + else if (const VariableArrayType *VAT = + dyn_cast(UnqAT)) + BoundExpr = VAT->getSizeExpr(); + else { + // Can't be a DependentSizedArrayType or an IncompleteArrayType since + // UnqAT is not incomplete and Range is not type-dependent. + assert(0 && "Unexpected array type in for-range"); + return StmtError(); + } + + // end-expr is __range + __bound. + EndExpr = ActOnBinOp(S, ColonLoc, tok::plus, RangeRef.get(), + BoundExpr.get()); + if (EndExpr.isInvalid()) + return StmtError(); + if (FinishForRangeVarDecl(*this, EndVar, EndExpr.get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + return StmtError(); + } + } else { + DeclarationNameInfo BeginNameInfo(&PP.getIdentifierTable().get("begin"), + ColonLoc); + DeclarationNameInfo EndNameInfo(&PP.getIdentifierTable().get("end"), + ColonLoc); + + LookupResult BeginMemberLookup(*this, BeginNameInfo, LookupMemberName); + LookupResult EndMemberLookup(*this, EndNameInfo, LookupMemberName); + + if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) { + // - if _RangeT is a class type, the unqualified-ids begin and end are + // looked up in the scope of class _RangeT as if by class member access + // lookup (3.4.5), and if either (or both) finds at least one + // declaration, begin-expr and end-expr are __range.begin() and + // __range.end(), respectively; + LookupQualifiedName(BeginMemberLookup, D); + LookupQualifiedName(EndMemberLookup, D); + + if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { + Diag(ColonLoc, diag::err_for_range_member_begin_end_mismatch) + << RangeType << BeginMemberLookup.empty(); + return StmtError(); + } + } else { + // - otherwise, begin-expr and end-expr are begin(__range) and + // end(__range), respectively, where begin and end are looked up with + // argument-dependent lookup (3.4.2). For the purposes of this name + // lookup, namespace std is an associated namespace. + } + + BeginExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, BeginVar, + BEF_begin, BeginNameInfo, + BeginMemberLookup, RangeRef.get()); + if (BeginExpr.isInvalid()) + return StmtError(); + + EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, EndVar, + BEF_end, EndNameInfo, + EndMemberLookup, RangeRef.get()); + if (EndExpr.isInvalid()) + return StmtError(); + } + + // C++0x [decl.spec.auto]p6: BeginType and EndType must be the same. + QualType BeginType = BeginVar->getType(), EndType = EndVar->getType(); + if (!Context.hasSameType(BeginType, EndType)) { + Diag(RangeLoc, diag::err_for_range_begin_end_types_differ) + << BeginType << EndType; + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + } + + Decl *BeginEndDecls[] = { BeginVar, EndVar }; + // Claim the type doesn't contain auto: we've already done the checking. + DeclGroupPtrTy BeginEndGroup = + BuildDeclaratorGroup(BeginEndDecls, 2, /*TypeMayContainAuto=*/false); + BeginEndDecl = ActOnDeclStmt(BeginEndGroup, ColonLoc, ColonLoc); + + ExprResult BeginRef = BuildDeclRefExpr(BeginVar, + BeginType.getNonReferenceType(), + VK_LValue, ColonLoc); + ExprResult EndRef = BuildDeclRefExpr(EndVar, EndType.getNonReferenceType(), + VK_LValue, ColonLoc); + + // Build and check __begin != __end expression. + NotEqExpr = ActOnBinOp(S, ColonLoc, tok::exclaimequal, + BeginRef.get(), EndRef.get()); + NotEqExpr = ActOnBooleanCondition(S, ColonLoc, NotEqExpr.get()); + NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); + if (NotEqExpr.isInvalid()) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + if (!Context.hasSameType(BeginType, EndType)) + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + return StmtError(); + } + + // Build and check ++__begin expression. + IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get()); + IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); + if (IncrExpr.isInvalid()) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return StmtError(); + } + + // Build and check *__begin expression. + ExprResult DerefExpr = ActOnUnaryOp(S, ColonLoc, tok::star, BeginRef.get()); + if (DerefExpr.isInvalid()) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return StmtError(); + } + + // Attach *__begin as initializer for VD. + if (!LoopVar->isInvalidDecl()) { + AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false, + /*TypeMayContainAuto=*/true); + if (LoopVar->isInvalidDecl()) + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + } + } + + return Owned(new (Context) CXXForRangeStmt(RangeDS, + cast_or_null(BeginEndDecl.get()), + NotEqExpr.take(), IncrExpr.take(), + LoopVarDS, /*Body=*/0, ForLoc, + ColonLoc, RParenLoc)); +} + +/// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement. +/// This is a separate step from ActOnCXXForRangeStmt because analysis of the +/// body cannot be performed until after the type of the range variable is +/// determined. +StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { + if (!S || !B) + return StmtError(); + + cast(S)->setBody(B); + return S; +} + StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *TheDecl) { @@ -1020,8 +1407,12 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, if (!E->isTypeDependent()) { QualType ETy = E->getType(); QualType DestTy = Context.getPointerType(Context.VoidTy.withConst()); + ExprResult ExprRes = Owned(E); AssignConvertType ConvTy = - CheckSingleAssignmentConstraints(DestTy, E); + CheckSingleAssignmentConstraints(DestTy, ExprRes); + if (ExprRes.isInvalid()) + return StmtError(); + E = ExprRes.take(); if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) return StmtError(); } @@ -1188,7 +1579,10 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (RetValExp) { // Don't call UsualUnaryConversions(), since we don't want to do // integer promotions here. - DefaultFunctionArrayLvalueConversion(RetValExp); + ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp); + if (Result.isInvalid()) + return StmtError(); + RetValExp = Result.take(); CurBlock->ReturnType = RetValExp->getType(); if (BlockDeclRefExpr *CDRE = dyn_cast(RetValExp)) { // We have to remove a 'const' added to copied-in variable which was @@ -1290,8 +1684,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (RetValExp->getType()->isVoidType()) D = diag::ext_return_has_void_expr; else { - IgnoredValueConversions(RetValExp); - ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid); + ExprResult Result = Owned(RetValExp); + Result = IgnoredValueConversions(Result.take()); + if (Result.isInvalid()) + return StmtError(); + RetValExp = Result.take(); + RetValExp = ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid).take(); } // return (some void expression); is legal in C++. @@ -1498,8 +1896,11 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, } } - DefaultFunctionArrayLvalueConversion(Exprs[i]); + ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); + if (Result.isInvalid()) + return StmtError(); + Exprs[i] = Result.take(); InputConstraintInfos.push_back(Info); } @@ -1614,7 +2015,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (InputDomain == AD_Int && OutputDomain == AD_Int && !isOperandMentioned(InputOpNo, Pieces) && InputExpr->isEvaluatable(Context)) { - ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast); + InputExpr = ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast).take(); Exprs[InputOpNo] = InputExpr; NS->setInputExpr(i, InputExpr); continue; @@ -1663,8 +2064,11 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { if (Throw) { - DefaultLvalueConversion(Throw); + ExprResult Result = DefaultLvalueConversion(Throw); + if (Result.isInvalid()) + return StmtError(); + Throw = Result.take(); QualType ThrowType = Throw->getType(); // Make sure the expression type is an ObjC pointer or "void *". if (!ThrowType->isDependentType() && @@ -1703,8 +2107,11 @@ Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr, Stmt *SyncBody) { getCurFunction()->setHasBranchProtectedScope(); - DefaultLvalueConversion(SyncExpr); + ExprResult Result = DefaultLvalueConversion(SyncExpr); + if (Result.isInvalid()) + return StmtError(); + SyncExpr = Result.take(); // Make sure the expression type is an ObjC pointer or "void *". if (!SyncExpr->getType()->isDependentType() && !SyncExpr->getType()->isObjCObjectPointerType()) { @@ -1766,7 +2173,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg RawHandlers) { // Don't report an error if 'try' is used in system headers. - if (!getLangOptions().Exceptions && + if (!getLangOptions().CXXExceptions && !getSourceManager().isInSystemHeader(TryLoc)) Diag(TryLoc, diag::err_exceptions_disabled) << "try"; @@ -1824,3 +2231,36 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers, NumHandlers)); } + +StmtResult +Sema::ActOnSEHTryBlock(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + assert(TryBlock && Handler); + + getCurFunction()->setHasBranchProtectedScope(); + + return Owned(SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler)); +} + +StmtResult +Sema::ActOnSEHExceptBlock(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + assert(FilterExpr && Block); + + if(!FilterExpr->getType()->isIntegerType()) { + return StmtError(Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral) << FilterExpr->getType()); + } + + return Owned(SEHExceptStmt::Create(Context,Loc,FilterExpr,Block)); +} + +StmtResult +Sema::ActOnSEHFinallyBlock(SourceLocation Loc, + Stmt *Block) { + assert(Block); + return Owned(SEHFinallyStmt::Create(Context,Loc,Block)); +} + diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index f02dd2582402..ef0912485b66 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -76,13 +76,13 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, return 0; } -static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { +void Sema::FilterAcceptableTemplateNames(LookupResult &R) { // The set of class templates we've already seen. llvm::SmallPtrSet ClassTemplates; LookupResult::Filter filter = R.makeFilter(); while (filter.hasNext()) { NamedDecl *Orig = filter.next(); - NamedDecl *Repl = isAcceptableTemplateName(C, Orig); + NamedDecl *Repl = isAcceptableTemplateName(Context, Orig); if (!Repl) filter.erase(); else if (Repl != Orig) { @@ -114,6 +114,14 @@ static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { filter.done(); } +bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R) { + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) + if (isAcceptableTemplateName(Context, *I)) + return true; + + return false; +} + TemplateNameKind Sema::isTemplateName(Scope *S, CXXScopeSpec &SS, bool hasTemplateKeyword, @@ -289,7 +297,7 @@ void Sema::LookupTemplateName(LookupResult &Found, DeclarationName Name = Found.getLookupName(); if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx, false, CTC_CXXCasts)) { - FilterAcceptableTemplateNames(Context, Found); + FilterAcceptableTemplateNames(Found); if (!Found.empty()) { if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) @@ -311,7 +319,7 @@ void Sema::LookupTemplateName(LookupResult &Found, } } - FilterAcceptableTemplateNames(Context, Found); + FilterAcceptableTemplateNames(Found); if (Found.empty()) { if (isDependent) MemberOfUnknownSpecialization = true; @@ -327,7 +335,7 @@ void Sema::LookupTemplateName(LookupResult &Found, LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(), LookupOrdinaryName); LookupName(FoundOuter, S); - FilterAcceptableTemplateNames(Context, FoundOuter); + FilterAcceptableTemplateNames(FoundOuter); if (FoundOuter.empty()) { // - if the name is not found, the name found in the class of the @@ -368,9 +376,6 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { - NestedNameSpecifier *Qualifier - = static_cast(SS.getScopeRep()); - DeclContext *DC = getFunctionLevelDeclContext(); if (!isAddressOfOperand && @@ -386,7 +391,7 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, /*This*/ 0, ThisType, /*IsArrow*/ true, /*Op*/ SourceLocation(), - Qualifier, SS.getRange(), + SS.getWithLocInContext(Context), FirstQualifierInScope, NameInfo, TemplateArgs)); @@ -472,7 +477,8 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, else TArg = Template; return TemplateArgumentLoc(TArg, - Arg.getScopeSpec().getRange(), + Arg.getScopeSpec().getWithLocInContext( + SemaRef.Context), Arg.getLocation(), Arg.getEllipsisLoc()); } @@ -497,7 +503,7 @@ void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, /// (otherwise, "class" was used), and KeyLoc is the location of the /// "class" or "typename" keyword. ParamName is the name of the /// parameter (NULL indicates an unnamed template parameter) and -/// ParamName is the location of the parameter name (if any). +/// ParamNameLoc is the location of the parameter name (if any). /// If the type parameter has a default argument, it will be added /// later via ActOnTypeParameterDefault. Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, @@ -527,8 +533,9 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, TemplateTypeParmDecl *Param = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(), - Loc, Depth, Position, ParamName, Typename, - Ellipsis); + KeyLoc, Loc, Depth, Position, ParamName, + Typename, Ellipsis); + Param->setAccess(AS_public); if (Invalid) Param->setInvalidDecl(); @@ -651,9 +658,12 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, bool IsParameterPack = D.hasEllipsis(); NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), + D.getSourceRange().getBegin(), D.getIdentifierLoc(), Depth, Position, ParamName, T, IsParameterPack, TInfo); + Param->setAccess(AS_public); + if (Invalid) Param->setInvalidDecl(); @@ -678,10 +688,12 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, return Param; TemplateArgument Converted; - if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) { + ExprResult DefaultRes = CheckTemplateArgument(Param, Param->getType(), Default, Converted); + if (DefaultRes.isInvalid()) { Param->setInvalidDecl(); return Param; } + Default = DefaultRes.take(); Param->setDefaultArgument(Default, false); } @@ -707,13 +719,13 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S, // Construct the parameter object. bool IsParameterPack = EllipsisLoc.isValid(); - // FIXME: Pack-ness is dropped TemplateTemplateParmDecl *Param = TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), NameLoc.isInvalid()? TmpLoc : NameLoc, Depth, Position, IsParameterPack, Name, Params); - + Param->setAccess(AS_public); + // If the template template parameter has a name, then link the identifier // into the scope and lookup mechanisms. if (Name) { @@ -791,7 +803,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, TemplateParameterList *TemplateParams, - AccessSpecifier AS) { + AccessSpecifier AS, + unsigned NumOuterTemplateParamLists, + TemplateParameterList** OuterTemplateParamLists) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); assert(TUK != TUK_Reference && "Can only declare or define class templates"); @@ -961,11 +975,15 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, } CXXRecordDecl *NewClass = - CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, KWLoc, + CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name, PrevClassTemplate? PrevClassTemplate->getTemplatedDecl() : 0, /*DelayTypeCreation=*/true); SetNestedNameSpecifier(NewClass, SS); + if (NumOuterTemplateParamLists > 0) + NewClass->setTemplateParameterListsInfo(Context, + NumOuterTemplateParamLists, + OuterTemplateParamLists); ClassTemplateDecl *NewTemplate = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, @@ -1089,7 +1107,8 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, /// \brief Check for unexpanded parameter packs within the template parameters /// of a template template parameter, recursively. -bool DiagnoseUnexpandedParameterPacks(Sema &S, TemplateTemplateParmDecl *TTP){ +static bool DiagnoseUnexpandedParameterPacks(Sema &S, + TemplateTemplateParmDecl *TTP) { TemplateParameterList *Params = TTP->getTemplateParameters(); for (unsigned I = 0, N = Params->size(); I != N; ++I) { NamedDecl *P = Params->getParam(I); @@ -1448,9 +1467,9 @@ DependsOnTemplateParameters(const TemplateSpecializationType *TemplateId, /// /// \returns the template parameter list, if any, that corresponds to the /// name that is preceded by the scope specifier @p SS. This template -/// parameter list may be have template parameters (if we're declaring a +/// parameter list may have template parameters (if we're declaring a /// template) or may have no template parameters (if we're declaring a -/// template specialization), or may be NULL (if we were's declaring isn't +/// template specialization), or may be NULL (if what we're declaring isn't /// itself a template). TemplateParameterList * Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, @@ -1631,14 +1650,42 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, return ParamLists[NumParamLists - 1]; } +void Sema::NoteAllFoundTemplates(TemplateName Name) { + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { + Diag(Template->getLocation(), diag::note_template_declared_here) + << (isa(Template)? 0 + : isa(Template)? 1 + : 2) + << Template->getDeclName(); + return; + } + + if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) { + for (OverloadedTemplateStorage::iterator I = OST->begin(), + IEnd = OST->end(); + I != IEnd; ++I) + Diag((*I)->getLocation(), diag::note_template_declared_here) + << 0 << (*I)->getDeclName(); + + return; + } +} + + QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &TemplateArgs) { + TemplateArgumentListInfo &TemplateArgs) { TemplateDecl *Template = Name.getAsTemplateDecl(); - if (!Template) { - // The template name does not resolve to a template, so we just - // build a dependent template-id type. - return Context.getTemplateSpecializationType(Name, TemplateArgs); + if (!Template || isa(Template)) { + // We might have a substituted template template parameter pack. If so, + // build a template specialization type for it. + if (Name.getAsSubstTemplateTemplateParmPack()) + return Context.getTemplateSpecializationType(Name, TemplateArgs); + + Diag(TemplateLoc, diag::err_template_id_not_a_type) + << Name; + NoteAllFoundTemplates(Name); + return QualType(); } // Check that the template argument list is well-formed for this @@ -1726,6 +1773,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Decl = ClassTemplateSpecializationDecl::Create(Context, ClassTemplate->getTemplatedDecl()->getTagKind(), ClassTemplate->getDeclContext(), + ClassTemplate->getLocation(), ClassTemplate->getLocation(), ClassTemplate, Converted.data(), @@ -1746,77 +1794,148 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, } TypeResult -Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, +Sema::ActOnTemplateIdType(CXXScopeSpec &SS, + TemplateTy TemplateD, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc) { + if (SS.isInvalid()) + return true; + TemplateName Template = TemplateD.getAsVal(); // Translate the parser's template argument list in our AST format. TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); translateTemplateArguments(TemplateArgsIn, TemplateArgs); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + QualType T = Context.getDependentTemplateSpecializationType(ETK_None, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Build type-source information. + TypeLocBuilder TLB; + DependentTemplateSpecializationTypeLoc SpecTL + = TLB.push(T); + SpecTL.setKeywordLoc(SourceLocation()); + SpecTL.setNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); + } + QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); TemplateArgsIn.release(); if (Result.isNull()) return true; - TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Result); - TemplateSpecializationTypeLoc TL - = cast(DI->getTypeLoc()); - TL.setTemplateNameLoc(TemplateLoc); - TL.setLAngleLoc(LAngleLoc); - TL.setRAngleLoc(RAngleLoc); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); + // Build type-source information. + TypeLocBuilder TLB; + TemplateSpecializationTypeLoc SpecTL + = TLB.push(Result); + SpecTL.setTemplateNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) + SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); - return CreateParsedType(Result, DI); + if (SS.isNotEmpty()) { + // Create an elaborated-type-specifier containing the nested-name-specifier. + Result = Context.getElaboratedType(ETK_None, SS.getScopeRep(), Result); + ElaboratedTypeLoc ElabTL = TLB.push(Result); + ElabTL.setKeywordLoc(SourceLocation()); + ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + } + + return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } -TypeResult Sema::ActOnTagTemplateIdType(CXXScopeSpec &SS, - TypeResult TypeResult, - TagUseKind TUK, +TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, TypeSpecifierType TagSpec, - SourceLocation TagLoc) { - if (TypeResult.isInvalid()) - return ::TypeResult(); - - TypeSourceInfo *DI; - QualType Type = GetTypeFromParser(TypeResult.get(), &DI); - - // Verify the tag specifier. + SourceLocation TagLoc, + CXXScopeSpec &SS, + TemplateTy TemplateD, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc) { + TemplateName Template = TemplateD.getAsVal(); + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + // Determine the tag kind TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTagTypeKind(TagKind); - if (const RecordType *RT = Type->getAs()) { + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + QualType T = Context.getDependentTemplateSpecializationType(Keyword, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Build type-source information. + TypeLocBuilder TLB; + DependentTemplateSpecializationTypeLoc SpecTL + = TLB.push(T); + SpecTL.setKeywordLoc(TagLoc); + SpecTL.setNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); + } + + QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); + if (Result.isNull()) + return TypeResult(); + + // Check the tag kind + if (const RecordType *RT = Result->getAs()) { RecordDecl *D = RT->getDecl(); - + IdentifierInfo *Id = D->getIdentifier(); assert(Id && "templated class must have an identifier"); - + if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) { Diag(TagLoc, diag::err_use_with_wrong_tag) - << Type + << Result << FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName()); Diag(D->getLocation(), diag::note_previous_use); } } + + // Provide source-location information for the template specialization. + TypeLocBuilder TLB; + TemplateSpecializationTypeLoc SpecTL + = TLB.push(Result); + SpecTL.setTemplateNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) + SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); - ElaboratedTypeKeyword Keyword - = TypeWithKeyword::getKeywordForTagTypeKind(TagKind); - QualType ElabType = Context.getElaboratedType(Keyword, /*NNS=*/0, Type); - - TypeSourceInfo *ElabDI = Context.CreateTypeSourceInfo(ElabType); - ElaboratedTypeLoc TL = cast(ElabDI->getTypeLoc()); - TL.setKeywordLoc(TagLoc); - TL.setQualifierRange(SS.getRange()); - TL.getNamedTypeLoc().initializeFullCopy(DI->getTypeLoc()); - return CreateParsedType(ElabType, ElabDI); + // Construct an elaborated type containing the nested-name-specifier (if any) + // and keyword. + Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result); + ElaboratedTypeLoc ElabTL = TLB.push(Result); + ElabTL.setKeywordLoc(TagLoc); + ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, - LookupResult &R, - bool RequiresADL, + LookupResult &R, + bool RequiresADL, const TemplateArgumentListInfo &TemplateArgs) { // FIXME: Can we do any checking at this point? I guess we could check the // template arguments that we have against the template name, if the template @@ -1832,19 +1951,12 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, assert(!R.empty() && "empty lookup results when building templateid"); assert(!R.isAmbiguous() && "ambiguous lookup when building templateid"); - NestedNameSpecifier *Qualifier = 0; - SourceRange QualifierRange; - if (SS.isSet()) { - Qualifier = static_cast(SS.getScopeRep()); - QualifierRange = SS.getRange(); - } - // We don't want lookup warnings at this point. R.suppressDiagnostics(); UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), - Qualifier, QualifierRange, + SS.getWithLocInContext(Context), R.getLookupNameInfo(), RequiresADL, TemplateArgs, R.begin(), R.end()); @@ -1935,7 +2047,8 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, MemberOfUnknownSpecialization); if (TNK == TNK_Non_template && LookupCtx->isDependentContext() && isa(LookupCtx) && - cast(LookupCtx)->hasAnyDependentBases()) { + (!cast(LookupCtx)->hasDefinition() || + cast(LookupCtx)->hasAnyDependentBases())) { // This is a dependent template. Handle it below. } else if (TNK == TNK_Non_template) { Diag(Name.getSourceRange().getBegin(), @@ -2043,7 +2156,6 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, /// /// \param Converted the list of template arguments provided for template /// parameters that precede \p Param in the template parameter list. -/// /// \returns the substituted template argument, or NULL if an error occurred. static TypeSourceInfo * SubstDefaultTemplateArgument(Sema &SemaRef, @@ -2140,6 +2252,9 @@ SubstDefaultTemplateArgument(Sema &SemaRef, /// \param Converted the list of template arguments provided for template /// parameters that precede \p Param in the template parameter list. /// +/// \param QualifierLoc Will be set to the nested-name-specifier (with +/// source-location information) that precedes the template name. +/// /// \returns the substituted template argument, or NULL if an error occurred. static TemplateName SubstDefaultTemplateArgument(Sema &SemaRef, @@ -2147,7 +2262,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef, SourceLocation TemplateLoc, SourceLocation RAngleLoc, TemplateTemplateParmDecl *Param, - llvm::SmallVectorImpl &Converted) { + llvm::SmallVectorImpl &Converted, + NestedNameSpecifierLoc &QualifierLoc) { TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted.data(), Converted.size()); @@ -2159,7 +2275,16 @@ SubstDefaultTemplateArgument(Sema &SemaRef, Converted.size(), SourceRange(TemplateLoc, RAngleLoc)); - return SemaRef.SubstTemplateName( + // Substitute into the nested-name-specifier first, + QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + AllTemplateArgs); + if (!QualifierLoc) + return TemplateName(); + } + + return SemaRef.SubstTemplateName(QualifierLoc, Param->getDefaultArgument().getArgument().getAsTemplate(), Param->getDefaultArgument().getTemplateNameLoc(), AllTemplateArgs); @@ -2195,10 +2320,10 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, return TemplateArgumentLoc(); ExprResult Arg = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - NonTypeParm, - Converted); + TemplateLoc, + RAngleLoc, + NonTypeParm, + Converted); if (Arg.isInvalid()) return TemplateArgumentLoc(); @@ -2211,16 +2336,19 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, if (!TempTempParm->hasDefaultArgument()) return TemplateArgumentLoc(); + + NestedNameSpecifierLoc QualifierLoc; TemplateName TName = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, TempTempParm, - Converted); + Converted, + QualifierLoc); if (TName.isNull()) return TemplateArgumentLoc(); return TemplateArgumentLoc(TemplateArgument(TName), - TempTempParm->getDefaultArgument().getTemplateQualifierRange(), + TempTempParm->getDefaultArgument().getTemplateQualifierLoc(), TempTempParm->getDefaultArgument().getTemplateNameLoc()); } @@ -2300,9 +2428,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, return true; case TemplateArgument::Expression: { - Expr *E = Arg.getArgument().getAsExpr(); TemplateArgument Result; - if (CheckTemplateArgument(NTTP, NTTPType, E, Result, CTAK)) + ExprResult Res = + CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(), + Result, CTAK); + if (Res.isInvalid()) return true; Converted.push_back(Result); @@ -2331,28 +2461,23 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, DeclarationNameInfo NameInfo(DTN->getIdentifier(), Arg.getTemplateNameLoc()); - // FIXME: TemplateArgumentLoc should store a NestedNameSpecifierLoc - // for the template name. CXXScopeSpec SS; - SS.MakeTrivial(Context, DTN->getQualifier(), - Arg.getTemplateQualifierRange()); - Expr *E = DependentScopeDeclRefExpr::Create(Context, + SS.Adopt(Arg.getTemplateQualifierLoc()); + ExprResult E = Owned(DependentScopeDeclRefExpr::Create(Context, SS.getWithLocInContext(Context), - NameInfo); + NameInfo)); // If we parsed the template argument as a pack expansion, create a // pack expansion expression. if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){ - ExprResult Expansion = ActOnPackExpansion(E, - Arg.getTemplateEllipsisLoc()); - if (Expansion.isInvalid()) + E = ActOnPackExpansion(E.take(), Arg.getTemplateEllipsisLoc()); + if (E.isInvalid()) return true; - - E = Expansion.get(); } TemplateArgument Result; - if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) + E = CheckTemplateArgument(NTTP, NTTPType, E.take(), Result); + if (E.isInvalid()) return true; Converted.push_back(Result); @@ -2461,7 +2586,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &TemplateArgs, + TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, llvm::SmallVectorImpl &Converted) { TemplateParameterList *Params = Template->getTemplateParameters(); @@ -2499,6 +2624,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // a template-id shall match the type and form specified for the // corresponding parameter declared by the template in its // template-parameter-list. + bool isTemplateTemplateParameter = isa(Template); llvm::SmallVector ArgumentPack; TemplateParameterList::iterator Param = Params->begin(), ParamEnd = Params->end(); @@ -2604,17 +2730,18 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, break; } + NestedNameSpecifierLoc QualifierLoc; TemplateName Name = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, TempParm, - Converted); + Converted, + QualifierLoc); if (Name.isNull()) return true; - Arg = TemplateArgumentLoc(TemplateArgument(Name), - TempParm->getDefaultArgument().getTemplateQualifierRange(), - TempParm->getDefaultArgument().getTemplateNameLoc()); + Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc, + TempParm->getDefaultArgument().getTemplateNameLoc()); } // Introduce an instantiation record that describes where we are using @@ -2628,6 +2755,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, RAngleLoc, 0, Converted)) return true; + // Core issue 150 (assumed resolution): if this is a template template + // parameter, keep track of the default template arguments from the + // template definition. + if (isTemplateTemplateParameter) + TemplateArgs.addArgument(Arg); + // Move to the next template parameter and argument. ++Param; ++ArgIdx; @@ -2853,7 +2986,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { return true; } - if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl()) { + if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) { S.Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR; S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here); return true; @@ -2961,13 +3094,25 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, SourceLocation AddrOpLoc; if (UnaryOperator *UnOp = dyn_cast(Arg)) { if (UnOp->getOpcode() == UO_AddrOf) { + // Support &__uuidof(class_with_uuid) as a non-type template argument. + // Very common in Microsoft COM headers. + if (S.getLangOptions().Microsoft && + isa(UnOp->getSubExpr())) { + Converted = TemplateArgument(ArgIn); + return false; + } + DRE = dyn_cast(UnOp->getSubExpr()); AddressTaken = true; AddrOpLoc = UnOp->getOperatorLoc(); } - } else + } else { + if (S.getLangOptions().Microsoft && isa(Arg)) { + Converted = TemplateArgument(ArgIn); + return false; + } DRE = dyn_cast(Arg); - + } if (!DRE) { S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) << Arg->getSourceRange(); @@ -3266,15 +3411,14 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, /// non-type template parameter. /// /// This routine implements the semantics of C++ [temp.arg.nontype]. -/// It returns true if an error occurred, and false otherwise. \p +/// If an error occurred, it returns ExprError(); otherwise, it +/// returns the converted template argument. \p /// InstantiatedParamType is the type of the non-type template /// parameter after it has been instantiated. -/// -/// If no error was detected, Converted receives the converted template argument. -bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, - QualType InstantiatedParamType, Expr *&Arg, - TemplateArgument &Converted, - CheckTemplateArgumentKind CTAK) { +ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, + QualType InstantiatedParamType, Expr *Arg, + TemplateArgument &Converted, + CheckTemplateArgumentKind CTAK) { SourceLocation StartLoc = Arg->getSourceRange().getBegin(); // If either the parameter has a dependent type or the argument is @@ -3282,7 +3426,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) { // FIXME: Produce a cloned, canonical expression? Converted = TemplateArgument(Arg); - return false; + return Owned(Arg); } // C++ [temp.arg.nontype]p5: @@ -3312,12 +3456,12 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, diag::err_template_arg_not_integral_or_enumeral) << ArgType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } else if (!Arg->isValueDependent() && !Arg->isIntegerConstantExpr(Value, Context, &NonConstantLoc)) { Diag(NonConstantLoc, diag::err_template_arg_not_ice) << ArgType << Arg->getSourceRange(); - return true; + return ExprError(); } // From here on out, all we care about are the unqualified forms @@ -3340,21 +3484,21 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) << ArgType << ParamType; Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } else if (ParamType->isBooleanType()) { // This is an integral-to-boolean conversion. - ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean); + Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).take(); } else if (IsIntegralPromotion(Arg, ArgType, ParamType) || !ParamType->isEnumeralType()) { // This is an integral promotion or conversion. - ImpCastExprToType(Arg, ParamType, CK_IntegralCast); + Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).take(); } else { // We can't perform this conversion. Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } QualType IntegerType = Context.getCanonicalType(ParamType); @@ -3404,13 +3548,13 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // The argument is value-dependent. Create a new // TemplateArgument with the converted expression. Converted = TemplateArgument(Arg); - return false; + return Owned(Arg); } Converted = TemplateArgument(Value, ParamType->isEnumeralType() ? ParamType : IntegerType); - return false; + return Owned(Arg); } DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction @@ -3422,7 +3566,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (ArgType->isNullPtrType() && (ParamType->isPointerType() || ParamType->isMemberPointerType())) { Converted = TemplateArgument((NamedDecl *)0); - return false; + return Owned(Arg); } // Handle pointer-to-function, reference-to-function, and @@ -3454,22 +3598,25 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, true, FoundResult)) { if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) - return true; + return ExprError(); Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); ArgType = Arg->getType(); } else - return true; + return ExprError(); } - if (!ParamType->isMemberPointerType()) - return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted); + if (!ParamType->isMemberPointerType()) { + if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted)) + return ExprError(); + return Owned(Arg); + } if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType(), false)) { - ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)); + Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take(); } else if (!Context.hasSameUnqualifiedType(ArgType, ParamType.getNonReferenceType())) { // We can't perform this conversion. @@ -3477,10 +3624,12 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } - return CheckTemplateArgumentPointerToMember(Arg, Converted); + if (CheckTemplateArgumentPointerToMember(Arg, Converted)) + return ExprError(); + return Owned(Arg); } if (ParamType->isPointerType()) { @@ -3491,9 +3640,11 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, assert(ParamType->getPointeeType()->isIncompleteOrObjectType() && "Only object pointers allowed here"); - return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted); + if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted)) + return ExprError(); + return Owned(Arg); } if (const ReferenceType *ParamRefType = ParamType->getAs()) { @@ -3512,17 +3663,19 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, true, FoundResult)) { if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) - return true; + return ExprError(); Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); ArgType = Arg->getType(); } else - return true; + return ExprError(); } - return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted); + if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted)) + return ExprError(); + return Owned(Arg); } // -- For a non-type template-parameter of type pointer to data @@ -3532,17 +3685,19 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (Context.hasSameUnqualifiedType(ParamType, ArgType)) { // Types match exactly: nothing more to do here. } else if (IsQualificationConversion(ArgType, ParamType, false)) { - ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)); + Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take(); } else { // We can't perform this conversion. Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } - return CheckTemplateArgumentPointerToMember(Arg, Converted); + if (CheckTemplateArgumentPointerToMember(Arg, Converted)) + return ExprError(); + return Owned(Arg); } /// \brief Check a template argument against its corresponding @@ -3636,11 +3791,8 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, // the element type on the parameter could be more qualified than the // element type in the expression we constructed. if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(), - ParamType.getUnqualifiedType(), false)) { - Expr *RefE = RefExpr.takeAs(); - ImpCastExprToType(RefE, ParamType.getUnqualifiedType(), CK_NoOp); - RefExpr = Owned(RefE); - } + ParamType.getUnqualifiedType(), false)) + RefExpr = ImpCastExprToType(RefExpr.take(), ParamType.getUnqualifiedType(), CK_NoOp); assert(!RefExpr.isInvalid() && Context.hasSameType(((Expr*) RefExpr.get())->getType(), @@ -3659,12 +3811,9 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, if (T->isFunctionType() || T->isArrayType()) { // Decay functions and arrays. - Expr *RefE = (Expr *)RefExpr.get(); - DefaultFunctionArrayConversion(RefE); - if (RefE != RefExpr.get()) { - RefExpr.release(); - RefExpr = Owned(RefE); - } + RefExpr = DefaultFunctionArrayConversion(RefExpr.take()); + if (RefExpr.isInvalid()) + return ExprError(); return move(RefExpr); } @@ -3703,18 +3852,18 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, if (T->isCharType() || T->isWideCharType()) return Owned(new (Context) CharacterLiteral( Arg.getAsIntegral()->getZExtValue(), - T->isWideCharType(), - T, - Loc)); + T->isWideCharType(), T, Loc)); if (T->isBooleanType()) return Owned(new (Context) CXXBoolLiteralExpr( Arg.getAsIntegral()->getBoolValue(), - T, - Loc)); + T, Loc)); + // If this is an enum type that we're instantiating, we need to use an integer + // type the same size as the enumerator. We don't want to build an + // IntegerLiteral with enum type. QualType BT; if (const EnumType *ET = T->getAs()) - BT = ET->getDecl()->getPromotionType(); + BT = ET->getDecl()->getIntegerType(); else BT = T; @@ -3722,10 +3871,9 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, if (T->isEnumeralType()) { // FIXME: This is a hack. We need a better way to handle substituted // non-type template parameters. - E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, - E, 0, - Context.getTrivialTypeSourceInfo(T, Loc), - Loc, Loc); + E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0, + Context.getTrivialTypeSourceInfo(T, Loc), + Loc, Loc); } return Owned(E); @@ -4245,7 +4393,7 @@ static NamedDecl *getPreviousDecl(NamedDecl *ND) { return FD->getPreviousDeclaration(); if (TagDecl *TD = dyn_cast(ND)) return TD->getPreviousDeclaration(); - if (TypedefDecl *TD = dyn_cast(ND)) + if (TypedefNameDecl *TD = dyn_cast(ND)) return TD->getPreviousDeclaration(); if (FunctionTemplateDecl *FTD = dyn_cast(ND)) return FTD->getPreviousDeclaration(); @@ -4268,6 +4416,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, MultiTemplateParamsArg TemplateParameterLists) { assert(TUK != TUK_Reference && "References are not specializations"); + // NOTE: KWLoc is the location of the tag keyword. This will instead + // store the location of the outermost template keyword in the declaration. + SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0 + ? TemplateParameterLists.get()[0]->getTemplateLoc() : SourceLocation(); + // Find the class template we're specializing TemplateName Name = TemplateD.getAsVal(); ClassTemplateDecl *ClassTemplate @@ -4298,10 +4451,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (Invalid) return true; - unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); - if (TemplateParams) - --NumMatchedTemplateParamLists; - if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; @@ -4443,10 +4592,15 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Since the only prior class template specialization with these // arguments was referenced but not declared, or we're only // referencing this specialization as a friend, reuse that - // declaration node as our own, updating its source location to - // reflect our new declaration. + // declaration node as our own, updating its source location and + // the list of outer template parameters to reflect our new declaration. Specialization = PrevDecl; Specialization->setLocation(TemplateNameLoc); + if (TemplateParameterLists.size() > 0) { + Specialization->setTemplateParameterListsInfo(Context, + TemplateParameterLists.size(), + (TemplateParameterList**) TemplateParameterLists.release()); + } PrevDecl = 0; CanonType = Context.getTypeDeclType(Specialization); } else if (isPartialSpecialization) { @@ -4471,7 +4625,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateNameLoc, Attr, TemplateParams, - AS_none); + AS_none, + TemplateParameterLists.size() - 1, + (TemplateParameterList**) TemplateParameterLists.release()); } // Create a new class template partial specialization declaration node. @@ -4482,7 +4638,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create(Context, Kind, ClassTemplate->getDeclContext(), - TemplateNameLoc, + KWLoc, TemplateNameLoc, TemplateParams, ClassTemplate, Converted.data(), @@ -4492,9 +4648,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, PrevPartial, SequenceNumber); SetNestedNameSpecifier(Partial, SS); - if (NumMatchedTemplateParamLists > 0 && SS.isSet()) { + if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size() - 1, (TemplateParameterList**) TemplateParameterLists.release()); } @@ -4545,15 +4701,15 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Specialization = ClassTemplateSpecializationDecl::Create(Context, Kind, ClassTemplate->getDeclContext(), - TemplateNameLoc, + KWLoc, TemplateNameLoc, ClassTemplate, Converted.data(), Converted.size(), PrevDecl); SetNestedNameSpecifier(Specialization, SS); - if (NumMatchedTemplateParamLists > 0 && SS.isSet()) { + if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size(), (TemplateParameterList**) TemplateParameterLists.release()); } @@ -4623,8 +4779,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateArgs, CanonType); if (TUK != TUK_Friend) { Specialization->setTypeAsWritten(WrittenTy); - if (TemplateParams) - Specialization->setTemplateKeywordLoc(TemplateParams->getTemplateLoc()); + Specialization->setTemplateKeywordLoc(TemplateKWLoc); } TemplateArgsIn.release(); @@ -4927,7 +5082,7 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, /// this function specialization. bool Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous) { // The set of function template specializations that could match this // explicit function template specialization. @@ -4983,7 +5138,17 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // Ignore access information; it doesn't figure into redeclaration checking. FunctionDecl *Specialization = cast(*Result); - Specialization->setLocation(FD->getLocation()); + + FunctionTemplateSpecializationInfo *SpecInfo + = Specialization->getTemplateSpecializationInfo(); + assert(SpecInfo && "Function template specialization info missing?"); + { + // Note: do not overwrite location info if previous template + // specialization kind was explicit. + TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind(); + if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) + Specialization->setLocation(FD->getLocation()); + } // FIXME: Check if the prior specialization has a point of instantiation. // If so, we have run afoul of . @@ -5006,10 +5171,6 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // before the first use of that specialization that would cause an implicit // instantiation to take place, in every translation unit in which such a // use occurs; no diagnostic is required. - FunctionTemplateSpecializationInfo *SpecInfo - = Specialization->getTemplateSpecializationInfo(); - assert(SpecInfo && "Function template specialization info missing?"); - bool HasNoEffect = false; if (!isFriend && CheckSpecializationInstantiationRedecl(FD->getLocation(), @@ -5402,7 +5563,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization = ClassTemplateSpecializationDecl::Create(Context, Kind, ClassTemplate->getDeclContext(), - TemplateNameLoc, + KWLoc, TemplateNameLoc, ClassTemplate, Converted.data(), Converted.size(), @@ -5883,26 +6044,34 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, return true; } + // Create the resulting type. ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind); - return ParsedType::make(Context.getDependentNameType(Kwd, NNS, Name)); + QualType Result = Context.getDependentNameType(Kwd, NNS, Name); + + // Create type-source location information for this type. + TypeLocBuilder TLB; + DependentNameTypeLoc TL = TLB.push(Result); + TL.setKeywordLoc(TagLoc); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(NameLoc); + return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } TypeResult Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, const CXXScopeSpec &SS, const IdentifierInfo &II, SourceLocation IdLoc) { - NestedNameSpecifier *NNS - = static_cast(SS.getScopeRep()); - if (!NNS) + if (SS.isInvalid()) return true; - + if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && !getLangOptions().CPlusPlus0x) Diag(TypenameLoc, diag::ext_typename_outside_of_template) << FixItHint::CreateRemoval(TypenameLoc); - QualType T = CheckTypenameType(ETK_Typename, NNS, II, - TypenameLoc, SS.getRange(), IdLoc); + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None, + TypenameLoc, QualifierLoc, II, IdLoc); if (T.isNull()) return true; @@ -5910,12 +6079,12 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, if (isa(T)) { DependentNameTypeLoc TL = cast(TSI->getTypeLoc()); TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(IdLoc); } else { ElaboratedTypeLoc TL = cast(TSI->getTypeLoc()); TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(QualifierLoc); cast(TL.getNamedTypeLoc()).setNameLoc(IdLoc); } @@ -5923,91 +6092,94 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, } TypeResult -Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, SourceLocation TemplateLoc, - ParsedType Ty) { +Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, + SourceLocation TemplateLoc, + TemplateTy TemplateIn, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc) { if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && !getLangOptions().CPlusPlus0x) Diag(TypenameLoc, diag::ext_typename_outside_of_template) - << FixItHint::CreateRemoval(TypenameLoc); - - TypeSourceInfo *InnerTSI = 0; - QualType T = GetTypeFromParser(Ty, &InnerTSI); - - assert(isa(T) && - "Expected a template specialization type"); - - if (computeDeclContext(SS, false)) { - // If we can compute a declaration context, then the "typename" - // keyword was superfluous. Just build an ElaboratedType to keep - // track of the nested-name-specifier. - - // Push the inner type, preserving its source locations if possible. + << FixItHint::CreateRemoval(TypenameLoc); + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + TemplateName Template = TemplateIn.get(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + // Construct a dependent template specialization type. + assert(DTN && "dependent template has non-dependent name?"); + assert(DTN->getQualifier() + == static_cast(SS.getScopeRep())); + QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Create source-location information for this type. TypeLocBuilder Builder; - if (InnerTSI) - Builder.pushFullCopy(InnerTSI->getTypeLoc()); - else - Builder.push(T).initialize(Context, - TemplateLoc); - - /* Note: NNS already embedded in template specialization type T. */ - T = Context.getElaboratedType(ETK_Typename, /*NNS=*/0, T); - ElaboratedTypeLoc TL = Builder.push(T); - TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(SS.getRange()); - - TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T); - return CreateParsedType(T, TSI); - } - - // TODO: it's really silly that we make a template specialization - // type earlier only to drop it again here. - const TemplateSpecializationType *TST = cast(T); - DependentTemplateName *DTN = - TST->getTemplateName().getAsDependentTemplateName(); - assert(DTN && "dependent template has non-dependent name?"); - assert(DTN->getQualifier() - == static_cast(SS.getScopeRep())); - T = Context.getDependentTemplateSpecializationType(ETK_Typename, - DTN->getQualifier(), - DTN->getIdentifier(), - TST->getNumArgs(), - TST->getArgs()); - TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - DependentTemplateSpecializationTypeLoc TL = - cast(TSI->getTypeLoc()); - if (InnerTSI) { - TemplateSpecializationTypeLoc TSTL = - cast(InnerTSI->getTypeLoc()); - TL.setLAngleLoc(TSTL.getLAngleLoc()); - TL.setRAngleLoc(TSTL.getRAngleLoc()); - for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I) - TL.setArgLocInfo(I, TSTL.getArgLocInfo(I)); - } else { - // FIXME: Poor source-location information here. - TL.initializeLocal(Context, TemplateLoc); + DependentTemplateSpecializationTypeLoc SpecTL + = Builder.push(T); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setKeywordLoc(TypenameLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + SpecTL.setNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } + + QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); + if (T.isNull()) + return true; + + // Provide source-location information for the template specialization + // type. + TypeLocBuilder Builder; + TemplateSpecializationTypeLoc SpecTL + = Builder.push(T); + + // FIXME: No place to set the location of the 'template' keyword! + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T); + ElaboratedTypeLoc TL = Builder.push(T); TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + + TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T); return CreateParsedType(T, TSI); } + /// \brief Build the type that describes a C++ typename specifier, /// e.g., "typename T::type". QualType -Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, const IdentifierInfo &II, - SourceLocation KeywordLoc, SourceRange NNSRange, +Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, + SourceLocation KeywordLoc, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo &II, SourceLocation IILoc) { CXXScopeSpec SS; - SS.MakeTrivial(Context, NNS, NNSRange); + SS.Adopt(QualifierLoc); DeclContext *Ctx = computeDeclContext(SS); if (!Ctx) { // If the nested-name-specifier is dependent and couldn't be // resolved to a type, build a typename type. - assert(NNS->isDependent()); - return Context.getDependentNameType(Keyword, NNS, &II); + assert(QualifierLoc.getNestedNameSpecifier()->isDependent()); + return Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + &II); } // If the nested-name-specifier refers to the current instantiation, @@ -6032,7 +6204,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, case LookupResult::FoundUnresolvedValue: { // We found a using declaration that is a value. Most likely, the using // declaration itself is meant to have the 'typename' keyword. - SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(), + SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(), IILoc); Diag(IILoc, diag::err_typename_refers_to_using_value_decl) << Name << Ctx << FullRange; @@ -6048,13 +6220,16 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, case LookupResult::NotFoundInCurrentInstantiation: // Okay, it's a member of an unknown instantiation. - return Context.getDependentNameType(Keyword, NNS, &II); + return Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + &II); case LookupResult::Found: if (TypeDecl *Type = dyn_cast(Result.getFoundDecl())) { // We found a type. Build an ElaboratedType, since the // typename-specifier was just sugar. - return Context.getElaboratedType(ETK_Typename, NNS, + return Context.getElaboratedType(ETK_Typename, + QualifierLoc.getNestedNameSpecifier(), Context.getTypeDeclType(Type)); } @@ -6077,7 +6252,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // If we get here, it's because name lookup did not find a // type. Emit an appropriate diagnostic and return an error. - SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(), + SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(), IILoc); Diag(IILoc, DiagID) << FullRange << Name << Ctx; if (Referenced) @@ -6225,3 +6400,24 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, Out << ']'; return Out.str(); } + +void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag) { + if (!FD) + return; + FD->setLateTemplateParsed(Flag); +} + +bool Sema::IsInsideALocalClassWithinATemplateFunction() { + DeclContext *DC = CurContext; + + while (DC) { + if (CXXRecordDecl *RD = dyn_cast(CurContext)) { + const FunctionDecl *FD = RD->isLocalClass(); + return (FD && FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate); + } else if (DC->isTranslationUnit() || DC->isNamespace()) + return false; + + DC = DC->getParent(); + } + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index 139fafb346f9..235af049cf84 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -800,6 +800,32 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_Success; } +/// \brief Determine whether the parameter has qualifiers that are either +/// inconsistent with or a superset of the argument's qualifiers. +static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType, + QualType ArgType) { + Qualifiers ParamQs = ParamType.getQualifiers(); + Qualifiers ArgQs = ArgType.getQualifiers(); + + if (ParamQs == ArgQs) + return false; + + // Mismatched (but not missing) Objective-C GC attributes. + if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() && + ParamQs.hasObjCGCAttr()) + return true; + + // Mismatched (but not missing) address spaces. + if (ParamQs.getAddressSpace() != ArgQs.getAddressSpace() && + ParamQs.hasAddressSpace()) + return true; + + // CVR qualifier superset. + return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) && + ((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers()) + == ParamQs.getCVRQualifiers()); +} + /// \brief Deduce the template arguments by comparing the parameter type and /// the argument type (C++ [temp.deduct.type]). /// @@ -875,9 +901,12 @@ DeduceTemplateArguments(Sema &S, Comparison.ParamIsRvalueRef = ParamRef->getAs(); Comparison.ArgIsRvalueRef = ArgRef->getAs(); Comparison.Qualifiers = NeitherMoreQualified; - if (Param.isMoreQualifiedThan(Arg)) + + Qualifiers ParamQuals = Param.getQualifiers(); + Qualifiers ArgQuals = Arg.getQualifiers(); + if (ParamQuals.isStrictSupersetOf(ArgQuals)) Comparison.Qualifiers = ParamMoreQualified; - else if (Arg.isMoreQualifiedThan(Param)) + else if (ArgQuals.isStrictSupersetOf(ParamQuals)) Comparison.Qualifiers = ArgMoreQualified; RefParamComparisons->push_back(Comparison); } @@ -949,7 +978,6 @@ DeduceTemplateArguments(Sema &S, // If the argument type is an array type, move the qualifiers up to the // top level, so they can be matched with the qualifiers on the parameter. - // FIXME: address spaces, ObjC GC qualifiers if (isa(Arg)) { Qualifiers Quals; Arg = S.Context.getUnqualifiedArrayType(Arg, Quals); @@ -961,7 +989,8 @@ DeduceTemplateArguments(Sema &S, // The argument type can not be less qualified than the parameter // type. - if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) { + if (!(TDF & TDF_IgnoreQualifiers) && + hasInconsistentOrSupersetQualifiersOf(Param, Arg)) { Info.Param = cast(TemplateParams->getParam(Index)); Info.FirstArg = TemplateArgument(Param); Info.SecondArg = TemplateArgument(Arg); @@ -972,8 +1001,18 @@ DeduceTemplateArguments(Sema &S, assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function"); QualType DeducedType = Arg; - // local manipulation is okay because it's canonical - DeducedType.removeLocalCVRQualifiers(Param.getCVRQualifiers()); + // Remove any qualifiers on the parameter from the deduced type. + // We checked the qualifiers for consistency above. + Qualifiers DeducedQs = DeducedType.getQualifiers(); + Qualifiers ParamQs = Param.getQualifiers(); + DeducedQs.removeCVRQualifiers(ParamQs.getCVRQualifiers()); + if (ParamQs.hasObjCGCAttr()) + DeducedQs.removeObjCGCAttr(); + if (ParamQs.hasAddressSpace()) + DeducedQs.removeAddressSpace(); + DeducedType = S.Context.getQualifiedType(DeducedType.getUnqualifiedType(), + DeducedQs); + if (RecanonicalizeArg) DeducedType = S.Context.getCanonicalType(DeducedType); @@ -1006,7 +1045,7 @@ DeduceTemplateArguments(Sema &S, // Check the cv-qualifiers on the parameter and argument types. if (!(TDF & TDF_IgnoreQualifiers)) { if (TDF & TDF_ParamWithReferenceType) { - if (Param.isMoreQualifiedThan(Arg)) + if (hasInconsistentOrSupersetQualifiersOf(Param, Arg)) return Sema::TDK_NonDeducedMismatch; } else if (!IsPossiblyOpaquelyQualifiedType(Param)) { if (Param.getCVRQualifiers() != Arg.getCVRQualifiers()) @@ -1728,11 +1767,24 @@ getTrivialTemplateArgumentLoc(Sema &S, return TemplateArgumentLoc(TemplateArgument(E), E); } - case TemplateArgument::Template: - return TemplateArgumentLoc(Arg, SourceRange(), Loc); - - case TemplateArgument::TemplateExpansion: - return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc); + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Arg.getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc); + + if (Arg.getKind() == TemplateArgument::Template) + return TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(S.Context), + Loc); + + + return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(S.Context), + Loc, Loc); + } case TemplateArgument::Expression: return TemplateArgumentLoc(Arg, Arg.getAsExpr()); @@ -1996,7 +2048,7 @@ static bool isSimpleTemplateIdType(QualType T) { Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo &ExplicitTemplateArgs, + TemplateArgumentListInfo &ExplicitTemplateArgs, llvm::SmallVectorImpl &Deduced, llvm::SmallVectorImpl &ParamTypes, QualType *FunctionType, @@ -2442,8 +2494,8 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, // C++0x [temp.deduct.call]p3: // If P is a cv-qualified type, the top level cv-qualifiers of P's type // are ignored for type deduction. - if (ParamType.getCVRQualifiers()) - ParamType = ParamType.getLocalUnqualifiedType(); + if (ParamType.hasQualifiers()) + ParamType = ParamType.getUnqualifiedType(); const ReferenceType *ParamRefType = ParamType->getAs(); if (ParamRefType) { QualType PointeeType = ParamRefType->getPointeeType(); @@ -2499,8 +2551,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, else { // - If A is a cv-qualified type, the top level cv-qualifiers of A's // type are ignored for type deduction. - if (ArgType.getCVRQualifiers()) - ArgType = ArgType.getUnqualifiedType(); + ArgType = ArgType.getUnqualifiedType(); } } @@ -2563,7 +2614,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { @@ -2761,7 +2812,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { @@ -2832,18 +2883,18 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, QualType P = Context.getCanonicalType(FromType); QualType A = Context.getCanonicalType(ToType); - // C++0x [temp.deduct.conv]p3: + // C++0x [temp.deduct.conv]p2: // If P is a reference type, the type referred to by P is used for // type deduction. if (const ReferenceType *PRef = P->getAs()) P = PRef->getPointeeType(); - // C++0x [temp.deduct.conv]p3: - // If A is a reference type, the type referred to by A is used + // C++0x [temp.deduct.conv]p4: + // [...] If A is a reference type, the type referred to by A is used // for type deduction. if (const ReferenceType *ARef = A->getAs()) - A = ARef->getPointeeType(); - // C++ [temp.deduct.conv]p2: + A = ARef->getPointeeType().getUnqualifiedType(); + // C++ [temp.deduct.conv]p3: // // If A is not a reference type: else { @@ -2864,9 +2915,10 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, else P = P.getUnqualifiedType(); - // C++0x [temp.deduct.conv]p3: + // C++0x [temp.deduct.conv]p4: // If A is a cv-qualified type, the top level cv-qualifiers of A's - // type are ignored for type deduction. + // type are ignored for type deduction. If A is a reference type, the type + // referred to by A is used for type deduction. A = A.getUnqualifiedType(); } @@ -2941,7 +2993,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, @@ -2989,11 +3041,14 @@ namespace { /// /// \param Result if type deduction was successful, this will be set to the /// deduced type. This may still contain undeduced autos if the type is -/// dependent. +/// dependent. This will be set to null if deduction succeeded, but auto +/// substitution failed; the appropriate diagnostic will already have been +/// produced in that case. /// /// \returns true if deduction succeeded, false if it failed. bool -Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) { +Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init, + TypeSourceInfo *&Result) { if (Init->isTypeDependent()) { Result = Type; return true; @@ -3004,14 +3059,18 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) { LocalInstantiationScope InstScope(*this); // Build template void Func(FuncParam); - QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false); - TemplateTypeParmDecl TemplParam(0, Loc, 0, false, TemplArg, false); - NamedDecl *TemplParamPtr = &TemplParam; + TemplateTypeParmDecl *TemplParam = + TemplateTypeParmDecl::Create(Context, 0, SourceLocation(), Loc, 0, 0, 0, + false, false); + QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0); + NamedDecl *TemplParamPtr = TemplParam; FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr, Loc); - QualType FuncParam = + TypeSourceInfo *FuncParamInfo = SubstituteAutoTransform(*this, TemplArg).TransformType(Type); + assert(FuncParamInfo && "substituting template parameter for 'auto' failed"); + QualType FuncParam = FuncParamInfo->getType(); // Deduce type of TemplParam in Func(Init) llvm::SmallVector Deduced; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index ae0ac9cbe35c..92ba095cd6c8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -95,6 +95,12 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, assert(Function->getPrimaryTemplate() && "No function template?"); if (Function->getPrimaryTemplate()->isMemberSpecialization()) break; + } else if (FunctionTemplateDecl *FunTmpl + = Function->getDescribedFunctionTemplate()) { + // Add the "injected" template arguments. + std::pair + Injected = FunTmpl->getInjectedTemplateArgs(); + Result.addOuterTemplateArguments(Injected.first, Injected.second); } // If this is a friend declaration and it declares an entity at @@ -718,8 +724,9 @@ namespace { /// as an instantiated local. VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *Declarator, - IdentifierInfo *Name, - SourceLocation Loc); + SourceLocation StartLoc, + SourceLocation NameLoc, + IdentifierInfo *Name); /// \brief Rebuild the Objective-C exception declaration and register the /// declaration as an instantiated local. @@ -730,9 +737,12 @@ namespace { /// elaborated type. QualType RebuildElaboratedType(SourceLocation KeywordLoc, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType T); + NestedNameSpecifierLoc QualifierLoc, + QualType T); - TemplateName TransformTemplateName(TemplateName Name, + TemplateName TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, QualType ObjectType = QualType(), NamedDecl *FirstQualifierInScope = 0); @@ -747,6 +757,7 @@ namespace { QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL); ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, llvm::Optional NumExpansions); /// \brief Transforms a template type parameter type by performing @@ -871,10 +882,11 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, VarDecl * TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *Declarator, - IdentifierInfo *Name, - SourceLocation Loc) { + SourceLocation StartLoc, + SourceLocation NameLoc, + IdentifierInfo *Name) { VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, Declarator, - Name, Loc); + StartLoc, NameLoc, Name); if (Var) getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var); return Var; @@ -892,7 +904,7 @@ VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, QualType TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, + NestedNameSpecifierLoc QualifierLoc, QualType T) { if (const TagType *TT = T->getAs()) { TagDecl* TD = TT->getDecl(); @@ -918,10 +930,13 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc, return TreeTransform::RebuildElaboratedType(KeywordLoc, Keyword, - NNS, T); + QualifierLoc, + T); } -TemplateName TemplateInstantiator::TransformTemplateName(TemplateName Name, +TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, QualType ObjectType, NamedDecl *FirstQualifierInScope) { if (TemplateTemplateParmDecl *TTP @@ -955,24 +970,31 @@ TemplateName TemplateInstantiator::TransformTemplateName(TemplateName Name, TemplateName Template = Arg.getAsTemplate(); assert(!Template.isNull() && Template.getAsTemplateDecl() && "Wrong kind of template template argument"); + + // We don't ever want to substitute for a qualified template name, since + // the qualifier is handled separately. So, look through the qualified + // template name to its underlying declaration. + if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Template = TemplateName(QTN->getTemplateDecl()); + return Template; } } if (SubstTemplateTemplateParmPackStorage *SubstPack - = Name.getAsSubstTemplateTemplateParmPack()) { + = Name.getAsSubstTemplateTemplateParmPack()) { if (getSema().ArgumentPackSubstitutionIndex == -1) return Name; - + const TemplateArgument &ArgPack = SubstPack->getArgumentPack(); assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() && "Pack substitution index out-of-range"); return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex] - .getAsTemplate(); + .getAsTemplate(); } - return inherited::TransformTemplateName(Name, ObjectType, - FirstQualifierInScope); + return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType, + FirstQualifierInScope); } ExprResult @@ -1153,8 +1175,9 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, ParmVarDecl * TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, llvm::Optional NumExpansions) { - return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, + return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment, NumExpansions); } @@ -1217,12 +1240,17 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, // the template parameter list of a member template inside the // template we are instantiating). Create a new template type // parameter with the template "level" reduced by one. + TemplateTypeParmDecl *NewTTPDecl = 0; + if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) + NewTTPDecl = cast_or_null( + TransformDecl(TL.getNameLoc(), OldTTPDecl)); + QualType Result = getSema().Context.getTemplateTypeParmType(T->getDepth() - TemplateArgs.getNumLevels(), T->getIndex(), T->isParameterPack(), - T->getName()); + NewTTPDecl); TemplateTypeParmTypeLoc NewTL = TLB.push(Result); NewTL.setNameLoc(TL.getNameLoc()); return Result; @@ -1396,6 +1424,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, const MultiLevelTemplateArgumentList &TemplateArgs, + int indexAdjustment, llvm::Optional NumExpansions) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; @@ -1432,9 +1461,10 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, } ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(), - NewDI, NewDI->getType(), - OldParm->getIdentifier(), + OldParm->getInnerLocStart(), OldParm->getLocation(), + OldParm->getIdentifier(), + NewDI->getType(), NewDI, OldParm->getStorageClass(), OldParm->getStorageClassAsWritten()); if (!NewParm) @@ -1465,6 +1495,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext // can be anything, is this right ? NewParm->setDeclContext(CurContext); + + NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(), + OldParm->getFunctionScopeIndex() + indexAdjustment); return NewParm; } @@ -1508,6 +1541,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, } SourceLocation EllipsisLoc; + TypeSourceInfo *BaseTypeLoc; if (Base->isPackExpansion()) { // This is a pack expansion. See whether we should expand it now, or // wait until later. @@ -1558,13 +1592,18 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, // The resulting base specifier will (still) be a pack expansion. EllipsisLoc = Base->getEllipsisLoc(); + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1); + BaseTypeLoc = SubstType(Base->getTypeSourceInfo(), + TemplateArgs, + Base->getSourceRange().getBegin(), + DeclarationName()); + } else { + BaseTypeLoc = SubstType(Base->getTypeSourceInfo(), + TemplateArgs, + Base->getSourceRange().getBegin(), + DeclarationName()); } - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1); - TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(), - TemplateArgs, - Base->getSourceRange().getBegin(), - DeclarationName()); if (!BaseTypeLoc) { Invalid = true; continue; @@ -1622,9 +1661,18 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, CXXRecordDecl *PatternDef = cast_or_null(Pattern->getDefinition()); - if (!PatternDef) { - if (!Complain) { + if (!PatternDef || PatternDef->isBeingDefined()) { + if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) { // Say nothing + } else if (PatternDef) { + assert(PatternDef->isBeingDefined()); + Diag(PointOfInstantiation, + diag::err_template_instantiate_within_definition) + << (TSK != TSK_ImplicitInstantiation) + << Context.getTypeDeclType(Instantiation); + // Not much point in noting the template declaration here, since + // we're lexically inside it. + Instantiation->setInvalidDecl(); } else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) { Diag(PointOfInstantiation, diag::err_implicit_instantiate_member_undefined) @@ -2130,16 +2178,6 @@ bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall, return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs); } -/// \brief Do template substitution on a nested-name-specifier. -NestedNameSpecifier * -Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS, - SourceRange Range, - const MultiLevelTemplateArgumentList &TemplateArgs) { - TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(), - DeclarationName()); - return Instantiator.TransformNestedNameSpecifier(NNS, Range); -} - NestedNameSpecifierLoc Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const MultiLevelTemplateArgumentList &TemplateArgs) { @@ -2161,11 +2199,14 @@ Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, } TemplateName -Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc, +Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, + TemplateName Name, SourceLocation Loc, const MultiLevelTemplateArgumentList &TemplateArgs) { TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, DeclarationName()); - return Instantiator.TransformTemplateName(Name); + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + return Instantiator.TransformTemplateName(SS, Name, Loc); } bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3a40b6fd77a7..6e11ef5bbc5f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -128,7 +128,8 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { return Inst; } -Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { +Decl *TemplateDeclInstantiator::VisitTypedefNameDecl(TypedefNameDecl *D, + bool IsTypeAlias) { bool Invalid = false; TypeSourceInfo *DI = D->getTypeSourceInfo(); if (DI->getType()->isDependentType() || @@ -144,9 +145,13 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { } // Create the new typedef - TypedefDecl *Typedef - = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(), - D->getIdentifier(), DI); + TypedefNameDecl *Typedef; + if (IsTypeAlias) + Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + D->getLocation(), D->getIdentifier(), DI); + else + Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + D->getLocation(), D->getIdentifier(), DI); if (Invalid) Typedef->setInvalidDecl(); @@ -154,17 +159,20 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { // tag decl, re-establish that relationship for the new typedef. if (const TagType *oldTagType = D->getUnderlyingType()->getAs()) { TagDecl *oldTag = oldTagType->getDecl(); - if (oldTag->getTypedefForAnonDecl() == D) { + if (oldTag->getTypedefNameForAnonDecl() == D) { TagDecl *newTag = DI->getType()->castAs()->getDecl(); - assert(!newTag->getIdentifier() && !newTag->getTypedefForAnonDecl()); - newTag->setTypedefForAnonDecl(Typedef); + assert(!newTag->getIdentifier() && !newTag->getTypedefNameForAnonDecl()); + newTag->setTypedefNameForAnonDecl(Typedef); } } - if (TypedefDecl *Prev = D->getPreviousDeclaration()) { + if (TypedefNameDecl *Prev = D->getPreviousDeclaration()) { NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, TemplateArgs); - Typedef->setPreviousDeclaration(cast(InstPrev)); + if (!InstPrev) + return 0; + + Typedef->setPreviousDeclaration(cast(InstPrev)); } SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); @@ -175,6 +183,14 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { return Typedef; } +Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { + return VisitTypedefNameDecl(D, /*IsTypeAlias=*/false); +} + +Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { + return VisitTypedefNameDecl(D, /*IsTypeAlias=*/true); +} + /// \brief Instantiate an initializer, breaking it into separate /// initialization arguments. /// @@ -261,12 +277,14 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // Build the instantiated declaration VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner, + D->getInnerLocStart(), D->getLocation(), D->getIdentifier(), DI->getType(), DI, D->getStorageClass(), D->getStorageClassAsWritten()); Var->setThreadSpecified(D->isThreadSpecified()); Var->setCXXDirectInitializer(D->hasCXXDirectInitializer()); + Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Var)) @@ -280,8 +298,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { Var->setAccess(D->getAccess()); - if (!D->isStaticDataMember()) + if (!D->isStaticDataMember()) { Var->setUsed(D->isUsed(false)); + Var->setReferenced(D->isReferenced()); + } // FIXME: In theory, we could have a previous declaration for variables that // are not static data members. @@ -346,7 +366,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { } SemaRef.PopExpressionEvaluationContext(); - } else if (!Var->isStaticDataMember() || Var->isOutOfLine()) + } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) && + !Var->isCXXForRangeDecl()) SemaRef.ActOnUninitializedDecl(Var, false); // Diagnose unused local variables. @@ -448,9 +469,14 @@ Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) { int i = 0; for (IndirectFieldDecl::chain_iterator PI = D->chain_begin(), PE = D->chain_end(); - PI != PE; ++PI) - NamedChain[i++] = (SemaRef.FindInstantiatedDecl(D->getLocation(), - *PI, TemplateArgs)); + PI != PE; ++PI) { + NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), *PI, + TemplateArgs); + if (!Next) + return 0; + + NamedChain[i++] = Next; + } QualType T = cast(NamedChain[i-1])->getType(); IndirectFieldDecl* IndirectField @@ -469,10 +495,18 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // Handle friend type expressions by simply substituting template // parameters into the pattern type and checking the result. if (TypeSourceInfo *Ty = D->getFriendType()) { - TypeSourceInfo *InstTy = - SemaRef.SubstType(Ty, TemplateArgs, - D->getLocation(), DeclarationName()); - if (!InstTy) + TypeSourceInfo *InstTy; + // If this is an unsupported friend, don't bother substituting template + // arguments into it. The actual type referred to won't be used by any + // parts of Clang, and may not be valid for instantiating. Just use the + // same info for the instantiated friend. + if (D->isUnsupportedFriend()) { + InstTy = Ty; + } else { + InstTy = SemaRef.SubstType(Ty, TemplateArgs, + D->getLocation(), DeclarationName()); + } + if (!InstTy) return 0; FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getFriendLoc(), InstTy); @@ -519,13 +553,13 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { D->getMessage(); return SemaRef.ActOnStaticAssertDeclaration(D->getLocation(), InstantiatedAssertExpr.get(), - Message.get()); + Message.get(), + D->getRParenLoc()); } Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { - EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, + EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), D->getIdentifier(), - D->getTagKeywordLoc(), /*PrevDecl=*/0, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); if (D->isFixed()) { @@ -750,8 +784,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *RecordInst = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC, - Pattern->getLocation(), Pattern->getIdentifier(), - Pattern->getTagKeywordLoc(), PrevDecl, + Pattern->getLocStart(), Pattern->getLocation(), + Pattern->getIdentifier(), PrevDecl, /*DelayTypeCreation=*/true); if (QualifierLoc) @@ -892,8 +926,8 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, - D->getLocation(), D->getIdentifier(), - D->getTagKeywordLoc(), PrevDecl); + D->getLocStart(), D->getLocation(), + D->getIdentifier(), PrevDecl); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Record)) @@ -991,8 +1025,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } FunctionDecl *Function = - FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(), - D->getDeclName(), T, TInfo, + FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), + D->getLocation(), D->getDeclName(), T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype()); @@ -1288,30 +1322,33 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, CXXRecordDecl *Record = cast(DC); CXXMethodDecl *Method = 0; + SourceLocation StartLoc = D->getInnerLocStart(); DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); if (CXXConstructorDecl *Constructor = dyn_cast(D)) { Method = CXXConstructorDecl::Create(SemaRef.Context, Record, - NameInfo, T, TInfo, + StartLoc, NameInfo, T, TInfo, Constructor->isExplicit(), Constructor->isInlineSpecified(), false); } else if (CXXDestructorDecl *Destructor = dyn_cast(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, - NameInfo, T, TInfo, + StartLoc, NameInfo, T, TInfo, Destructor->isInlineSpecified(), false); } else if (CXXConversionDecl *Conversion = dyn_cast(D)) { Method = CXXConversionDecl::Create(SemaRef.Context, Record, - NameInfo, T, TInfo, + StartLoc, NameInfo, T, TInfo, Conversion->isInlineSpecified(), - Conversion->isExplicit()); + Conversion->isExplicit(), + Conversion->getLocEnd()); } else { Method = CXXMethodDecl::Create(SemaRef.Context, Record, - NameInfo, T, TInfo, + StartLoc, NameInfo, T, TInfo, D->isStatic(), D->getStorageClassAsWritten(), - D->isInlineSpecified()); + D->isInlineSpecified(), + D->getLocEnd()); } if (QualifierLoc) @@ -1431,23 +1468,24 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { } ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { - return SemaRef.SubstParmVarDecl(D, TemplateArgs, llvm::Optional()); + return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, + llvm::Optional()); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( TemplateTypeParmDecl *D) { // TODO: don't always clone when decls are refcounted. - const Type* T = D->getTypeForDecl(); - assert(T->isTemplateTypeParmType()); - const TemplateTypeParmType *TTPT = T->getAs(); + assert(D->getTypeForDecl()->isTemplateTypeParmType()); TemplateTypeParmDecl *Inst = - TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), - TTPT->getDepth() - TemplateArgs.getNumLevels(), - TTPT->getIndex(), D->getIdentifier(), + TemplateTypeParmDecl::Create(SemaRef.Context, Owner, + D->getLocStart(), D->getLocation(), + D->getDepth() - TemplateArgs.getNumLevels(), + D->getIndex(), D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack()); - + Inst->setAccess(AS_public); + if (D->hasDefaultArgument()) Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false); @@ -1567,7 +1605,6 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( return 0; // Check that this type is acceptable for a non-type template parameter. - bool Invalid = false; T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(), D->getLocation()); if (T.isNull()) { @@ -1579,7 +1616,8 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( NonTypeTemplateParmDecl *Param; if (IsExpandedParameterPack) Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, - D->getLocation(), + D->getInnerLocStart(), + D->getLocation(), D->getDepth() - TemplateArgs.getNumLevels(), D->getPosition(), D->getIdentifier(), T, @@ -1589,12 +1627,14 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( ExpandedParameterPackTypesAsWritten.data()); else Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, + D->getInnerLocStart(), D->getLocation(), D->getDepth() - TemplateArgs.getNumLevels(), D->getPosition(), D->getIdentifier(), T, D->isParameterPack(), DI); + Param->setAccess(AS_public); if (Invalid) Param->setInvalidDecl(); @@ -1628,6 +1668,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( D->getPosition(), D->isParameterPack(), D->getIdentifier(), InstParams); Param->setDefaultArgument(D->getDefaultArgument(), false); + Param->setAccess(AS_public); // Introduce this template parameter's instantiation into the instantiation // scope. @@ -1719,9 +1760,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { I != E; ++I) { UsingShadowDecl *Shadow = *I; NamedDecl *InstTarget = - cast(SemaRef.FindInstantiatedDecl(Shadow->getLocation(), - Shadow->getTargetDecl(), - TemplateArgs)); + cast_or_null(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), + Shadow->getTargetDecl(), + TemplateArgs)); + if (!InstTarget) + return 0; if (CheckRedeclaration && SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev)) @@ -1936,7 +1980,8 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context, PartialSpec->getTagKind(), Owner, - PartialSpec->getLocation(), + PartialSpec->getLocStart(), + PartialSpec->getLocation(), InstParams, ClassTemplate, Converted.data(), @@ -2063,8 +2108,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, const FunctionProtoType *Proto = Tmpl->getType()->getAs(); assert(Proto && "Function template without prototype?"); - if (Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec() || - Proto->getNoReturnAttr()) { + if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) { // The function has an exception specification or a "noreturn" // attribute. Substitute into each of the exception types. llvm::SmallVector Exceptions; @@ -2078,7 +2122,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, Unexpanded); assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); - + bool Expand = false; bool RetainExpansion = false; llvm::Optional NumExpansions @@ -2092,7 +2136,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, RetainExpansion, NumExpansions)) break; - + if (!Expand) { // We can't expand this pack expansion into separate arguments yet; // just substitute into the pattern and create a new pack expansion @@ -2108,7 +2152,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, Exceptions.push_back(T); continue; } - + // Substitute into the pack expansion pattern for each template bool Invalid = false; for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) { @@ -2121,13 +2165,13 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, Invalid = true; break; } - + Exceptions.push_back(T); } - + if (Invalid) break; - + continue; } @@ -2140,14 +2184,20 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, Exceptions.push_back(T); } + Expr *NoexceptExpr = 0; + if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) { + ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs); + if (E.isUsable()) + NoexceptExpr = E.take(); + } // Rebuild the function type FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); - EPI.HasExceptionSpec = Proto->hasExceptionSpec(); - EPI.HasAnyExceptionSpec = Proto->hasAnyExceptionSpec(); + EPI.ExceptionSpecType = Proto->getExceptionSpecType(); EPI.NumExceptions = Exceptions.size(); EPI.Exceptions = Exceptions.data(); + EPI.NoexceptExpr = NoexceptExpr; EPI.ExtInfo = Proto->getExtInfo(); const FunctionProtoType *NewProto @@ -2218,6 +2268,21 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (PatternDecl) Pattern = PatternDecl->getBody(PatternDecl); + // Postpone late parsed template instantiations. + if (PatternDecl->isLateTemplateParsed() && !LateTemplateParser) { + PendingInstantiations.push_back( + std::make_pair(Function, PointOfInstantiation)); + return; + } + + // Call the LateTemplateParser callback if there a need to late parse + // a templated function definition. + if (!Pattern && PatternDecl && PatternDecl->isLateTemplateParsed() && + LateTemplateParser) { + LateTemplateParser(OpaqueParser, PatternDecl); + Pattern = PatternDecl->getBody(PatternDecl); + } + if (!Pattern) { if (DefinitionRequired) { if (Function->getPrimaryTemplate()) @@ -2573,10 +2638,15 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, New->getParent(), EllipsisLoc); } else if (Init->isMemberInitializer()) { - FieldDecl *Member = cast(FindInstantiatedDecl( + FieldDecl *Member = cast_or_null(FindInstantiatedDecl( Init->getMemberLocation(), Init->getMember(), TemplateArgs)); + if (!Member) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), NewArgs.size(), @@ -2585,10 +2655,16 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, Init->getRParenLoc()); } else if (Init->isIndirectMemberInitializer()) { IndirectFieldDecl *IndirectMember = - cast(FindInstantiatedDecl( + cast_or_null(FindInstantiatedDecl( Init->getMemberLocation(), Init->getIndirectMember(), TemplateArgs)); + if (!IndirectMember) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } + NewInit = BuildMemberInitializer(IndirectMember, (Expr **)NewArgs.data(), NewArgs.size(), Init->getSourceLocation(), @@ -2917,7 +2993,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // FIXME: Can we use the CurrentInstantiationScope to avoid this // extra instantiation in the common case? - T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName()); + T = SubstType(T, TemplateArgs, Loc, DeclarationName()); assert(!T.isNull() && "Instantiation of injected-class-name cannot fail."); if (!T->isDependentType()) { @@ -2974,11 +3050,14 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // If our context used to be dependent, we may need to instantiate // it before performing lookup into that context. + bool IsBeingInstantiated = false; if (CXXRecordDecl *Spec = dyn_cast(ParentDC)) { if (!Spec->isDependentContext()) { QualType T = Context.getTypeDeclType(Spec); const RecordType *Tag = T->getAs(); assert(Tag && "type of non-dependent record is not a RecordType"); + if (Tag->isBeingDefined()) + IsBeingInstantiated = true; if (!Tag->isBeingDefined() && RequireCompleteType(Loc, T, diag::err_incomplete_type)) return 0; @@ -3005,11 +3084,29 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, ParentDC->decls_end()); } - // UsingShadowDecls can instantiate to nothing because of using hiding. - assert((Result || isa(D) || D->isInvalidDecl() || - cast(ParentDC)->isInvalidDecl()) - && "Unable to find instantiation of declaration!"); - + if (!Result) { + if (isa(D)) { + // UsingShadowDecls can instantiate to nothing because of using hiding. + } else if (Diags.hasErrorOccurred()) { + // We've already complained about something, so most likely this + // declaration failed to instantiate. There's no point in complaining + // further, since this is normal in invalid code. + } else if (IsBeingInstantiated) { + // The class in which this member exists is currently being + // instantiated, and we haven't gotten around to instantiating this + // member yet. This can happen when the code uses forward declarations + // of member classes, and introduces ordering dependencies via + // template instantiation. + Diag(Loc, diag::err_member_not_yet_instantiated) + << D->getDeclName() + << Context.getTypeDeclType(cast(ParentDC)); + Diag(D->getLocation(), diag::note_non_instantiated_member_here); + } else { + // We should have found something, but didn't. + llvm_unreachable("Unable to find instantiation of declaration!"); + } + } + D = Result; } @@ -3018,7 +3115,10 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, /// \brief Performs template instantiation for all implicit template /// instantiations we have seen until this point. -void Sema::PerformPendingInstantiations(bool LocalOnly) { +/// +/// \returns true if anything was instantiated. +bool Sema::PerformPendingInstantiations(bool LocalOnly) { + bool InstantiatedAnything = false; while (!PendingLocalImplicitInstantiations.empty() || (!LocalOnly && !PendingInstantiations.empty())) { PendingImplicitInstantiation Inst; @@ -3039,6 +3139,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { TSK_ExplicitInstantiationDefinition; InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, DefinitionRequired); + InstantiatedAnything = true; continue; } @@ -3075,7 +3176,10 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { TSK_ExplicitInstantiationDefinition; InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true, DefinitionRequired); + InstantiatedAnything = true; } + + return InstantiatedAnything; } void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp index 0da801c7e343..096d353bccc3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -167,7 +167,7 @@ DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc, IdentifierInfo *Name = 0; if (const TemplateTypeParmType *TTP = Unexpanded[I].first.dyn_cast()) - Name = TTP->getName(); + Name = TTP->getIdentifier(); else Name = Unexpanded[I].first.get()->getIdentifier(); @@ -483,7 +483,7 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, = Unexpanded[I].first.dyn_cast()) { Depth = TTP->getDepth(); Index = TTP->getIndex(); - Name = TTP->getName(); + Name = TTP->getIdentifier(); } else { NamedDecl *ND = Unexpanded[I].first.get(); if (isa(ND)) @@ -649,6 +649,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_struct: case TST_class: case TST_auto: + case TST_unknown_anytype: case TST_error: break; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index ba80076003c9..00ac1d63dbe7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" +#include "clang/Basic/OpenCL.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" @@ -22,6 +23,7 @@ #include "clang/AST/Expr.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ErrorHandling.h" @@ -70,6 +72,40 @@ static bool isOmittedBlockReturnType(const Declarator &D) { return false; } +/// diagnoseBadTypeAttribute - Diagnoses a type attribute which +/// doesn't apply to the given type. +static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, + QualType type) { + bool useInstantiationLoc = false; + + unsigned diagID = 0; + switch (attr.getKind()) { + case AttributeList::AT_objc_gc: + diagID = diag::warn_pointer_attribute_wrong_type; + useInstantiationLoc = true; + break; + + default: + // Assume everything else was a function attribute. + diagID = diag::warn_function_attribute_wrong_type; + break; + } + + SourceLocation loc = attr.getLoc(); + llvm::StringRef name = attr.getName()->getName(); + + // The GC attributes are usually written with macros; special-case them. + if (useInstantiationLoc && loc.isMacroID() && attr.getParameterName()) { + if (attr.getParameterName()->isStr("strong")) { + if (S.findMacroSpelling(loc, "__strong")) name = "__strong"; + } else if (attr.getParameterName()->isStr("weak")) { + if (S.findMacroSpelling(loc, "__weak")) name = "__weak"; + } + } + + S.Diag(loc, diagID) << name << type; +} + // objc_gc applies to Objective-C pointers or, otherwise, to the // smallest available pointer type (i.e. 'void*' in 'void**'). #define OBJC_POINTER_TYPE_ATTRS_CASELIST \ @@ -83,7 +119,8 @@ static bool isOmittedBlockReturnType(const Declarator &D) { case AttributeList::AT_stdcall: \ case AttributeList::AT_thiscall: \ case AttributeList::AT_pascal: \ - case AttributeList::AT_regparm + case AttributeList::AT_regparm: \ + case AttributeList::AT_pcs \ namespace { /// An object which stores processing state for the entire @@ -102,6 +139,9 @@ namespace { /// Whether there are non-trivial modifications to the decl spec. bool trivial; + /// Whether we saved the attributes in the decl spec. + bool hasSavedAttrs; + /// The original set of attributes on the DeclSpec. llvm::SmallVector savedAttrs; @@ -113,7 +153,7 @@ namespace { TypeProcessingState(Sema &sema, Declarator &declarator) : sema(sema), declarator(declarator), chunkIndex(declarator.getNumTypeObjects()), - trivial(true) {} + trivial(true), hasSavedAttrs(false) {} Sema &getSema() const { return sema; @@ -142,13 +182,14 @@ namespace { /// Save the current set of attributes on the DeclSpec. void saveDeclSpecAttrs() { // Don't try to save them multiple times. - if (!savedAttrs.empty()) return; + if (hasSavedAttrs) return; DeclSpec &spec = getMutableDeclSpec(); for (AttributeList *attr = spec.getAttributes().getList(); attr; attr = attr->getNext()) savedAttrs.push_back(attr); trivial &= savedAttrs.empty(); + hasSavedAttrs = true; } /// Record that we had nowhere to put the given type attribute. @@ -162,11 +203,8 @@ namespace { void diagnoseIgnoredTypeAttrs(QualType type) const { for (llvm::SmallVectorImpl::const_iterator i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end(); - i != e; ++i) { - AttributeList &attr = **i; - getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type) - << attr.getName() << type; - } + i != e; ++i) + diagnoseBadTypeAttribute(getSema(), **i, type); } ~TypeProcessingState() { @@ -181,7 +219,13 @@ namespace { } void restoreDeclSpecAttrs() { - assert(!savedAttrs.empty()); + assert(hasSavedAttrs); + + if (savedAttrs.empty()) { + getMutableDeclSpec().getAttributes().set(0); + return; + } + getMutableDeclSpec().getAttributes().set(savedAttrs[0]); for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i) savedAttrs[i]->setNext(savedAttrs[i+1]); @@ -287,9 +331,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, } } error: - - state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type) - << attr.getName() << type; + + diagnoseBadTypeAttribute(state.getSema(), attr, type); } /// Distribute an objc_gc type attribute that was written on the @@ -328,8 +371,15 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, // That might actually be the decl spec if we weren't blocked by // anything in the declarator. if (considerDeclSpec) { - if (handleObjCPointerTypeAttr(state, attr, declSpecType)) + if (handleObjCPointerTypeAttr(state, attr, declSpecType)) { + // Splice the attribute into the decl spec. Prevents the + // attribute from being applied multiple times and gives + // the source-location-filler something to work with. + state.saveDeclSpecAttrs(); + moveAttrFromListToList(attr, declarator.getAttrListRef(), + declarator.getMutableDeclSpec().getAttributes().getListRef()); return; + } } // Otherwise, if we found an appropriate chunk, splice the attribute @@ -374,8 +424,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, } } - state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type) - << attr.getName() << type; + diagnoseBadTypeAttribute(state.getSema(), attr, type); } /// Try to distribute a function type attribute to the innermost @@ -505,13 +554,12 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, // ...and *prepend* it to the declarator. declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction( - ParsedAttributes(), /*proto*/ true, /*variadic*/ false, SourceLocation(), /*args*/ 0, 0, /*type quals*/ 0, /*ref-qualifier*/true, SourceLocation(), - /*EH*/ false, SourceLocation(), false, 0, 0, 0, + /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0, /*parens*/ loc, loc, declarator)); @@ -698,7 +746,7 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) { } // If the type is deprecated or unavailable, diagnose it. - S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc()); + S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc()); assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!"); @@ -706,12 +754,11 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) { // TypeQuals handled by caller. Result = Context.getTypeDeclType(D); - // In C++, make an ElaboratedType. - if (S.getLangOptions().CPlusPlus) { - ElaboratedTypeKeyword Keyword - = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType()); - Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result); - } + // In both C and C++, make an ElaboratedType. + ElaboratedTypeKeyword Keyword + = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType()); + Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result); + if (D->isInvalidDecl()) declarator.setInvalidType(true); break; @@ -795,6 +842,10 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) { break; } + case DeclSpec::TST_unknown_anytype: + Result = Context.UnknownAnyTy; + break; + case DeclSpec::TST_error: Result = Context.IntTy; declarator.setInvalidType(true); @@ -1108,8 +1159,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, } // Do lvalue-to-rvalue conversions on the array size expression. - if (ArraySize && !ArraySize->isRValue()) - DefaultLvalueConversion(ArraySize); + if (ArraySize && !ArraySize->isRValue()) { + ExprResult Result = DefaultLvalueConversion(ArraySize); + if (Result.isInvalid()) + return QualType(); + + ArraySize = Result.take(); + } // C99 6.7.5.2p1: The size expression shall have integer type. // TODO: in theory, if we were insane, we could allow contextual @@ -1464,19 +1520,27 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, TypeProcessingState state(*this, D); + // In C++0x, deallocation functions (normal and array operator delete) + // are implicitly noexcept. + bool ImplicitlyNoexcept = false; + switch (D.getName().getKind()) { - case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_OperatorFunctionId: + if (getLangOptions().CPlusPlus0x) { + OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator; + if (OO == OO_Delete || OO == OO_Array_Delete) + ImplicitlyNoexcept = true; + } + // Intentional fall-through. + case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_TemplateId: T = ConvertDeclSpecToType(*this, state); if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) { TagDecl* Owned = cast(D.getDeclSpec().getRepAsDecl()); - // Owned is embedded if it was defined here, or if it is the - // very first (i.e., canonical) declaration of this tag type. - Owned->setEmbeddedInDeclarator(Owned->isDefinition() || - Owned->isCanonicalDecl()); + // Owned declaration is embedded in declarator. + Owned->setEmbeddedInDeclarator(true); if (OwnedDecl) *OwnedDecl = Owned; } break; @@ -1512,6 +1576,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::KNRTypeListContext: assert(0 && "K&R type lists aren't allowed in C++"); break; + case Declarator::ObjCPrototypeContext: case Declarator::PrototypeContext: Error = 0; // Function prototype break; @@ -1535,9 +1600,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::TemplateTypeArgContext: Error = 7; // Template type argument break; + case Declarator::AliasDeclContext: + Error = 9; // Type alias + break; case Declarator::TypeNameContext: if (!AutoAllowedInTypeName) - Error = 10; // Generic + Error = 11; // Generic break; case Declarator::FileContext: case Declarator::BlockContext: @@ -1551,7 +1619,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // In Objective-C it is an error to use 'auto' on a function declarator. if (D.isFunctionDeclarator()) - Error = 9; + Error = 10; // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator // contains a trailing return type. That is only legal at the outermost @@ -1588,6 +1656,11 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (D.getIdentifier()) Name = D.getIdentifier(); + // Does this declaration declare a typedef-name? + bool IsTypedefName = + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef || + D.getContext() == Declarator::AliasDeclContext; + // Walk the DeclTypeInfo, building the recursive type as we go. // DeclTypeInfos are ordered from the identifier out, which is // opposite of what we want :). @@ -1660,8 +1733,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, ASM = ArrayType::Static; else ASM = ArrayType::Normal; - if (ASM == ArrayType::Star && - D.getContext() != Declarator::PrototypeContext) { + if (ASM == ArrayType::Star && !D.isPrototypeContext()) { // FIXME: This check isn't quite right: it allows star in prototypes // for function definitions, and disallows some edge cases detailed // in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html @@ -1728,7 +1800,8 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // cv-qualifiers on return types are pointless except when the type is a // class type in C++. - if (T->isPointerType() && T.getCVRQualifiers() && + if (isa(T) && T.getLocalCVRQualifiers() && + (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId) && (!getLangOptions().CPlusPlus || !T->isDependentType())) { assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?"); DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1); @@ -1764,9 +1837,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Exception specs are not allowed in typedefs. Complain, but add it // anyway. - if (FTI.hasExceptionSpec && - D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef); + if (IsTypedefName && FTI.getExceptionSpecType()) + Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef) + << (D.getContext() == Declarator::AliasDeclContext); if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) { // Simple void foo(), where the incoming T is the result type. @@ -1845,9 +1918,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } else if (!FTI.hasPrototype) { if (ArgTy->isPromotableIntegerType()) { ArgTy = Context.getPromotedIntegerType(ArgTy); + Param->setKNRPromoted(true); } else if (const BuiltinType* BTy = ArgTy->getAs()) { - if (BTy->getKind() == BuiltinType::Float) + if (BTy->getKind() == BuiltinType::Float) { ArgTy = Context.DoubleTy; + Param->setKNRPromoted(true); + } } } @@ -1855,9 +1931,8 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } llvm::SmallVector Exceptions; - if (FTI.hasExceptionSpec) { - EPI.HasExceptionSpec = FTI.hasExceptionSpec; - EPI.HasAnyExceptionSpec = FTI.hasAnyExceptionSpec; + EPI.ExceptionSpecType = FTI.getExceptionSpecType(); + if (FTI.getExceptionSpecType() == EST_Dynamic) { Exceptions.reserve(FTI.NumExceptions); for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { // FIXME: Preserve type source info. @@ -1869,6 +1944,27 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } EPI.NumExceptions = Exceptions.size(); EPI.Exceptions = Exceptions.data(); + } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) { + // If an error occurred, there's no expression here. + if (Expr *NoexceptExpr = FTI.NoexceptExpr) { + assert((NoexceptExpr->isTypeDependent() || + NoexceptExpr->getType()->getCanonicalTypeUnqualified() == + Context.BoolTy) && + "Parser should have made sure that the expression is boolean"); + SourceLocation ErrLoc; + llvm::APSInt Dummy; + if (!NoexceptExpr->isValueDependent() && + !NoexceptExpr->isIntegerConstantExpr(Dummy, Context, &ErrLoc, + /*evaluated*/false)) + Diag(ErrLoc, diag::err_noexcept_needs_constant_expression) + << NoexceptExpr->getSourceRange(); + else + EPI.NoexceptExpr = NoexceptExpr; + } + } else if (FTI.getExceptionSpecType() == EST_None && + ImplicitlyNoexcept && chunkIndex == 0) { + // Only the outermost chunk is marked noexcept, of course. + EPI.ExceptionSpecType = EST_BasicNoexcept; } T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI); @@ -1903,11 +1999,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: ClsType = QualType(NNS->getAsType(), 0); - // Note: if NNS is dependent, then its prefix (if any) is already - // included in ClsType; this does not hold if the NNS is - // nondependent: in this case (if there is indeed a prefix) - // ClsType needs to be wrapped into an elaborated type. - if (NNSPrefix && !NNS->isDependent()) + // Note: if the NNS has a prefix and ClsType is a nondependent + // TemplateSpecializationType, then the NNS prefix is NOT included + // in ClsType; hence we wrap ClsType into an ElaboratedType. + // NOTE: in particular, no wrap occurs if ClsType already is an + // Elaborated, DependentName, or DependentTemplateSpecialization. + if (NNSPrefix && isa(NNS->getAsType())) ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType); break; } @@ -1968,8 +2065,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // declaration. if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) && !(D.getContext() == Declarator::TemplateTypeArgContext && - !D.isFunctionDeclarator()) && - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + !D.isFunctionDeclarator()) && !IsTypedefName && (FreeFunction || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) { if (D.getContext() == Declarator::TemplateTypeArgContext) { @@ -2053,8 +2149,10 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Diagnose any ignored type attributes. if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T); - // If there's a constexpr specifier, treat it as a top-level const. - if (D.getDeclSpec().isConstexprSpecified()) { + // C++0x [dcl.constexpr]p9: + // A constexpr specifier used in an object declaration declares the object + // as const. + if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) { T.addConst(); } @@ -2103,7 +2201,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::FileContext: case Declarator::KNRTypeListContext: + case Declarator::ObjCPrototypeContext: // FIXME: special diagnostic here? case Declarator::TypeNameContext: + case Declarator::AliasDeclContext: case Declarator::MemberContext: case Declarator::BlockContext: case Declarator::ForContext: @@ -2126,6 +2226,62 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, return GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo); } +/// Map an AttributedType::Kind to an AttributeList::Kind. +static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { + switch (kind) { + case AttributedType::attr_address_space: + return AttributeList::AT_address_space; + case AttributedType::attr_regparm: + return AttributeList::AT_regparm; + case AttributedType::attr_vector_size: + return AttributeList::AT_vector_size; + case AttributedType::attr_neon_vector_type: + return AttributeList::AT_neon_vector_type; + case AttributedType::attr_neon_polyvector_type: + return AttributeList::AT_neon_polyvector_type; + case AttributedType::attr_objc_gc: + return AttributeList::AT_objc_gc; + case AttributedType::attr_noreturn: + return AttributeList::AT_noreturn; + case AttributedType::attr_cdecl: + return AttributeList::AT_cdecl; + case AttributedType::attr_fastcall: + return AttributeList::AT_fastcall; + case AttributedType::attr_stdcall: + return AttributeList::AT_stdcall; + case AttributedType::attr_thiscall: + return AttributeList::AT_thiscall; + case AttributedType::attr_pascal: + return AttributeList::AT_pascal; + case AttributedType::attr_pcs: + return AttributeList::AT_pcs; + } + llvm_unreachable("unexpected attribute kind!"); + return AttributeList::Kind(); +} + +static void fillAttributedTypeLoc(AttributedTypeLoc TL, + const AttributeList *attrs) { + AttributedType::Kind kind = TL.getAttrKind(); + + assert(attrs && "no type attributes in the expected location!"); + AttributeList::Kind parsedKind = getAttrListKind(kind); + while (attrs->getKind() != parsedKind) { + attrs = attrs->getNext(); + assert(attrs && "no matching attribute in expected location!"); + } + + TL.setAttrNameLoc(attrs->getLoc()); + if (TL.hasAttrExprOperand()) + TL.setAttrExprOperand(attrs->getArg(0)); + else if (TL.hasAttrEnumOperand()) + TL.setAttrEnumOperandLoc(attrs->getParameterLoc()); + + // FIXME: preserve this information to here. + if (TL.hasAttrOperand()) + TL.setAttrOperandParensRange(SourceRange()); +} + namespace { class TypeSpecLocFiller : public TypeLocVisitor { ASTContext &Context; @@ -2135,6 +2291,10 @@ namespace { TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS) : Context(Context), DS(DS) {} + void VisitAttributedTypeLoc(AttributedTypeLoc TL) { + fillAttributedTypeLoc(TL, DS.getAttributes().getList()); + Visit(TL.getModifiedLoc()); + } void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { Visit(TL.getUnqualifiedLoc()); } @@ -2179,7 +2339,7 @@ namespace { // If we got no declarator info from previous Sema routines, // just fill with the typespec loc. if (!TInfo) { - TL.initialize(Context, DS.getTypeSpecTypeLoc()); + TL.initialize(Context, DS.getTypeSpecTypeNameLoc()); return; } @@ -2237,7 +2397,7 @@ namespace { ? DS.getTypeSpecTypeLoc() : SourceLocation()); const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierRange(SS.isEmpty() ? SourceRange(): SS.getRange()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); Visit(TL.getNextTypeLoc().getUnqualifiedLoc()); } void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { @@ -2255,9 +2415,8 @@ namespace { ? DS.getTypeSpecTypeLoc() : SourceLocation()); const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange()); - // FIXME: load appropriate source location. - TL.setNameLoc(DS.getTypeSpecTypeLoc()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); } void VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { @@ -2277,9 +2436,11 @@ namespace { ? DS.getTypeSpecTypeLoc() : SourceLocation()); const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange()); - // FIXME: load appropriate source location. - TL.setNameLoc(DS.getTypeSpecTypeLoc()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); + } + void VisitTagTypeLoc(TagTypeLoc TL) { + TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); } void VisitTypeLoc(TypeLoc TL) { @@ -2289,10 +2450,12 @@ namespace { }; class DeclaratorLocFiller : public TypeLocVisitor { + ASTContext &Context; const DeclaratorChunk &Chunk; public: - DeclaratorLocFiller(const DeclaratorChunk &Chunk) : Chunk(Chunk) {} + DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk) + : Context(Context), Chunk(Chunk) {} void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { llvm_unreachable("qualified type locs not expected here!"); @@ -2312,8 +2475,48 @@ namespace { } void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::MemberPointer); + const CXXScopeSpec& SS = Chunk.Mem.Scope(); + NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context); + + const Type* ClsTy = TL.getClass(); + QualType ClsQT = QualType(ClsTy, 0); + TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0); + // Now copy source location info into the type loc component. + TypeLoc ClsTL = ClsTInfo->getTypeLoc(); + switch (NNSLoc.getNestedNameSpecifier()->getKind()) { + case NestedNameSpecifier::Identifier: + assert(isa(ClsTy) && "Unexpected TypeLoc"); + { + DependentNameTypeLoc DNTLoc = cast(ClsTL); + DNTLoc.setKeywordLoc(SourceLocation()); + DNTLoc.setQualifierLoc(NNSLoc.getPrefix()); + DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc()); + } + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + if (isa(ClsTy)) { + ElaboratedTypeLoc ETLoc = *cast(&ClsTL); + ETLoc.setKeywordLoc(SourceLocation()); + ETLoc.setQualifierLoc(NNSLoc.getPrefix()); + TypeLoc NamedTL = ETLoc.getNamedTypeLoc(); + NamedTL.initializeFullCopy(NNSLoc.getTypeLoc()); + } else { + ClsTL.initializeFullCopy(NNSLoc.getTypeLoc()); + } + break; + + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Global: + llvm_unreachable("Nested-name-specifier must name a type"); + break; + } + + // Finally fill in MemberPointerLocInfo fields. TL.setStarLoc(Chunk.Loc); - // FIXME: nested name specifier + TL.setClassTInfo(ClsTInfo); } void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Reference); @@ -2334,8 +2537,8 @@ namespace { } void VisitFunctionTypeLoc(FunctionTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Function); - TL.setLParenLoc(Chunk.Loc); - TL.setRParenLoc(Chunk.EndLoc); + TL.setLocalRangeBegin(Chunk.Loc); + TL.setLocalRangeEnd(Chunk.EndLoc); TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType); const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun; @@ -2378,7 +2581,13 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, } for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { - DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL); + while (isa(CurrTL)) { + AttributedTypeLoc TL = cast(CurrTL); + fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs()); + CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + } + + DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -2434,7 +2643,8 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { // A type-specifier-seq shall not define a class or enumeration // unless it appears in the type-id of an alias-declaration // (7.1.3). - if (OwnedTag && OwnedTag->isDefinition()) + if (OwnedTag && OwnedTag->isDefinition() && + D.getContext() != Declarator::AliasDeclContext) Diag(OwnedTag->getLocation(), diag::err_type_defined_in_type_specifier) << Context.getTypeDeclType(OwnedTag); } @@ -2547,7 +2757,14 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, return true; } - type = S.Context.getObjCGCQualType(type, GCAttr); + QualType origType = type; + type = S.Context.getObjCGCQualType(origType, GCAttr); + + // Make an attributed type to preserve the source information. + if (attr.getLoc().isValid()) + type = S.Context.getAttributedType(AttributedType::attr_objc_gc, + origType, type); + return true; } @@ -2775,7 +2992,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, } // Also diagnose fastcall with regparm. - if (fn->getRegParmType()) { + if (fn->getHasRegParm()) { S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) << "regparm" << FunctionType::getNameForCallConv(CC); @@ -2789,6 +3006,41 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } +/// Handle OpenCL image access qualifiers: read_only, write_only, read_write +static void HandleOpenCLImageAccessAttribute(QualType& CurType, + const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return; + } + Expr *sizeExpr = static_cast(Attr.getArg(0)); + llvm::APSInt arg(32); + if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || + !sizeExpr->isIntegerConstantExpr(arg, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "opencl_image_access" << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + unsigned iarg = static_cast(arg.getZExtValue()); + switch (iarg) { + case CLIA_read_only: + case CLIA_write_only: + case CLIA_read_write: + // Implemented in a separate patch + break; + default: + // Implemented in a separate patch + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) + << sizeExpr->getSourceRange(); + Attr.setInvalid(); + break; + } +} + /// HandleVectorSizeAttribute - this attribute is only applicable to integral /// and float scalars, although arrays, pointers, and function return values are /// allowed in conjunction with this construct. Aggregates with this attribute @@ -2943,6 +3195,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, "neon_polyvector_type"); break; + case AttributeList::AT_opencl_image_access: + HandleOpenCLImageAccessAttribute(type, attr, state.getSema()); + break; + FUNCTION_TYPE_ATTRS_CASELIST: // Never process function type attributes as part of the // declaration-specifiers. @@ -3088,7 +3344,7 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword, } QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) { - ExprResult ER = CheckPlaceholderExpr(E, Loc); + ExprResult ER = CheckPlaceholderExpr(E); if (ER.isInvalid()) return QualType(); E = ER.take(); @@ -3101,7 +3357,7 @@ QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) { } QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) { - ExprResult ER = CheckPlaceholderExpr(E, Loc); + ExprResult ER = CheckPlaceholderExpr(E); if (ER.isInvalid()) return QualType(); E = ER.take(); diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp index c3415cb847ab..ab697eeed53b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp @@ -136,7 +136,7 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D, if (VD && VD->getType()->isFunctionPointerType()) return; // Also don't warn on function pointer typedefs. - TypedefDecl *TD = dyn_cast(D); + TypedefNameDecl *TD = dyn_cast(D); if (TD && (TD->getUnderlyingType()->isFunctionPointerType() || TD->getUnderlyingType()->isFunctionType())) return; diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index 57a44ad9d984..2a71e14265a8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -67,7 +67,7 @@ using namespace sema; /// /// Subclasses can customize the transformation at various levels. The /// most coarse-grained transformations involve replacing TransformType(), -/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifier(), +/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifierLoc(), /// TransformTemplateName(), or TransformTemplateArgument() with entirely /// new implementations. /// @@ -375,16 +375,6 @@ class TreeTransform { return cast_or_null(getDerived().TransformDecl(Loc, D)); } - /// \brief Transform the given nested-name-specifier. - /// - /// By default, transforms all of the types and declarations within the - /// nested-name-specifier. Subclasses may override this function to provide - /// alternate behavior. - NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS, - SourceRange Range, - QualType ObjectType = QualType(), - NamedDecl *FirstQualifierInScope = 0); - /// \brief Transform the given nested-name-specifier with source-location /// information. /// @@ -407,10 +397,27 @@ class TreeTransform { /// \brief Transform the given template name. /// + /// \param SS The nested-name-specifier that qualifies the template + /// name. This nested-name-specifier must already have been transformed. + /// + /// \param Name The template name to transform. + /// + /// \param NameLoc The source location of the template name. + /// + /// \param ObjectType If we're translating a template name within a member + /// access expression, this is the type of the object whose member template + /// is being referenced. + /// + /// \param FirstQualifierInScope If the first part of a nested-name-specifier + /// also refers to a name within the current (lexical) scope, this is the + /// declaration it refers to. + /// /// By default, transforms the template name by transforming the declarations /// and nested-name-specifiers that occur within the template name. /// Subclasses may override this function to provide alternate behavior. - TemplateName TransformTemplateName(TemplateName Name, + TemplateName TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, QualType ObjectType = QualType(), NamedDecl *FirstQualifierInScope = 0); @@ -483,6 +490,9 @@ class TreeTransform { QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T); #include "clang/AST/TypeLocNodes.def" + StmtResult + TransformSEHHandler(Stmt *Handler); + QualType TransformTemplateSpecializationType(TypeLocBuilder &TLB, TemplateSpecializationTypeLoc TL, @@ -491,7 +501,13 @@ class TreeTransform { QualType TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL, - NestedNameSpecifier *Prefix); + TemplateName Template, + CXXScopeSpec &SS); + + QualType + TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + NestedNameSpecifierLoc QualifierLoc); /// \brief Transforms the parameters of a function type into the /// given vectors. @@ -508,7 +524,11 @@ class TreeTransform { /// \brief Transforms a single function-type parameter. Return null /// on error. + /// + /// \param indexAdjustment - A number to add to the parameter's + /// scope index; can be negative ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, llvm::Optional NumExpansions); QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); @@ -656,7 +676,7 @@ class TreeTransform { QualType RebuildUnresolvedUsingType(Decl *D); /// \brief Build a new typedef type. - QualType RebuildTypedefType(TypedefDecl *Typedef) { + QualType RebuildTypedefType(TypedefNameDecl *Typedef) { return SemaRef.Context.getTypeDeclType(Typedef); } @@ -701,7 +721,7 @@ class TreeTransform { /// different behavior. QualType RebuildTemplateSpecializationType(TemplateName Template, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &Args); + TemplateArgumentListInfo &Args); /// \brief Build a new parenthesized type. /// @@ -718,8 +738,11 @@ class TreeTransform { /// Subclasses may override this routine to provide different behavior. QualType RebuildElaboratedType(SourceLocation KeywordLoc, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType Named) { - return SemaRef.Context.getElaboratedType(Keyword, NNS, Named); + NestedNameSpecifierLoc QualifierLoc, + QualType Named) { + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Named); } /// \brief Build a new typename type that refers to a template-id. @@ -728,34 +751,40 @@ class TreeTransform { /// nested-name-specifier and the given type. Subclasses may override /// this routine to provide different behavior. QualType RebuildDependentTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - const IdentifierInfo *Name, - SourceLocation NameLoc, - const TemplateArgumentListInfo &Args) { + ElaboratedTypeKeyword Keyword, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo *Name, + SourceLocation NameLoc, + TemplateArgumentListInfo &Args) { // Rebuild the template name. // TODO: avoid TemplateName abstraction - TemplateName InstName = - getDerived().RebuildTemplateName(Qualifier, QualifierRange, *Name, - QualType(), 0); + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + TemplateName InstName + = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(), 0); if (InstName.isNull()) return QualType(); - + // If it's still dependent, make a dependent specialization. if (InstName.getAsDependentTemplateName()) - return SemaRef.Context.getDependentTemplateSpecializationType( - Keyword, Qualifier, Name, Args); - + return SemaRef.Context.getDependentTemplateSpecializationType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Name, + Args); + // Otherwise, make an elaborated type wrapping a non-dependent // specialization. QualType T = - getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); + getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); if (T.isNull()) return QualType(); - - // NOTE: NNS is already recorded in template specialization type T. - return SemaRef.Context.getElaboratedType(Keyword, /*NNS=*/0, T); + + if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == 0) + return T; + + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + T); } /// \brief Build a new typename type that refers to an identifier. @@ -764,23 +793,24 @@ class TreeTransform { /// (or elaborated type). Subclasses may override this routine to provide /// different behavior. QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Id, SourceLocation KeywordLoc, - SourceRange NNSRange, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo *Id, SourceLocation IdLoc) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, NNS, NNSRange); + SS.Adopt(QualifierLoc); - if (NNS->isDependent()) { + if (QualifierLoc.getNestedNameSpecifier()->isDependent()) { // If the name is still dependent, just build a new dependent name type. if (!SemaRef.computeDeclContext(SS)) - return SemaRef.Context.getDependentNameType(Keyword, NNS, Id); + return SemaRef.Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Id); } if (Keyword == ETK_None || Keyword == ETK_Typename) - return SemaRef.CheckTypenameType(Keyword, NNS, *Id, - KeywordLoc, NNSRange, IdLoc); + return SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, + *Id, IdLoc); TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); @@ -828,7 +858,8 @@ class TreeTransform { NamedDecl *SomeDecl = Result.getRepresentativeDecl(); unsigned Kind = 0; if (isa(SomeDecl)) Kind = 1; - else if (isa(SomeDecl)) Kind = 2; + else if (isa(SomeDecl)) Kind = 2; + else if (isa(SomeDecl)) Kind = 3; SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << Kind; SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at); break; @@ -850,7 +881,9 @@ class TreeTransform { // Build the elaborated-type-specifier type. QualType T = SemaRef.Context.getTypeDeclType(Tag); - return SemaRef.Context.getElaboratedType(Keyword, NNS, T); + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + T); } /// \brief Build a new pack expansion type. @@ -865,56 +898,13 @@ class TreeTransform { NumExpansions); } - /// \brief Build a new nested-name-specifier given the prefix and an - /// identifier that names the next step in the nested-name-specifier. - /// - /// By default, performs semantic analysis when building the new - /// nested-name-specifier. Subclasses may override this routine to provide - /// different behavior. - NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - IdentifierInfo &II, - QualType ObjectType, - NamedDecl *FirstQualifierInScope); - - /// \brief Build a new nested-name-specifier given the prefix and the - /// namespace named in the next step in the nested-name-specifier. - /// - /// By default, performs semantic analysis when building the new - /// nested-name-specifier. Subclasses may override this routine to provide - /// different behavior. - NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - NamespaceDecl *NS); - - /// \brief Build a new nested-name-specifier given the prefix and the - /// namespace alias named in the next step in the nested-name-specifier. - /// - /// By default, performs semantic analysis when building the new - /// nested-name-specifier. Subclasses may override this routine to provide - /// different behavior. - NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - NamespaceAliasDecl *Alias); - - /// \brief Build a new nested-name-specifier given the prefix and the - /// type named in the next step in the nested-name-specifier. - /// - /// By default, performs semantic analysis when building the new - /// nested-name-specifier. Subclasses may override this routine to provide - /// different behavior. - NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - bool TemplateKW, - QualType T); - /// \brief Build a new template name given a nested name specifier, a flag /// indicating whether the "template" keyword was provided, and the template /// that the template name refers to. /// /// By default, builds the new template name directly. Subclasses may override /// this routine to provide different behavior. - TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, + TemplateName RebuildTemplateName(CXXScopeSpec &SS, bool TemplateKW, TemplateDecl *Template); @@ -925,9 +915,9 @@ class TreeTransform { /// be resolved to a specific template, then builds the appropriate kind of /// template name. Subclasses may override this routine to provide different /// behavior. - TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - const IdentifierInfo &II, + TemplateName RebuildTemplateName(CXXScopeSpec &SS, + const IdentifierInfo &Name, + SourceLocation NameLoc, QualType ObjectType, NamedDecl *FirstQualifierInScope); @@ -938,8 +928,9 @@ class TreeTransform { /// be resolved to a specific template, then builds the appropriate kind of /// template name. Subclasses may override this routine to provide different /// behavior. - TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, + TemplateName RebuildTemplateName(CXXScopeSpec &SS, OverloadedOperatorKind Operator, + SourceLocation NameLoc, QualType ObjectType); /// \brief Build a new template name given a template template parameter pack @@ -1147,9 +1138,10 @@ class TreeTransform { /// Subclasses may override this routine to provide different behavior. VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *TInfo, QualType T) { - return getSema().BuildObjCExceptionDecl(TInfo, T, - ExceptionDecl->getIdentifier(), - ExceptionDecl->getLocation()); + return getSema().BuildObjCExceptionDecl(TInfo, T, + ExceptionDecl->getInnerLocStart(), + ExceptionDecl->getLocation(), + ExceptionDecl->getIdentifier()); } /// \brief Build a new Objective-C @catch statement. @@ -1214,11 +1206,16 @@ class TreeTransform { /// /// By default, performs semantic analysis to build the new decaration. /// Subclasses may override this routine to provide different behavior. - VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, + VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *Declarator, - IdentifierInfo *Name, - SourceLocation Loc) { - return getSema().BuildExceptionDeclaration(0, Declarator, Name, Loc); + SourceLocation StartLoc, + SourceLocation IdLoc, + IdentifierInfo *Id) { + VarDecl *Var = getSema().BuildExceptionDeclaration(0, Declarator, + StartLoc, IdLoc, Id); + if (Var) + getSema().CurContext->addDecl(Var); + return Var; } /// \brief Build a new C++ catch statement. @@ -1242,6 +1239,46 @@ class TreeTransform { return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, move(Handlers)); } + /// \brief Build a new C++0x range-based for statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc, + SourceLocation ColonLoc, + Stmt *Range, Stmt *BeginEnd, + Expr *Cond, Expr *Inc, + Stmt *LoopVar, + SourceLocation RParenLoc) { + return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd, + Cond, Inc, LoopVar, RParenLoc); + } + + /// \brief Attach body to a C++0x range-based for statement. + /// + /// By default, performs semantic analysis to finish the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body) { + return getSema().FinishCXXForRangeStmt(ForRange, Body); + } + + StmtResult RebuildSEHTryStmt(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + return getSema().ActOnSEHTryBlock(IsCXXTry,TryLoc,TryBlock,Handler); + } + + StmtResult RebuildSEHExceptStmt(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + return getSema().ActOnSEHExceptBlock(Loc,FilterExpr,Block); + } + + StmtResult RebuildSEHFinallyStmt(SourceLocation Loc, + Stmt *Block) { + return getSema().ActOnSEHFinallyBlock(Loc,Block); + } + /// \brief Build a new expression that references a declaration. /// /// By default, performs semantic analysis to build the new expression. @@ -1257,13 +1294,12 @@ class TreeTransform { /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + ExprResult RebuildDeclRefExpr(NestedNameSpecifierLoc QualifierLoc, ValueDecl *VD, const DeclarationNameInfo &NameInfo, TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); + SS.Adopt(QualifierLoc); // FIXME: loses template args. @@ -1315,25 +1351,28 @@ class TreeTransform { NumComponents, RParenLoc); } - /// \brief Build a new sizeof or alignof expression with a type argument. + /// \brief Build a new sizeof, alignof or vec_step expression with a + /// type argument. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildSizeOfAlignOf(TypeSourceInfo *TInfo, - SourceLocation OpLoc, - bool isSizeOf, SourceRange R) { - return getSema().CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeOf, R); + ExprResult RebuildUnaryExprOrTypeTrait(TypeSourceInfo *TInfo, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { + return getSema().CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, R); } - /// \brief Build a new sizeof or alignof expression with an expression - /// argument. + /// \brief Build a new sizeof, alignof or vec step expression with an + /// expression argument. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildSizeOfAlignOf(Expr *SubExpr, SourceLocation OpLoc, - bool isSizeOf, SourceRange R) { + ExprResult RebuildUnaryExprOrTypeTrait(Expr *SubExpr, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { ExprResult Result - = getSema().CreateSizeOfAlignOfExpr(SubExpr, OpLoc, isSizeOf, R); + = getSema().CreateUnaryExprOrTypeTraitExpr(SubExpr, OpLoc, ExprKind, R); if (Result.isInvalid()) return ExprError(); @@ -1371,8 +1410,7 @@ class TreeTransform { /// Subclasses may override this routine to provide different behavior. ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc, bool isArrow, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, ValueDecl *Member, NamedDecl *FoundDecl, @@ -1382,14 +1420,17 @@ class TreeTransform { // We have a reference to an unnamed field. This is always the // base of an anonymous struct/union member access, i.e. the // field is always of record type. - assert(!Qualifier && "Can't have an unnamed field with a qualifier!"); + assert(!QualifierLoc && "Can't have an unnamed field with a qualifier!"); assert(Member->getType()->isRecordType() && "unnamed member not of record type?"); - if (getSema().PerformObjectMemberConversion(Base, Qualifier, - FoundDecl, Member)) + ExprResult BaseResult = + getSema().PerformObjectMemberConversion(Base, + QualifierLoc.getNestedNameSpecifier(), + FoundDecl, Member); + if (BaseResult.isInvalid()) return ExprError(); - + Base = BaseResult.take(); ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind(); MemberExpr *ME = new (getSema().Context) MemberExpr(Base, isArrow, @@ -1400,11 +1441,12 @@ class TreeTransform { } CXXScopeSpec SS; - if (Qualifier) { - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); - } + SS.Adopt(QualifierLoc); - getSema().DefaultFunctionArrayConversion(Base); + ExprResult BaseResult = getSema().DefaultFunctionArrayConversion(Base); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); QualType BaseType = Base->getType(); // FIXME: this involves duplicating earlier analysis in a lot of @@ -1586,6 +1628,22 @@ class TreeTransform { RParenLoc); } + /// \brief Build a new generic selection expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + TypeSourceInfo **Types, + Expr **Exprs, + unsigned NumAssocs) { + return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + ControllingExpr, Types, Exprs, + NumAssocs); + } + /// \brief Build a new overloaded operator call expression. /// /// By default, performs semantic analysis to build the new expression. @@ -1882,6 +1940,29 @@ class TreeTransform { return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc); } + /// \brief Build a new array type trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildArrayTypeTrait(ArrayTypeTrait Trait, + SourceLocation StartLoc, + TypeSourceInfo *TSInfo, + Expr *DimExpr, + SourceLocation RParenLoc) { + return getSema().BuildArrayTypeTrait(Trait, StartLoc, TSInfo, DimExpr, RParenLoc); + } + + /// \brief Build a new expression trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildExpressionTrait(ExpressionTrait Trait, + SourceLocation StartLoc, + Expr *Queried, + SourceLocation RParenLoc) { + return getSema().BuildExpressionTrait(Trait, StartLoc, Queried, RParenLoc); + } + /// \brief Build a new (previously unresolved) declaration reference /// expression. /// @@ -1968,16 +2049,15 @@ class TreeTransform { /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXDependentScopeMemberExpr(Expr *BaseE, - QualType BaseType, - bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + QualType BaseType, + bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); + SS.Adopt(QualifierLoc); return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc, IsArrow, @@ -1994,13 +2074,12 @@ class TreeTransform { QualType BaseType, SourceLocation OperatorLoc, bool IsArrow, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierInScope, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); + SS.Adopt(QualifierLoc); return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc, IsArrow, @@ -2076,20 +2155,20 @@ class TreeTransform { bool IsArrow, bool IsFreeIvar) { // FIXME: We lose track of the IsFreeIvar bit. CXXScopeSpec SS; - Expr *Base = BaseArg; + ExprResult Base = getSema().Owned(BaseArg); LookupResult R(getSema(), Ivar->getDeclName(), IvarLoc, Sema::LookupMemberName); ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, /*FIME:*/IvarLoc, SS, 0, false); - if (Result.isInvalid()) + if (Result.isInvalid() || Base.isInvalid()) return ExprError(); if (Result.get()) return move(Result); - return getSema().BuildMemberReferenceExpr(Base, Base->getType(), + return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/IvarLoc, IsArrow, SS, /*FirstQualifierInScope=*/0, R, @@ -2104,20 +2183,20 @@ class TreeTransform { ObjCPropertyDecl *Property, SourceLocation PropertyLoc) { CXXScopeSpec SS; - Expr *Base = BaseArg; + ExprResult Base = getSema().Owned(BaseArg); LookupResult R(getSema(), Property->getDeclName(), PropertyLoc, Sema::LookupMemberName); bool IsArrow = false; ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, /*FIME:*/PropertyLoc, SS, 0, false); - if (Result.isInvalid()) + if (Result.isInvalid() || Base.isInvalid()) return ExprError(); if (Result.get()) return move(Result); - return getSema().BuildMemberReferenceExpr(Base, Base->getType(), + return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/PropertyLoc, IsArrow, SS, /*FirstQualifierInScope=*/0, @@ -2148,19 +2227,19 @@ class TreeTransform { ExprResult RebuildObjCIsaExpr(Expr *BaseArg, SourceLocation IsaLoc, bool IsArrow) { CXXScopeSpec SS; - Expr *Base = BaseArg; + ExprResult Base = getSema().Owned(BaseArg); LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc, Sema::LookupMemberName); ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, /*FIME:*/IsaLoc, SS, 0, false); - if (Result.isInvalid()) + if (Result.isInvalid() || Base.isInvalid()) return ExprError(); if (Result.get()) return move(Result); - return getSema().BuildMemberReferenceExpr(Base, Base->getType(), + return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/IsaLoc, IsArrow, SS, /*FirstQualifierInScope=*/0, R, @@ -2183,28 +2262,25 @@ class TreeTransform { // Build a reference to the __builtin_shufflevector builtin FunctionDecl *Builtin = cast(*Lookup.first); - Expr *Callee - = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(), - VK_LValue, BuiltinLoc); - SemaRef.UsualUnaryConversions(Callee); + ExprResult Callee + = SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(), + VK_LValue, BuiltinLoc)); + Callee = SemaRef.UsualUnaryConversions(Callee.take()); + if (Callee.isInvalid()) + return ExprError(); // Build the CallExpr unsigned NumSubExprs = SubExprs.size(); Expr **Subs = (Expr **)SubExprs.release(); - CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, + ExprResult TheCall = SemaRef.Owned( + new (SemaRef.Context) CallExpr(SemaRef.Context, Callee.take(), Subs, NumSubExprs, Builtin->getCallResultType(), Expr::getValueKindForType(Builtin->getResultType()), - RParenLoc); - ExprResult OwnedCall(SemaRef.Owned(TheCall)); + RParenLoc)); // Type-check the __builtin_shufflevector expression. - ExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall); - if (Result.isInvalid()) - return ExprError(); - - OwnedCall.release(); - return move(Result); + return SemaRef.SemaBuiltinShuffleVector(cast(TheCall.take())); } /// \brief Build a new template argument pack expansion. @@ -2230,7 +2306,7 @@ class TreeTransform { return TemplateArgumentLoc(TemplateArgument( Pattern.getArgument().getAsTemplate(), NumExpansions), - Pattern.getTemplateQualifierRange(), + Pattern.getTemplateQualifierLoc(), Pattern.getTemplateNameLoc(), EllipsisLoc); @@ -2265,20 +2341,15 @@ class TreeTransform { } private: - QualType TransformTypeInObjectScope(QualType T, - QualType ObjectType, - NamedDecl *FirstQualifierInScope, - NestedNameSpecifier *Prefix); - - TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *T, - QualType ObjectType, - NamedDecl *FirstQualifierInScope, - NestedNameSpecifier *Prefix); - TypeLoc TransformTypeInObjectScope(TypeLoc TL, QualType ObjectType, NamedDecl *FirstQualifierInScope, CXXScopeSpec &SS); + + TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *TSInfo, + QualType ObjectType, + NamedDecl *FirstQualifierInScope, + CXXScopeSpec &SS); }; template @@ -2425,99 +2496,6 @@ bool TreeTransform::TransformExprs(Expr **Inputs, return false; } -template -NestedNameSpecifier * -TreeTransform::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, - SourceRange Range, - QualType ObjectType, - NamedDecl *FirstQualifierInScope) { - NestedNameSpecifier *Prefix = NNS->getPrefix(); - - // Transform the prefix of this nested name specifier. - if (Prefix) { - Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range, - ObjectType, - FirstQualifierInScope); - if (!Prefix) - return 0; - } - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - if (Prefix) { - // The object type and qualifier-in-scope really apply to the - // leftmost entity. - ObjectType = QualType(); - FirstQualifierInScope = 0; - } - - assert((Prefix || !ObjectType.isNull()) && - "Identifier nested-name-specifier with no prefix or object type"); - if (!getDerived().AlwaysRebuild() && Prefix == NNS->getPrefix() && - ObjectType.isNull()) - return NNS; - - return getDerived().RebuildNestedNameSpecifier(Prefix, Range, - *NNS->getAsIdentifier(), - ObjectType, - FirstQualifierInScope); - - case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS - = cast_or_null( - getDerived().TransformDecl(Range.getBegin(), - NNS->getAsNamespace())); - if (!getDerived().AlwaysRebuild() && - Prefix == NNS->getPrefix() && - NS == NNS->getAsNamespace()) - return NNS; - - return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS); - } - - case NestedNameSpecifier::NamespaceAlias: { - NamespaceAliasDecl *Alias - = cast_or_null( - getDerived().TransformDecl(Range.getBegin(), - NNS->getAsNamespaceAlias())); - if (!getDerived().AlwaysRebuild() && - Prefix == NNS->getPrefix() && - Alias == NNS->getAsNamespaceAlias()) - return NNS; - - return getDerived().RebuildNestedNameSpecifier(Prefix, Range, Alias); - } - - case NestedNameSpecifier::Global: - // There is no meaningful transformation that one could perform on the - // global scope. - return NNS; - - case NestedNameSpecifier::TypeSpecWithTemplate: - case NestedNameSpecifier::TypeSpec: { - TemporaryBase Rebase(*this, Range.getBegin(), DeclarationName()); - QualType T = TransformTypeInObjectScope(QualType(NNS->getAsType(), 0), - ObjectType, - FirstQualifierInScope, - Prefix); - if (T.isNull()) - return 0; - - if (!getDerived().AlwaysRebuild() && - Prefix == NNS->getPrefix() && - T == QualType(NNS->getAsType(), 0)) - return NNS; - - return getDerived().RebuildNestedNameSpecifier(Prefix, Range, - NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate, - T); - } - } - - // Required to silence a GCC warning - return 0; -} - template NestedNameSpecifierLoc TreeTransform::TransformNestedNameSpecifierLoc( @@ -2594,10 +2572,11 @@ TreeTransform::TransformNestedNameSpecifierLoc( << TL.getType() << SS.getRange(); return NestedNameSpecifierLoc(); } - } + } - // The qualifier-in-scope only applies to the leftmost entity. + // The qualifier-in-scope and object type only apply to the leftmost entity. FirstQualifierInScope = 0; + ObjectType = QualType(); } // Don't rebuild the nested-name-specifier if we don't have to. @@ -2669,89 +2648,73 @@ ::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) { template TemplateName -TreeTransform::TransformTemplateName(TemplateName Name, +TreeTransform::TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, QualType ObjectType, NamedDecl *FirstQualifierInScope) { - SourceLocation Loc = getDerived().getBaseLocation(); - if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { - NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(), - /*FIXME*/ SourceRange(Loc), - ObjectType, - FirstQualifierInScope); - if (!NNS) + TemplateDecl *Template = QTN->getTemplateDecl(); + assert(Template && "qualified template name must refer to a template"); + + TemplateDecl *TransTemplate + = cast_or_null(getDerived().TransformDecl(NameLoc, + Template)); + if (!TransTemplate) return TemplateName(); - - if (TemplateDecl *Template = QTN->getTemplateDecl()) { - TemplateDecl *TransTemplate - = cast_or_null(getDerived().TransformDecl(Loc, Template)); - if (!TransTemplate) - return TemplateName(); - - if (!getDerived().AlwaysRebuild() && - NNS == QTN->getQualifier() && - TransTemplate == Template) - return Name; - - return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(), - TransTemplate); - } - - // These should be getting filtered out before they make it into the AST. - llvm_unreachable("overloaded template name survived to here"); + + if (!getDerived().AlwaysRebuild() && + SS.getScopeRep() == QTN->getQualifier() && + TransTemplate == Template) + return Name; + + return getDerived().RebuildTemplateName(SS, QTN->hasTemplateKeyword(), + TransTemplate); } - + if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) { - NestedNameSpecifier *NNS = DTN->getQualifier(); - if (NNS) { - NNS = getDerived().TransformNestedNameSpecifier(NNS, - /*FIXME:*/SourceRange(Loc), - ObjectType, - FirstQualifierInScope); - if (!NNS) return TemplateName(); - + if (SS.getScopeRep()) { // These apply to the scope specifier, not the template. ObjectType = QualType(); FirstQualifierInScope = 0; - } - + } + if (!getDerived().AlwaysRebuild() && - NNS == DTN->getQualifier() && + SS.getScopeRep() == DTN->getQualifier() && ObjectType.isNull()) return Name; - + if (DTN->isIdentifier()) { - // FIXME: Bad range - SourceRange QualifierRange(getDerived().getBaseLocation()); - return getDerived().RebuildTemplateName(NNS, QualifierRange, + return getDerived().RebuildTemplateName(SS, *DTN->getIdentifier(), + NameLoc, ObjectType, FirstQualifierInScope); } - return getDerived().RebuildTemplateName(NNS, DTN->getOperator(), + return getDerived().RebuildTemplateName(SS, DTN->getOperator(), NameLoc, ObjectType); } - + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { TemplateDecl *TransTemplate - = cast_or_null(getDerived().TransformDecl(Loc, Template)); + = cast_or_null(getDerived().TransformDecl(NameLoc, + Template)); if (!TransTemplate) return TemplateName(); - + if (!getDerived().AlwaysRebuild() && TransTemplate == Template) return Name; - + return TemplateName(TransTemplate); } - + if (SubstTemplateTemplateParmPackStorage *SubstPack - = Name.getAsSubstTemplateTemplateParmPack()) { + = Name.getAsSubstTemplateTemplateParmPack()) { TemplateTemplateParmDecl *TransParam - = cast_or_null( - getDerived().TransformDecl(Loc, SubstPack->getParameterPack())); + = cast_or_null( + getDerived().TransformDecl(NameLoc, SubstPack->getParameterPack())); if (!TransParam) return TemplateName(); @@ -2785,12 +2748,25 @@ void TreeTransform::InventTemplateArgumentLoc( break; case TemplateArgument::Template: - Output = TemplateArgumentLoc(Arg, SourceRange(), Loc); - break; - - case TemplateArgument::TemplateExpansion: - Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc); + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Arg.getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(SemaRef.Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(SemaRef.Context, QTN->getQualifier(), Loc); + + if (Arg.getKind() == TemplateArgument::Template) + Output = TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(SemaRef.Context), + Loc); + else + Output = TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(SemaRef.Context), + Loc, Loc); + break; + } case TemplateArgument::Expression: Output = TemplateArgumentLoc(Arg, Arg.getAsExpr()); @@ -2849,14 +2825,22 @@ bool TreeTransform::TransformTemplateArgument( } case TemplateArgument::Template: { - TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName()); + NestedNameSpecifierLoc QualifierLoc = Input.getTemplateQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return true; + } + + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); TemplateName Template - = getDerived().TransformTemplateName(Arg.getAsTemplate()); + = getDerived().TransformTemplateName(SS, Arg.getAsTemplate(), + Input.getTemplateNameLoc()); if (Template.isNull()) return true; - Output = TemplateArgumentLoc(TemplateArgument(Template), - Input.getTemplateQualifierRange(), + Output = TemplateArgumentLoc(TemplateArgument(Template), QualifierLoc, Input.getTemplateNameLoc()); return false; } @@ -2872,8 +2856,7 @@ bool TreeTransform::TransformTemplateArgument( Expr *InputExpr = Input.getSourceExpression(); if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); - ExprResult E - = getDerived().TransformExpr(InputExpr); + ExprResult E = getDerived().TransformExpr(InputExpr); if (E.isInvalid()) return true; Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take()); return false; @@ -3177,96 +3160,12 @@ TreeTransform::TransformQualifiedType(TypeLocBuilder &TLB, return Result; } -/// \brief Transforms a type that was written in a scope specifier, -/// given an object type, the results of unqualified lookup, and -/// an already-instantiated prefix. -/// -/// The object type is provided iff the scope specifier qualifies the -/// member of a dependent member-access expression. The prefix is -/// provided iff the the scope specifier in which this appears has a -/// prefix. -/// -/// This is private to TreeTransform. -template -QualType -TreeTransform::TransformTypeInObjectScope(QualType T, - QualType ObjectType, - NamedDecl *UnqualLookup, - NestedNameSpecifier *Prefix) { - if (getDerived().AlreadyTransformed(T)) - return T; - - TypeSourceInfo *TSI = - SemaRef.Context.getTrivialTypeSourceInfo(T, getDerived().getBaseLocation()); - - TSI = getDerived().TransformTypeInObjectScope(TSI, ObjectType, - UnqualLookup, Prefix); - if (!TSI) return QualType(); - return TSI->getType(); -} - -template -TypeSourceInfo * -TreeTransform::TransformTypeInObjectScope(TypeSourceInfo *TSI, - QualType ObjectType, - NamedDecl *UnqualLookup, - NestedNameSpecifier *Prefix) { - // TODO: in some cases, we might have some verification to do here. - if (ObjectType.isNull()) - return getDerived().TransformType(TSI); - - QualType T = TSI->getType(); - if (getDerived().AlreadyTransformed(T)) - return TSI; - - TypeLocBuilder TLB; - QualType Result; - - if (isa(T)) { - TemplateSpecializationTypeLoc TL - = cast(TSI->getTypeLoc()); - - TemplateName Template = - getDerived().TransformTemplateName(TL.getTypePtr()->getTemplateName(), - ObjectType, UnqualLookup); - if (Template.isNull()) return 0; - - Result = getDerived() - .TransformTemplateSpecializationType(TLB, TL, Template); - } else if (isa(T)) { - DependentTemplateSpecializationTypeLoc TL - = cast(TSI->getTypeLoc()); - - Result = getDerived() - .TransformDependentTemplateSpecializationType(TLB, TL, Prefix); - } else { - // Nothing special needs to be done for these. - Result = getDerived().TransformType(TLB, TSI->getTypeLoc()); - } - - if (Result.isNull()) return 0; - return TLB.getTypeSourceInfo(SemaRef.Context, Result); -} - template TypeLoc TreeTransform::TransformTypeInObjectScope(TypeLoc TL, QualType ObjectType, NamedDecl *UnqualLookup, CXXScopeSpec &SS) { - // FIXME: Painfully copy-paste from the above! - - // TODO: in some cases, we might have some verification to do here. - if (ObjectType.isNull()) { - TypeLocBuilder TLB; - TLB.reserve(TL.getFullDataSize()); - QualType Result = getDerived().TransformType(TLB, TL); - if (Result.isNull()) - return TypeLoc(); - - return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc(); - } - QualType T = TL.getType(); if (getDerived().AlreadyTransformed(T)) return TL; @@ -3279,7 +3178,9 @@ TreeTransform::TransformTypeInObjectScope(TypeLoc TL, = cast(TL); TemplateName Template = - getDerived().TransformTemplateName(SpecTL.getTypePtr()->getTemplateName(), + getDerived().TransformTemplateName(SS, + SpecTL.getTypePtr()->getTemplateName(), + SpecTL.getTemplateNameLoc(), ObjectType, UnqualLookup); if (Template.isNull()) return TypeLoc(); @@ -3290,9 +3191,18 @@ TreeTransform::TransformTypeInObjectScope(TypeLoc TL, DependentTemplateSpecializationTypeLoc SpecTL = cast(TL); + TemplateName Template + = getDerived().RebuildTemplateName(SS, + *SpecTL.getTypePtr()->getIdentifier(), + SpecTL.getNameLoc(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return TypeLoc(); + Result = getDerived().TransformDependentTemplateSpecializationType(TLB, - SpecTL, - SS.getScopeRep()); + SpecTL, + Template, + SS); } else { // Nothing special needs to be done for these. Result = getDerived().TransformType(TLB, TL); @@ -3304,6 +3214,63 @@ TreeTransform::TransformTypeInObjectScope(TypeLoc TL, return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc(); } +template +TypeSourceInfo * +TreeTransform::TransformTypeInObjectScope(TypeSourceInfo *TSInfo, + QualType ObjectType, + NamedDecl *UnqualLookup, + CXXScopeSpec &SS) { + // FIXME: Painfully copy-paste from the above! + + QualType T = TSInfo->getType(); + if (getDerived().AlreadyTransformed(T)) + return TSInfo; + + TypeLocBuilder TLB; + QualType Result; + + TypeLoc TL = TSInfo->getTypeLoc(); + if (isa(T)) { + TemplateSpecializationTypeLoc SpecTL + = cast(TL); + + TemplateName Template + = getDerived().TransformTemplateName(SS, + SpecTL.getTypePtr()->getTemplateName(), + SpecTL.getTemplateNameLoc(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return 0; + + Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, + Template); + } else if (isa(T)) { + DependentTemplateSpecializationTypeLoc SpecTL + = cast(TL); + + TemplateName Template + = getDerived().RebuildTemplateName(SS, + *SpecTL.getTypePtr()->getIdentifier(), + SpecTL.getNameLoc(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return 0; + + Result = getDerived().TransformDependentTemplateSpecializationType(TLB, + SpecTL, + Template, + SS); + } else { + // Nothing special needs to be done for these. + Result = getDerived().TransformType(TLB, TL); + } + + if (Result.isNull()) + return 0; + + return TLB.getTypeSourceInfo(SemaRef.Context, Result); +} + template static inline QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) { TyLoc NewT = TLB.push(T.getType()); @@ -3438,23 +3405,34 @@ template QualType TreeTransform::TransformMemberPointerType(TypeLocBuilder &TLB, MemberPointerTypeLoc TL) { - const MemberPointerType *T = TL.getTypePtr(); - QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc()); if (PointeeType.isNull()) return QualType(); - // TODO: preserve source information for this. - QualType ClassType - = getDerived().TransformType(QualType(T->getClass(), 0)); - if (ClassType.isNull()) - return QualType(); + TypeSourceInfo* OldClsTInfo = TL.getClassTInfo(); + TypeSourceInfo* NewClsTInfo = 0; + if (OldClsTInfo) { + NewClsTInfo = getDerived().TransformType(OldClsTInfo); + if (!NewClsTInfo) + return QualType(); + } + + const MemberPointerType *T = TL.getTypePtr(); + QualType OldClsType = QualType(T->getClass(), 0); + QualType NewClsType; + if (NewClsTInfo) + NewClsType = NewClsTInfo->getType(); + else { + NewClsType = getDerived().TransformType(OldClsType); + if (NewClsType.isNull()) + return QualType(); + } QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeType() || - ClassType != QualType(T->getClass(), 0)) { - Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType, + NewClsType != OldClsType) { + Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType, TL.getStarLoc()); if (Result.isNull()) return QualType(); @@ -3462,6 +3440,7 @@ TreeTransform::TransformMemberPointerType(TypeLocBuilder &TLB, MemberPointerTypeLoc NewTL = TLB.push(Result); NewTL.setSigilLoc(TL.getSigilLoc()); + NewTL.setClassTInfo(NewClsTInfo); return Result; } @@ -3707,6 +3686,7 @@ QualType TreeTransform::TransformExtVectorType(TypeLocBuilder &TLB, template ParmVarDecl * TreeTransform::TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, llvm::Optional NumExpansions) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; @@ -3741,18 +3721,22 @@ TreeTransform::TransformFunctionTypeParam(ParmVarDecl *OldParm, if (!NewDI) return 0; - if (NewDI == OldDI) + if (NewDI == OldDI && indexAdjustment == 0) return OldParm; - else - return ParmVarDecl::Create(SemaRef.Context, - OldParm->getDeclContext(), - OldParm->getLocation(), - OldParm->getIdentifier(), - NewDI->getType(), - NewDI, - OldParm->getStorageClass(), - OldParm->getStorageClassAsWritten(), - /* DefArg */ NULL); + + ParmVarDecl *newParm = ParmVarDecl::Create(SemaRef.Context, + OldParm->getDeclContext(), + OldParm->getInnerLocStart(), + OldParm->getLocation(), + OldParm->getIdentifier(), + NewDI->getType(), + NewDI, + OldParm->getStorageClass(), + OldParm->getStorageClassAsWritten(), + /* DefArg */ NULL); + newParm->setScopeInfo(OldParm->getFunctionScopeDepth(), + OldParm->getFunctionScopeIndex() + indexAdjustment); + return newParm; } template @@ -3762,9 +3746,14 @@ bool TreeTransform:: const QualType *ParamTypes, llvm::SmallVectorImpl &OutParamTypes, llvm::SmallVectorImpl *PVars) { + int indexAdjustment = 0; + for (unsigned i = 0; i != NumParams; ++i) { if (ParmVarDecl *OldParm = Params[i]) { + assert(OldParm->getFunctionScopeIndex() == i); + llvm::Optional NumExpansions; + ParmVarDecl *NewParm = 0; if (OldParm->isParameterPack()) { // We have a function parameter pack that may need to be expanded. llvm::SmallVector Unexpanded; @@ -3774,7 +3763,8 @@ bool TreeTransform:: PackExpansionTypeLoc ExpansionTL = cast(TL); TypeLoc Pattern = ExpansionTL.getPatternLoc(); SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); - + assert(Unexpanded.size() > 0 && "Could not find parameter packs!"); + // Determine whether we should expand the parameter packs. bool ShouldExpand = false; bool RetainExpansion = false; @@ -3799,6 +3789,7 @@ bool TreeTransform:: Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment++, OrigNumExpansions); if (!NewParm) return true; @@ -3814,6 +3805,7 @@ bool TreeTransform:: ForgetPartiallySubstitutedPackRAII Forget(getDerived()); ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment++, OrigNumExpansions); if (!NewParm) return true; @@ -3823,17 +3815,28 @@ bool TreeTransform:: PVars->push_back(NewParm); } + // The next parameter should have the same adjustment as the + // last thing we pushed, but we post-incremented indexAdjustment + // on every push. Also, if we push nothing, the adjustment should + // go down by one. + indexAdjustment--; + // We're done with the pack expansion. continue; } // We'll substitute the parameter now without expanding the pack // expansion. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment, + NumExpansions); + } else { + NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment, + llvm::Optional()); } - - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); - ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, - NumExpansions); + if (!NewParm) return true; @@ -3848,6 +3851,7 @@ bool TreeTransform:: QualType OldType = ParamTypes[i]; bool IsPackExpansion = false; llvm::Optional NumExpansions; + QualType NewType; if (const PackExpansionType *Expansion = dyn_cast(OldType)) { // We have a function parameter pack that may need to be expanded. @@ -3902,10 +3906,12 @@ bool TreeTransform:: // expansion. OldType = Expansion->getPattern(); IsPackExpansion = true; + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + NewType = getDerived().TransformType(OldType); + } else { + NewType = getDerived().TransformType(OldType); } - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); - QualType NewType = getDerived().TransformType(OldType); if (NewType.isNull()) return true; @@ -3918,8 +3924,16 @@ bool TreeTransform:: PVars->push_back(0); } - return false; +#ifndef NDEBUG + if (PVars) { + for (unsigned i = 0, e = PVars->size(); i != e; ++i) + if (ParmVarDecl *parm = (*PVars)[i]) + assert(parm->getFunctionScopeIndex() == i); } +#endif + + return false; +} template QualType @@ -3983,8 +3997,8 @@ TreeTransform::TransformFunctionProtoType(TypeLocBuilder &TLB, } FunctionProtoTypeLoc NewTL = TLB.push(Result); - NewTL.setLParenLoc(TL.getLParenLoc()); - NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); + NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); NewTL.setTrailingReturn(TL.getTrailingReturn()); for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i) NewTL.setArg(i, ParamDecls[i]); @@ -4007,8 +4021,8 @@ QualType TreeTransform::TransformFunctionNoProtoType( Result = getDerived().RebuildFunctionNoProtoType(ResultType); FunctionNoProtoTypeLoc NewTL = TLB.push(Result); - NewTL.setLParenLoc(TL.getLParenLoc()); - NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); + NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); NewTL.setTrailingReturn(false); return Result; @@ -4041,9 +4055,9 @@ template QualType TreeTransform::TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { const TypedefType *T = TL.getTypePtr(); - TypedefDecl *Typedef - = cast_or_null(getDerived().TransformDecl(TL.getNameLoc(), - T->getDecl())); + TypedefNameDecl *Typedef + = cast_or_null(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); if (!Typedef) return QualType(); @@ -4236,7 +4250,28 @@ template QualType TreeTransform::TransformSubstTemplateTypeParmType( TypeLocBuilder &TLB, SubstTemplateTypeParmTypeLoc TL) { - return TransformTypeSpecType(TLB, TL); + const SubstTemplateTypeParmType *T = TL.getTypePtr(); + + // Substitute into the replacement type, which itself might involve something + // that needs to be transformed. This only tends to occur with default + // template arguments of template template parameters. + TemporaryBase Rebase(*this, TL.getNameLoc(), DeclarationName()); + QualType Replacement = getDerived().TransformType(T->getReplacementType()); + if (Replacement.isNull()) + return QualType(); + + // Always canonicalize the replacement type. + Replacement = SemaRef.Context.getCanonicalType(Replacement); + QualType Result + = SemaRef.Context.getSubstTemplateTypeParmType(T->getReplacedParameter(), + Replacement); + + // Propagate type-source information. + SubstTemplateTypeParmTypeLoc NewTL + = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } template @@ -4252,8 +4287,12 @@ QualType TreeTransform::TransformTemplateSpecializationType( TemplateSpecializationTypeLoc TL) { const TemplateSpecializationType *T = TL.getTypePtr(); + // The nested-name-specifier never matters in a TemplateSpecializationType, + // because we can't have a dependent nested-name-specifier anyway. + CXXScopeSpec SS; TemplateName Template - = getDerived().TransformTemplateName(T->getTemplateName()); + = getDerived().TransformTemplateName(SS, T->getTemplateName(), + TL.getTemplateNameLoc()); if (Template.isNull()) return QualType(); @@ -4362,18 +4401,76 @@ QualType TreeTransform::TransformTemplateSpecializationType( return Result; } +template +QualType TreeTransform::TransformDependentTemplateSpecializationType( + TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + TemplateName Template, + CXXScopeSpec &SS) { + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + typedef TemplateArgumentLocContainerIterator< + DependentTemplateSpecializationTypeLoc> ArgIterator; + if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), + ArgIterator(TL, TL.getNumArgs()), + NewTemplateArgs)) + return QualType(); + + // FIXME: maybe don't rebuild if all the template arguments are the same. + + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + QualType Result + = getSema().Context.getDependentTemplateSpecializationType( + TL.getTypePtr()->getKeyword(), + DTN->getQualifier(), + DTN->getIdentifier(), + NewTemplateArgs); + + DependentTemplateSpecializationTypeLoc NewTL + = TLB.push(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + + NewTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context)); + NewTL.setNameLoc(TL.getNameLoc()); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) + NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + return Result; + } + + QualType Result + = getDerived().RebuildTemplateSpecializationType(Template, + TL.getNameLoc(), + NewTemplateArgs); + + if (!Result.isNull()) { + /// FIXME: Wrap this in an elaborated-type-specifier? + TemplateSpecializationTypeLoc NewTL + = TLB.push(Result); + NewTL.setTemplateNameLoc(TL.getNameLoc()); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) + NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + } + + return Result; +} + template QualType TreeTransform::TransformElaboratedType(TypeLocBuilder &TLB, ElaboratedTypeLoc TL) { const ElaboratedType *T = TL.getTypePtr(); - NestedNameSpecifier *NNS = 0; + NestedNameSpecifierLoc QualifierLoc; // NOTE: the qualifier in an ElaboratedType is optional. - if (T->getQualifier() != 0) { - NNS = getDerived().TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange()); - if (!NNS) + if (TL.getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) return QualType(); } @@ -4383,18 +4480,18 @@ TreeTransform::TransformElaboratedType(TypeLocBuilder &TLB, QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || - NNS != T->getQualifier() || + QualifierLoc != TL.getQualifierLoc() || NamedT != T->getNamedType()) { Result = getDerived().RebuildElaboratedType(TL.getKeywordLoc(), - T->getKeyword(), NNS, NamedT); + T->getKeyword(), + QualifierLoc, NamedT); if (Result.isNull()) return QualType(); } ElaboratedTypeLoc NewTL = TLB.push(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); - + NewTL.setQualifierLoc(QualifierLoc); return Result; } @@ -4462,17 +4559,16 @@ QualType TreeTransform::TransformDependentNameType(TypeLocBuilder &TLB, DependentNameTypeLoc TL) { const DependentNameType *T = TL.getTypePtr(); - NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange()); - if (!NNS) + NestedNameSpecifierLoc QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) return QualType(); QualType Result - = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - T->getIdentifier(), + = getDerived().RebuildDependentNameType(T->getKeyword(), TL.getKeywordLoc(), - TL.getQualifierRange(), + QualifierLoc, + T->getIdentifier(), TL.getNameLoc()); if (Result.isNull()) return QualType(); @@ -4483,11 +4579,11 @@ QualType TreeTransform::TransformDependentNameType(TypeLocBuilder &TLB, ElaboratedTypeLoc NewTL = TLB.push(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); + NewTL.setQualifierLoc(QualifierLoc); } else { DependentNameTypeLoc NewTL = TLB.push(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); + NewTL.setQualifierLoc(QualifierLoc); NewTL.setNameLoc(TL.getNameLoc()); } return Result; @@ -4497,65 +4593,79 @@ template QualType TreeTransform:: TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL) { - const DependentTemplateSpecializationType *T = TL.getTypePtr(); - - NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange()); - if (!NNS) - return QualType(); - + NestedNameSpecifierLoc QualifierLoc; + if (TL.getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) + return QualType(); + } + return getDerived() - .TransformDependentTemplateSpecializationType(TLB, TL, NNS); + .TransformDependentTemplateSpecializationType(TLB, TL, QualifierLoc); } template QualType TreeTransform:: - TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, - DependentTemplateSpecializationTypeLoc TL, - NestedNameSpecifier *NNS) { +TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + NestedNameSpecifierLoc QualifierLoc) { const DependentTemplateSpecializationType *T = TL.getTypePtr(); - + TemplateArgumentListInfo NewTemplateArgs; NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); - - // FIXME: Nested-name-specifier source location info! + typedef TemplateArgumentLocContainerIterator< - DependentTemplateSpecializationTypeLoc> ArgIterator; + DependentTemplateSpecializationTypeLoc> ArgIterator; if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), ArgIterator(TL, TL.getNumArgs()), NewTemplateArgs)) return QualType(); - + QualType Result = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(), - NNS, - TL.getQualifierRange(), + QualifierLoc, T->getIdentifier(), - TL.getNameLoc(), - NewTemplateArgs); + TL.getNameLoc(), + NewTemplateArgs); if (Result.isNull()) return QualType(); - + if (const ElaboratedType *ElabT = dyn_cast(Result)) { QualType NamedT = ElabT->getNamedType(); - + // Copy information relevant to the template specialization. TemplateSpecializationTypeLoc NamedTL = TLB.push(NamedT); + NamedTL.setTemplateNameLoc(TL.getNameLoc()); NamedTL.setLAngleLoc(TL.getLAngleLoc()); NamedTL.setRAngleLoc(TL.getRAngleLoc()); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - NamedTL.setArgLocInfo(I, TL.getArgLocInfo(I)); - + for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) + NamedTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); + // Copy information relevant to the elaborated type. ElaboratedTypeLoc NewTL = TLB.push(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); + NewTL.setQualifierLoc(QualifierLoc); + } else if (isa(Result)) { + DependentTemplateSpecializationTypeLoc SpecTL + = TLB.push(Result); + SpecTL.setKeywordLoc(TL.getKeywordLoc()); + SpecTL.setQualifierLoc(QualifierLoc); + SpecTL.setNameLoc(TL.getNameLoc()); + SpecTL.setLAngleLoc(TL.getLAngleLoc()); + SpecTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) + SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); } else { - TypeLoc NewTL(Result, TL.getOpaqueData()); - TLB.pushFullCopy(NewTL); + TemplateSpecializationTypeLoc SpecTL + = TLB.push(Result); + SpecTL.setTemplateNameLoc(TL.getNameLoc()); + SpecTL.setLAngleLoc(TL.getLAngleLoc()); + SpecTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) + SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); } return Result; } @@ -5304,8 +5414,9 @@ TreeTransform::TransformCXXCatchStmt(CXXCatchStmt *S) { return StmtError(); Var = getDerived().RebuildExceptionDecl(ExceptionDecl, T, - ExceptionDecl->getIdentifier(), - ExceptionDecl->getLocation()); + ExceptionDecl->getInnerLocStart(), + ExceptionDecl->getLocation(), + ExceptionDecl->getIdentifier()); if (!Var || Var->isInvalidDecl()) return StmtError(); } @@ -5356,6 +5467,112 @@ TreeTransform::TransformCXXTryStmt(CXXTryStmt *S) { move_arg(Handlers)); } +template +StmtResult +TreeTransform::TransformCXXForRangeStmt(CXXForRangeStmt *S) { + StmtResult Range = getDerived().TransformStmt(S->getRangeStmt()); + if (Range.isInvalid()) + return StmtError(); + + StmtResult BeginEnd = getDerived().TransformStmt(S->getBeginEndStmt()); + if (BeginEnd.isInvalid()) + return StmtError(); + + ExprResult Cond = getDerived().TransformExpr(S->getCond()); + if (Cond.isInvalid()) + return StmtError(); + + ExprResult Inc = getDerived().TransformExpr(S->getInc()); + if (Inc.isInvalid()) + return StmtError(); + + StmtResult LoopVar = getDerived().TransformStmt(S->getLoopVarStmt()); + if (LoopVar.isInvalid()) + return StmtError(); + + StmtResult NewStmt = S; + if (getDerived().AlwaysRebuild() || + Range.get() != S->getRangeStmt() || + BeginEnd.get() != S->getBeginEndStmt() || + Cond.get() != S->getCond() || + Inc.get() != S->getInc() || + LoopVar.get() != S->getLoopVarStmt()) + NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), + S->getColonLoc(), Range.get(), + BeginEnd.get(), Cond.get(), + Inc.get(), LoopVar.get(), + S->getRParenLoc()); + + StmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return StmtError(); + + // Body has changed but we didn't rebuild the for-range statement. Rebuild + // it now so we have a new statement to attach the body to. + if (Body.get() != S->getBody() && NewStmt.get() == S) + NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), + S->getColonLoc(), Range.get(), + BeginEnd.get(), Cond.get(), + Inc.get(), LoopVar.get(), + S->getRParenLoc()); + + if (NewStmt.get() == S) + return SemaRef.Owned(S); + + return FinishCXXForRangeStmt(NewStmt.get(), Body.get()); +} + +template +StmtResult +TreeTransform::TransformSEHTryStmt(SEHTryStmt *S) { + StmtResult TryBlock; // = getDerived().TransformCompoundStmt(S->getTryBlock()); + if(TryBlock.isInvalid()) return StmtError(); + + StmtResult Handler = getDerived().TransformSEHHandler(S->getHandler()); + if(!getDerived().AlwaysRebuild() && + TryBlock.get() == S->getTryBlock() && + Handler.get() == S->getHandler()) + return SemaRef.Owned(S); + + return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(), + S->getTryLoc(), + TryBlock.take(), + Handler.take()); +} + +template +StmtResult +TreeTransform::TransformSEHFinallyStmt(SEHFinallyStmt *S) { + StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); + if(Block.isInvalid()) return StmtError(); + + return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(), + Block.take()); +} + +template +StmtResult +TreeTransform::TransformSEHExceptStmt(SEHExceptStmt *S) { + ExprResult FilterExpr = getDerived().TransformExpr(S->getFilterExpr()); + if(FilterExpr.isInvalid()) return StmtError(); + + StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); + if(Block.isInvalid()) return StmtError(); + + return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(), + FilterExpr.take(), + Block.take()); +} + +template +StmtResult +TreeTransform::TransformSEHHandler(Stmt *Handler) { + if(isa(Handler)) + return getDerived().TransformSEHFinallyStmt(cast(Handler)); + else + return getDerived().TransformSEHExceptStmt(cast(Handler)); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// @@ -5368,11 +5585,11 @@ TreeTransform::TransformPredefinedExpr(PredefinedExpr *E) { template ExprResult TreeTransform::TransformDeclRefExpr(DeclRefExpr *E) { - NestedNameSpecifier *Qualifier = 0; - if (E->getQualifier()) { - Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (!Qualifier) + NestedNameSpecifierLoc QualifierLoc; + if (E->getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); + if (!QualifierLoc) return ExprError(); } @@ -5390,7 +5607,7 @@ TreeTransform::TransformDeclRefExpr(DeclRefExpr *E) { } if (!getDerived().AlwaysRebuild() && - Qualifier == E->getQualifier() && + QualifierLoc == E->getQualifierLoc() && ND == E->getDecl() && NameInfo.getName() == E->getDecl()->getDeclName() && !E->hasExplicitTemplateArgs()) { @@ -5413,8 +5630,8 @@ TreeTransform::TransformDeclRefExpr(DeclRefExpr *E) { return ExprError(); } - return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(), - ND, NameInfo, TemplateArgs); + return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo, + TemplateArgs); } template @@ -5447,6 +5664,42 @@ TreeTransform::TransformCharacterLiteral(CharacterLiteral *E) { return SemaRef.Owned(E); } +template +ExprResult +TreeTransform::TransformGenericSelectionExpr(GenericSelectionExpr *E) { + ExprResult ControllingExpr = + getDerived().TransformExpr(E->getControllingExpr()); + if (ControllingExpr.isInvalid()) + return ExprError(); + + llvm::SmallVector AssocExprs; + llvm::SmallVector AssocTypes; + for (unsigned i = 0; i != E->getNumAssocs(); ++i) { + TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i); + if (TS) { + TypeSourceInfo *AssocType = getDerived().TransformType(TS); + if (!AssocType) + return ExprError(); + AssocTypes.push_back(AssocType); + } else { + AssocTypes.push_back(0); + } + + ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i)); + if (AssocExpr.isInvalid()) + return ExprError(); + AssocExprs.push_back(AssocExpr.release()); + } + + return getDerived().RebuildGenericSelectionExpr(E->getGenericLoc(), + E->getDefaultLoc(), + E->getRParenLoc(), + ControllingExpr.release(), + AssocTypes.data(), + AssocExprs.data(), + E->getNumAssocs()); +} + template ExprResult TreeTransform::TransformParenExpr(ParenExpr *E) { @@ -5498,8 +5751,8 @@ TreeTransform::TransformOffsetOfExpr(OffsetOfExpr *E) { const Node &ON = E->getComponent(I); Component Comp; Comp.isBrackets = true; - Comp.LocStart = ON.getRange().getBegin(); - Comp.LocEnd = ON.getRange().getEnd(); + Comp.LocStart = ON.getSourceRange().getBegin(); + Comp.LocEnd = ON.getSourceRange().getEnd(); switch (ON.getKind()) { case Node::Array: { Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex()); @@ -5552,7 +5805,8 @@ TreeTransform::TransformOpaqueValueExpr(OpaqueValueExpr *E) { template ExprResult -TreeTransform::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { +TreeTransform::TransformUnaryExprOrTypeTraitExpr( + UnaryExprOrTypeTraitExpr *E) { if (E->isArgumentType()) { TypeSourceInfo *OldT = E->getArgumentTypeInfo(); @@ -5563,9 +5817,9 @@ TreeTransform::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { if (!getDerived().AlwaysRebuild() && OldT == NewT) return SemaRef.Owned(E); - return getDerived().RebuildSizeOfAlignOf(NewT, E->getOperatorLoc(), - E->isSizeOf(), - E->getSourceRange()); + return getDerived().RebuildUnaryExprOrTypeTrait(NewT, E->getOperatorLoc(), + E->getKind(), + E->getSourceRange()); } ExprResult SubExpr; @@ -5583,9 +5837,10 @@ TreeTransform::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return SemaRef.Owned(E); } - return getDerived().RebuildSizeOfAlignOf(SubExpr.get(), E->getOperatorLoc(), - E->isSizeOf(), - E->getSourceRange()); + return getDerived().RebuildUnaryExprOrTypeTrait(SubExpr.get(), + E->getOperatorLoc(), + E->getKind(), + E->getSourceRange()); } template @@ -5646,12 +5901,12 @@ TreeTransform::TransformMemberExpr(MemberExpr *E) { if (Base.isInvalid()) return ExprError(); - NestedNameSpecifier *Qualifier = 0; + NestedNameSpecifierLoc QualifierLoc; if (E->hasQualifier()) { - Qualifier - = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (Qualifier == 0) + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); + + if (!QualifierLoc) return ExprError(); } @@ -5673,7 +5928,7 @@ TreeTransform::TransformMemberExpr(MemberExpr *E) { if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase() && - Qualifier == E->getQualifier() && + QualifierLoc == E->getQualifierLoc() && Member == E->getMemberDecl() && FoundDecl == E->getFoundDecl() && !E->hasExplicitTemplateArgs()) { @@ -5706,8 +5961,7 @@ TreeTransform::TransformMemberExpr(MemberExpr *E) { return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc, E->isArrow(), - Qualifier, - E->getQualifierRange(), + QualifierLoc, E->getMemberNameInfo(), Member, FoundDecl, @@ -6333,7 +6587,7 @@ TreeTransform::TransformCXXUuidofExpr(CXXUuidofExpr *E) { TInfo == E->getTypeOperandSourceInfo()) return SemaRef.Owned(E); - return getDerived().RebuildCXXTypeidExpr(E->getType(), + return getDerived().RebuildCXXUuidofExpr(E->getType(), E->getLocStart(), TInfo, E->getLocEnd()); @@ -6623,8 +6877,7 @@ TreeTransform::TransformCXXPseudoDestructorExpr( if (E->getDestroyedTypeInfo()) { TypeSourceInfo *DestroyedTypeInfo = getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(), - ObjectType, 0, - QualifierLoc.getNestedNameSpecifier()); + ObjectType, 0, SS); if (!DestroyedTypeInfo) return ExprError(); Destroyed = DestroyedTypeInfo; @@ -6670,8 +6923,6 @@ template ExprResult TreeTransform::TransformUnresolvedLookupExpr( UnresolvedLookupExpr *Old) { - TemporaryBase Rebase(*this, Old->getNameLoc(), DeclarationName()); - LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), Sema::LookupOrdinaryName); @@ -6708,14 +6959,13 @@ TreeTransform::TransformUnresolvedLookupExpr( // Rebuild the nested-name qualifier, if present. CXXScopeSpec SS; - NestedNameSpecifier *Qualifier = 0; - if (Old->getQualifier()) { - Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(), - Old->getQualifierRange()); - if (!Qualifier) + if (Old->getQualifierLoc()) { + NestedNameSpecifierLoc QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc()); + if (!QualifierLoc) return ExprError(); - SS.MakeTrivial(SemaRef.Context, Qualifier, Old->getQualifierRange()); + SS.Adopt(QualifierLoc); } if (Old->getNamingClass()) { @@ -6783,6 +7033,53 @@ TreeTransform::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { E->getLocEnd()); } +template +ExprResult +TreeTransform::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo()); + if (!T) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getQueriedTypeSourceInfo()) + return SemaRef.Owned(E); + + ExprResult SubExpr; + { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + SubExpr = getDerived().TransformExpr(E->getDimensionExpression()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getDimensionExpression()) + return SemaRef.Owned(E); + } + + return getDerived().RebuildArrayTypeTrait(E->getTrait(), + E->getLocStart(), + T, + SubExpr.get(), + E->getLocEnd()); +} + +template +ExprResult +TreeTransform::TransformExpressionTraitExpr(ExpressionTraitExpr *E) { + ExprResult SubExpr; + { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + SubExpr = getDerived().TransformExpr(E->getQueriedExpression()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getQueriedExpression()) + return SemaRef.Owned(E); + } + + return getDerived().RebuildExpressionTrait( + E->getTrait(), E->getLocStart(), SubExpr.get(), E->getLocEnd()); +} + template ExprResult TreeTransform::TransformDependentScopeDeclRefExpr( @@ -6994,16 +7291,16 @@ TreeTransform::TransformCXXDependentScopeMemberExpr( // the member name. NamedDecl *FirstQualifierInScope = getDerived().TransformFirstQualifierInScope( - E->getFirstQualifierFoundInScope(), - E->getQualifierRange().getBegin()); + E->getFirstQualifierFoundInScope(), + E->getQualifierLoc().getBeginLoc()); - NestedNameSpecifier *Qualifier = 0; + NestedNameSpecifierLoc QualifierLoc; if (E->getQualifier()) { - Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange(), - ObjectType, - FirstQualifierInScope); - if (!Qualifier) + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc(), + ObjectType, + FirstQualifierInScope); + if (!QualifierLoc) return ExprError(); } @@ -7022,7 +7319,7 @@ TreeTransform::TransformCXXDependentScopeMemberExpr( if (!getDerived().AlwaysRebuild() && Base.get() == OldBase && BaseType == E->getBaseType() && - Qualifier == E->getQualifier() && + QualifierLoc == E->getQualifierLoc() && NameInfo.getName() == E->getMember() && FirstQualifierInScope == E->getFirstQualifierFoundInScope()) return SemaRef.Owned(E); @@ -7031,8 +7328,7 @@ TreeTransform::TransformCXXDependentScopeMemberExpr( BaseType, E->isArrow(), E->getOperatorLoc(), - Qualifier, - E->getQualifierRange(), + QualifierLoc, FirstQualifierInScope, NameInfo, /*TemplateArgs*/ 0); @@ -7048,8 +7344,7 @@ TreeTransform::TransformCXXDependentScopeMemberExpr( BaseType, E->isArrow(), E->getOperatorLoc(), - Qualifier, - E->getQualifierRange(), + QualifierLoc, FirstQualifierInScope, NameInfo, &TransArgs); @@ -7070,12 +7365,11 @@ TreeTransform::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) BaseType = getDerived().TransformType(Old->getBaseType()); } - NestedNameSpecifier *Qualifier = 0; - if (Old->getQualifier()) { - Qualifier - = getDerived().TransformNestedNameSpecifier(Old->getQualifier(), - Old->getQualifierRange()); - if (Qualifier == 0) + NestedNameSpecifierLoc QualifierLoc; + if (Old->getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc()); + if (!QualifierLoc) return ExprError(); } @@ -7093,8 +7387,10 @@ TreeTransform::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) // This can happen because of dependent hiding. if (isa(*I)) continue; - else + else { + R.clear(); return ExprError(); + } } // Expand using declarations. @@ -7143,8 +7439,7 @@ TreeTransform::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) BaseType, Old->getOperatorLoc(), Old->isArrow(), - Qualifier, - Old->getQualifierRange(), + QualifierLoc, FirstQualifierInScope, R, (Old->hasExplicitTemplateArgs() @@ -7490,8 +7785,6 @@ TreeTransform::TransformBlockExpr(BlockExpr *E) { template ExprResult TreeTransform::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { - NestedNameSpecifier *Qualifier = 0; - ValueDecl *ND = cast_or_null(getDerived().TransformDecl(E->getLocation(), E->getDecl())); @@ -7508,7 +7801,7 @@ TreeTransform::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { } DeclarationNameInfo NameInfo(E->getDecl()->getDeclName(), E->getLocation()); - return getDerived().RebuildDeclRefExpr(Qualifier, SourceLocation(), + return getDerived().RebuildDeclRefExpr(NestedNameSpecifierLoc(), ND, NameInfo, 0); } @@ -7720,88 +8013,33 @@ template QualType TreeTransform::RebuildTemplateSpecializationType( TemplateName Template, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs) { + TemplateArgumentListInfo &TemplateArgs) { return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); } -template -NestedNameSpecifier * -TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - IdentifierInfo &II, - QualType ObjectType, - NamedDecl *FirstQualifierInScope) { - CXXScopeSpec SS; - // FIXME: The source location information is all wrong. - SS.MakeTrivial(SemaRef.Context, Prefix, Range); - if (SemaRef.BuildCXXNestedNameSpecifier(0, II, /*FIXME:*/Range.getBegin(), - /*FIXME:*/Range.getEnd(), - ObjectType, false, - SS, FirstQualifierInScope, - false)) - return 0; - - return SS.getScopeRep(); -} - -template -NestedNameSpecifier * -TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - NamespaceDecl *NS) { - return NestedNameSpecifier::Create(SemaRef.Context, Prefix, NS); -} - -template -NestedNameSpecifier * -TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - NamespaceAliasDecl *Alias) { - return NestedNameSpecifier::Create(SemaRef.Context, Prefix, Alias); -} - -template -NestedNameSpecifier * -TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - bool TemplateKW, - QualType T) { - if (T->isDependentType() || T->isRecordType() || - (SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) { - assert(!T.hasLocalQualifiers() && "Can't get cv-qualifiers here"); - return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW, - T.getTypePtr()); - } - - SemaRef.Diag(Range.getBegin(), diag::err_nested_name_spec_non_tag) << T; - return 0; -} - template TemplateName -TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, +TreeTransform::RebuildTemplateName(CXXScopeSpec &SS, bool TemplateKW, TemplateDecl *Template) { - return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, + return SemaRef.Context.getQualifiedTemplateName(SS.getScopeRep(), TemplateKW, Template); } template TemplateName -TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - const IdentifierInfo &II, +TreeTransform::RebuildTemplateName(CXXScopeSpec &SS, + const IdentifierInfo &Name, + SourceLocation NameLoc, QualType ObjectType, NamedDecl *FirstQualifierInScope) { - CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); - UnqualifiedId Name; - Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation()); + UnqualifiedId TemplateName; + TemplateName.setIdentifier(&Name, NameLoc); Sema::TemplateTy Template; getSema().ActOnDependentTemplateName(/*Scope=*/0, - /*FIXME:*/getDerived().getBaseLocation(), + /*FIXME:*/SourceLocation(), SS, - Name, + TemplateName, ParsedType::make(ObjectType), /*EnteringContext=*/false, Template); @@ -7810,18 +8048,17 @@ TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, template TemplateName -TreeTransform::RebuildTemplateName(NestedNameSpecifier *Qualifier, +TreeTransform::RebuildTemplateName(CXXScopeSpec &SS, OverloadedOperatorKind Operator, + SourceLocation NameLoc, QualType ObjectType) { - CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, SourceRange(getDerived().getBaseLocation())); UnqualifiedId Name; - SourceLocation SymbolLocations[3]; // FIXME: Bogus location information. - Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(), - Operator, SymbolLocations); + // FIXME: Bogus location information. + SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc }; + Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations); Sema::TemplateTy Template; getSema().ActOnDependentTemplateName(/*Scope=*/0, - /*FIXME:*/getDerived().getBaseLocation(), + /*FIXME:*/SourceLocation(), SS, Name, ParsedType::make(ObjectType), diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h index 1e0a7c454675..3570737d11bc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h +++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h @@ -44,8 +44,7 @@ class TypeLocBuilder { public: TypeLocBuilder() - : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) - {} + : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {} ~TypeLocBuilder() { if (Buffer != InlineBuffer) diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp index 5e94f59ad493..782e5c6aa79f 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp @@ -50,7 +50,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { case BuiltinType::Char16: ID = PREDEF_TYPE_CHAR16_ID; break; case BuiltinType::Char32: ID = PREDEF_TYPE_CHAR32_ID; break; case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break; + case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER; break; case BuiltinType::Dependent: ID = PREDEF_TYPE_DEPENDENT_ID; break; + case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY; break; case BuiltinType::ObjCId: ID = PREDEF_TYPE_OBJC_ID; break; case BuiltinType::ObjCClass: ID = PREDEF_TYPE_OBJC_CLASS; break; case BuiltinType::ObjCSel: ID = PREDEF_TYPE_OBJC_SEL; break; diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h index d4166998d1cf..838df13f2d8f 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h @@ -23,7 +23,9 @@ namespace serialization { enum DeclUpdateKind { UPD_CXX_SET_DEFINITIONDATA, UPD_CXX_ADDED_IMPLICIT_MEMBER, - UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION + UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, + UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, + UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER }; TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index c3953ba554dc..d2e41a96c946 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -23,6 +23,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" #include "clang/Lex/MacroInfo.h" @@ -36,6 +37,7 @@ #include "clang/Basic/FileSystemStatCache.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" +#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Support/MemoryBuffer.h" @@ -77,6 +79,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_BENIGN(Digraphs); PARSE_LANGOPT_BENIGN(HexFloats); PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99); + PARSE_LANGOPT_IMPORTANT(C1X, diag::warn_pch_c1x); PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions); PARSE_LANGOPT_BENIGN(MSCVersion); PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus); @@ -126,6 +129,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level); PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline); PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline); + PARSE_LANGOPT_IMPORTANT(Deprecated, diag::warn_pch_deprecated); PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control); PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed); PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar); @@ -953,8 +957,16 @@ bool ASTReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, return false; } -void ASTReader::Error(const char *Msg) { - Diag(diag::err_fe_pch_malformed) << Msg; +void ASTReader::Error(llvm::StringRef Msg) { + Error(diag::err_fe_pch_malformed, Msg); +} + +void ASTReader::Error(unsigned DiagID, + llvm::StringRef Arg1, llvm::StringRef Arg2) { + if (Diags.isDiagnosticInFlight()) + Diags.SetDelayedDiagnostic(DiagID, Arg1, Arg2); + else + Diag(DiagID) << Arg1 << Arg2; } /// \brief Tell the AST listener about the predefines buffers in the chain. @@ -1306,8 +1318,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) { || (time_t)Record[5] != File->getModificationTime() #endif )) { - Diag(diag::err_fe_pch_file_modified) - << Filename; + Error(diag::err_fe_pch_file_modified, Filename); return Failure; } @@ -2460,20 +2471,26 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName, if (CurrentDir.empty()) CurrentDir = "."; } - // Open the AST file. - // - // FIXME: This shouldn't be here, we should just take a raw_ostream. - std::string ErrStr; - llvm::error_code ec; - if (FileName == "-") { - ec = llvm::MemoryBuffer::getSTDIN(F.Buffer); - if (ec) - ErrStr = ec.message(); - } else - F.Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrStr)); - if (!F.Buffer) { - Error(ErrStr.c_str()); - return IgnorePCH; + if (!ASTBuffers.empty()) { + F.Buffer.reset(ASTBuffers.back()); + ASTBuffers.pop_back(); + assert(F.Buffer && "Passed null buffer"); + } else { + // Open the AST file. + // + // FIXME: This shouldn't be here, we should just take a raw_ostream. + std::string ErrStr; + llvm::error_code ec; + if (FileName == "-") { + ec = llvm::MemoryBuffer::getSTDIN(F.Buffer); + if (ec) + ErrStr = ec.message(); + } else + F.Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrStr)); + if (!F.Buffer) { + Error(ErrStr.c_str()); + return IgnorePCH; + } } // Initialize the stream @@ -2668,6 +2685,11 @@ void ASTReader::InitializeContext(ASTContext &Ctx) { if (SpecialTypes[SPECIAL_TYPE_INT128_INSTALLED]) Context->setInt128Installed(); + if (unsigned AutoDeduct = SpecialTypes[SPECIAL_TYPE_AUTO_DEDUCT]) + Context->AutoDeductTy = GetType(AutoDeduct); + if (unsigned AutoRRefDeduct = SpecialTypes[SPECIAL_TYPE_AUTO_RREF_DEDUCT]) + Context->AutoRRefDeductTy = GetType(AutoRRefDeduct); + ReadPragmaDiagnosticMappings(Context->getDiagnostics()); // If there were any CUDA special declarations, deserialize them. @@ -2786,6 +2808,7 @@ bool ASTReader::ParseLanguageOptions( PARSE_LANGOPT(Digraphs); PARSE_LANGOPT(HexFloats); PARSE_LANGOPT(C99); + PARSE_LANGOPT(C1X); PARSE_LANGOPT(Microsoft); PARSE_LANGOPT(CPlusPlus); PARSE_LANGOPT(CPlusPlus0x); @@ -2823,6 +2846,7 @@ bool ASTReader::ParseLanguageOptions( PARSE_LANGOPT(PICLevel); PARSE_LANGOPT(GNUInline); PARSE_LANGOPT(NoInline); + PARSE_LANGOPT(Deprecated); PARSE_LANGOPT(AccessControl); PARSE_LANGOPT(CharIsSigned); PARSE_LANGOPT(ShortWChar); @@ -2836,7 +2860,9 @@ bool ASTReader::ParseLanguageOptions( PARSE_LANGOPT(CUDA); PARSE_LANGOPT(CatchUndefined); PARSE_LANGOPT(DefaultFPContract); - // FIXME: Missing ElideConstructors?! + PARSE_LANGOPT(ElideConstructors); + PARSE_LANGOPT(SpellChecking); + PARSE_LANGOPT(MRTD); #undef PARSE_LANGOPT return Listener->ReadLanguageOptions(LangOpts); @@ -2999,12 +3025,12 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { } case TYPE_LVALUE_REFERENCE: { - if (Record.size() != 1) { + if (Record.size() != 2) { Error("Incorrect encoding of lvalue reference type"); return QualType(); } QualType PointeeType = GetType(Record[0]); - return Context->getLValueReferenceType(PointeeType); + return Context->getLValueReferenceType(PointeeType, Record[1]); } case TYPE_RVALUE_REFERENCE: { @@ -3082,12 +3108,12 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { } case TYPE_FUNCTION_NO_PROTO: { - if (Record.size() != 4) { + if (Record.size() != 5) { Error("incorrect encoding of no-proto function type"); return QualType(); } QualType ResultType = GetType(Record[0]); - FunctionType::ExtInfo Info(Record[1], Record[2], (CallingConv)Record[3]); + FunctionType::ExtInfo Info(Record[1], Record[2], Record[3], (CallingConv)Record[4]); return Context->getFunctionNoProtoType(ResultType, Info); } @@ -3096,10 +3122,11 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { FunctionProtoType::ExtProtoInfo EPI; EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1], - /*regparm*/ Record[2], - static_cast(Record[3])); + /*hasregparm*/ Record[2], + /*regparm*/ Record[3], + static_cast(Record[4])); - unsigned Idx = 4; + unsigned Idx = 5; unsigned NumParams = Record[Idx++]; llvm::SmallVector ParamTypes; for (unsigned I = 0; I != NumParams; ++I) @@ -3108,13 +3135,18 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { EPI.Variadic = Record[Idx++]; EPI.TypeQuals = Record[Idx++]; EPI.RefQualifier = static_cast(Record[Idx++]); - EPI.HasExceptionSpec = Record[Idx++]; - EPI.HasAnyExceptionSpec = Record[Idx++]; - EPI.NumExceptions = Record[Idx++]; - llvm::SmallVector Exceptions; - for (unsigned I = 0; I != EPI.NumExceptions; ++I) - Exceptions.push_back(GetType(Record[Idx++])); - EPI.Exceptions = Exceptions.data(); + ExceptionSpecificationType EST = + static_cast(Record[Idx++]); + EPI.ExceptionSpecType = EST; + if (EST == EST_Dynamic) { + EPI.NumExceptions = Record[Idx++]; + llvm::SmallVector Exceptions; + for (unsigned I = 0; I != EPI.NumExceptions; ++I) + Exceptions.push_back(GetType(Record[Idx++])); + EPI.Exceptions = Exceptions.data(); + } else if (EST == EST_ComputedNoexcept) { + EPI.NoexceptExpr = ReadExpr(*Loc.F); + } return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams, EPI); } @@ -3128,7 +3160,7 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("incorrect encoding of typedef type"); return QualType(); } - TypedefDecl *Decl = cast(GetDecl(Record[0])); + TypedefNameDecl *Decl = cast(GetDecl(Record[0])); QualType Canonical = GetType(Record[1]); if (!Canonical.isNull()) Canonical = Context->getCanonicalType(Canonical); @@ -3271,8 +3303,9 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { unsigned Depth = Record[Idx++]; unsigned Index = Record[Idx++]; bool Pack = Record[Idx++]; - IdentifierInfo *Name = GetIdentifierInfo(Record, Idx); - return Context->getTemplateTypeParmType(Depth, Index, Pack, Name); + TemplateTypeParmDecl *D = + cast_or_null(GetDecl(Record[Idx++])); + return Context->getTemplateTypeParmType(Depth, Index, Pack, D); } case TYPE_DEPENDENT_NAME: { @@ -3398,6 +3431,7 @@ void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { } void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { TL.setStarLoc(ReadSourceLocation(Record, Idx)); + TL.setClassTInfo(Reader.GetTypeSourceInfo(F, Record, Idx)); } void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { TL.setLBracketLoc(ReadSourceLocation(Record, Idx)); @@ -3431,8 +3465,8 @@ void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation(Record, Idx)); } void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { - TL.setLParenLoc(ReadSourceLocation(Record, Idx)); - TL.setRParenLoc(ReadSourceLocation(Record, Idx)); + TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx)); + TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx)); TL.setTrailingReturn(Record[Idx++]); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { TL.setArg(i, cast_or_null(Reader.GetDecl(Record[Idx++]))); @@ -3517,20 +3551,20 @@ void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) { } void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { TL.setKeywordLoc(ReadSourceLocation(Record, Idx)); - TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx)); + TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); } void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { TL.setNameLoc(ReadSourceLocation(Record, Idx)); } void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { TL.setKeywordLoc(ReadSourceLocation(Record, Idx)); - TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx)); + TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); TL.setNameLoc(ReadSourceLocation(Record, Idx)); } void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { TL.setKeywordLoc(ReadSourceLocation(Record, Idx)); - TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx)); + TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx)); TL.setNameLoc(ReadSourceLocation(Record, Idx)); TL.setLAngleLoc(ReadSourceLocation(Record, Idx)); TL.setRAngleLoc(ReadSourceLocation(Record, Idx)); @@ -3605,7 +3639,9 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break; case PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break; case PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break; + case PREDEF_TYPE_BOUND_MEMBER: T = Context->BoundMemberTy; break; case PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break; + case PREDEF_TYPE_UNKNOWN_ANY: T = Context->UnknownAnyTy; break; case PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break; case PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break; case PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break; @@ -3675,16 +3711,18 @@ ASTReader::GetTemplateArgumentLocInfo(PerFileData &F, case TemplateArgument::Type: return GetTypeSourceInfo(F, Record, Index); case TemplateArgument::Template: { - SourceRange QualifierRange = ReadSourceRange(F, Record, Index); + NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, + Index); SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index); - return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc, + return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, SourceLocation()); } case TemplateArgument::TemplateExpansion: { - SourceRange QualifierRange = ReadSourceRange(F, Record, Index); + NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, + Index); SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index); SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index); - return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc, + return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc); } case TemplateArgument::Null: @@ -3722,11 +3760,13 @@ ASTReader::GetCXXBaseSpecifiersOffset(serialization::CXXBaseSpecifiersID ID) { --ID; uint64_t Offset = 0; for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - if (ID < Chain[I]->LocalNumCXXBaseSpecifiers) - return Offset + Chain[I]->CXXBaseSpecifiersOffsets[ID]; + PerFileData &F = *Chain[N - I - 1]; + + if (ID < F.LocalNumCXXBaseSpecifiers) + return Offset + F.CXXBaseSpecifiersOffsets[ID]; - ID -= Chain[I]->LocalNumCXXBaseSpecifiers; - Offset += Chain[I]->SizeInBits; + ID -= F.LocalNumCXXBaseSpecifiers; + Offset += F.SizeInBits; } assert(false && "CXXBaseSpecifiers not found"); @@ -3737,14 +3777,14 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { // Figure out which AST file contains this offset. PerFileData *F = 0; for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - if (Offset < Chain[I]->SizeInBits) { - F = Chain[I]; + if (Offset < Chain[N - I - 1]->SizeInBits) { + F = Chain[N - I - 1]; break; } - Offset -= Chain[I]->SizeInBits; + Offset -= Chain[N - I - 1]->SizeInBits; } - + if (!F) { Error("Malformed AST file: C++ base specifiers at impossible offset"); return 0; @@ -4014,6 +4054,23 @@ void ASTReader::PrintStats() { std::fprintf(stderr, "\n"); } +/// Return the amount of memory used by memory buffers, breaking down +/// by heap-backed versus mmap'ed memory. +void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { + for (unsigned i = 0, e = Chain.size(); i != e; ++i) + if (llvm::MemoryBuffer *buf = Chain[i]->Buffer.get()) { + size_t bytes = buf->getBufferSize(); + switch (buf->getBufferKind()) { + case llvm::MemoryBuffer::MemoryBuffer_Malloc: + sizes.malloc_bytes += bytes; + break; + case llvm::MemoryBuffer::MemoryBuffer_MMap: + sizes.mmap_bytes += bytes; + break; + } + } +} + void ASTReader::InitializeSema(Sema &S) { SemaObj = &S; S.ExternalSource = this; @@ -4054,7 +4111,7 @@ void ASTReader::InitializeSema(Sema &S) { // and add them to Sema's vector of such declarations. for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) SemaObj->ExtVectorDecls.push_back( - cast(GetDecl(ExtVectorDecls[I]))); + cast(GetDecl(ExtVectorDecls[I]))); // FIXME: Do VTable uses and dynamic classes deserialize too much ? // Can we cut them down before writing them ? @@ -4087,22 +4144,22 @@ void ASTReader::InitializeSema(Sema &S) { SemaObj->ReferencedSelectors.insert(std::make_pair(Sel, SelLoc)); } } - - // If there were any pending implicit instantiations, deserialize them - // and add them to Sema's queue of such instantiations. - assert(F->PendingInstantiations.size() % 2 == 0 && - "Expected pairs of entries"); - for (unsigned Idx = 0, N = F->PendingInstantiations.size(); Idx < N;) { - ValueDecl *D=cast(GetDecl(F->PendingInstantiations[Idx++])); - SourceLocation Loc = ReadSourceLocation(*F, F->PendingInstantiations,Idx); - SemaObj->PendingInstantiations.push_back(std::make_pair(D, Loc)); - } } - // The two special data sets below always come from the most recent PCH, + // The special data sets below always come from the most recent PCH, // which is at the front of the chain. PerFileData &F = *Chain.front(); + // If there were any pending implicit instantiations, deserialize them + // and add them to Sema's queue of such instantiations. + assert(F.PendingInstantiations.size() % 2 == 0 && + "Expected pairs of entries"); + for (unsigned Idx = 0, N = F.PendingInstantiations.size(); Idx < N;) { + ValueDecl *D=cast(GetDecl(F.PendingInstantiations[Idx++])); + SourceLocation Loc = ReadSourceLocation(F, F.PendingInstantiations,Idx); + SemaObj->PendingInstantiations.push_back(std::make_pair(D, Loc)); + } + // If there were any weak undeclared identifiers, deserialize them and add to // Sema's list of weak undeclared identifiers. if (!WeakUndeclaredIdentifiers.empty()) { @@ -4354,8 +4411,8 @@ IdentifierInfo *ASTReader::DecodeIdentifierInfo(unsigned ID) { return IdentifiersLoaded[ID]; } -void ASTReader::ReadSLocEntry(unsigned ID) { - ReadSLocEntryRecord(ID); +bool ASTReader::ReadSLocEntry(unsigned ID) { + return ReadSLocEntryRecord(ID) != Success; } Selector ASTReader::DecodeSelector(unsigned ID) { @@ -4762,103 +4819,57 @@ NestedNameSpecifierLoc ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record, unsigned &Idx) { unsigned N = Record[Idx++]; - NestedNameSpecifier *NNS = 0, *Prev = 0; - llvm::SmallVector LocationData; + NestedNameSpecifierLocBuilder Builder; for (unsigned I = 0; I != N; ++I) { NestedNameSpecifier::SpecifierKind Kind = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; switch (Kind) { case NestedNameSpecifier::Identifier: { - // Nested-name-specifier - IdentifierInfo *II = GetIdentifierInfo(Record, Idx); - NNS = NestedNameSpecifier::Create(*Context, Prev, II); - - // Location information + IdentifierInfo *II = GetIdentifierInfo(Record, Idx); SourceRange Range = ReadSourceRange(F, Record, Idx); - unsigned RawStart = Range.getBegin().getRawEncoding(); - unsigned RawEnd = Range.getEnd().getRawEncoding(); - LocationData.append(reinterpret_cast(&RawStart), - reinterpret_cast(&RawStart) +sizeof(unsigned)); - LocationData.append(reinterpret_cast(&RawEnd), - reinterpret_cast(&RawEnd) + sizeof(unsigned)); + Builder.Extend(*Context, II, Range.getBegin(), Range.getEnd()); break; } case NestedNameSpecifier::Namespace: { - // Nested-name-specifier NamespaceDecl *NS = cast(GetDecl(Record[Idx++])); - NNS = NestedNameSpecifier::Create(*Context, Prev, NS); - - // Location information SourceRange Range = ReadSourceRange(F, Record, Idx); - unsigned RawStart = Range.getBegin().getRawEncoding(); - unsigned RawEnd = Range.getEnd().getRawEncoding(); - LocationData.append(reinterpret_cast(&RawStart), - reinterpret_cast(&RawStart) +sizeof(unsigned)); - LocationData.append(reinterpret_cast(&RawEnd), - reinterpret_cast(&RawEnd) + sizeof(unsigned)); + Builder.Extend(*Context, NS, Range.getBegin(), Range.getEnd()); break; } case NestedNameSpecifier::NamespaceAlias: { - // Nested-name-specifier NamespaceAliasDecl *Alias = cast(GetDecl(Record[Idx++])); - NNS = NestedNameSpecifier::Create(*Context, Prev, Alias); - - // Location information SourceRange Range = ReadSourceRange(F, Record, Idx); - unsigned RawStart = Range.getBegin().getRawEncoding(); - unsigned RawEnd = Range.getEnd().getRawEncoding(); - LocationData.append(reinterpret_cast(&RawStart), - reinterpret_cast(&RawStart) +sizeof(unsigned)); - LocationData.append(reinterpret_cast(&RawEnd), - reinterpret_cast(&RawEnd) + sizeof(unsigned)); - + Builder.Extend(*Context, Alias, Range.getBegin(), Range.getEnd()); break; } case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { - // Nested-name-specifier bool Template = Record[Idx++]; TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx); if (!T) return NestedNameSpecifierLoc(); - NNS = NestedNameSpecifier::Create(*Context, Prev, Template, - T->getType().getTypePtr()); - - // Location information. SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); - unsigned RawLocation = ColonColonLoc.getRawEncoding(); - void *OpaqueTypeData = T->getTypeLoc().getOpaqueData(); - LocationData.append(reinterpret_cast(&OpaqueTypeData), - (reinterpret_cast(&OpaqueTypeData) - + sizeof(void *))); - LocationData.append(reinterpret_cast(&RawLocation), - (reinterpret_cast(&RawLocation) + - sizeof(unsigned))); + + // FIXME: 'template' keyword location not saved anywhere, so we fake it. + Builder.Extend(*Context, + Template? T->getTypeLoc().getBeginLoc() : SourceLocation(), + T->getTypeLoc(), ColonColonLoc); break; } case NestedNameSpecifier::Global: { - // Nested-name-specifier - NNS = NestedNameSpecifier::GlobalSpecifier(*Context); - SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); - unsigned RawLocation = ColonColonLoc.getRawEncoding(); - LocationData.append(reinterpret_cast(&RawLocation), - (reinterpret_cast(&RawLocation) + - sizeof(unsigned))); + Builder.MakeGlobal(*Context, ColonColonLoc); break; } } - Prev = NNS; } - void *Mem = Context->Allocate(LocationData.size(), llvm::alignOf()); - memcpy(Mem, LocationData.data(), LocationData.size()); - return NestedNameSpecifierLoc(NNS, Mem); + return Builder.getWithLocInContext(*Context); } SourceRange @@ -4897,6 +4908,18 @@ std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) { return Result; } +VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, + unsigned &Idx) { + unsigned Major = Record[Idx++]; + unsigned Minor = Record[Idx++]; + unsigned Subminor = Record[Idx++]; + if (Minor == 0) + return VersionTuple(Major); + if (Subminor == 0) + return VersionTuple(Major, Minor - 1); + return VersionTuple(Major, Minor - 1, Subminor - 1); +} + CXXTemporary *ASTReader::ReadCXXTemporary(const RecordData &Record, unsigned &Idx) { CXXDestructorDecl *Decl = cast(GetDecl(Record[Idx++])); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp index 493ccbad8618..3a825de6e6d8 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp @@ -38,6 +38,9 @@ namespace clang { const RecordData &Record; unsigned &Idx; TypeID TypeIDForTypeDecl; + + DeclID DeclContextIDForTemplateParmDecl; + DeclID LexicalDeclContextIDForTemplateParmDecl; uint64_t GetCurrentCursorOffset(); SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) { @@ -79,7 +82,8 @@ namespace clang { void Visit(Decl *D); - void UpdateDecl(Decl *D, const RecordData &Record); + void UpdateDecl(Decl *D, ASTReader::PerFileData &Module, + const RecordData &Record); void VisitDecl(Decl *D); void VisitTranslationUnitDecl(TranslationUnitDecl *TU); @@ -90,6 +94,7 @@ namespace clang { void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *TD); void VisitTypedefDecl(TypedefDecl *TD); + void VisitTypeAliasDecl(TypeAliasDecl *TD); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); void VisitTagDecl(TagDecl *TD); void VisitEnumDecl(EnumDecl *ED); @@ -175,13 +180,32 @@ void ASTDeclReader::Visit(Decl *D) { // FunctionDecl's body was written last after all other Stmts/Exprs. if (Record[Idx++]) FD->setLazyBody(GetCurrentCursorOffset()); + } else if (D->isTemplateParameter()) { + // If we have a fully initialized template parameter, we can now + // set its DeclContext. + D->setDeclContext( + cast_or_null( + Reader.GetDecl(DeclContextIDForTemplateParmDecl))); + D->setLexicalDeclContext( + cast_or_null( + Reader.GetDecl(LexicalDeclContextIDForTemplateParmDecl))); } } void ASTDeclReader::VisitDecl(Decl *D) { - D->setDeclContext(cast_or_null(Reader.GetDecl(Record[Idx++]))); - D->setLexicalDeclContext( + if (D->isTemplateParameter()) { + // We don't want to deserialize the DeclContext of a template + // parameter immediately, because the template parameter might be + // used in the formulation of its DeclContext. Use the translation + // unit DeclContext as a placeholder. + DeclContextIDForTemplateParmDecl = Record[Idx++]; + LexicalDeclContextIDForTemplateParmDecl = Record[Idx++]; + D->setDeclContext(Reader.getContext()->getTranslationUnitDecl()); + } else { + D->setDeclContext(cast_or_null(Reader.GetDecl(Record[Idx++]))); + D->setLexicalDeclContext( cast_or_null(Reader.GetDecl(Record[Idx++]))); + } D->setLocation(ReadSourceLocation(Record, Idx)); D->setInvalidDecl(Record[Idx++]); if (Record[Idx++]) { // hasAttrs @@ -191,6 +215,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { } D->setImplicit(Record[Idx++]); D->setUsed(Record[Idx++]); + D->setReferenced(Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]); D->setPCHLevel(Record[Idx++] + (F.Type <= ASTReader::PCH)); } @@ -208,6 +233,7 @@ void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) { void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { VisitNamedDecl(TD); + TD->setLocStart(ReadSourceLocation(Record, Idx)); // Delay type reading until after we have fully initialized the decl. TypeIDForTypeDecl = Record[Idx++]; } @@ -217,6 +243,11 @@ void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); } +void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { + VisitTypeDecl(TD); + TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); +} + void ASTDeclReader::VisitTagDecl(TagDecl *TD) { VisitTypeDecl(TD); VisitRedeclarable(TD); @@ -225,14 +256,13 @@ void ASTDeclReader::VisitTagDecl(TagDecl *TD) { TD->setDefinition(Record[Idx++]); TD->setEmbeddedInDeclarator(Record[Idx++]); TD->setRBraceLoc(ReadSourceLocation(Record, Idx)); - TD->setTagKeywordLoc(ReadSourceLocation(Record, Idx)); if (Record[Idx++]) { // hasExtInfo TagDecl::ExtInfo *Info = new (*Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); - TD->TypedefDeclOrQualifier = Info; + TD->TypedefNameDeclOrQualifier = Info; } else - TD->setTypedefForAnonDecl( - cast_or_null(Reader.GetDecl(Record[Idx++]))); + TD->setTypedefNameForAnonDecl( + cast_or_null(Reader.GetDecl(Record[Idx++]))); } void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { @@ -272,6 +302,7 @@ void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { VisitValueDecl(DD); + DD->setInnerLocStart(ReadSourceLocation(Record, Idx)); if (Record[Idx++]) { // hasExtInfo DeclaratorDecl::ExtInfo *Info = new (*Reader.getContext()) DeclaratorDecl::ExtInfo(); @@ -655,12 +686,13 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) { void ASTDeclReader::VisitVarDecl(VarDecl *VD) { VisitDeclaratorDecl(VD); VisitRedeclarable(VD); - VD->SClass = (StorageClass)Record[Idx++]; - VD->setStorageClassAsWritten((StorageClass)Record[Idx++]); - VD->setThreadSpecified(Record[Idx++]); - VD->setCXXDirectInitializer(Record[Idx++]); - VD->setExceptionVariable(Record[Idx++]); - VD->setNRVOVariable(Record[Idx++]); + VD->VarDeclBits.SClass = (StorageClass)Record[Idx++]; + VD->VarDeclBits.SClassAsWritten = (StorageClass)Record[Idx++]; + VD->VarDeclBits.ThreadSpecified = Record[Idx++]; + VD->VarDeclBits.HasCXXDirectInit = Record[Idx++]; + VD->VarDeclBits.ExceptionVar = Record[Idx++]; + VD->VarDeclBits.NRVOVariable = Record[Idx++]; + VD->VarDeclBits.CXXForRangeDecl = Record[Idx++]; if (Record[Idx++]) VD->setInit(Reader.ReadExpr(F)); @@ -678,8 +710,19 @@ void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { VisitVarDecl(PD); - PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); - PD->setHasInheritedDefaultArg(Record[Idx++]); + unsigned isObjCMethodParam = Record[Idx++]; + unsigned scopeDepth = Record[Idx++]; + unsigned scopeIndex = Record[Idx++]; + unsigned declQualifier = Record[Idx++]; + if (isObjCMethodParam) { + assert(scopeDepth == 0); + PD->setObjCMethodScopeInfo(scopeIndex); + PD->ParmVarDeclBits.ScopeDepthOrObjCQuals = declQualifier; + } else { + PD->setScopeInfo(scopeDepth, scopeIndex); + } + PD->ParmVarDeclBits.IsKNRPromoted = Record[Idx++]; + PD->ParmVarDeclBits.HasInheritedDefaultArg = Record[Idx++]; if (Record[Idx++]) // hasUninstantiatedDefaultArg. PD->setUninstantiatedDefaultArg(Reader.ReadExpr(F)); } @@ -687,6 +730,7 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { VisitDecl(AD); AD->setAsmString(cast(Reader.ReadExpr(F))); + AD->setRParenLoc(ReadSourceLocation(Record, Idx)); } void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { @@ -720,19 +764,21 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) { VisitDecl(D); D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]); - D->setHasBraces(Record[Idx++]); + D->setExternLoc(ReadSourceLocation(Record, Idx)); + D->setRBraceLoc(ReadSourceLocation(Record, Idx)); } void ASTDeclReader::VisitLabelDecl(LabelDecl *D) { VisitNamedDecl(D); + D->setLocStart(ReadSourceLocation(Record, Idx)); } void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { VisitNamedDecl(D); D->IsInline = Record[Idx++]; - D->LBracLoc = ReadSourceLocation(Record, Idx); - D->RBracLoc = ReadSourceLocation(Record, Idx); + D->LocStart = ReadSourceLocation(Record, Idx); + D->RBraceLoc = ReadSourceLocation(Record, Idx); D->NextNamespace = Record[Idx++]; bool IsOriginal = Record[Idx++]; @@ -790,7 +836,6 @@ void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { VisitTypeDecl(D); - D->UsingLocation = ReadSourceLocation(Record, Idx); D->TypenameLocation = ReadSourceLocation(Record, Idx); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); } @@ -807,10 +852,19 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.Empty = Record[Idx++]; Data.Polymorphic = Record[Idx++]; Data.Abstract = Record[Idx++]; + Data.IsStandardLayout = Record[Idx++]; + Data.HasNoNonEmptyBases = Record[Idx++]; + Data.HasPrivateFields = Record[Idx++]; + Data.HasProtectedFields = Record[Idx++]; + Data.HasPublicFields = Record[Idx++]; Data.HasTrivialConstructor = Record[Idx++]; + Data.HasConstExprNonCopyMoveConstructor = Record[Idx++]; Data.HasTrivialCopyConstructor = Record[Idx++]; + Data.HasTrivialMoveConstructor = Record[Idx++]; Data.HasTrivialCopyAssignment = Record[Idx++]; + Data.HasTrivialMoveAssignment = Record[Idx++]; Data.HasTrivialDestructor = Record[Idx++]; + Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++]; Data.ComputedVisibleConversions = Record[Idx++]; Data.DeclaredDefaultConstructor = Record[Idx++]; Data.DeclaredCopyConstructor = Record[Idx++]; @@ -1172,7 +1226,6 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { VisitTypeDecl(D); D->setDeclaredWithTypename(Record[Idx++]); - D->setParameterPack(Record[Idx++]); bool Inherited = Record[Idx++]; TypeSourceInfo *DefArg = GetTypeSourceInfo(Record, Idx); @@ -1217,6 +1270,7 @@ void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { VisitDecl(D); D->AssertExpr = Reader.ReadExpr(F); D->Message = cast(Reader.ReadExpr(F)); + D->RParenLoc = ReadSourceLocation(Record, Idx); } std::pair @@ -1398,7 +1452,12 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { D = Context->getTranslationUnitDecl(); break; case DECL_TYPEDEF: - D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0); + D = TypedefDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + 0, 0); + break; + case DECL_TYPEALIAS: + D = TypeAliasDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + 0, 0); break; case DECL_ENUM: D = EnumDecl::Create(*Context, Decl::EmptyShell()); @@ -1411,19 +1470,20 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { 0, llvm::APSInt()); break; case DECL_FUNCTION: - D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(), - QualType(), 0); + D = FunctionDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + DeclarationName(), QualType(), 0); break; case DECL_LINKAGE_SPEC: - D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(), + D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), (LinkageSpecDecl::LanguageIDs)0, - false); + SourceLocation()); break; case DECL_LABEL: D = LabelDecl::Create(*Context, 0, SourceLocation(), 0); break; case DECL_NAMESPACE: - D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0); + D = NamespaceDecl::Create(*Context, 0, SourceLocation(), + SourceLocation(), 0); break; case DECL_NAMESPACE_ALIAS: D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(), @@ -1460,8 +1520,9 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { D = CXXRecordDecl::Create(*Context, Decl::EmptyShell()); break; case DECL_CXX_METHOD: - D = CXXMethodDecl::Create(*Context, 0, DeclarationNameInfo(), - QualType(), 0); + D = CXXMethodDecl::Create(*Context, 0, SourceLocation(), + DeclarationNameInfo(), QualType(), 0, + false, SC_None, false, SourceLocation()); break; case DECL_CXX_CONSTRUCTOR: D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell()); @@ -1482,38 +1543,38 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { D = FriendTemplateDecl::Create(*Context, Decl::EmptyShell()); break; case DECL_CLASS_TEMPLATE: - D = ClassTemplateDecl::Create(*Context, 0, SourceLocation(), - DeclarationName(), 0, 0, 0); + D = ClassTemplateDecl::Create(*Context, Decl::EmptyShell()); break; case DECL_CLASS_TEMPLATE_SPECIALIZATION: D = ClassTemplateSpecializationDecl::Create(*Context, Decl::EmptyShell()); break; case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: D = ClassTemplatePartialSpecializationDecl::Create(*Context, - Decl::EmptyShell()); + Decl::EmptyShell()); break; case DECL_FUNCTION_TEMPLATE: - D = FunctionTemplateDecl::Create(*Context, 0, SourceLocation(), - DeclarationName(), 0, 0); + D = FunctionTemplateDecl::Create(*Context, Decl::EmptyShell()); break; case DECL_TEMPLATE_TYPE_PARM: D = TemplateTypeParmDecl::Create(*Context, Decl::EmptyShell()); break; case DECL_NON_TYPE_TEMPLATE_PARM: - D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0, - QualType(), false, 0); + D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), + SourceLocation(), 0, 0, 0, QualType(), + false, 0); break; case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK: - D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0, - 0, QualType(), 0, 0, Record[Idx++], - 0); + D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), + SourceLocation(), 0, 0, 0, QualType(), + 0, 0, Record[Idx++], 0); break; case DECL_TEMPLATE_TEMPLATE_PARM: D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0, false, 0, 0); break; case DECL_STATIC_ASSERT: - D = StaticAssertDecl::Create(*Context, 0, SourceLocation(), 0, 0); + D = StaticAssertDecl::Create(*Context, 0, SourceLocation(), 0, 0, + SourceLocation()); break; case DECL_OBJC_METHOD: @@ -1524,15 +1585,15 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0); break; case DECL_OBJC_IVAR: - D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - ObjCIvarDecl::None); + D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + 0, QualType(), 0, ObjCIvarDecl::None); break; case DECL_OBJC_PROTOCOL: D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0); break; case DECL_OBJC_AT_DEFS_FIELD: - D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0, - QualType(), 0); + D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), + SourceLocation(), 0, QualType(), 0); break; case DECL_OBJC_CLASS: D = ObjCClassDecl::Create(*Context, 0, SourceLocation()); @@ -1564,16 +1625,16 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { SourceLocation()); break; case DECL_FIELD: - D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0, - false); + D = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, + QualType(), 0, 0, false); break; case DECL_INDIRECTFIELD: D = IndirectFieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0); break; case DECL_VAR: - D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - SC_None, SC_None); + D = VarDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, + QualType(), 0, SC_None, SC_None); break; case DECL_IMPLICIT_PARAM: @@ -1581,11 +1642,12 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { break; case DECL_PARM_VAR: - D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - SC_None, SC_None, 0); + D = ParmVarDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, + QualType(), 0, SC_None, SC_None, 0); break; case DECL_FILE_SCOPE_ASM: - D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0); + D = FileScopeAsmDecl::Create(*Context, 0, 0, SourceLocation(), + SourceLocation()); break; case DECL_BLOCK: D = BlockDecl::Create(*Context, 0, SourceLocation()); @@ -1614,22 +1676,26 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { // so we need to make sure we insert in front. For all other contexts, // the vector is empty here anyway, so there's no loss in efficiency. Infos.insert(Infos.begin(), Info); + } - // Now add the pending visible updates for this decl context, if it has - // any. - DeclContextVisibleUpdatesPending::iterator I = - PendingVisibleUpdates.find(ID); - if (I != PendingVisibleUpdates.end()) { - DeclContextVisibleUpdates &U = I->second; - Info.LexicalDecls = 0; - Info.NumLexicalDecls = 0; - for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end(); - UI != UE; ++UI) { - Info.NameLookupTableData = *UI; - Infos.push_back(Info); - } - PendingVisibleUpdates.erase(I); + // Now add the pending visible updates for this decl context, if it has any. + DeclContextVisibleUpdatesPending::iterator I = + PendingVisibleUpdates.find(ID); + if (I != PendingVisibleUpdates.end()) { + // There are updates. This means the context has external visible + // storage, even if the original stored version didn't. + DC->setHasExternalVisibleStorage(true); + DeclContextVisibleUpdates &U = I->second; + DeclContextInfos &Infos = DeclContextOffsets[DC]; + DeclContextInfo Info; + Info.LexicalDecls = 0; + Info.NumLexicalDecls = 0; + for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end(); + UI != UE; ++UI) { + Info.NameLookupTableData = *UI; + Infos.push_back(Info); } + PendingVisibleUpdates.erase(I); } } assert(Idx == Record.size()); @@ -1652,7 +1718,7 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { unsigned RecCode = Cursor.ReadRecord(Code, Record); (void)RecCode; assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!"); - Reader.UpdateDecl(D, Record); + Reader.UpdateDecl(D, *F, Record); } } @@ -1666,7 +1732,8 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { return D; } -void ASTDeclReader::UpdateDecl(Decl *D, const RecordData &Record) { +void ASTDeclReader::UpdateDecl(Decl *D, ASTReader::PerFileData &Module, + const RecordData &Record) { unsigned Idx = 0; while (Idx < Record.size()) { switch ((DeclUpdateKind)Record[Idx++]) { @@ -1686,6 +1753,26 @@ void ASTDeclReader::UpdateDecl(Decl *D, const RecordData &Record) { case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: // It will be added to the template's specializations set when loaded. Reader.GetDecl(Record[Idx++]); + break; + + case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { + NamespaceDecl *Anon = cast(Reader.GetDecl(Record[Idx++])); + // Guard against these being loaded out of original order. Don't use + // getNextNamespace(), since it tries to access the context and can't in + // the middle of deserialization. + if (!Anon->NextNamespace) { + if (TranslationUnitDecl *TU = dyn_cast(D)) + TU->setAnonymousNamespace(Anon); + else + cast(D)->OrigOrAnonNamespace.setPointer(Anon); + } + break; + } + + case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: + cast(D)->getMemberSpecializationInfo()->setPointOfInstantiation( + Reader.ReadSourceLocation(Module, Record, Idx)); + break; } } } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp index 42f0b1aacef3..918db7e367c6 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp @@ -97,7 +97,7 @@ namespace clang { void VisitParenListExpr(ParenListExpr *E); void VisitUnaryOperator(UnaryOperator *E); void VisitOffsetOfExpr(OffsetOfExpr *E); - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); + void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); void VisitArraySubscriptExpr(ArraySubscriptExpr *E); void VisitCallExpr(CallExpr *E); void VisitMemberExpr(MemberExpr *E); @@ -122,6 +122,7 @@ namespace clang { void VisitShuffleVectorExpr(ShuffleVectorExpr *E); void VisitBlockExpr(BlockExpr *E); void VisitBlockDeclRefExpr(BlockDeclRefExpr *E); + void VisitGenericSelectionExpr(GenericSelectionExpr *E); void VisitObjCStringLiteral(ObjCStringLiteral *E); void VisitObjCEncodeExpr(ObjCEncodeExpr *E); void VisitObjCSelectorExpr(ObjCSelectorExpr *E); @@ -141,6 +142,7 @@ namespace clang { // C++ Statements void VisitCXXCatchStmt(CXXCatchStmt *S); void VisitCXXTryStmt(CXXTryStmt *S); + void VisitCXXForRangeStmt(CXXForRangeStmt *); void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); void VisitCXXConstructExpr(CXXConstructExpr *E); @@ -177,6 +179,8 @@ namespace clang { void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E); + void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); + void VisitExpressionTraitExpr(ExpressionTraitExpr *E); void VisitCXXNoexceptExpr(CXXNoexceptExpr *E); void VisitPackExpansionExpr(PackExpansionExpr *E); void VisitSizeOfPackExpr(SizeOfPackExpr *E); @@ -208,7 +212,7 @@ void ASTStmtReader::VisitStmt(Stmt *S) { void ASTStmtReader::VisitNullStmt(NullStmt *S) { VisitStmt(S); S->setSemiLoc(ReadSourceLocation(Record, Idx)); - S->LeadingEmptyMacro = Record[Idx++]; + S->LeadingEmptyMacro = ReadSourceLocation(Record, Idx); } void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) { @@ -421,23 +425,23 @@ void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { VisitExpr(E); - bool HasQualifier = Record[Idx++]; - bool HasExplicitTemplateArgs = Record[Idx++]; - - E->DecoratedD.setInt((HasQualifier? DeclRefExpr::HasQualifierFlag : 0) | - (HasExplicitTemplateArgs - ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0)); - - if (HasQualifier) { - E->getNameQualifier()->NNS = Reader.ReadNestedNameSpecifier(Record, Idx); - E->getNameQualifier()->Range = ReadSourceRange(Record, Idx); - } + E->DeclRefExprBits.HasQualifier = Record[Idx++]; + E->DeclRefExprBits.HasFoundDecl = Record[Idx++]; + E->DeclRefExprBits.HasExplicitTemplateArgs = Record[Idx++]; + unsigned NumTemplateArgs = 0; + if (E->hasExplicitTemplateArgs()) + NumTemplateArgs = Record[Idx++]; - if (HasExplicitTemplateArgs) { - unsigned NumTemplateArgs = Record[Idx++]; + if (E->hasQualifier()) + E->getInternalQualifierLoc() + = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); + + if (E->hasFoundDecl()) + E->getInternalFoundDecl() = cast(Reader.GetDecl(Record[Idx++])); + + if (E->hasExplicitTemplateArgs()) ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), NumTemplateArgs); - } E->setDecl(cast(Reader.GetDecl(Record[Idx++]))); E->setLocation(ReadSourceLocation(Record, Idx)); @@ -468,7 +472,8 @@ void ASTStmtReader::VisitStringLiteral(StringLiteral *E) { assert(Record[Idx] == E->getNumConcatenated() && "Wrong number of concatenated tokens!"); ++Idx; - E->setWide(Record[Idx++]); + E->IsWide = Record[Idx++]; + E->IsPascal = Record[Idx++]; // Read string data llvm::SmallString<16> Str(&Record[Idx], &Record[Idx] + Len); @@ -555,9 +560,9 @@ void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { E->setIndexExpr(I, Reader.ReadSubExpr()); } -void ASTStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { +void ASTStmtReader::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { VisitExpr(E); - E->setSizeof(Record[Idx++]); + E->setKind(static_cast(Record[Idx++])); if (Record[Idx] == 0) { E->setArgument(Reader.ReadSubExpr()); ++Idx; @@ -680,16 +685,29 @@ void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { VisitExpr(E); - unsigned NumInits = Record[Idx++]; - E->reserveInits(*Reader.getContext(), NumInits); - for (unsigned I = 0; I != NumInits; ++I) - E->updateInit(*Reader.getContext(), I, Reader.ReadSubExpr()); E->setSyntacticForm(cast_or_null(Reader.ReadSubStmt())); E->setLBraceLoc(ReadSourceLocation(Record, Idx)); E->setRBraceLoc(ReadSourceLocation(Record, Idx)); - E->setInitializedFieldInUnion( - cast_or_null(Reader.GetDecl(Record[Idx++]))); + bool isArrayFiller = Record[Idx++]; + Expr *filler = 0; + if (isArrayFiller) { + filler = Reader.ReadSubExpr(); + E->ArrayFillerOrUnionFieldInit = filler; + } else + E->ArrayFillerOrUnionFieldInit + = cast_or_null(Reader.GetDecl(Record[Idx++])); E->sawArrayRangeDesignator(Record[Idx++]); + unsigned NumInits = Record[Idx++]; + E->reserveInits(*Reader.getContext(), NumInits); + if (isArrayFiller) { + for (unsigned I = 0; I != NumInits; ++I) { + Expr *init = Reader.ReadSubExpr(); + E->updateInit(*Reader.getContext(), I, init ? init : filler); + } + } else { + for (unsigned I = 0; I != NumInits; ++I) + E->updateInit(*Reader.getContext(), I, Reader.ReadSubExpr()); + } } void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { @@ -820,6 +838,25 @@ void ASTStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { E->setConstQualAdded(Record[Idx++]); } +void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { + VisitExpr(E); + E->NumAssocs = Record[Idx++]; + E->AssocTypes = new (*Reader.getContext()) TypeSourceInfo*[E->NumAssocs]; + E->SubExprs = + new(*Reader.getContext()) Stmt*[GenericSelectionExpr::END_EXPR+E->NumAssocs]; + + E->SubExprs[GenericSelectionExpr::CONTROLLING] = Reader.ReadSubExpr(); + for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { + E->AssocTypes[I] = GetTypeSourceInfo(Record, Idx); + E->SubExprs[GenericSelectionExpr::END_EXPR+I] = Reader.ReadSubExpr(); + } + E->ResultIndex = Record[Idx++]; + + E->GenericLoc = ReadSourceLocation(Record, Idx); + E->DefaultLoc = ReadSourceLocation(Record, Idx); + E->RParenLoc = ReadSourceLocation(Record, Idx); +} + //===----------------------------------------------------------------------===// // Objective-C Expressions and Statements @@ -998,6 +1035,19 @@ void ASTStmtReader::VisitCXXTryStmt(CXXTryStmt *S) { S->getStmts()[i + 1] = Reader.ReadSubStmt(); } +void ASTStmtReader::VisitCXXForRangeStmt(CXXForRangeStmt *S) { + VisitStmt(S); + S->setForLoc(ReadSourceLocation(Record, Idx)); + S->setColonLoc(ReadSourceLocation(Record, Idx)); + S->setRParenLoc(ReadSourceLocation(Record, Idx)); + S->setRangeStmt(Reader.ReadSubStmt()); + S->setBeginEndStmt(Reader.ReadSubStmt()); + S->setCond(Reader.ReadSubExpr()); + S->setInc(Reader.ReadSubExpr()); + S->setLoopVarStmt(Reader.ReadSubStmt()); + S->setBody(Reader.ReadSubStmt()); +} + void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); E->setOperator((OverloadedOperatorKind)Record[Idx++]); @@ -1201,14 +1251,13 @@ ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), Record[Idx++]); - E->setBase(Reader.ReadSubExpr()); - E->setBaseType(Reader.GetType(Record[Idx++])); - E->setArrow(Record[Idx++]); - E->setOperatorLoc(ReadSourceLocation(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(ReadSourceRange(Record, Idx)); - E->setFirstQualifierFoundInScope( - cast_or_null(Reader.GetDecl(Record[Idx++]))); + E->Base = Reader.ReadSubExpr(); + E->BaseType = Reader.GetType(Record[Idx++]); + E->IsArrow = Record[Idx++]; + E->OperatorLoc = ReadSourceLocation(Record, Idx); + E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); + E->FirstQualifierFoundInScope + = cast_or_null(Reader.GetDecl(Record[Idx++])); ReadDeclarationNameInfo(E->MemberNameInfo, Record, Idx); } @@ -1254,24 +1303,25 @@ void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { E->initializeResults(*Reader.getContext(), Decls.begin(), Decls.end()); ReadDeclarationNameInfo(E->NameInfo, Record, Idx); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(ReadSourceRange(Record, Idx)); + E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); } void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { VisitOverloadExpr(E); - E->setArrow(Record[Idx++]); - E->setHasUnresolvedUsing(Record[Idx++]); - E->setBase(Reader.ReadSubExpr()); - E->setBaseType(Reader.GetType(Record[Idx++])); - E->setOperatorLoc(ReadSourceLocation(Record, Idx)); + E->IsArrow = Record[Idx++]; + E->HasUnresolvedUsing = Record[Idx++]; + E->Base = Reader.ReadSubExpr(); + E->BaseType = Reader.GetType(Record[Idx++]); + E->OperatorLoc = ReadSourceLocation(Record, Idx); } void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); - E->setRequiresADL(Record[Idx++]); - E->setOverloaded(Record[Idx++]); - E->setNamingClass(cast_or_null(Reader.GetDecl(Record[Idx++]))); + E->RequiresADL = Record[Idx++]; + if (E->RequiresADL) + E->StdIsAssociatedNamespace = Record[Idx++]; + E->Overloaded = Record[Idx++]; + E->NamingClass = cast_or_null(Reader.GetDecl(Record[Idx++])); } void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { @@ -1295,6 +1345,26 @@ void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { E->RhsType = GetTypeSourceInfo(Record, Idx); } +void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + VisitExpr(E); + E->ATT = (ArrayTypeTrait)Record[Idx++]; + E->Value = (unsigned int)Record[Idx++]; + SourceRange Range = ReadSourceRange(Record, Idx); + E->Loc = Range.getBegin(); + E->RParen = Range.getEnd(); + E->QueriedType = GetTypeSourceInfo(Record, Idx); +} + +void ASTStmtReader::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { + VisitExpr(E); + E->ET = (ExpressionTrait)Record[Idx++]; + E->Value = (bool)Record[Idx++]; + SourceRange Range = ReadSourceRange(Record, Idx); + E->QueriedExpression = Reader.ReadSubExpr(); + E->Loc = Range.getBegin(); + E->RParen = Range.getEnd(); +} + void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { VisitExpr(E); E->Value = (bool)Record[Idx++]; @@ -1500,12 +1570,13 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_DECL_REF: - S = DeclRefExpr::CreateEmpty(*Context, - /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], - /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1], - /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1] - ? Record[ASTStmtReader::NumExprFields + 2] - : 0); + S = DeclRefExpr::CreateEmpty( + *Context, + /*HasQualifier=*/Record[ASTStmtReader::NumExprFields], + /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], + /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2], + /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ? + Record[ASTStmtReader::NumExprFields + 3] : 0); break; case EXPR_INTEGER_LITERAL: @@ -1548,7 +1619,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { break; case EXPR_SIZEOF_ALIGN_OF: - S = new (Context) SizeOfAlignOfExpr(Empty); + S = new (Context) UnaryExprOrTypeTraitExpr(Empty); break; case EXPR_ARRAY_SUBSCRIPT: @@ -1565,11 +1636,9 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { // logic with a MemberExpr::CreateEmpty. assert(Idx == 0); - NestedNameSpecifier *NNS = 0; - SourceRange QualifierRange; + NestedNameSpecifierLoc QualifierLoc; if (Record[Idx++]) { // HasQualifier. - NNS = ReadNestedNameSpecifier(Record, Idx); - QualifierRange = ReadSourceRange(F, Record, Idx); + QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx); } TemplateArgumentListInfo ArgInfo; @@ -1595,7 +1664,7 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc); bool IsArrow = Record[Idx++]; - S = MemberExpr::Create(*Context, Base, IsArrow, NNS, QualifierRange, + S = MemberExpr::Create(*Context, Base, IsArrow, QualifierLoc, MemberD, FoundDecl, MemberNameInfo, HasExplicitTemplateArgs ? &ArgInfo : 0, T, VK, OK); ReadDeclarationNameLoc(F, cast(S)->MemberDNLoc, @@ -1683,6 +1752,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { S = new (Context) BlockDeclRefExpr(Empty); break; + case EXPR_GENERIC_SELECTION: + S = new (Context) GenericSelectionExpr(Empty); + break; + case EXPR_OBJC_STRING_LITERAL: S = new (Context) ObjCStringLiteral(Empty); break; @@ -1741,6 +1814,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { /*NumHandlers=*/Record[ASTStmtReader::NumStmtFields]); break; + case STMT_CXX_FOR_RANGE: + S = new (Context) CXXForRangeStmt(Empty); + break; + case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(*Context, Empty); break; @@ -1881,6 +1958,14 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { S = new (Context) BinaryTypeTraitExpr(Empty); break; + case EXPR_ARRAY_TYPE_TRAIT: + S = new (Context) ArrayTypeTraitExpr(Empty); + break; + + case EXPR_CXX_EXPRESSION_TRAIT: + S = new (Context) ExpressionTraitExpr(Empty); + break; + case EXPR_CXX_NOEXCEPT: S = new (Context) CXXNoexceptExpr(Empty); break; diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp index 383ca3dffc6c..6d44fb63e5a2 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp @@ -37,6 +37,7 @@ #include "clang/Basic/SourceManagerInternals.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" +#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/StringExtras.h" @@ -50,12 +51,16 @@ using namespace clang; using namespace clang::serialization; template -T *data(std::vector &v) { - return v.empty() ? 0 : &v.front(); +static llvm::StringRef data(const std::vector &v) { + if (v.empty()) return llvm::StringRef(); + return llvm::StringRef(reinterpret_cast(&v[0]), + sizeof(T) * v.size()); } -template -const T *data(const std::vector &v) { - return v.empty() ? 0 : &v.front(); + +template +static llvm::StringRef data(const llvm::SmallVectorImpl &v) { + return llvm::StringRef(reinterpret_cast(v.data()), + sizeof(T) * v.size()); } //===----------------------------------------------------------------------===// @@ -104,12 +109,13 @@ void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) { } void ASTTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); + Writer.AddTypeRef(T->getPointeeTypeAsWritten(), Record); + Record.push_back(T->isSpelledAsLValue()); Code = TYPE_LVALUE_REFERENCE; } void ASTTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); + Writer.AddTypeRef(T->getPointeeTypeAsWritten(), Record); Code = TYPE_RVALUE_REFERENCE; } @@ -160,6 +166,7 @@ void ASTTypeWriter::VisitFunctionType(const FunctionType *T) { Writer.AddTypeRef(T->getResultType(), Record); FunctionType::ExtInfo C = T->getExtInfo(); Record.push_back(C.getNoReturn()); + Record.push_back(C.getHasRegParm()); Record.push_back(C.getRegParm()); // FIXME: need to stabilize encoding of calling convention... Record.push_back(C.getCC()); @@ -178,11 +185,14 @@ void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { Record.push_back(T->isVariadic()); Record.push_back(T->getTypeQuals()); Record.push_back(static_cast(T->getRefQualifier())); - Record.push_back(T->hasExceptionSpec()); - Record.push_back(T->hasAnyExceptionSpec()); - Record.push_back(T->getNumExceptions()); - for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) - Writer.AddTypeRef(T->getExceptionType(I), Record); + Record.push_back(T->getExceptionSpecType()); + if (T->getExceptionSpecType() == EST_Dynamic) { + Record.push_back(T->getNumExceptions()); + for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) + Writer.AddTypeRef(T->getExceptionType(I), Record); + } else if (T->getExceptionSpecType() == EST_ComputedNoexcept) { + Writer.AddStmt(T->getNoexceptExpr()); + } Code = TYPE_FUNCTION_PROTO; } @@ -293,7 +303,7 @@ ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { Record.push_back(T->getDepth()); Record.push_back(T->getIndex()); Record.push_back(T->isParameterPack()); - Writer.AddIdentifierRef(T->getName(), Record); + Writer.AddDeclRef(T->getDecl(), Record); Code = TYPE_TEMPLATE_TYPE_PARM; } @@ -418,6 +428,7 @@ void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { } void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { Writer.AddSourceLocation(TL.getStarLoc(), Record); + Writer.AddTypeSourceInfo(TL.getClassTInfo(), Record); } void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) { Writer.AddSourceLocation(TL.getLBracketLoc(), Record); @@ -450,8 +461,8 @@ void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { - Writer.AddSourceLocation(TL.getLParenLoc(), Record); - Writer.AddSourceLocation(TL.getRParenLoc(), Record); + Writer.AddSourceLocation(TL.getLocalRangeBegin(), Record); + Writer.AddSourceLocation(TL.getLocalRangeEnd(), Record); Record.push_back(TL.getTrailingReturn()); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) Writer.AddDeclRef(TL.getArg(i), Record); @@ -532,20 +543,20 @@ void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) { } void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); + Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); } void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); + Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); Writer.AddSourceLocation(TL.getNameLoc(), Record); } void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); + Writer.AddNestedNameSpecifierLoc(TL.getQualifierLoc(), Record); Writer.AddSourceLocation(TL.getNameLoc(), Record); Writer.AddSourceLocation(TL.getLAngleLoc(), Record); Writer.AddSourceLocation(TL.getRAngleLoc(), Record); @@ -652,6 +663,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_SHUFFLE_VECTOR); RECORD(EXPR_BLOCK); RECORD(EXPR_BLOCK_DECL_REF); + RECORD(EXPR_GENERIC_SELECTION); RECORD(EXPR_OBJC_STRING_LITERAL); RECORD(EXPR_OBJC_ENCODE); RECORD(EXPR_OBJC_SELECTOR_EXPR); @@ -1000,6 +1012,7 @@ void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.Digraphs); // C94, C99 and C++ Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants. Record.push_back(LangOpts.C99); // C99 Support + Record.push_back(LangOpts.C1X); // C1X Support Record.push_back(LangOpts.Microsoft); // Microsoft extensions. // LangOpts.MSCVersion is ignored because all it does it set a macro, which is // already saved elsewhere. @@ -1054,6 +1067,7 @@ void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be // used (instead of C99 semantics). Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined. + Record.push_back(LangOpts.Deprecated); // Should __DEPRECATED be defined. Record.push_back(LangOpts.AccessControl); // Whether C++ access control should // be enabled. Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or @@ -1072,6 +1086,7 @@ void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.DefaultFPContract); Record.push_back(LangOpts.ElideConstructors); Record.push_back(LangOpts.SpellChecking); + Record.push_back(LangOpts.MRTD); Stream.EmitRecord(LANGUAGE_OPTIONS, Record); } @@ -1427,7 +1442,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Figure out which record code to use. unsigned Code; if (SLoc->isFile()) { - if (SLoc->getFile().getContentCache()->Entry) + if (SLoc->getFile().getContentCache()->OrigEntry) Code = SM_SLOC_FILE_ENTRY; else Code = SM_SLOC_BUFFER_ENTRY; @@ -1444,17 +1459,27 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.push_back(File.hasLineDirectives()); const SrcMgr::ContentCache *Content = File.getContentCache(); - if (Content->Entry) { + if (Content->OrigEntry) { + assert(Content->OrigEntry == Content->ContentsEntry && + "Writing to AST an overriden file is not supported"); + // The source location entry is a file. The blob associated // with this entry is the file name. // Emit size/modification time for this file. - Record.push_back(Content->Entry->getSize()); - Record.push_back(Content->Entry->getModificationTime()); + Record.push_back(Content->OrigEntry->getSize()); + Record.push_back(Content->OrigEntry->getModificationTime()); // Turn the file name into an absolute path, if it isn't already. - const char *Filename = Content->Entry->getName(); + const char *Filename = Content->OrigEntry->getName(); llvm::SmallString<128> FilePath(Filename); + + // Ask the file manager to fixup the relative path for us. This will + // honor the working directory. + SourceMgr.getFileManager().FixupRelativePath(FilePath); + + // FIXME: This call to make_absolute shouldn't be necessary, the + // call to FixupRelativePath should always return an absolute path. llvm::sys::fs::make_absolute(FilePath); Filename = FilePath.c_str(); @@ -1517,9 +1542,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.push_back(SLocEntryOffsets.size()); unsigned BaseOffset = Chain ? Chain->getNextSLocOffset() : 0; Record.push_back(SourceMgr.getNextOffset() - BaseOffset); - Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, - (const char *)data(SLocEntryOffsets), - SLocEntryOffsets.size()*sizeof(SLocEntryOffsets[0])); + Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, data(SLocEntryOffsets)); // Write the source location entry preloads array, telling the AST // reader which source locations entries it should load eagerly. @@ -1778,8 +1801,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { Record.push_back(NumPreprocessingRecords); Record.push_back(MacroDefinitionOffsets.size()); Stream.EmitRecordWithBlob(MacroDefOffsetAbbrev, Record, - (const char *)data(MacroDefinitionOffsets), - MacroDefinitionOffsets.size() * sizeof(uint32_t)); + data(MacroDefinitionOffsets)); } } @@ -1809,6 +1831,29 @@ void ASTWriter::WritePragmaDiagnosticMappings(const Diagnostic &Diag) { Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record); } +void ASTWriter::WriteCXXBaseSpecifiersOffsets() { + if (CXXBaseSpecifiersOffsets.empty()) + return; + + RecordData Record; + + // Create a blob abbreviation for the C++ base specifiers offsets. + using namespace llvm; + + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(CXX_BASE_SPECIFIER_OFFSETS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned BaseSpecifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + + // Write the selector offsets table. + Record.clear(); + Record.push_back(CXX_BASE_SPECIFIER_OFFSETS); + Record.push_back(CXXBaseSpecifiersOffsets.size()); + Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record, + data(CXXBaseSpecifiersOffsets)); +} + //===----------------------------------------------------------------------===// // Type Serialization //===----------------------------------------------------------------------===// @@ -1881,9 +1926,7 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, Decls.push_back(std::make_pair((*D)->getKind(), GetDeclRef(*D))); ++NumLexicalDeclContexts; - Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, - reinterpret_cast(Decls.data()), - Decls.size() * sizeof(KindDeclIDPair)); + Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, data(Decls)); return Offset; } @@ -1900,9 +1943,7 @@ void ASTWriter::WriteTypeDeclOffsets() { Record.clear(); Record.push_back(TYPE_OFFSET); Record.push_back(TypeOffsets.size()); - Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, - (const char *)data(TypeOffsets), - TypeOffsets.size() * sizeof(TypeOffsets[0])); + Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, data(TypeOffsets)); // Write the declaration offsets array Abbrev = new BitCodeAbbrev(); @@ -1913,9 +1954,7 @@ void ASTWriter::WriteTypeDeclOffsets() { Record.clear(); Record.push_back(DECL_OFFSET); Record.push_back(DeclOffsets.size()); - Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, - (const char *)data(DeclOffsets), - DeclOffsets.size() * sizeof(DeclOffsets[0])); + Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets)); } //===----------------------------------------------------------------------===// @@ -2102,8 +2141,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { Record.push_back(SELECTOR_OFFSETS); Record.push_back(SelectorOffsets.size()); Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record, - (const char *)data(SelectorOffsets), - SelectorOffsets.size() * 4); + data(SelectorOffsets)); } } @@ -2305,8 +2343,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) { Record.push_back(IDENTIFIER_OFFSET); Record.push_back(IdentifierOffsets.size()); Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record, - (const char *)data(IdentifierOffsets), - IdentifierOffsets.size() * sizeof(uint32_t)); + data(IdentifierOffsets)); } //===----------------------------------------------------------------------===// @@ -2583,6 +2620,19 @@ void ASTWriter::AddString(llvm::StringRef Str, RecordDataImpl &Record) { Record.insert(Record.end(), Str.begin(), Str.end()); } +void ASTWriter::AddVersionTuple(const VersionTuple &Version, + RecordDataImpl &Record) { + Record.push_back(Version.getMajor()); + if (llvm::Optional Minor = Version.getMinor()) + Record.push_back(*Minor + 1); + else + Record.push_back(0); + if (llvm::Optional Subminor = Version.getSubminor()) + Record.push_back(*Subminor + 1); + else + Record.push_back(0); +} + /// \brief Note that the identifier II occurs at the given offset /// within the identifier table. void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { @@ -2770,6 +2820,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, AddTypeRef(Context.ObjCSelRedefinitionType, Record); AddTypeRef(Context.getRawNSConstantStringType(), Record); Record.push_back(Context.isInt128Installed()); + AddTypeRef(Context.AutoDeductTy, Record); + AddTypeRef(Context.AutoRRefDeductTy, Record); Stream.EmitRecord(SPECIAL_TYPES, Record); // Keep writing types and declarations until all types and @@ -2797,25 +2849,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, WriteTypeDeclOffsets(); WritePragmaDiagnosticMappings(Context.getDiagnostics()); - // Write the C++ base-specifier set offsets. - if (!CXXBaseSpecifiersOffsets.empty()) { - // Create a blob abbreviation for the C++ base specifiers offsets. - using namespace llvm; - - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(CXX_BASE_SPECIFIER_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned BaseSpecifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the selector offsets table. - Record.clear(); - Record.push_back(CXX_BASE_SPECIFIER_OFFSETS); - Record.push_back(CXXBaseSpecifiersOffsets.size()); - Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record, - (const char *)CXXBaseSpecifiersOffsets.data(), - CXXBaseSpecifiersOffsets.size() * sizeof(uint32_t)); - } + WriteCXXBaseSpecifiersOffsets(); // Write the record containing external, unnamed definitions. if (!ExternalDefinitions.empty()) @@ -2911,8 +2945,7 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, Record.clear(); Record.push_back(TU_UPDATE_LEXICAL); Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, - reinterpret_cast(NewGlobalDecls.data()), - NewGlobalDecls.size() * sizeof(KindDeclIDPair)); + data(NewGlobalDecls)); // And a visible updates block for the DeclContexts. Abv = new llvm::BitCodeAbbrev(); Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); @@ -2997,10 +3030,8 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, for (std::deque::iterator I = SemaRef.PendingInstantiations.begin(), N = SemaRef.PendingInstantiations.end(); I != N; ++I) { - if (I->first->getPCHLevel() == 0) { - AddDeclRef(I->first, PendingInstantiations); - AddSourceLocation(I->second, PendingInstantiations); - } + AddDeclRef(I->first, PendingInstantiations); + AddSourceLocation(I->second, PendingInstantiations); } assert(SemaRef.PendingLocalImplicitInstantiations.empty() && "There are local ones at end of translation unit!"); @@ -3040,6 +3071,8 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, // write all of them again). WritePragmaDiagnosticMappings(Context.getDiagnostics()); + WriteCXXBaseSpecifiersOffsets(); + /// Build a record containing first declarations from a chained PCH and the /// most recent declarations in this AST that they point to. RecordData FirstLatestDeclIDs; @@ -3245,11 +3278,11 @@ void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record); break; case TemplateArgument::Template: - AddSourceRange(Arg.getTemplateQualifierRange(), Record); + AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc(), Record); AddSourceLocation(Arg.getTemplateNameLoc(), Record); break; case TemplateArgument::TemplateExpansion: - AddSourceRange(Arg.getTemplateQualifierRange(), Record); + AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc(), Record); AddSourceLocation(Arg.getTemplateNameLoc(), Record); AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record); break; @@ -3452,7 +3485,7 @@ void ASTWriter::AddQualifierInfo(const QualifierInfo &Info, void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record) { // Nested name specifiers usually aren't too long. I think that 8 would - // typically accomodate the vast majority. + // typically accommodate the vast majority. llvm::SmallVector NestedNames; // Push each of the NNS's onto a stack for serialization in reverse order. @@ -3495,7 +3528,7 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, void ASTWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, RecordDataImpl &Record) { // Nested name specifiers usually aren't too long. I think that 8 would - // typically accomodate the vast majority. + // typically accommodate the vast majority. llvm::SmallVector NestedNames; // Push each of the nested-name-specifiers's onto a stack for @@ -3749,10 +3782,19 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.Empty); Record.push_back(Data.Polymorphic); Record.push_back(Data.Abstract); + Record.push_back(Data.IsStandardLayout); + Record.push_back(Data.HasNoNonEmptyBases); + Record.push_back(Data.HasPrivateFields); + Record.push_back(Data.HasProtectedFields); + Record.push_back(Data.HasPublicFields); Record.push_back(Data.HasTrivialConstructor); + Record.push_back(Data.HasConstExprNonCopyMoveConstructor); Record.push_back(Data.HasTrivialCopyConstructor); + Record.push_back(Data.HasTrivialMoveConstructor); Record.push_back(Data.HasTrivialCopyAssignment); + Record.push_back(Data.HasTrivialMoveAssignment); Record.push_back(Data.HasTrivialDestructor); + Record.push_back(Data.HasNonLiteralTypeFieldsOrBases); Record.push_back(Data.ComputedVisibleConversions); Record.push_back(Data.DeclaredDefaultConstructor); Record.push_back(Data.DeclaredCopyConstructor); @@ -3897,4 +3939,37 @@ void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, AddDeclRef(D, Record); } +void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D) { + // The specializations set is kept in the canonical template. + TD = TD->getCanonicalDecl(); + if (!(D->getPCHLevel() == 0 && TD->getPCHLevel() > 0)) + return; // Not a source specialization added to a template from PCH. + + UpdateRecord &Record = DeclUpdates[TD]; + Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION); + AddDeclRef(D, Record); +} + +void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { + if (D->getPCHLevel() == 0) + return; // Declaration not imported from PCH. + + // Implicit decl from a PCH was defined. + // FIXME: Should implicit definition be a separate FunctionDecl? + RewriteDecl(D); +} + +void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { + if (D->getPCHLevel() == 0) + return; + + // Since the actual instantiation is delayed, this really means that we need + // to update the instantiation location. + UpdateRecord &Record = DeclUpdates[D]; + Record.push_back(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER); + AddSourceLocation( + D->getMemberSpecializationInfo()->getPointOfInstantiation(), Record); +} + ASTSerializationListener::~ASTSerializationListener() { } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp index 12d1226be94e..1ca00a32f820 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Serialization/ASTWriter.h" +#include "ASTCommon.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" @@ -21,6 +22,7 @@ #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; +using namespace serialization; //===----------------------------------------------------------------------===// // Declaration serialization @@ -53,6 +55,7 @@ namespace clang { void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *D); void VisitTypedefDecl(TypedefDecl *D); + void VisitTypeAliasDecl(TypeAliasDecl *D); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); void VisitTagDecl(TagDecl *D); void VisitEnumDecl(EnumDecl *D); @@ -140,6 +143,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) { Writer.WriteAttributes(D->getAttrs(), Record); Record.push_back(D->isImplicit()); Record.push_back(D->isUsed(false)); + Record.push_back(D->isReferenced()); Record.push_back(D->getAccess()); Record.push_back(D->getPCHLevel()); } @@ -157,6 +161,7 @@ void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) { void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { VisitNamedDecl(D); + Writer.AddSourceLocation(D->getLocStart(), Record); Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); } @@ -166,6 +171,12 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { Code = serialization::DECL_TYPEDEF; } +void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { + VisitTypeDecl(D); + Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); + Code = serialization::DECL_TYPEALIAS; +} + void ASTDeclWriter::VisitTagDecl(TagDecl *D) { VisitTypeDecl(D); VisitRedeclarable(D); @@ -174,12 +185,11 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) { Record.push_back(D->isDefinition()); Record.push_back(D->isEmbeddedInDeclarator()); Writer.AddSourceLocation(D->getRBraceLoc(), Record); - Writer.AddSourceLocation(D->getTagKeywordLoc(), Record); Record.push_back(D->hasExtInfo()); if (D->hasExtInfo()) Writer.AddQualifierInfo(*D->getExtInfo(), Record); else - Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record); + Writer.AddDeclRef(D->getTypedefNameForAnonDecl(), Record); } void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { @@ -221,6 +231,7 @@ void ASTDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) { void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { VisitValueDecl(D); + Writer.AddSourceLocation(D->getInnerLocStart(), Record); Record.push_back(D->hasExtInfo()); if (D->hasExtInfo()) Writer.AddQualifierInfo(*D->getExtInfo(), Record); @@ -552,6 +563,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(D->hasCXXDirectInitializer()); Record.push_back(D->isExceptionVariable()); Record.push_back(D->isNRVOVariable()); + Record.push_back(D->isCXXForRangeDecl()); Record.push_back(D->getInit() ? 1 : 0); if (D->getInit()) Writer.AddStmt(D->getInit()); @@ -575,7 +587,11 @@ void ASTDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) { void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { VisitVarDecl(D); + Record.push_back(D->isObjCMethodParameter()); + Record.push_back(D->getFunctionScopeDepth()); + Record.push_back(D->getFunctionScopeIndex()); Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding + Record.push_back(D->isKNRPromoted()); Record.push_back(D->hasInheritedDefaultArg()); Record.push_back(D->hasUninstantiatedDefaultArg()); if (D->hasUninstantiatedDefaultArg()) @@ -593,7 +609,9 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { D->getPCHLevel() == 0 && D->getStorageClass() == 0 && !D->hasCXXDirectInitializer() && // Can params have this ever? + D->getFunctionScopeDepth() == 0 && D->getObjCDeclQualifier() == 0 && + !D->isKNRPromoted() && !D->hasInheritedDefaultArg() && D->getInit() == 0 && !D->hasUninstantiatedDefaultArg()) // No default expr. @@ -613,6 +631,7 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { VisitDecl(D); Writer.AddStmt(D->getAsmString()); + Writer.AddSourceLocation(D->getRParenLoc(), Record); Code = serialization::DECL_FILE_SCOPE_ASM; } @@ -645,15 +664,15 @@ void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) { void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { VisitDecl(D); - // FIXME: It might be nice to serialize the brace locations for this - // declaration, which don't seem to be readily available in the AST. Record.push_back(D->getLanguage()); - Record.push_back(D->hasBraces()); + Writer.AddSourceLocation(D->getExternLoc(), Record); + Writer.AddSourceLocation(D->getRBraceLoc(), Record); Code = serialization::DECL_LINKAGE_SPEC; } void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) { VisitNamedDecl(D); + Writer.AddSourceLocation(D->getLocStart(), Record); Code = serialization::DECL_LABEL; } @@ -661,8 +680,8 @@ void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) { void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { VisitNamedDecl(D); Record.push_back(D->isInline()); - Writer.AddSourceLocation(D->getLBracLoc(), Record); - Writer.AddSourceLocation(D->getRBracLoc(), Record); + Writer.AddSourceLocation(D->getLocStart(), Record); + Writer.AddSourceLocation(D->getRBraceLoc(), Record); Writer.AddDeclRef(D->getNextNamespace(), Record); // Only write one reference--original or anonymous @@ -692,6 +711,20 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { } } } + + if (Writer.hasChain() && D->isAnonymousNamespace() && !D->getNextNamespace()){ + // This is a most recent reopening of the anonymous namespace. If its parent + // is in a previous PCH (or is the TU), mark that parent for update, because + // the original namespace always points to the latest re-opening of its + // anonymous namespace. + Decl *Parent = cast( + D->getParent()->getRedeclContext()->getPrimaryContext()); + if (Parent->getPCHLevel() > 0) { + ASTWriter::UpdateRecord &Record = Writer.DeclUpdates[Parent]; + Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE); + Writer.AddDeclRef(D, Record); + } + } } void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { @@ -743,7 +776,6 @@ void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { VisitTypeDecl(D); - Writer.AddSourceLocation(D->getUsingLoc(), Record); Writer.AddSourceLocation(D->getTypenameLoc(), Record); Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Code = serialization::DECL_UNRESOLVED_USING_TYPENAME; @@ -1001,7 +1033,6 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { VisitTypeDecl(D); Record.push_back(D->wasDeclaredWithTypename()); - Record.push_back(D->isParameterPack()); Record.push_back(D->defaultArgumentWasInherited()); Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record); @@ -1054,6 +1085,7 @@ void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) { VisitDecl(D); Writer.AddStmt(D->getAssertExpr()); Writer.AddStmt(D->getMessage()); + Writer.AddSourceLocation(D->getRParenLoc(), Record); Code = serialization::DECL_STATIC_ASSERT; } @@ -1121,6 +1153,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed + Abv->Add(BitCodeAbbrevOp(0)); // isReferenced Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier Abv->Add(BitCodeAbbrevOp(0)); // PCH level @@ -1130,6 +1163,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // ValueDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo Abv->Add(BitCodeAbbrevOp(serialization::PREDEF_TYPE_NULL_ID)); // InfoType // VarDecl @@ -1140,10 +1174,15 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable + Abv->Add(BitCodeAbbrevOp(0)); // isCXXForRangeDecl Abv->Add(BitCodeAbbrevOp(0)); // HasInit Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo // ParmVarDecl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsObjCMethodParameter + Abv->Add(BitCodeAbbrevOp(0)); // ScopeDepth + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ScopeIndex Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier + Abv->Add(BitCodeAbbrevOp(0)); // KNRPromoted Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp index af846a92800c..bd5889ad9299 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp @@ -68,7 +68,7 @@ namespace clang { void VisitParenListExpr(ParenListExpr *E); void VisitUnaryOperator(UnaryOperator *E); void VisitOffsetOfExpr(OffsetOfExpr *E); - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); + void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); void VisitArraySubscriptExpr(ArraySubscriptExpr *E); void VisitCallExpr(CallExpr *E); void VisitMemberExpr(MemberExpr *E); @@ -93,6 +93,7 @@ namespace clang { void VisitShuffleVectorExpr(ShuffleVectorExpr *E); void VisitBlockExpr(BlockExpr *E); void VisitBlockDeclRefExpr(BlockDeclRefExpr *E); + void VisitGenericSelectionExpr(GenericSelectionExpr *E); // Objective-C Expressions void VisitObjCStringLiteral(ObjCStringLiteral *E); @@ -115,6 +116,7 @@ namespace clang { // C++ Statements void VisitCXXCatchStmt(CXXCatchStmt *S); void VisitCXXTryStmt(CXXTryStmt *S); + void VisitCXXForRangeStmt(CXXForRangeStmt *); void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); void VisitCXXMemberCallExpr(CXXMemberCallExpr *E); @@ -151,6 +153,8 @@ namespace clang { void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E); + void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); + void VisitExpressionTraitExpr(ExpressionTraitExpr *E); void VisitCXXNoexceptExpr(CXXNoexceptExpr *E); void VisitPackExpansionExpr(PackExpansionExpr *E); void VisitSizeOfPackExpr(SizeOfPackExpr *E); @@ -177,7 +181,7 @@ void ASTStmtWriter::VisitStmt(Stmt *S) { void ASTStmtWriter::VisitNullStmt(NullStmt *S) { VisitStmt(S); Writer.AddSourceLocation(S->getSemiLoc(), Record); - Record.push_back(S->LeadingEmptyMacro); + Writer.AddSourceLocation(S->LeadingEmptyMacro, Record); Code = serialization::STMT_NULL; } @@ -380,19 +384,23 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { VisitExpr(E); Record.push_back(E->hasQualifier()); + Record.push_back(E->getDecl() != E->getFoundDecl()); Record.push_back(E->hasExplicitTemplateArgs()); - if (E->hasQualifier()) { - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - } - if (E->hasExplicitTemplateArgs()) { unsigned NumTemplateArgs = E->getNumTemplateArgs(); Record.push_back(NumTemplateArgs); - AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs()); } + if (E->hasQualifier()) + Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); + + if (E->getDecl() != E->getFoundDecl()) + Writer.AddDeclRef(E->getFoundDecl(), Record); + + if (E->hasExplicitTemplateArgs()) + AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs()); + Writer.AddDeclRef(E->getDecl(), Record); Writer.AddSourceLocation(E->getLocation(), Record); Writer.AddDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName(), Record); @@ -425,6 +433,7 @@ void ASTStmtWriter::VisitStringLiteral(StringLiteral *E) { Record.push_back(E->getByteLength()); Record.push_back(E->getNumConcatenated()); Record.push_back(E->isWide()); + Record.push_back(E->isPascal()); // FIXME: String data should be stored as a blob at the end of the // StringLiteral. However, we can't do so now because we have no // provision for coping with abbreviations when we're jumping around @@ -479,8 +488,8 @@ void ASTStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) { for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { const OffsetOfExpr::OffsetOfNode &ON = E->getComponent(I); Record.push_back(ON.getKind()); // FIXME: Stable encoding - Writer.AddSourceLocation(ON.getRange().getBegin(), Record); - Writer.AddSourceLocation(ON.getRange().getEnd(), Record); + Writer.AddSourceLocation(ON.getSourceRange().getBegin(), Record); + Writer.AddSourceLocation(ON.getSourceRange().getEnd(), Record); switch (ON.getKind()) { case OffsetOfExpr::OffsetOfNode::Array: Record.push_back(ON.getArrayExprIndex()); @@ -504,9 +513,9 @@ void ASTStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) { Code = serialization::EXPR_OFFSETOF; } -void ASTStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { +void ASTStmtWriter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { VisitExpr(E); - Record.push_back(E->isSizeOf()); + Record.push_back(E->getKind()); if (E->isArgumentType()) Writer.AddTypeSourceInfo(E->getArgumentTypeInfo(), Record); else { @@ -541,10 +550,8 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { // Don't call VisitExpr, we'll write everything here. Record.push_back(E->hasQualifier()); - if (E->hasQualifier()) { - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - } + if (E->hasQualifier()) + Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); Record.push_back(E->hasExplicitTemplateArgs()); if (E->hasExplicitTemplateArgs()) { @@ -666,14 +673,27 @@ void ASTStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) { VisitExpr(E); - Record.push_back(E->getNumInits()); - for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) - Writer.AddStmt(E->getInit(I)); Writer.AddStmt(E->getSyntacticForm()); Writer.AddSourceLocation(E->getLBraceLoc(), Record); Writer.AddSourceLocation(E->getRBraceLoc(), Record); - Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record); + bool isArrayFiller = E->ArrayFillerOrUnionFieldInit.is(); + Record.push_back(isArrayFiller); + if (isArrayFiller) + Writer.AddStmt(E->getArrayFiller()); + else + Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record); Record.push_back(E->hadArrayRangeDesignator()); + Record.push_back(E->getNumInits()); + if (isArrayFiller) { + // ArrayFiller may have filled "holes" due to designated initializer. + // Replace them by 0 to indicate that the filler goes in that place. + Expr *filler = E->getArrayFiller(); + for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) + Writer.AddStmt(E->getInit(I) != filler ? E->getInit(I) : 0); + } else { + for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) + Writer.AddStmt(E->getInit(I)); + } Code = serialization::EXPR_INIT_LIST; } @@ -785,6 +805,23 @@ void ASTStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { Code = serialization::EXPR_BLOCK_DECL_REF; } +void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { + VisitExpr(E); + Record.push_back(E->getNumAssocs()); + + Writer.AddStmt(E->getControllingExpr()); + for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { + Writer.AddTypeSourceInfo(E->getAssocTypeSourceInfo(I), Record); + Writer.AddStmt(E->getAssocExpr(I)); + } + Record.push_back(E->isResultDependent() ? -1U : E->getResultIndex()); + + Writer.AddSourceLocation(E->getGenericLoc(), Record); + Writer.AddSourceLocation(E->getDefaultLoc(), Record); + Writer.AddSourceLocation(E->getRParenLoc(), Record); + Code = serialization::EXPR_GENERIC_SELECTION; +} + //===----------------------------------------------------------------------===// // Objective-C Expressions and Statements. //===----------------------------------------------------------------------===// @@ -964,6 +1001,20 @@ void ASTStmtWriter::VisitCXXTryStmt(CXXTryStmt *S) { Code = serialization::STMT_CXX_TRY; } +void ASTStmtWriter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { + VisitStmt(S); + Writer.AddSourceLocation(S->getForLoc(), Record); + Writer.AddSourceLocation(S->getColonLoc(), Record); + Writer.AddSourceLocation(S->getRParenLoc(), Record); + Writer.AddStmt(S->getRangeStmt()); + Writer.AddStmt(S->getBeginEndStmt()); + Writer.AddStmt(S->getCond()); + Writer.AddStmt(S->getInc()); + Writer.AddStmt(S->getLoopVarStmt()); + Writer.AddStmt(S->getBody()); + Code = serialization::STMT_CXX_FOR_RANGE; +} + void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); Record.push_back(E->getOperator()); @@ -1196,8 +1247,7 @@ ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ Writer.AddTypeRef(E->getBaseType(), Record); Record.push_back(E->isArrow()); Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); + Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); Writer.AddDeclRef(E->getFirstQualifierFoundInScope(), Record); Writer.AddDeclarationNameInfo(E->MemberNameInfo, Record); Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER; @@ -1253,8 +1303,7 @@ void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) { } Writer.AddDeclarationNameInfo(E->NameInfo, Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); + Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); } void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { @@ -1270,6 +1319,8 @@ void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { VisitOverloadExpr(E); Record.push_back(E->requiresADL()); + if (E->requiresADL()) + Record.push_back(E->isStdAssociatedNamespace()); Record.push_back(E->isOverloaded()); Writer.AddDeclRef(E->getNamingClass(), Record); Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP; @@ -1294,6 +1345,24 @@ void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { Code = serialization::EXPR_BINARY_TYPE_TRAIT; } +void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + VisitExpr(E); + Record.push_back(E->getTrait()); + Record.push_back(E->getValue()); + Writer.AddSourceRange(E->getSourceRange(), Record); + Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(), Record); + Code = serialization::EXPR_ARRAY_TYPE_TRAIT; +} + +void ASTStmtWriter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { + VisitExpr(E); + Record.push_back(E->getTrait()); + Record.push_back(E->getValue()); + Writer.AddSourceRange(E->getSourceRange(), Record); + Writer.AddStmt(E->getQueriedExpression()); + Code = serialization::EXPR_CXX_EXPRESSION_TRAIT; +} + void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { VisitExpr(E); Record.push_back(E->getValue()); @@ -1424,7 +1493,7 @@ void ASTWriter::FlushStmts() { WriteSubStmt(StmtsToEmit[I]); assert(N == StmtsToEmit.size() && - "Substatement writen via AddStmt rather than WriteSubStmt!"); + "Substatement written via AddStmt rather than WriteSubStmt!"); // Note that we are at the end of a full expression. Any // expression records that follow this one are part of a different diff --git a/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp b/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp new file mode 100644 index 000000000000..da5be957a530 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Serialization/ChainedIncludesSource.cpp @@ -0,0 +1,235 @@ +//===- ChainedIncludesSource.cpp - Chained PCHs in Memory -------*- 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 ChainedIncludesSource class, which converts headers +// to chained PCHs in memory, mainly used for testing. +// +//===----------------------------------------------------------------------===// + +#include "clang/Serialization/ChainedIncludesSource.h" +#include "clang/Serialization/ASTReader.h" +#include "clang/Serialization/ASTWriter.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/ASTUnit.h" +#include "clang/Parse/ParseAST.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace clang; + +static ASTReader *createASTReader(CompilerInstance &CI, + llvm::StringRef pchFile, + llvm::MemoryBuffer **memBufs, + unsigned numBufs, + ASTDeserializationListener *deserialListener = 0) { + Preprocessor &PP = CI.getPreprocessor(); + llvm::OwningPtr Reader; + Reader.reset(new ASTReader(PP, &CI.getASTContext(), /*isysroot=*/0, + /*DisableValidation=*/true)); + Reader->setASTMemoryBuffers(memBufs, numBufs); + Reader->setDeserializationListener(deserialListener); + switch (Reader->ReadAST(pchFile, ASTReader::PCH)) { + case ASTReader::Success: + // Set the predefines buffer as suggested by the PCH reader. + PP.setPredefines(Reader->getSuggestedPredefines()); + return Reader.take(); + + case ASTReader::Failure: + case ASTReader::IgnorePCH: + break; + } + return 0; +} + +ChainedIncludesSource::~ChainedIncludesSource() { + for (unsigned i = 0, e = CIs.size(); i != e; ++i) + delete CIs[i]; +} + +ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { + + std::vector &includes = CI.getPreprocessorOpts().ChainedIncludes; + assert(!includes.empty() && "No '-chain-include' in options!"); + + llvm::OwningPtr source(new ChainedIncludesSource()); + InputKind IK = CI.getFrontendOpts().Inputs[0].first; + + llvm::SmallVector serialBufs; + + for (unsigned i = 0, e = includes.size(); i != e; ++i) { + bool firstInclude = (i == 0); + llvm::OwningPtr CInvok; + CInvok.reset(new CompilerInvocation(CI.getInvocation())); + + CInvok->getPreprocessorOpts().ChainedIncludes.clear(); + CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear(); + CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear(); + CInvok->getPreprocessorOpts().DisablePCHValidation = true; + CInvok->getPreprocessorOpts().Includes.clear(); + CInvok->getPreprocessorOpts().MacroIncludes.clear(); + CInvok->getPreprocessorOpts().Macros.clear(); + + CInvok->getFrontendOpts().Inputs.clear(); + CInvok->getFrontendOpts().Inputs.push_back(std::make_pair(IK, includes[i])); + + TextDiagnosticPrinter *DiagClient = + new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions()); + llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + llvm::IntrusiveRefCntPtr Diags(new Diagnostic(DiagID, + DiagClient)); + + llvm::OwningPtr Clang(new CompilerInstance()); + Clang->setInvocation(CInvok.take()); + Clang->setDiagnostics(Diags.getPtr()); + Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), + Clang->getTargetOpts())); + Clang->createFileManager(); + Clang->createSourceManager(Clang->getFileManager()); + Clang->createPreprocessor(); + Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(), + &Clang->getPreprocessor()); + Clang->createASTContext(); + + llvm::SmallVector serialAST; + llvm::raw_svector_ostream OS(serialAST); + llvm::OwningPtr consumer; + consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", + /*Chaining=*/!firstInclude, + /*isysroot=*/0, &OS)); + Clang->getASTContext().setASTMutationListener( + consumer->GetASTMutationListener()); + Clang->setASTConsumer(consumer.take()); + Clang->createSema(/*CompleteTranslationUnit=*/false, 0); + + if (firstInclude) { + Preprocessor &PP = Clang->getPreprocessor(); + PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), + PP.getLangOptions()); + } else { + assert(!serialBufs.empty()); + llvm::SmallVector bufs; + for (unsigned si = 0, se = serialBufs.size(); si != se; ++si) { + bufs.push_back(llvm::MemoryBuffer::getMemBufferCopy( + llvm::StringRef(serialBufs[si]->getBufferStart(), + serialBufs[si]->getBufferSize()))); + } + std::string pchName = includes[i-1]; + llvm::raw_string_ostream os(pchName); + os << ".pch" << i-1; + os.flush(); + llvm::OwningPtr Reader; + Reader.reset(createASTReader(*Clang, pchName, bufs.data(), bufs.size(), + Clang->getASTConsumer().GetASTDeserializationListener())); + if (!Reader) + return 0; + Clang->getASTContext().setExternalSource(Reader); + } + + if (!Clang->InitializeSourceManager(includes[i])) + return 0; + + ParseAST(Clang->getSema()); + OS.flush(); + Clang->getDiagnosticClient().EndSourceFile(); + serialBufs.push_back( + llvm::MemoryBuffer::getMemBufferCopy(llvm::StringRef(serialAST.data(), + serialAST.size()))); + source->CIs.push_back(Clang.take()); + } + + assert(!serialBufs.empty()); + std::string pchName = includes.back() + ".pch-final"; + llvm::OwningPtr Reader; + Reader.reset(createASTReader(CI, pchName, + serialBufs.data(), serialBufs.size())); + if (!Reader) + return 0; + + source->FinalReader.reset(Reader.take()); + return source.take(); +} + +//===----------------------------------------------------------------------===// +// ExternalASTSource interface. +//===----------------------------------------------------------------------===// + +Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) { + return getFinalReader().GetExternalDecl(ID); +} +Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) { + return getFinalReader().GetExternalSelector(ID); +} +uint32_t ChainedIncludesSource::GetNumExternalSelectors() { + return getFinalReader().GetNumExternalSelectors(); +} +Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) { + return getFinalReader().GetExternalDeclStmt(Offset); +} +CXXBaseSpecifier * +ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { + return getFinalReader().GetExternalCXXBaseSpecifiers(Offset); +} +DeclContextLookupResult +ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) { + return getFinalReader().FindExternalVisibleDeclsByName(DC, Name); +} +void ChainedIncludesSource::MaterializeVisibleDecls(const DeclContext *DC) { + return getFinalReader().MaterializeVisibleDecls(DC); +} +bool ChainedIncludesSource::FindExternalLexicalDecls(const DeclContext *DC, + bool (*isKindWeWant)(Decl::Kind), + llvm::SmallVectorImpl &Result) { + return getFinalReader().FindExternalLexicalDecls(DC, isKindWeWant, Result); +} +void ChainedIncludesSource::CompleteType(TagDecl *Tag) { + return getFinalReader().CompleteType(Tag); +} +void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) { + return getFinalReader().CompleteType(Class); +} +void ChainedIncludesSource::StartedDeserializing() { + return getFinalReader().StartedDeserializing(); +} +void ChainedIncludesSource::FinishedDeserializing() { + return getFinalReader().FinishedDeserializing(); +} +void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) { + return getFinalReader().StartTranslationUnit(Consumer); +} +void ChainedIncludesSource::PrintStats() { + return getFinalReader().PrintStats(); +} +void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{ + for (unsigned i = 0, e = CIs.size(); i != e; ++i) { + if (const ExternalASTSource *eSrc = + CIs[i]->getASTContext().getExternalSource()) { + eSrc->getMemoryBufferSizes(sizes); + } + } + + getFinalReader().getMemoryBufferSizes(sizes); +} + +void ChainedIncludesSource::InitializeSema(Sema &S) { + return getFinalReader().InitializeSema(S); +} +void ChainedIncludesSource::ForgetSema() { + return getFinalReader().ForgetSema(); +} +std::pair +ChainedIncludesSource::ReadMethodPool(Selector Sel) { + return getFinalReader().ReadMethodPool(Sel); +} +bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) { + return getFinalReader().LookupUnqualified(R, S); +} + diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp index 8832b053db00..8fc6d2a2933e 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp @@ -13,34 +13,25 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { class AdjustedReturnValueChecker : - public CheckerVisitor { + public Checker< check::PostStmt > { public: - AdjustedReturnValueChecker() {} - - void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE); - - static void *getTag() { - static int x = 0; return &x; - } + void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; }; } -void ento::RegisterAdjustedReturnValueChecker(ExprEngine &Eng) { - Eng.registerCheck(new AdjustedReturnValueChecker()); -} - -void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext &C, - const CallExpr *CE) { +void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE, + CheckerContext &C) const { // Get the result type of the call. QualType expectedResultTy = CE->getType(); @@ -94,3 +85,7 @@ void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext &C, C.generateNode(state->BindExpr(CE, V)); } } + +void ento::registerAdjustedReturnValueChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp index 7b68887f6640..983427afb62d 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp @@ -9,13 +9,13 @@ // This file reports various statistics about analyzer visitation. //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" -// FIXME: Restructure checker registration. -#include "ExperimentalChecks.h" - #include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallPtrSet.h" @@ -23,32 +23,20 @@ using namespace clang; using namespace ento; namespace { -class AnalyzerStatsChecker : public CheckerVisitor { +class AnalyzerStatsChecker : public Checker { public: - static void *getTag(); - void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng); - -private: - llvm::SmallPtrSet reachable; + void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const; }; } -void *AnalyzerStatsChecker::getTag() { - static int x = 0; - return &x; -} - -void ento::RegisterAnalyzerStatsChecker(ExprEngine &Eng) { - Eng.registerCheck(new AnalyzerStatsChecker()); -} - -void AnalyzerStatsChecker::VisitEndAnalysis(ExplodedGraph &G, +void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &B, - ExprEngine &Eng) { + ExprEngine &Eng) const { const CFG *C = 0; const Decl *D = 0; const LocationContext *LC = 0; const SourceManager &SM = B.getSourceManager(); + llvm::SmallPtrSet reachable; // Iterate over explodedgraph for (ExplodedGraph::node_iterator I = G.nodes_begin(); @@ -100,8 +88,8 @@ void AnalyzerStatsChecker::VisitEndAnalysis(ExplodedGraph &G, } output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: " - << unreachable << " | Aborted Block: " - << (Eng.wasBlockAborted() ? "yes" : "no") + << unreachable << " | Exhausted Block: " + << (Eng.wasBlocksExhausted() ? "yes" : "no") << " | Empty WorkList: " << (Eng.hasEmptyWorkList() ? "yes" : "no"); @@ -109,10 +97,10 @@ void AnalyzerStatsChecker::VisitEndAnalysis(ExplodedGraph &G, D->getLocation()); // Emit warning for each block we bailed out on - typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator; + typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator; const CoreEngine &CE = Eng.getCoreEngine(); - for (AbortedIterator I = CE.blocks_aborted_begin(), - E = CE.blocks_aborted_end(); I != E; ++I) { + for (ExhaustedIterator I = CE.blocks_exhausted_begin(), + E = CE.blocks_exhausted_end(); I != E; ++I) { const BlockEdge &BE = I->first; const CFGBlock *Exit = BE.getDst(); const CFGElement &CE = Exit->front(); @@ -121,3 +109,7 @@ void AnalyzerStatsChecker::VisitEndAnalysis(ExplodedGraph &G, "stopped analyzing at this point", CS->getStmt()->getLocStart()); } } + +void ento::registerAnalyzerStatsChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp index 25e224e50c68..eb9665a4a343 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -24,7 +24,7 @@ using namespace ento; namespace { class ArrayBoundChecker : - public CheckerV2 { + public Checker { mutable llvm::OwningPtr BT; public: void checkLocation(SVal l, bool isLoad, CheckerContext &C) const; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp index f803d27a2678..65a6e633dc8e 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -12,9 +12,11 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/AST/CharUnits.h" @@ -23,18 +25,16 @@ using namespace ento; namespace { class ArrayBoundCheckerV2 : - public CheckerVisitor { - BuiltinBug *BT; + public Checker { + mutable llvm::OwningPtr BT; enum OOB_Kind { OOB_Precedes, OOB_Excedes }; void reportOOB(CheckerContext &C, const GRState *errorState, - OOB_Kind kind); + OOB_Kind kind) const; public: - ArrayBoundCheckerV2() : BT(0) {} - static void *getTag() { static int x = 0; return &x; } - void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad); + void checkLocation(SVal l, bool isLoad, CheckerContext &C) const; }; // FIXME: Eventually replace RegionRawOffset with this class. @@ -62,13 +62,24 @@ class RegionRawOffsetV2 { }; } -void ento::RegisterArrayBoundCheckerV2(ExprEngine &Eng) { - Eng.registerCheck(new ArrayBoundCheckerV2()); +static SVal computeExtentBegin(SValBuilder &svalBuilder, + const MemRegion *region) { + while (true) + switch (region->getKind()) { + default: + return svalBuilder.makeZeroArrayIndex(); + case MemRegion::SymbolicRegionKind: + // FIXME: improve this later by tracking symbolic lower bounds + // for symbolic regions. + return UnknownVal(); + case MemRegion::ElementRegionKind: + region = cast(region)->getSuperRegion(); + continue; + } } -void ArrayBoundCheckerV2::visitLocation(CheckerContext &checkerContext, - const Stmt *S, - SVal location, bool isLoad) { +void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad, + CheckerContext &checkerContext) const { // NOTE: Instead of using GRState::assumeInBound(), we are prototyping // some new logic here that reasons directly about memory region extents. @@ -89,31 +100,36 @@ void ArrayBoundCheckerV2::visitLocation(CheckerContext &checkerContext, if (!rawOffset.getRegion()) return; - // CHECK LOWER BOUND: Is byteOffset < 0? If so, we are doing a load/store + // CHECK LOWER BOUND: Is byteOffset < extent begin? + // If so, we are doing a load/store // before the first valid offset in the memory region. - SVal lowerBound - = svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), - svalBuilder.makeZeroArrayIndex(), - svalBuilder.getConditionType()); + SVal extentBegin = computeExtentBegin(svalBuilder, rawOffset.getRegion()); + + if (isa(extentBegin)) { + SVal lowerBound + = svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), + cast(extentBegin), + svalBuilder.getConditionType()); - NonLoc *lowerBoundToCheck = dyn_cast(&lowerBound); - if (!lowerBoundToCheck) - return; + NonLoc *lowerBoundToCheck = dyn_cast(&lowerBound); + if (!lowerBoundToCheck) + return; - const GRState *state_precedesLowerBound, *state_withinLowerBound; - llvm::tie(state_precedesLowerBound, state_withinLowerBound) = + const GRState *state_precedesLowerBound, *state_withinLowerBound; + llvm::tie(state_precedesLowerBound, state_withinLowerBound) = state->assume(*lowerBoundToCheck); - // Are we constrained enough to definitely precede the lower bound? - if (state_precedesLowerBound && !state_withinLowerBound) { - reportOOB(checkerContext, state_precedesLowerBound, OOB_Precedes); - return; - } + // Are we constrained enough to definitely precede the lower bound? + if (state_precedesLowerBound && !state_withinLowerBound) { + reportOOB(checkerContext, state_precedesLowerBound, OOB_Precedes); + return; + } - // Otherwise, assume the constraint of the lower bound. - assert(state_withinLowerBound); - state = state_withinLowerBound; + // Otherwise, assume the constraint of the lower bound. + assert(state_withinLowerBound); + state = state_withinLowerBound; + } do { // CHECK UPPER BOUND: Is byteOffset >= extent(baseRegion)? If so, @@ -153,14 +169,14 @@ void ArrayBoundCheckerV2::visitLocation(CheckerContext &checkerContext, void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext, const GRState *errorState, - OOB_Kind kind) { + OOB_Kind kind) const { ExplodedNode *errorNode = checkerContext.generateSink(errorState); if (!errorNode) return; if (!BT) - BT = new BuiltinBug("Out-of-bound access"); + BT.reset(new BuiltinBug("Out-of-bound access")); // FIXME: This diagnostics are preliminary. We should get far better // diagnostics for explaining buffer overruns. @@ -237,9 +253,11 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(const GRState *state, while (region) { switch (region->getKind()) { default: { - if (const SubRegion *subReg = dyn_cast(region)) + if (const SubRegion *subReg = dyn_cast(region)) { + offset = getValue(offset, svalBuilder); if (!offset.isUnknownOrUndef()) return RegionRawOffsetV2(subReg, offset); + } return RegionRawOffsetV2(); } case MemRegion::ElementRegionKind: { @@ -274,4 +292,6 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(const GRState *state, } - +void ento::registerArrayBoundCheckerV2(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp index e4865b142c0c..d88a111e9a56 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp @@ -12,33 +12,27 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { class AttrNonNullChecker - : public CheckerVisitor { - BugType *BT; + : public Checker< check::PreStmt > { + mutable llvm::OwningPtr BT; public: - AttrNonNullChecker() : BT(0) {} - static void *getTag() { - static int x = 0; - return &x; - } - void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); + + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; }; } // end anonymous namespace -void ento::RegisterAttrNonNullChecker(ExprEngine &Eng) { - Eng.registerCheck(new AttrNonNullChecker()); -} - -void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C, - const CallExpr *CE) { +void AttrNonNullChecker::checkPreStmt(const CallExpr *CE, + CheckerContext &C) const { const GRState *state = C.getState(); // Check if the callee has a 'nonnull' attribute. @@ -103,8 +97,8 @@ void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C, // created. Ownership is transferred to the BugReporter object once // the BugReport is passed to 'EmitWarning'. if (!BT) - BT = new BugType("Argument with 'nonnull' attribute passed null", - "API"); + BT.reset(new BugType("Argument with 'nonnull' attribute passed null", + "API")); EnhancedBugReport *R = new EnhancedBugReport(*BT, @@ -134,3 +128,7 @@ void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C, // If 'state' has been updated generated a new node. C.addTransition(state); } + +void ento::registerAttrNonNullChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 7aff2010d84d..235b400eb9e3 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -13,10 +13,9 @@ // //===----------------------------------------------------------------------===// -#include "BasicObjCFoundationChecks.h" - #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/Analysis/DomainSpecific/CocoaConventions.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" @@ -24,7 +23,6 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" -#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" @@ -44,20 +42,21 @@ class APIMisuse : public BugType { // Utility functions. //===----------------------------------------------------------------------===// -static const ObjCInterfaceType* GetReceiverType(const ObjCMessage &msg) { - if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface()) - return ID->getTypeForDecl()->getAs(); - return NULL; -} - static const char* GetReceiverNameType(const ObjCMessage &msg) { - if (const ObjCInterfaceType *ReceiverType = GetReceiverType(msg)) - return ReceiverType->getDecl()->getIdentifier()->getNameStart(); - return NULL; + if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface()) + return ID->getIdentifier()->getNameStart(); + return 0; } -static bool isNSString(llvm::StringRef ClassName) { - return ClassName == "NSString" || ClassName == "NSMutableString"; +static bool isReceiverClassOrSuperclass(const ObjCInterfaceDecl *ID, + llvm::StringRef ClassName) { + if (ID->getIdentifier()->getName() == ClassName) + return true; + + if (const ObjCInterfaceDecl *Super = ID->getSuperClass()) + return isReceiverClassOrSuperclass(Super, ClassName); + + return false; } static inline bool isNil(SVal X) { @@ -69,7 +68,7 @@ static inline bool isNil(SVal X) { //===----------------------------------------------------------------------===// namespace { - class NilArgChecker : public CheckerV2 { + class NilArgChecker : public Checker { mutable llvm::OwningPtr BT; void WarnNilArg(CheckerContext &C, @@ -101,11 +100,11 @@ void NilArgChecker::WarnNilArg(CheckerContext &C, void NilArgChecker::checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const { - const ObjCInterfaceType *ReceiverType = GetReceiverType(msg); - if (!ReceiverType) + const ObjCInterfaceDecl *ID = msg.getReceiverInterface(); + if (!ID) return; - if (isNSString(ReceiverType->getDecl()->getIdentifier()->getName())) { + if (isReceiverClassOrSuperclass(ID, "NSString")) { Selector S = msg.getSelector(); if (S.isUnarySelector()) @@ -140,7 +139,7 @@ void NilArgChecker::checkPreObjCMessage(ObjCMessage msg, //===----------------------------------------------------------------------===// namespace { -class CFNumberCreateChecker : public CheckerV2< check::PreStmt > { +class CFNumberCreateChecker : public Checker< check::PreStmt > { mutable llvm::OwningPtr BT; mutable IdentifierInfo* II; public: @@ -347,7 +346,7 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE, //===----------------------------------------------------------------------===// namespace { -class CFRetainReleaseChecker : public CheckerV2< check::PreStmt > { +class CFRetainReleaseChecker : public Checker< check::PreStmt > { mutable llvm::OwningPtr BT; mutable IdentifierInfo *Retain, *Release; public: @@ -429,7 +428,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr* CE, //===----------------------------------------------------------------------===// namespace { -class ClassReleaseChecker : public CheckerV2 { +class ClassReleaseChecker : public Checker { mutable Selector releaseS; mutable Selector retainS; mutable Selector autoreleaseS; @@ -478,6 +477,165 @@ void ClassReleaseChecker::checkPreObjCMessage(ObjCMessage msg, } } +//===----------------------------------------------------------------------===// +// Check for passing non-Objective-C types to variadic methods that expect +// only Objective-C types. +//===----------------------------------------------------------------------===// + +namespace { +class VariadicMethodTypeChecker : public Checker { + mutable Selector arrayWithObjectsS; + mutable Selector dictionaryWithObjectsAndKeysS; + mutable Selector setWithObjectsS; + mutable Selector initWithObjectsS; + mutable Selector initWithObjectsAndKeysS; + mutable llvm::OwningPtr BT; + + bool isVariadicMessage(const ObjCMessage &msg) const; + +public: + void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; +}; +} + +/// isVariadicMessage - Returns whether the given message is a variadic message, +/// where all arguments must be Objective-C types. +bool +VariadicMethodTypeChecker::isVariadicMessage(const ObjCMessage &msg) const { + const ObjCMethodDecl *MD = msg.getMethodDecl(); + + if (!MD || !MD->isVariadic() || isa(MD->getDeclContext())) + return false; + + Selector S = msg.getSelector(); + + if (msg.isInstanceMessage()) { + // FIXME: Ideally we'd look at the receiver interface here, but that's not + // useful for init, because alloc returns 'id'. In theory, this could lead + // to false positives, for example if there existed a class that had an + // initWithObjects: implementation that does accept non-Objective-C pointer + // types, but the chance of that happening is pretty small compared to the + // gains that this analysis gives. + const ObjCInterfaceDecl *Class = MD->getClassInterface(); + + // -[NSArray initWithObjects:] + if (isReceiverClassOrSuperclass(Class, "NSArray") && + S == initWithObjectsS) + return true; + + // -[NSDictionary initWithObjectsAndKeys:] + if (isReceiverClassOrSuperclass(Class, "NSDictionary") && + S == initWithObjectsAndKeysS) + return true; + + // -[NSSet initWithObjects:] + if (isReceiverClassOrSuperclass(Class, "NSSet") && + S == initWithObjectsS) + return true; + } else { + const ObjCInterfaceDecl *Class = msg.getReceiverInterface(); + + // -[NSArray arrayWithObjects:] + if (isReceiverClassOrSuperclass(Class, "NSArray") && + S == arrayWithObjectsS) + return true; + + // -[NSDictionary dictionaryWithObjectsAndKeys:] + if (isReceiverClassOrSuperclass(Class, "NSDictionary") && + S == dictionaryWithObjectsAndKeysS) + return true; + + // -[NSSet setWithObjects:] + if (isReceiverClassOrSuperclass(Class, "NSSet") && + S == setWithObjectsS) + return true; + } + + return false; +} + +void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg, + CheckerContext &C) const { + if (!BT) { + BT.reset(new APIMisuse("Arguments passed to variadic method aren't all " + "Objective-C pointer types")); + + ASTContext &Ctx = C.getASTContext(); + arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx); + dictionaryWithObjectsAndKeysS = + GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx); + setWithObjectsS = GetUnarySelector("setWithObjects", Ctx); + + initWithObjectsS = GetUnarySelector("initWithObjects", Ctx); + initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx); + } + + if (!isVariadicMessage(msg)) + return; + + // We are not interested in the selector arguments since they have + // well-defined types, so the compiler will issue a warning for them. + unsigned variadicArgsBegin = msg.getSelector().getNumArgs(); + + // We're not interested in the last argument since it has to be nil or the + // compiler would have issued a warning for it elsewhere. + unsigned variadicArgsEnd = msg.getNumArgs() - 1; + + if (variadicArgsEnd <= variadicArgsBegin) + return; + + // Verify that all arguments have Objective-C types. + llvm::Optional errorNode; + const GRState *state = C.getState(); + + for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) { + QualType ArgTy = msg.getArgType(I); + if (ArgTy->isObjCObjectPointerType()) + continue; + + // Block pointers are treaded as Objective-C pointers. + if (ArgTy->isBlockPointerType()) + continue; + + // Ignore pointer constants. + if (isa(msg.getArgSVal(I, state))) + continue; + + // Ignore pointer types annotated with 'NSObject' attribute. + if (C.getASTContext().isObjCNSObjectType(ArgTy)) + continue; + + // Ignore CF references, which can be toll-free bridged. + if (cocoa::isCFObjectRef(ArgTy)) + continue; + + // Generate only one error node to use for all bug reports. + if (!errorNode.hasValue()) { + errorNode = C.generateNode(); + } + + if (!errorNode.getValue()) + continue; + + llvm::SmallString<128> sbuf; + llvm::raw_svector_ostream os(sbuf); + + if (const char *TypeName = GetReceiverNameType(msg)) + os << "Argument to '" << TypeName << "' method '"; + else + os << "Argument to method '"; + + os << msg.getSelector().getAsString() + << "' should be an Objective-C pointer type, not '" + << ArgTy.getAsString() << "'"; + + RangedBugReport *R = new RangedBugReport(*BT, os.str(), + errorNode.getValue()); + R->addRange(msg.getArgSourceRange(I)); + C.EmitReport(R); + } +} + //===----------------------------------------------------------------------===// // Check registration. //===----------------------------------------------------------------------===// @@ -497,3 +655,7 @@ void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) { void ento::registerClassReleaseChecker(CheckerManager &mgr) { mgr.registerChecker(); } + +void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.h deleted file mode 100644 index 92cfb1ae556c..000000000000 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.h +++ /dev/null @@ -1,35 +0,0 @@ -//== BasicObjCFoundationChecks.h - Simple Apple-Foundation checks -*- 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 BasicObjCFoundationChecks, a class that encapsulates -// a set of simple checks to run on Objective-C code using Apple's Foundation -// classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_GR_BASICOBJCFOUNDATIONCHECKS -#define LLVM_CLANG_GR_BASICOBJCFOUNDATIONCHECKS - -namespace clang { - -class ASTContext; -class Decl; - -namespace ento { - -class BugReporter; -class ExprEngine; - -void RegisterNSErrorChecks(BugReporter& BR, ExprEngine &Eng, const Decl &D); - -} // end GR namespace - -} // end clang namespace - -#endif diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index 417b015ca39a..12ac652ba060 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -11,8 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/Basic/Builtins.h" using namespace clang; @@ -20,19 +22,15 @@ using namespace ento; namespace { -class BuiltinFunctionChecker : public Checker { +class BuiltinFunctionChecker : public Checker { public: - static void *getTag() { static int tag = 0; return &tag; } - virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE); + bool evalCall(const CallExpr *CE, CheckerContext &C) const; }; } -void ento::RegisterBuiltinFunctionChecker(ExprEngine &Eng) { - Eng.registerCheck(new BuiltinFunctionChecker()); -} - -bool BuiltinFunctionChecker::evalCallExpr(CheckerContext &C,const CallExpr *CE){ +bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, + CheckerContext &C) const{ const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); SVal L = state->getSVal(Callee); @@ -81,3 +79,7 @@ bool BuiltinFunctionChecker::evalCallExpr(CheckerContext &C,const CallExpr *CE){ return false; } + +void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 2566e3cbb430..a6a256a87bcf 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -24,7 +24,7 @@ using namespace clang; using namespace ento; namespace { -class CStringChecker : public CheckerV2< eval::Call, +class CStringChecker : public Checker< eval::Call, check::PreStmt, check::LiveSymbols, check::DeadSymbols, @@ -49,11 +49,14 @@ class CStringChecker : public CheckerV2< eval::Call, const CallExpr *) const; void evalMemcpy(CheckerContext &C, const CallExpr *CE) const; + void evalMempcpy(CheckerContext &C, const CallExpr *CE) const; void evalMemmove(CheckerContext &C, const CallExpr *CE) const; void evalBcopy(CheckerContext &C, const CallExpr *CE) const; - void evalCopyCommon(CheckerContext &C, const GRState *state, + void evalCopyCommon(CheckerContext &C, const CallExpr *CE, + const GRState *state, const Expr *Size, const Expr *Source, const Expr *Dest, - bool Restricted = false) const; + bool Restricted = false, + bool IsMempcpy = false) const; void evalMemcmp(CheckerContext &C, const CallExpr *CE) const; @@ -66,7 +69,16 @@ class CStringChecker : public CheckerV2< eval::Call, void evalStrncpy(CheckerContext &C, const CallExpr *CE) const; void evalStpcpy(CheckerContext &C, const CallExpr *CE) const; void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd, - bool isStrncpy) const; + bool isBounded, bool isAppending) const; + + void evalStrcat(CheckerContext &C, const CallExpr *CE) const; + void evalStrncat(CheckerContext &C, const CallExpr *CE) const; + + void evalStrcmp(CheckerContext &C, const CallExpr *CE) const; + void evalStrncmp(CheckerContext &C, const CallExpr *CE) const; + void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const; + void evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, + bool isBounded = false, bool ignoreCase = false) const; // Utility methods std::pair @@ -81,6 +93,11 @@ class CStringChecker : public CheckerV2< eval::Call, SVal getCStringLength(CheckerContext &C, const GRState *&state, const Expr *Ex, SVal Buf) const; + const StringLiteral *getCStringLiteral(CheckerContext &C, + const GRState *&state, + const Expr *expr, + SVal val) const; + static const GRState *InvalidateBuffer(CheckerContext &C, const GRState *state, const Expr *Ex, SVal V); @@ -275,7 +292,7 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C, NonLoc LastOffset = cast(svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy)); - // Check that the first buffer is sufficently long. + // Check that the first buffer is sufficiently long. SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); if (Loc *BufLoc = dyn_cast(&BufStart)) { SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, @@ -581,6 +598,26 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, } } +const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C, + const GRState *&state, const Expr *expr, SVal val) const { + + // Get the memory region pointed to by the val. + const MemRegion *bufRegion = val.getAsRegion(); + if (!bufRegion) + return NULL; + + // Strip casts off the memory region. + bufRegion = bufRegion->StripCasts(); + + // Cast the memory region to a string region. + const StringRegion *strRegion= dyn_cast(bufRegion); + if (!strRegion) + return NULL; + + // Return the actual string in the string region. + return strRegion->getStringLiteral(); +} + const GRState *CStringChecker::InvalidateBuffer(CheckerContext &C, const GRState *state, const Expr *E, SVal V) { @@ -655,9 +692,12 @@ bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, // evaluation of individual function calls. //===----------------------------------------------------------------------===// -void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state, +void CStringChecker::evalCopyCommon(CheckerContext &C, + const CallExpr *CE, + const GRState *state, const Expr *Size, const Expr *Dest, - const Expr *Source, bool Restricted) const { + const Expr *Source, bool Restricted, + bool IsMempcpy) const { // See if the size argument is zero. SVal sizeVal = state->getSVal(Size); QualType sizeTy = Size->getType(); @@ -665,12 +705,39 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state, const GRState *stateZeroSize, *stateNonZeroSize; llvm::tie(stateZeroSize, stateNonZeroSize) = assumeZero(C, state, sizeVal, sizeTy); - // If the size is zero, there won't be any actual memory access. - if (stateZeroSize) + // Get the value of the Dest. + SVal destVal = state->getSVal(Dest); + + // If the size is zero, there won't be any actual memory access, so + // just bind the return value to the destination buffer and return. + if (stateZeroSize) { C.addTransition(stateZeroSize); + if (IsMempcpy) + state->BindExpr(CE, destVal); + else + state->BindExpr(CE, sizeVal); + return; + } // If the size can be nonzero, we have to check the other arguments. if (stateNonZeroSize) { + + // Ensure the destination is not null. If it is NULL there will be a + // NULL pointer dereference. + state = checkNonNull(C, state, Dest, destVal); + if (!state) + return; + + // Get the value of the Src. + SVal srcVal = state->getSVal(Source); + + // Ensure the source is not null. If it is NULL there will be a + // NULL pointer dereference. + state = checkNonNull(C, state, Source, srcVal); + if (!state) + return; + + // Ensure the buffers do not overlap. state = stateNonZeroSize; state = CheckBufferAccess(C, state, Size, Dest, Source, /* FirstIsDst = */ true); @@ -678,6 +745,26 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state, state = CheckOverlap(C, state, Size, Dest, Source); if (state) { + + // If this is mempcpy, get the byte after the last byte copied and + // bind the expr. + if (IsMempcpy) { + loc::MemRegionVal *destRegVal = dyn_cast(&destVal); + + // Get the length to copy. + SVal lenVal = state->getSVal(Size); + NonLoc *lenValNonLoc = dyn_cast(&lenVal); + + // Get the byte after the last byte copied. + SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, + *destRegVal, + *lenValNonLoc, + Dest->getType()); + + // The byte after the last byte copied is the return value. + state = state->BindExpr(CE, lastElement); + } + // Invalidate the destination. // FIXME: Even if we can't perfectly model the copy, we should see if we // can use LazyCompoundVals to copy the source values into the destination. @@ -696,7 +783,16 @@ void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { const Expr *Dest = CE->getArg(0); const GRState *state = C.getState(); state = state->BindExpr(CE, state->getSVal(Dest)); - evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true); + evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true); +} + +void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { + // void *mempcpy(void *restrict dst, const void *restrict src, size_t n); + // The return value is a pointer to the byte following the last written byte. + const Expr *Dest = CE->getArg(0); + const GRState *state = C.getState(); + + evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true); } void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { @@ -705,12 +801,13 @@ void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { const Expr *Dest = CE->getArg(0); const GRState *state = C.getState(); state = state->BindExpr(CE, state->getSVal(Dest)); - evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1)); + evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1)); } void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { // void bcopy(const void *src, void *dst, size_t n); - evalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0)); + evalCopyCommon(C, CE, C.getState(), + CE->getArg(2), CE->getArg(1), CE->getArg(0)); } void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { @@ -849,24 +946,50 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const { // char *strcpy(char *restrict dst, const char *restrict src); - evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ false); + evalStrcpyCommon(C, CE, + /* returnEnd = */ false, + /* isBounded = */ false, + /* isAppending = */ false); } void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const { // char *strcpy(char *restrict dst, const char *restrict src); - evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ true); + evalStrcpyCommon(C, CE, + /* returnEnd = */ false, + /* isBounded = */ true, + /* isAppending = */ false); } void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const { // char *stpcpy(char *restrict dst, const char *restrict src); - evalStrcpyCommon(C, CE, /* returnEnd = */ true, /* isStrncpy = */ false); + evalStrcpyCommon(C, CE, + /* returnEnd = */ true, + /* isBounded = */ false, + /* isAppending = */ false); +} + +void CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const { + //char *strcat(char *restrict s1, const char *restrict s2); + evalStrcpyCommon(C, CE, + /* returnEnd = */ false, + /* isBounded = */ false, + /* isAppending = */ true); +} + +void CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const { + //char *strncat(char *restrict s1, const char *restrict s2, size_t n); + evalStrcpyCommon(C, CE, + /* returnEnd = */ false, + /* isBounded = */ true, + /* isAppending = */ true); } void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, - bool returnEnd, bool isStrncpy) const { + bool returnEnd, bool isBounded, + bool isAppending) const { const GRState *state = C.getState(); - // Check that the destination is non-null + // Check that the destination is non-null. const Expr *Dst = CE->getArg(0); SVal DstVal = state->getSVal(Dst); @@ -888,18 +1011,26 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, if (strLength.isUndef()) return; - if (isStrncpy) { - // Get the max number of characters to copy + // If the function is strncpy, strncat, etc... it is bounded. + if (isBounded) { + // Get the max number of characters to copy. const Expr *lenExpr = CE->getArg(2); SVal lenVal = state->getSVal(lenExpr); + // Cast the length to a NonLoc SVal. If it is not a NonLoc then give up. NonLoc *strLengthNL = dyn_cast(&strLength); + if (!strLengthNL) + return; + + // Cast the max length to a NonLoc SVal. If it is not a NonLoc then give up. NonLoc *lenValNL = dyn_cast(&lenVal); + if (!lenValNL) + return; QualType cmpTy = C.getSValBuilder().getContext().IntTy; const GRState *stateTrue, *stateFalse; - // Check if the max number to copy is less than the length of the src + // Check if the max number to copy is less than the length of the src. llvm::tie(stateTrue, stateFalse) = state->assume(cast (C.getSValBuilder().evalBinOpNN(state, BO_GT, @@ -913,6 +1044,29 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, } } + // If this is an appending function (strcat, strncat...) then set the + // string length to strlen(src) + strlen(dst) since the buffer will + // ultimately contain both. + if (isAppending) { + // Get the string length of the destination, or give up. + SVal dstStrLength = getCStringLength(C, state, Dst, DstVal); + if (dstStrLength.isUndef()) + return; + + NonLoc *srcStrLengthNL = dyn_cast(&strLength); + NonLoc *dstStrLengthNL = dyn_cast(&dstStrLength); + + // If src or dst cast to NonLoc is NULL, give up. + if ((!srcStrLengthNL) || (!dstStrLengthNL)) + return; + + QualType addTy = C.getSValBuilder().getContext().getSizeType(); + + strLength = C.getSValBuilder().evalBinOpNN(state, BO_Add, + *srcStrLengthNL, *dstStrLengthNL, + addTy); + } + SVal Result = (returnEnd ? UnknownVal() : DstVal); // If the destination is a MemRegion, try to check for a buffer overflow and @@ -958,6 +1112,113 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, C.addTransition(state); } +void CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const { + //int strcmp(const char *restrict s1, const char *restrict s2); + evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ false); +} + +void CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const { + //int strncmp(const char *restrict s1, const char *restrict s2, size_t n); + evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ false); +} + +void CStringChecker::evalStrcasecmp(CheckerContext &C, + const CallExpr *CE) const { + //int strcasecmp(const char *restrict s1, const char *restrict s2); + evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true); +} + +void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, + bool isBounded, bool ignoreCase) const { + const GRState *state = C.getState(); + + // Check that the first string is non-null + const Expr *s1 = CE->getArg(0); + SVal s1Val = state->getSVal(s1); + state = checkNonNull(C, state, s1, s1Val); + if (!state) + return; + + // Check that the second string is non-null. + const Expr *s2 = CE->getArg(1); + SVal s2Val = state->getSVal(s2); + state = checkNonNull(C, state, s2, s2Val); + if (!state) + return; + + // Get the string length of the first string or give up. + SVal s1Length = getCStringLength(C, state, s1, s1Val); + if (s1Length.isUndef()) + return; + + // Get the string length of the second string or give up. + SVal s2Length = getCStringLength(C, state, s2, s2Val); + if (s2Length.isUndef()) + return; + + // Get the string literal of the first string. + const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val); + if (!s1StrLiteral) + return; + llvm::StringRef s1StrRef = s1StrLiteral->getString(); + + // Get the string literal of the second string. + const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val); + if (!s2StrLiteral) + return; + llvm::StringRef s2StrRef = s2StrLiteral->getString(); + + int result; + if (isBounded) { + // Get the max number of characters to compare. + const Expr *lenExpr = CE->getArg(2); + SVal lenVal = state->getSVal(lenExpr); + + // Dynamically cast the length to a ConcreteInt. If it is not a ConcreteInt + // then give up, otherwise get the value and use it as the bounds. + nonloc::ConcreteInt *CI = dyn_cast(&lenVal); + if (!CI) + return; + llvm::APSInt lenInt(CI->getValue()); + + // Compare using the bounds provided like strncmp() does. + if (ignoreCase) { + // TODO Implement compare_lower(RHS, n) in LLVM StringRef. + // result = s1StrRef.compare_lower(s2StrRef, + // (size_t)lenInt.getLimitedValue()); + + // For now, give up. + return; + } else { + // Create substrings of each to compare the prefix. + llvm::StringRef s1SubStr = + s1StrRef.substr(0, (size_t)lenInt.getLimitedValue()); + llvm::StringRef s2SubStr = + s2StrRef.substr(0, (size_t)lenInt.getLimitedValue()); + + // Compare the substrings. + result = s1SubStr.compare(s2SubStr); + } + } else { + // Compare string 1 to string 2 the same way strcmp() does. + if (ignoreCase) { + result = s1StrRef.compare_lower(s2StrRef); + } else { + result = s1StrRef.compare(s2StrRef); + } + } + + // Build the SVal of the comparison to bind the return value. + SValBuilder &svalBuilder = C.getSValBuilder(); + QualType intTy = svalBuilder.getContext().IntTy; + SVal resultVal = svalBuilder.makeIntVal(result, intTy); + + // Bind the return value of the expression. + // Set the return value. + state = state->BindExpr(CE, resultVal); + C.addTransition(state); +} + //===----------------------------------------------------------------------===// // The driver method, and other Checker callbacks. //===----------------------------------------------------------------------===// @@ -982,13 +1243,19 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { FnCheck evalFunction = llvm::StringSwitch(Name) .Cases("memcpy", "__memcpy_chk", &CStringChecker::evalMemcpy) + .Case("mempcpy", &CStringChecker::evalMempcpy) .Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp) .Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove) .Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy) .Cases("strncpy", "__strncpy_chk", &CStringChecker::evalStrncpy) .Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy) + .Cases("strcat", "__strcat_chk", &CStringChecker::evalStrcat) + .Cases("strncat", "__strncat_chk", &CStringChecker::evalStrncat) .Case("strlen", &CStringChecker::evalstrLength) .Case("strnlen", &CStringChecker::evalstrnLength) + .Case("strcmp", &CStringChecker::evalStrcmp) + .Case("strncmp", &CStringChecker::evalStrncmp) + .Case("strcasecmp", &CStringChecker::evalStrcasecmp) .Case("bcopy", &CStringChecker::evalBcopy) .Default(NULL); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index 415900eb000e..dfe0a0e6f50a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -12,62 +12,51 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/AST/ParentMap.h" #include "clang/Basic/TargetInfo.h" -#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { class CallAndMessageChecker - : public CheckerVisitor { - BugType *BT_call_null; - BugType *BT_call_undef; - BugType *BT_call_arg; - BugType *BT_msg_undef; - BugType *BT_msg_arg; - BugType *BT_msg_ret; + : public Checker< check::PreStmt, check::PreObjCMessage > { + mutable llvm::OwningPtr BT_call_null; + mutable llvm::OwningPtr BT_call_undef; + mutable llvm::OwningPtr BT_call_arg; + mutable llvm::OwningPtr BT_msg_undef; + mutable llvm::OwningPtr BT_msg_arg; + mutable llvm::OwningPtr BT_msg_ret; public: - CallAndMessageChecker() : - BT_call_null(0), BT_call_undef(0), BT_call_arg(0), - BT_msg_undef(0), BT_msg_arg(0), BT_msg_ret(0) {} - static void *getTag() { - static int x = 0; - return &x; - } - - void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); - void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg); - bool evalNilReceiver(CheckerContext &C, ObjCMessage msg); + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; + void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; private: - void PreVisitProcessArgs(CheckerContext &C, CallOrObjCMessage callOrMsg, - const char *BT_desc, BugType *&BT); - bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange argRange, - const Expr *argEx, const char *BT_desc, BugType *&BT); + static void PreVisitProcessArgs(CheckerContext &C,CallOrObjCMessage callOrMsg, + const char *BT_desc, llvm::OwningPtr &BT); + static bool PreVisitProcessArg(CheckerContext &C, SVal V,SourceRange argRange, + const Expr *argEx, const char *BT_desc, llvm::OwningPtr &BT); - void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE); + static void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE); void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg, - ExplodedNode *N); + ExplodedNode *N) const; void HandleNilReceiver(CheckerContext &C, const GRState *state, - ObjCMessage msg); + ObjCMessage msg) const; - void LazyInit_BT(const char *desc, BugType *&BT) { + static void LazyInit_BT(const char *desc, llvm::OwningPtr &BT) { if (!BT) - BT = new BuiltinBug(desc); + BT.reset(new BuiltinBug(desc)); } }; } // end anonymous namespace -void ento::RegisterCallAndMessageChecker(ExprEngine &Eng) { - Eng.registerCheck(new CallAndMessageChecker()); -} - void CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE) { ExplodedNode *N = C.generateSink(); @@ -83,7 +72,7 @@ void CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C, void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C, CallOrObjCMessage callOrMsg, const char *BT_desc, - BugType *&BT) { + llvm::OwningPtr &BT) { for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i) if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i), callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i), @@ -95,7 +84,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange argRange, const Expr *argEx, const char *BT_desc, - BugType *&BT) { + llvm::OwningPtr &BT) { if (V.isUndef()) { if (ExplodedNode *N = C.generateSink()) { @@ -198,25 +187,25 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C, return false; } -void CallAndMessageChecker::PreVisitCallExpr(CheckerContext &C, - const CallExpr *CE){ +void CallAndMessageChecker::checkPreStmt(const CallExpr *CE, + CheckerContext &C) const{ const Expr *Callee = CE->getCallee()->IgnoreParens(); SVal L = C.getState()->getSVal(Callee); if (L.isUndef()) { if (!BT_call_undef) - BT_call_undef = - new BuiltinBug("Called function pointer is an uninitalized pointer value"); - EmitBadCall(BT_call_undef, C, CE); + BT_call_undef.reset(new BuiltinBug("Called function pointer is an " + "uninitalized pointer value")); + EmitBadCall(BT_call_undef.get(), C, CE); return; } if (isa(L)) { if (!BT_call_null) - BT_call_null = - new BuiltinBug("Called function pointer is null (null dereference)"); - EmitBadCall(BT_call_null, C, CE); + BT_call_null.reset( + new BuiltinBug("Called function pointer is null (null dereference)")); + EmitBadCall(BT_call_null.get(), C, CE); } PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState()), @@ -224,18 +213,19 @@ void CallAndMessageChecker::PreVisitCallExpr(CheckerContext &C, BT_call_arg); } -void CallAndMessageChecker::preVisitObjCMessage(CheckerContext &C, - ObjCMessage msg) { +void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg, + CheckerContext &C) const { const GRState *state = C.getState(); // FIXME: Handle 'super'? - if (const Expr *receiver = msg.getInstanceReceiver()) - if (state->getSVal(receiver).isUndef()) { + if (const Expr *receiver = msg.getInstanceReceiver()) { + SVal recVal = state->getSVal(receiver); + if (recVal.isUndef()) { if (ExplodedNode *N = C.generateSink()) { if (!BT_msg_undef) - BT_msg_undef = - new BuiltinBug("Receiver in message expression is an uninitialized value"); + BT_msg_undef.reset(new BuiltinBug("Receiver in message expression is " + "an uninitialized value")); EnhancedBugReport *R = new EnhancedBugReport(*BT_msg_undef, BT_msg_undef->getName(), N); R->addRange(receiver->getSourceRange()); @@ -244,7 +234,20 @@ void CallAndMessageChecker::preVisitObjCMessage(CheckerContext &C, C.EmitReport(R); } return; + } else { + // Bifurcate the state into nil and non-nil ones. + DefinedOrUnknownSVal receiverVal = cast(recVal); + + const GRState *notNilState, *nilState; + llvm::tie(notNilState, nilState) = state->assume(receiverVal); + + // Handle receiver must be nil. + if (nilState && !notNilState) { + HandleNilReceiver(C, state, msg); + return; + } } + } const char *bugDesc = msg.isPropertySetter() ? "Argument for property setter is an uninitialized value" @@ -253,20 +256,14 @@ void CallAndMessageChecker::preVisitObjCMessage(CheckerContext &C, PreVisitProcessArgs(C, CallOrObjCMessage(msg, state), bugDesc, BT_msg_arg); } -bool CallAndMessageChecker::evalNilReceiver(CheckerContext &C, - ObjCMessage msg) { - HandleNilReceiver(C, C.getState(), msg); - return true; // Nil receiver is not handled elsewhere. -} - void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg, - ExplodedNode *N) { + ExplodedNode *N) const { if (!BT_msg_ret) - BT_msg_ret = + BT_msg_ret.reset( new BuiltinBug("Receiver in message expression is " - "'nil' and returns a garbage value"); + "'nil' and returns a garbage value")); llvm::SmallString<200> buf; llvm::raw_svector_ostream os(buf); @@ -292,7 +289,7 @@ static bool supportsNilWithFloatRet(const llvm::Triple &triple) { void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, const GRState *state, - ObjCMessage msg) { + ObjCMessage msg) const { ASTContext &Ctx = C.getASTContext(); // Check the return type of the message expression. A message to nil will @@ -356,3 +353,7 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, C.addTransition(state); } + +void ento::registerCallAndMessageChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp index 6a4506bcf844..585a87d498d3 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -22,7 +22,7 @@ using namespace clang; using namespace ento; namespace { -class CastSizeChecker : public CheckerV2< check::PreStmt > { +class CastSizeChecker : public Checker< check::PreStmt > { mutable llvm::OwningPtr BT; public: void checkPreStmt(const CastExpr *CE, CheckerContext &C) const; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp index 04cc253fc609..3210b0a4bb61 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp @@ -14,7 +14,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -23,7 +23,7 @@ using namespace clang; using namespace ento; namespace { -class CastToStructChecker : public CheckerV2< check::PreStmt > { +class CastToStructChecker : public Checker< check::PreStmt > { mutable llvm::OwningPtr BT; public: diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp index ad3bab6f7ea9..0c693a0bd1b6 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp @@ -14,7 +14,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -267,7 +267,7 @@ static void checkObjCDealloc(const ObjCImplementationDecl* D, //===----------------------------------------------------------------------===// namespace { -class ObjCDeallocChecker : public CheckerV2< +class ObjCDeallocChecker : public Checker< check::ASTDecl > { public: void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& mgr, diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp index 369ba0bbb2ac..fec06a95350e 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp @@ -14,7 +14,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/AST/DeclObjC.h" @@ -125,7 +125,7 @@ static void CheckObjCInstMethSignature(const ObjCImplementationDecl* ID, //===----------------------------------------------------------------------===// namespace { -class ObjCMethSigsChecker : public CheckerV2< +class ObjCMethSigsChecker : public Checker< check::ASTDecl > { public: void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& mgr, diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp index 185520c8df18..53810eed1255 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp @@ -12,11 +12,12 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/Basic/TargetInfo.h" #include "clang/AST/StmtVisitor.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; using namespace ento; @@ -33,21 +34,13 @@ static bool isArc4RandomAvailable(const ASTContext &Ctx) { namespace { class WalkAST : public StmtVisitor { BugReporter &BR; - IdentifierInfo *II_gets; - IdentifierInfo *II_getpw; - IdentifierInfo *II_mktemp; - enum { num_rands = 9 }; - IdentifierInfo *II_rand[num_rands]; - IdentifierInfo *II_random; enum { num_setids = 6 }; IdentifierInfo *II_setid[num_setids]; const bool CheckRand; public: - WalkAST(BugReporter &br) : BR(br), - II_gets(0), II_getpw(0), II_mktemp(0), - II_rand(), II_random(0), II_setid(), + WalkAST(BugReporter &br) : BR(br), II_setid(), CheckRand(isArc4RandomAvailable(BR.getContext())) {} // Statement visitor methods. @@ -59,16 +52,22 @@ class WalkAST : public StmtVisitor { void VisitChildren(Stmt *S); // Helpers. - IdentifierInfo *GetIdentifier(IdentifierInfo *& II, const char *str); + IdentifierInfo *getIdentifier(IdentifierInfo *& II, const char *str); + bool checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD); + + typedef void (WalkAST::*FnCheck)(const CallExpr *, + const FunctionDecl *); // Checker-specific methods. - void CheckLoopConditionForFloat(const ForStmt *FS); - void CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD); - void CheckCall_getpw(const CallExpr *CE, const FunctionDecl *FD); - void CheckCall_mktemp(const CallExpr *CE, const FunctionDecl *FD); - void CheckCall_rand(const CallExpr *CE, const FunctionDecl *FD); - void CheckCall_random(const CallExpr *CE, const FunctionDecl *FD); - void CheckUncheckedReturnValue(CallExpr *CE); + void checkLoopConditionForFloat(const ForStmt *FS); + void checkCall_gets(const CallExpr *CE, const FunctionDecl *FD); + void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD); + void checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD); + void checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD); + void checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD); + void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD); + void checkCall_random(const CallExpr *CE, const FunctionDecl *FD); + void checkUncheckedReturnValue(CallExpr *CE); }; } // end anonymous namespace @@ -76,7 +75,7 @@ class WalkAST : public StmtVisitor { // Helper methods. //===----------------------------------------------------------------------===// -IdentifierInfo *WalkAST::GetIdentifier(IdentifierInfo *& II, const char *str) { +IdentifierInfo *WalkAST::getIdentifier(IdentifierInfo *& II, const char *str) { if (!II) II = &BR.getContext().Idents.get(str); @@ -94,15 +93,43 @@ void WalkAST::VisitChildren(Stmt *S) { } void WalkAST::VisitCallExpr(CallExpr *CE) { - if (const FunctionDecl *FD = CE->getDirectCallee()) { - CheckCall_gets(CE, FD); - CheckCall_getpw(CE, FD); - CheckCall_mktemp(CE, FD); - if (CheckRand) { - CheckCall_rand(CE, FD); - CheckCall_random(CE, FD); - } - } + // Get the callee. + const FunctionDecl *FD = CE->getDirectCallee(); + + if (!FD) + return; + + // Get the name of the callee. If it's a builtin, strip off the prefix. + IdentifierInfo *II = FD->getIdentifier(); + if (!II) // if no identifier, not a simple C function + return; + llvm::StringRef Name = II->getName(); + if (Name.startswith("__builtin_")) + Name = Name.substr(10); + + // Set the evaluation function by switching on the callee name. + FnCheck evalFunction = llvm::StringSwitch(Name) + .Case("gets", &WalkAST::checkCall_gets) + .Case("getpw", &WalkAST::checkCall_getpw) + .Case("mktemp", &WalkAST::checkCall_mktemp) + .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy) + .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat) + .Case("drand48", &WalkAST::checkCall_rand) + .Case("erand48", &WalkAST::checkCall_rand) + .Case("jrand48", &WalkAST::checkCall_rand) + .Case("lrand48", &WalkAST::checkCall_rand) + .Case("mrand48", &WalkAST::checkCall_rand) + .Case("nrand48", &WalkAST::checkCall_rand) + .Case("lcong48", &WalkAST::checkCall_rand) + .Case("rand", &WalkAST::checkCall_rand) + .Case("rand_r", &WalkAST::checkCall_rand) + .Case("random", &WalkAST::checkCall_random) + .Default(NULL); + + // If the callee isn't defined, it is not of security concern. + // Check and evaluate the call. + if (evalFunction) + (this->*evalFunction)(CE, FD); // Recurse and check children. VisitChildren(CE); @@ -112,13 +139,13 @@ void WalkAST::VisitCompoundStmt(CompoundStmt *S) { for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I) if (Stmt *child = *I) { if (CallExpr *CE = dyn_cast(child)) - CheckUncheckedReturnValue(CE); + checkUncheckedReturnValue(CE); Visit(child); } } void WalkAST::VisitForStmt(ForStmt *FS) { - CheckLoopConditionForFloat(FS); + checkLoopConditionForFloat(FS); // Recurse and check children. VisitChildren(FS); @@ -131,7 +158,7 @@ void WalkAST::VisitForStmt(ForStmt *FS) { //===----------------------------------------------------------------------===// static const DeclRefExpr* -GetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) { +getIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) { expr = expr->IgnoreParenCasts(); if (const BinaryOperator *B = dyn_cast(expr)) { @@ -139,10 +166,10 @@ GetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) { B->getOpcode() == BO_Comma)) return NULL; - if (const DeclRefExpr *lhs = GetIncrementedVar(B->getLHS(), x, y)) + if (const DeclRefExpr *lhs = getIncrementedVar(B->getLHS(), x, y)) return lhs; - if (const DeclRefExpr *rhs = GetIncrementedVar(B->getRHS(), x, y)) + if (const DeclRefExpr *rhs = getIncrementedVar(B->getRHS(), x, y)) return rhs; return NULL; @@ -155,7 +182,7 @@ GetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) { if (const UnaryOperator *U = dyn_cast(expr)) return U->isIncrementDecrementOp() - ? GetIncrementedVar(U->getSubExpr(), x, y) : NULL; + ? getIncrementedVar(U->getSubExpr(), x, y) : NULL; return NULL; } @@ -164,7 +191,7 @@ GetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) { /// use a floating point variable as a loop counter. /// CERT: FLP30-C, FLP30-CPP. /// -void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) { +void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) { // Does the loop have a condition? const Expr *condition = FS->getCond(); @@ -211,7 +238,7 @@ void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) { return; // Does either variable appear in increment? - const DeclRefExpr *drInc = GetIncrementedVar(increment, vdLHS, vdRHS); + const DeclRefExpr *drInc = getIncrementedVar(increment, vdLHS, vdRHS); if (!drInc) return; @@ -243,10 +270,7 @@ void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) { // CWE-242: Use of Inherently Dangerous Function //===----------------------------------------------------------------------===// -void WalkAST::CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD) { - if (FD->getIdentifier() != GetIdentifier(II_gets, "gets")) - return; - +void WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) { const FunctionProtoType *FPT = dyn_cast(FD->getType().IgnoreParens()); if (!FPT) @@ -278,10 +302,7 @@ void WalkAST::CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD) { // CWE-477: Use of Obsolete Functions //===----------------------------------------------------------------------===// -void WalkAST::CheckCall_getpw(const CallExpr *CE, const FunctionDecl *FD) { - if (FD->getIdentifier() != GetIdentifier(II_getpw, "getpw")) - return; - +void WalkAST::checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD) { const FunctionProtoType *FPT = dyn_cast(FD->getType().IgnoreParens()); if (!FPT) @@ -317,16 +338,13 @@ void WalkAST::CheckCall_getpw(const CallExpr *CE, const FunctionDecl *FD) { // CWE-377: Insecure Temporary File //===----------------------------------------------------------------------===// -void WalkAST::CheckCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) { - if (FD->getIdentifier() != GetIdentifier(II_mktemp, "mktemp")) - return; - +void WalkAST::checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) { const FunctionProtoType *FPT = dyn_cast(FD->getType().IgnoreParens()); if(!FPT) return; - // Verify that the funcion takes a single argument. + // Verify that the function takes a single argument. if (FPT->getNumArgs() != 1) return; @@ -348,33 +366,87 @@ void WalkAST::CheckCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) { CE->getLocStart(), &R, 1); } +//===----------------------------------------------------------------------===// +// Check: Any use of 'strcpy' is insecure. +// +// CWE-119: Improper Restriction of Operations within +// the Bounds of a Memory Buffer +//===----------------------------------------------------------------------===// +void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) { + if (!checkCall_strCommon(CE, FD)) + return; + + // Issue a warning. + SourceRange R = CE->getCallee()->getSourceRange(); + BR.EmitBasicReport("Potential insecure memory buffer bounds restriction in " + "call 'strcpy'", + "Security", + "Call to function 'strcpy' is insecure as it does not " + "provide bounding of the memory buffer. Replace " + "unbounded copy functions with analogous functions that " + "support length arguments such as 'strncpy'. CWE-119.", + CE->getLocStart(), &R, 1); +} + +//===----------------------------------------------------------------------===// +// Check: Any use of 'strcat' is insecure. +// +// CWE-119: Improper Restriction of Operations within +// the Bounds of a Memory Buffer +//===----------------------------------------------------------------------===// +void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) { + if (!checkCall_strCommon(CE, FD)) + return; + + // Issue a warning. + SourceRange R = CE->getCallee()->getSourceRange(); + BR.EmitBasicReport("Potential insecure memory buffer bounds restriction in " + "call 'strcat'", + "Security", + "Call to function 'strcat' is insecure as it does not " + "provide bounding of the memory buffer. Replace " + "unbounded copy functions with analogous functions that " + "support length arguments such as 'strncat'. CWE-119.", + CE->getLocStart(), &R, 1); +} + +//===----------------------------------------------------------------------===// +// Common check for str* functions with no bounds parameters. +//===----------------------------------------------------------------------===// +bool WalkAST::checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD) { + const FunctionProtoType *FPT + = dyn_cast(FD->getType().IgnoreParens()); + if (!FPT) + return false; + + // Verify the function takes two arguments, three in the _chk version. + int numArgs = FPT->getNumArgs(); + if (numArgs != 2 && numArgs != 3) + return false; + + // Verify the type for both arguments. + for (int i = 0; i < 2; i++) { + // Verify that the arguments are pointers. + const PointerType *PT = dyn_cast(FPT->getArgType(i)); + if (!PT) + return false; + + // Verify that the argument is a 'char*'. + if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy) + return false; + } + + return true; +} + //===----------------------------------------------------------------------===// // Check: Linear congruent random number generators should not be used // Originally: // CWE-338: Use of cryptographically weak prng //===----------------------------------------------------------------------===// -void WalkAST::CheckCall_rand(const CallExpr *CE, const FunctionDecl *FD) { - if (II_rand[0] == NULL) { - // This check applies to these functions - static const char * const identifiers[num_rands] = { - "drand48", "erand48", "jrand48", "lrand48", "mrand48", "nrand48", - "lcong48", - "rand", "rand_r" - }; - - for (size_t i = 0; i < num_rands; i++) - II_rand[i] = &BR.getContext().Idents.get(identifiers[i]); - } - - const IdentifierInfo *id = FD->getIdentifier(); - size_t identifierid; - - for (identifierid = 0; identifierid < num_rands; identifierid++) - if (id == II_rand[identifierid]) - break; - - if (identifierid >= num_rands) +void WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) { + if (!CheckRand) return; const FunctionProtoType *FTP @@ -415,8 +487,8 @@ void WalkAST::CheckCall_rand(const CallExpr *CE, const FunctionDecl *FD) { // Originally: //===----------------------------------------------------------------------===// -void WalkAST::CheckCall_random(const CallExpr *CE, const FunctionDecl *FD) { - if (FD->getIdentifier() != GetIdentifier(II_random, "random")) +void WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) { + if (!CheckRand) return; const FunctionProtoType *FTP @@ -442,7 +514,7 @@ void WalkAST::CheckCall_random(const CallExpr *CE, const FunctionDecl *FD) { // Originally: //===----------------------------------------------------------------------===// -void WalkAST::CheckUncheckedReturnValue(CallExpr *CE) { +void WalkAST::checkUncheckedReturnValue(CallExpr *CE) { const FunctionDecl *FD = CE->getDirectCallee(); if (!FD) return; @@ -502,7 +574,7 @@ void WalkAST::CheckUncheckedReturnValue(CallExpr *CE) { //===----------------------------------------------------------------------===// namespace { -class SecuritySyntaxChecker : public CheckerV2 { +class SecuritySyntaxChecker : public Checker { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp index d46ac8121b5a..abf53fd3db28 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/AST/StmtVisitor.h" @@ -26,7 +26,7 @@ class WalkAST : public StmtVisitor { public: WalkAST(BugReporter &br) : BR(br) {} - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); + void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); void VisitStmt(Stmt *S) { VisitChildren(S); } void VisitChildren(Stmt *S); }; @@ -39,8 +39,8 @@ void WalkAST::VisitChildren(Stmt *S) { } // CWE-467: Use of sizeof() on a Pointer Type -void WalkAST::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { - if (!E->isSizeOf()) +void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { + if (E->getKind() != UETT_SizeOf) return; // If an explicit type is used in the code, usually the coder knows what he is @@ -72,7 +72,7 @@ void WalkAST::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { //===----------------------------------------------------------------------===// namespace { -class SizeofPointerChecker : public CheckerV2 { +class SizeofPointerChecker : public Checker { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td index 894b961f7d1e..1a71fc4074ba 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td @@ -9,44 +9,275 @@ include "clang/StaticAnalyzer/Checkers/CheckerBase.td" +//===----------------------------------------------------------------------===// +// Groups. +//===----------------------------------------------------------------------===// + +def AllExperimental : CheckerGroup<"all-experimental">; + //===----------------------------------------------------------------------===// // Packages. //===----------------------------------------------------------------------===// def Core : Package<"core">; -def Cocoa : Package<"cocoa">; +def CoreBuiltin : Package<"builtin">, InPackage; +def CoreUninitialized : Package<"uninitialized">, InPackage; +def CoreExperimental : Package<"experimental">, InPackage, + InGroup, Hidden; + +def Cplusplus : Package<"cplusplus">; +def CplusplusExperimental : Package<"experimental">, InPackage, + InGroup, Hidden; + +def DeadCode : Package<"deadcode">; +def DeadCodeExperimental : Package<"experimental">, InPackage, + InGroup, Hidden; + +def Security : Package <"security">; +def SecurityExperimental : Package<"experimental">, InPackage, + InGroup, Hidden; + def Unix : Package<"unix">; -def MacOSX : Package<"macosx">; +def UnixExperimental : Package<"experimental">, InPackage, + InGroup, Hidden; -def CoreExperimental : Package<"experimental">, - InPackage, Hidden; - -def CocoaExperimental : Package<"experimental">, - InPackage, Hidden; - -def UnixExperimental : Package<"experimental">, - InPackage, Hidden; +def OSX : Package<"osx">; +def Cocoa : Package<"cocoa">, InPackage; +def CocoaExperimental : Package<"experimental">, InPackage, + InGroup, Hidden; +def CoreFoundation : Package<"coreFoundation">, InPackage; def LLVM : Package<"llvm">; def Debug : Package<"debug">; //===----------------------------------------------------------------------===// -// Groups. +// Core Checkers. //===----------------------------------------------------------------------===// -def AllExperimental : CheckerGroup<"all-experimental">, - Hidden; +let ParentPackage = Core in { + +def DereferenceChecker : Checker<"NullDereference">, + HelpText<"Check for dereferences of null pointers">, + DescFile<"DereferenceChecker.cpp">; + +def CallAndMessageChecker : Checker<"CallAndMessage">, + HelpText<"Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)">, + DescFile<"CallAndMessageChecker.cpp">; + +def AdjustedReturnValueChecker : Checker<"AdjustedReturnValue">, + HelpText<"Check to see if the return value of a function call is different than the caller expects (e.g., from calls through function pointers)">, + DescFile<"AdjustedReturnValueChecker.cpp">; + +def AttrNonNullChecker : Checker<"AttributeNonNull">, + HelpText<"Check for null pointers passed as arguments to a function whose arguments are marked with the 'nonnull' attribute">, + DescFile<"AttrNonNullChecker.cpp">; + +def VLASizeChecker : Checker<"VLASize">, + HelpText<"Check for declarations of VLA of undefined or zero size">, + DescFile<"VLASizeChecker.cpp">; + +def DivZeroChecker : Checker<"DivideZero">, + HelpText<"Check for division by zero">, + DescFile<"DivZeroChecker.cpp">; + +def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">, + HelpText<"Check for undefined results of binary operators">, + DescFile<"UndefResultChecker.cpp">; + +def StackAddrEscapeChecker : Checker<"StackAddressEscape">, + HelpText<"Check that addresses to stack memory do not escape the function">, + DescFile<"StackAddrEscapeChecker.cpp">; + +} // end "core" + +let ParentPackage = CoreExperimental in { + +def CastSizeChecker : Checker<"CastSize">, + HelpText<"Check when casting a malloc'ed type T, whether the size is a multiple of the size of T">, + DescFile<"CastSizeChecker.cpp">; + +def CastToStructChecker : Checker<"CastToStruct">, + HelpText<"Check for cast from non-struct pointer to struct pointer">, + DescFile<"CastToStructChecker.cpp">; + +def FixedAddressChecker : Checker<"FixedAddr">, + HelpText<"Check for assignment of a fixed address to a pointer">, + DescFile<"FixedAddressChecker.cpp">; + +def PointerArithChecker : Checker<"PointerArithm">, + HelpText<"Check for pointer arithmetic on locations other than array elements">, + DescFile<"PointerArithChecker">; + +def PointerSubChecker : Checker<"PointerSub">, + HelpText<"Check for pointer subtractions on two pointers pointing to different memory chunks">, + DescFile<"PointerSubChecker">; + +def SizeofPointerChecker : Checker<"SizeofPtr">, + HelpText<"Warn about unintended use of sizeof() on pointer expressions">, + DescFile<"CheckSizeofPointer.cpp">; + +} // end "core.experimental" //===----------------------------------------------------------------------===// -// Checkers. +// Evaluate "builtin" functions. //===----------------------------------------------------------------------===// +let ParentPackage = CoreBuiltin in { + +def NoReturnFunctionChecker : Checker<"NoReturnFunctions">, + HelpText<"Evaluate \"panic\" functions that are known to not return to the caller">, + DescFile<"NoReturnFunctionChecker.cpp">; + +def BuiltinFunctionChecker : Checker<"BuiltinFunctions">, + HelpText<"Evaluate compiler builtin functions (e.g., alloca())">, + DescFile<"BuiltinFunctionChecker.cpp">; + +} // end "core.builtin" + +//===----------------------------------------------------------------------===// +// Uninitialized values checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = CoreUninitialized in { + +def UndefinedArraySubscriptChecker : Checker<"ArraySubscript">, + HelpText<"Check for uninitialized values used as array subscripts">, + DescFile<"UndefinedArraySubscriptChecker.cpp">; + +def UndefinedAssignmentChecker : Checker<"Assign">, + HelpText<"Check for assigning uninitialized values">, + DescFile<"UndefinedAssignmentChecker.cpp">; + +def UndefBranchChecker : Checker<"Branch">, + HelpText<"Check for uninitialized values used as branch conditions">, + DescFile<"UndefBranchChecker.cpp">; + +def UndefCapturedBlockVarChecker : Checker<"CapturedBlockVariable">, + HelpText<"Check for blocks that capture uninitialized values">, + DescFile<"UndefCapturedBlockVarChecker.cpp">; + +def ReturnUndefChecker : Checker<"UndefReturn">, + HelpText<"Check for uninitialized values being returned to the caller">, + DescFile<"ReturnUndefChecker.cpp">; + +} // end "core.uninitialized" + +//===----------------------------------------------------------------------===// +// C++ checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = CplusplusExperimental in { + +def CStringChecker : Checker<"CString">, + HelpText<"Check calls to functions in ">, + DescFile<"CStringChecker.cpp">; + +def IteratorsChecker : Checker<"Iterators">, + HelpText<"Check improper uses of STL vector iterators">, + DescFile<"IteratorsChecker.cpp">; + +} // end: "cplusplus.experimental" + +//===----------------------------------------------------------------------===// +// Deadcode checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = DeadCode in { + +def DeadStoresChecker : Checker<"DeadStores">, + HelpText<"Check for values stored to variables that are never read afterwards">, + DescFile<"DeadStoresChecker.cpp">; + +def IdempotentOperationChecker : Checker<"IdempotentOperations">, + HelpText<"Warn about idempotent operations">, + DescFile<"IdempotentOperationChecker.cpp">; + +} // end DeadCode + +let ParentPackage = DeadCodeExperimental in { + +def UnreachableCodeChecker : Checker<"UnreachableCode">, + HelpText<"Check unreachable code">, + DescFile<"UnreachableCodeChecker.cpp">; + +} // end "deadcode.experimental" + +//===----------------------------------------------------------------------===// +// Security checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = SecurityExperimental in { + +def SecuritySyntaxChecker : Checker<"SecuritySyntactic">, + HelpText<"Perform quick security API checks that require no data flow">, + DescFile<"CheckSecuritySyntaxOnly.cpp">; + +def ArrayBoundChecker : Checker<"ArrayBound">, + HelpText<"Warn about buffer overflows (older checker)">, + DescFile<"ArrayBoundChecker.cpp">; + +def ArrayBoundCheckerV2 : Checker<"ArrayBoundV2">, + HelpText<"Warn about buffer overflows (newer checker)">, + DescFile<"ArrayBoundCheckerV2.cpp">; + +def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">, + HelpText<"Check for an out-of-bound pointer being returned to callers">, + DescFile<"ReturnPointerRangeChecker.cpp">; + +} // end "security.experimental" + +//===----------------------------------------------------------------------===// +// Unix API checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = Unix in { + +def UnixAPIChecker : Checker<"API">, + HelpText<"Check calls to various UNIX/Posix functions">, + DescFile<"UnixAPIChecker.cpp">; + +} // end "unix" + +let ParentPackage = UnixExperimental in { + +def ChrootChecker : Checker<"Chroot">, + HelpText<"Check improper use of chroot">, + DescFile<"ChrootChecker.cpp">; + +def MallocChecker : Checker<"Malloc">, + HelpText<"Check for potential memory leaks, double free, and use-after-free problems">, + DescFile<"MallocChecker.cpp">; + +def PthreadLockChecker : Checker<"PthreadLock">, + HelpText<"Simple lock -> unlock checker">, + DescFile<"PthreadLockChecker.cpp">; + +def StreamChecker : Checker<"Stream">, + HelpText<"Check stream handling functions">, + DescFile<"StreamChecker.cpp">; + +} // end "unix.experimental" + +//===----------------------------------------------------------------------===// +// Mac OS X, Cocoa, and Core Foundation checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = OSX in { + +def MacOSXAPIChecker : Checker<"API">, + InPackage, + HelpText<"Check for proper uses of various Mac OS X APIs">, + DescFile<"MacOSXAPIChecker.cpp">; + +def OSAtomicChecker : Checker<"AtomicCAS">, + InPackage, + HelpText<"Evaluate calls to OSAtomic functions">, + DescFile<"OSAtomicChecker.cpp">; + +} // end "macosx" + let ParentPackage = Cocoa in { -def ObjCSelfInitChecker : Checker<"SelfInit">, - HelpText<"Check that 'self' is propely initialized inside an initializer method">, - DescFile<"ObjCSelfInitChecker.cpp">; - def ObjCAtSyncChecker : Checker<"AtSync">, HelpText<"Check for null pointers used as mutexes for @synchronized">, DescFile<"ObjCAtSyncChecker.cpp">; @@ -59,155 +290,86 @@ def ClassReleaseChecker : Checker<"ClassRelease">, HelpText<"Check for sending 'retain', 'release', or 'autorelease' directly to a Class">, DescFile<"BasicObjCFoundationChecks.cpp">; +def VariadicMethodTypeChecker : Checker<"VariadicMethodTypes">, + HelpText<"Check for passing non-Objective-C types to variadic methods that expect" + "only Objective-C types">, + DescFile<"BasicObjCFoundationChecks.cpp">; + def NSAutoreleasePoolChecker : Checker<"NSAutoreleasePool">, - HelpText<"Warn for subpar uses of NSAutoreleasePool">, + HelpText<"Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode">, DescFile<"NSAutoreleasePoolChecker.cpp">; -def ObjCMethSigsChecker : Checker<"MethodSigs">, +def ObjCMethSigsChecker : Checker<"IncompatibleMethodTypes">, HelpText<"Warn about Objective-C method signatures with type incompatibilities">, DescFile<"CheckObjCInstMethSignature.cpp">; def ObjCUnusedIvarsChecker : Checker<"UnusedIvars">, HelpText<"Warn about private ivars that are never used">, DescFile<"ObjCUnusedIVarsChecker.cpp">; + +def NSErrorChecker : Checker<"NSError">, + HelpText<"Check usage of NSError** parameters">, + DescFile<"NSErrorChecker.cpp">; } // end "cocoa" -def StackAddrEscapeChecker : Checker<"StackAddrEscape">, - InPackage, - HelpText<"Check that addresses to stack memory do not escape the function">, - DescFile<"StackAddrEscapeChecker.cpp">; +let ParentPackage = CocoaExperimental in { -def DeadStoresChecker : Checker<"DeadStores">, - InPackage, - HelpText<"Check for values stored to a variables that are never read afterwards">, - DescFile<"DeadStoresChecker.cpp">; +def ObjCSelfInitChecker : Checker<"SelfInit">, + HelpText<"Check that 'self' is properly initialized inside an initializer method">, + DescFile<"ObjCSelfInitChecker.cpp">; -def UnixAPIChecker : Checker<"API">, - InPackage, - HelpText<"Check calls to various UNIX/Posix functions">, - DescFile<"UnixAPIChecker.cpp">; +def ObjCDeallocChecker : Checker<"Dealloc">, + HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">, + DescFile<"CheckObjCDealloc.cpp">; -def MacOSXAPIChecker : Checker<"API">, - InPackage, - HelpText<"Check for proper uses of various Mac OS X APIs">, - DescFile<"MacOSXAPIChecker.cpp">; +} // end "cocoa.experimental" + +let ParentPackage = CoreFoundation in { def CFNumberCreateChecker : Checker<"CFNumber">, - InPackage, HelpText<"Check for proper uses of CFNumberCreate">, DescFile<"BasicObjCFoundationChecks.cpp">; def CFRetainReleaseChecker : Checker<"CFRetainRelease">, - InPackage, HelpText<"Check for null arguments to CFRetain/CFRelease">, DescFile<"BasicObjCFoundationChecks.cpp">; +def CFErrorChecker : Checker<"CFError">, + HelpText<"Check usage of CFErrorRef* parameters">, + DescFile<"NSErrorChecker.cpp">; +} + +//===----------------------------------------------------------------------===// +// Checkers for LLVM development. +//===----------------------------------------------------------------------===// + def LLVMConventionsChecker : Checker<"Conventions">, InPackage, HelpText<"Check code for LLVM codebase conventions">, DescFile<"LLVMConventionsChecker.cpp">; +//===----------------------------------------------------------------------===// +// Debugging checkers (for analyzer development). +//===----------------------------------------------------------------------===// + +let ParentPackage = Debug in { + def LiveVariablesDumper : Checker<"DumpLiveVars">, - InPackage, HelpText<"Print results of live variable analysis">, DescFile<"DebugCheckers.cpp">; def CFGViewer : Checker<"ViewCFG">, - InPackage, HelpText<"View Control-Flow Graphs using GraphViz">, DescFile<"DebugCheckers.cpp">; def CFGDumper : Checker<"DumpCFG">, - InPackage, HelpText<"Display Control-Flow Graphs">, DescFile<"DebugCheckers.cpp">; -//===----------------------------------------------------------------------===// -// Hidden experimental checkers. -//===----------------------------------------------------------------------===// +def AnalyzerStatsChecker : Checker<"Stats">, + HelpText<"Emit warnings with analyzer statistics">, + DescFile<"AnalyzerStatsChecker.cpp">; -let Group = AllExperimental in { +} // end "debug" -def CStringChecker : Checker<"CString">, - InPackage, - HelpText<"Check calls to functions in ">, - DescFile<"CStringChecker.cpp">; - -def UnreachableCodeChecker : Checker<"UnreachableCode">, - InPackage, - HelpText<"Check unreachable code">, - DescFile<"UnreachableCodeChecker.cpp">, - Hidden; // Must be specified explicitly in order to run. - -def IdempotentOperationChecker : Checker<"IdempotentOps">, - InPackage, - HelpText<"Warn about idempotent operations">, - DescFile<"IdempotentOperationChecker.cpp">; - -def CastToStructChecker : Checker<"CastToStruct">, - InPackage, - HelpText<"Check for cast from non-struct pointer to struct pointer">, - DescFile<"CastToStructChecker.cpp">; - -def FixedAddressChecker : Checker<"FixedAddr">, - InPackage, - HelpText<"Check for assignment of a fixed address to a pointer">, - DescFile<"FixedAddressChecker.cpp">; - -def PointerArithChecker : Checker<"PointerArithm">, - InPackage, - HelpText<"Check for pointer arithmetic on locations other than array elements">, - DescFile<"PointerArithChecker">; - -def PointerSubChecker : Checker<"PointerSub">, - InPackage, - HelpText<"Check for pointer subtractions on two pointers pointing to different memory chunks">, - DescFile<"PointerSubChecker">; - -def SizeofPointerChecker : Checker<"SizeofPtr">, - InPackage, - HelpText<"Warn about unintended use of sizeof() on pointer expressions">, - DescFile<"CheckSizeofPointer.cpp">; - -def SecuritySyntaxChecker : Checker<"SecuritySyntactic">, - InPackage, - HelpText<"Perform quick security checks that require no data flow">, - DescFile<"CheckSecuritySyntaxOnly.cpp">; - -def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">, - InPackage, - HelpText<"Check for an out-of-bound pointer being returned to callers">, - DescFile<"ReturnPointerRangeChecker.cpp">; - -def ArrayBoundChecker : Checker<"ArrayBound">, - InPackage, - HelpText<"Check for an out-of-bound pointer being returned to callers">, - DescFile<"ArrayBoundChecker.cpp">; - -def CastSizeChecker : Checker<"CastSize">, - InPackage, - HelpText<"Check when casting a malloc'ed type T, whether the size is a multiple of the size of T">, - DescFile<"CastSizeChecker.cpp">; - -def ObjCDeallocChecker : Checker<"Dealloc">, - InPackage, - HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">, - DescFile<"CheckObjCDealloc.cpp">; - -def ChrootChecker : Checker<"Chroot">, - InPackage, - HelpText<"Check improper use of chroot">, - DescFile<"ChrootChecker.cpp">; - -def PthreadLockChecker : Checker<"PthreadLock">, - InPackage, - HelpText<"Simple lock -> unlock checker">, - DescFile<"PthreadLockChecker.cpp">; - -def StreamChecker : Checker<"Stream">, - InPackage, - HelpText<"Check stream handling functions">, - DescFile<"StreamChecker.cpp">; - -} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp index b6eef6d150d4..50b57d1ae497 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -38,7 +38,7 @@ bool isRootChanged(intptr_t k) { return k == ROOT_CHANGED; } // ROOT_CHANGED<--chdir(..)-- JAIL_ENTERED<--chdir(..)-- // | | // bug<--foo()-- JAIL_ENTERED<--foo()-- -class ChrootChecker : public CheckerV2 > { +class ChrootChecker : public Checker > { mutable IdentifierInfo *II_chroot, *II_chdir; // This bug refers to possibly break out of a chroot() jail. mutable llvm::OwningPtr BT_BreakJail; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp index 5c0c9504db03..291f8e01f4b9 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp @@ -45,17 +45,54 @@ struct StaticCheckerInfoRec { const char *FullName; void (*RegFunc)(CheckerManager &mgr); const char *HelpText; + int GroupIndex; bool Hidden; }; +struct StaticPackageInfoRec { + const char *FullName; + int GroupIndex; + bool Hidden; +}; + +struct StaticGroupInfoRec { + const char *FullName; +}; + } // end anonymous namespace. +static const StaticPackageInfoRec StaticPackageInfo[] = { +#define GET_PACKAGES +#define PACKAGE(FULLNAME, GROUPINDEX, HIDDEN) \ + { FULLNAME, GROUPINDEX, HIDDEN }, +#include "Checkers.inc" + { 0, -1, 0 } +#undef PACKAGE +#undef GET_PACKAGES +}; + +static const unsigned NumPackages = sizeof(StaticPackageInfo) + / sizeof(StaticPackageInfoRec) - 1; + +static const StaticGroupInfoRec StaticGroupInfo[] = { +#define GET_GROUPS +#define GROUP(FULLNAME) \ + { FULLNAME }, +#include "Checkers.inc" + { 0 } +#undef GROUP +#undef GET_GROUPS +}; + +static const unsigned NumGroups = sizeof(StaticGroupInfo) + / sizeof(StaticGroupInfoRec) - 1; + static const StaticCheckerInfoRec StaticCheckerInfo[] = { #define GET_CHECKERS -#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,HIDDEN) \ - { FULLNAME, register##CLASS, HELPTEXT, HIDDEN }, +#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,GROUPINDEX,HIDDEN) \ + { FULLNAME, register##CLASS, HELPTEXT, GROUPINDEX, HIDDEN }, #include "Checkers.inc" - { 0, 0, 0, 0} + { 0, 0, 0, -1, 0} #undef CHECKER #undef GET_CHECKERS }; @@ -101,8 +138,9 @@ static void collectCheckers(const CheckNameOption *checkName, if (const short *member = checkName->Members) { if (enable) { - if (collectHidden || !StaticCheckerInfo[*member].Hidden) - checkers.insert(&StaticCheckerInfo[*member]); + for (; *member != -1; ++member) + if (collectHidden || !StaticCheckerInfo[*member].Hidden) + checkers.insert(&StaticCheckerInfo[*member]); } else { for (; *member != -1; ++member) checkers.erase(&StaticCheckerInfo[*member]); @@ -144,6 +182,48 @@ void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr, } } +//===----------------------------------------------------------------------===// +// Printing Help. +//===----------------------------------------------------------------------===// + +static void printPackageOption(llvm::raw_ostream &OS) { + // Find the maximum option length. + unsigned OptionFieldWidth = 0; + for (unsigned i = 0; i != NumPackages; ++i) { + // Limit the amount of padding we are willing to give up for alignment. + unsigned Length = strlen(StaticPackageInfo[i].FullName); + if (Length <= 30) + OptionFieldWidth = std::max(OptionFieldWidth, Length); + } + + const unsigned InitialPad = 2; + for (unsigned i = 0; i != NumPackages; ++i) { + const StaticPackageInfoRec &package = StaticPackageInfo[i]; + const std::string &Option = package.FullName; + int Pad = OptionFieldWidth - int(Option.size()); + OS.indent(InitialPad) << Option; + + if (package.GroupIndex != -1 || package.Hidden) { + // Break on long option names. + if (Pad < 0) { + OS << "\n"; + Pad = OptionFieldWidth + InitialPad; + } + OS.indent(Pad + 1) << "["; + if (package.GroupIndex != -1) { + OS << "Group=" << StaticGroupInfo[package.GroupIndex].FullName; + if (package.Hidden) + OS << ", "; + } + if (package.Hidden) + OS << "Hidden"; + OS << "]"; + } + + OS << "\n"; + } +} + typedef std::map SortedCheckers; static void printCheckerOption(llvm::raw_ostream &OS,SortedCheckers &checkers) { @@ -161,6 +241,7 @@ static void printCheckerOption(llvm::raw_ostream &OS,SortedCheckers &checkers) { for (SortedCheckers::iterator I = checkers.begin(), E = checkers.end(); I != E; ++I) { const std::string &Option = I->first; + const StaticCheckerInfoRec &checker = *I->second; int Pad = OptionFieldWidth - int(Option.size()); OS.indent(InitialPad) << Option; @@ -169,11 +250,36 @@ static void printCheckerOption(llvm::raw_ostream &OS,SortedCheckers &checkers) { OS << "\n"; Pad = OptionFieldWidth + InitialPad; } - OS.indent(Pad + 1) << I->second->HelpText << '\n'; + OS.indent(Pad + 1) << checker.HelpText; + + if (checker.GroupIndex != -1 || checker.Hidden) { + OS << " ["; + if (checker.GroupIndex != -1) { + OS << "Group=" << StaticGroupInfo[checker.GroupIndex].FullName; + if (checker.Hidden) + OS << ", "; + } + if (checker.Hidden) + OS << "Hidden"; + OS << "]"; + } + + OS << "\n"; } } void ClangSACheckerProvider::printHelp(llvm::raw_ostream &OS) { + OS << "USAGE: -analyzer-checker \n"; + + OS << "\nGROUPS:\n"; + for (unsigned i = 0; i != NumGroups; ++i) + OS.indent(2) << StaticGroupInfo[i].FullName << "\n"; + + OS << "\nPACKAGES:\n"; + printPackageOption(OS); + + OS << "\nCHECKERS:\n"; + // Sort checkers according to their full name. SortedCheckers checkers; for (unsigned i = 0; i != NumCheckers; ++i) diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h index 73239f55b4e4..5524b0f53276 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h @@ -21,7 +21,7 @@ namespace ento { class CheckerManager; #define GET_CHECKERS -#define CHECKER(FULLNAME,CLASS,CXXFILE,HELPTEXT,HIDDEN) \ +#define CHECKER(FULLNAME,CLASS,CXXFILE,HELPTEXT,GROUPINDEX,HIDDEN) \ void register##CLASS(CheckerManager &mgr); #include "Checkers.inc" #undef CHECKER diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index 3b39372725a4..bc1d823dde03 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -13,8 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" -#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/Visitors/CFGRecStmtVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -342,7 +341,7 @@ class FindEscaped : public CFGRecStmtDeclVisitor{ //===----------------------------------------------------------------------===// namespace { -class DeadStoresChecker : public CheckerV2 { +class DeadStoresChecker : public Checker { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp index 091d99b1352c..486b7f7feb1b 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/Analysis/Analyses/LiveVariables.h" @@ -24,7 +24,7 @@ using namespace ento; //===----------------------------------------------------------------------===// namespace { -class LiveVariablesDumper : public CheckerV2 { +class LiveVariablesDumper : public Checker { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { @@ -44,7 +44,7 @@ void ento::registerLiveVariablesDumper(CheckerManager &mgr) { //===----------------------------------------------------------------------===// namespace { -class CFGViewer : public CheckerV2 { +class CFGViewer : public Checker { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { @@ -64,7 +64,7 @@ void ento::registerCFGViewer(CheckerManager &mgr) { //===----------------------------------------------------------------------===// namespace { -class CFGDumper : public CheckerV2 { +class CFGDumper : public Checker { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp index 606ac4ab4e4e..baaf8b3aff8a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -12,51 +12,31 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" using namespace clang; using namespace ento; namespace { -class DereferenceChecker : public Checker { - BuiltinBug *BT_null; - BuiltinBug *BT_undef; - llvm::SmallVector ImplicitNullDerefNodes; -public: - DereferenceChecker() : BT_null(0), BT_undef(0) {} - static void *getTag() { static int tag = 0; return &tag; } - void visitLocation(CheckerContext &C, const Stmt *S, SVal location, - bool isLoad); +class DereferenceChecker + : public Checker< check::Location, + EventDispatcher > { + mutable llvm::OwningPtr BT_null; + mutable llvm::OwningPtr BT_undef; - std::pair - getImplicitNodes() const { - return std::make_pair(ImplicitNullDerefNodes.data(), - ImplicitNullDerefNodes.data() + - ImplicitNullDerefNodes.size()); - } - void AddDerefSource(llvm::raw_ostream &os, - llvm::SmallVectorImpl &Ranges, - const Expr *Ex, bool loadedFrom = false); +public: + void checkLocation(SVal location, bool isLoad, CheckerContext &C) const; + + static void AddDerefSource(llvm::raw_ostream &os, + llvm::SmallVectorImpl &Ranges, + const Expr *Ex, bool loadedFrom = false); }; } // end anonymous namespace -void ento::RegisterDereferenceChecker(ExprEngine &Eng) { - Eng.registerCheck(new DereferenceChecker()); -} - -std::pair -ento::GetImplicitNullDereferences(ExprEngine &Eng) { - DereferenceChecker *checker = Eng.getChecker(); - if (!checker) - return std::make_pair((ExplodedNode * const *) 0, - (ExplodedNode * const *) 0); - return checker->getImplicitNodes(); -} - void DereferenceChecker::AddDerefSource(llvm::raw_ostream &os, llvm::SmallVectorImpl &Ranges, const Expr *Ex, @@ -85,13 +65,13 @@ void DereferenceChecker::AddDerefSource(llvm::raw_ostream &os, } } -void DereferenceChecker::visitLocation(CheckerContext &C, const Stmt *S, - SVal l, bool isLoad) { +void DereferenceChecker::checkLocation(SVal l, bool isLoad, + CheckerContext &C) const { // Check for dereference of an undefined value. if (l.isUndef()) { if (ExplodedNode *N = C.generateSink()) { if (!BT_undef) - BT_undef = new BuiltinBug("Dereference of undefined pointer value"); + BT_undef.reset(new BuiltinBug("Dereference of undefined pointer value")); EnhancedBugReport *report = new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N); @@ -108,6 +88,7 @@ void DereferenceChecker::visitLocation(CheckerContext &C, const Stmt *S, if (!isa(location)) return; + const Stmt *S = C.getStmt(); const GRState *state = C.getState(); const GRState *notNullState, *nullState; llvm::tie(notNullState, nullState) = state->assume(location); @@ -123,7 +104,7 @@ void DereferenceChecker::visitLocation(CheckerContext &C, const Stmt *S, // We know that 'location' cannot be non-null. This is what // we call an "explicit" null dereference. if (!BT_null) - BT_null = new BuiltinBug("Dereference of null pointer"); + BT_null.reset(new BuiltinBug("Dereference of null pointer")); llvm::SmallString<100> buf; llvm::SmallVector Ranges; @@ -195,11 +176,17 @@ void DereferenceChecker::visitLocation(CheckerContext &C, const Stmt *S, // Otherwise, we have the case where the location could either be // null or not-null. Record the error node as an "implicit" null // dereference. - if (ExplodedNode *N = C.generateSink(nullState)) - ImplicitNullDerefNodes.push_back(N); + if (ExplodedNode *N = C.generateSink(nullState)) { + ImplicitNullDerefEvent event = { l, isLoad, N, &C.getBugReporter() }; + dispatchEvent(event); + } } } // From this point forward, we know that the location is not null. C.addTransition(notNullState); } + +void ento::registerDereferenceChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp index 20cc90492246..07fb5aa998be 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp @@ -12,34 +12,25 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { -class DivZeroChecker : public CheckerVisitor { - BuiltinBug *BT; +class DivZeroChecker : public Checker< check::PreStmt > { + mutable llvm::OwningPtr BT; public: - DivZeroChecker() : BT(0) {} - static void *getTag(); - void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); + void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; }; } // end anonymous namespace -void ento::RegisterDivZeroChecker(ExprEngine &Eng) { - Eng.registerCheck(new DivZeroChecker()); -} - -void *DivZeroChecker::getTag() { - static int x; - return &x; -} - -void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C, - const BinaryOperator *B) { +void DivZeroChecker::checkPreStmt(const BinaryOperator *B, + CheckerContext &C) const { BinaryOperator::Opcode Op = B->getOpcode(); if (Op != BO_Div && Op != BO_Rem && @@ -67,7 +58,7 @@ void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C, if (stateZero && !stateNotZero) { if (ExplodedNode *N = C.generateSink(stateZero)) { if (!BT) - BT = new BuiltinBug("Division by zero"); + BT.reset(new BuiltinBug("Division by zero")); EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getDescription(), N); @@ -84,3 +75,7 @@ void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C, // zero denom case for now. C.addTransition(stateNotZero); } + +void ento::registerDivZeroChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp deleted file mode 100644 index 990ba1c02b94..000000000000 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp +++ /dev/null @@ -1,26 +0,0 @@ -//=-- ExperimentalChecks.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 defines functions to instantiate and register experimental -// checks in ExprEngine. -// -//===----------------------------------------------------------------------===// - -#include "InternalChecks.h" -#include "ExperimentalChecks.h" -#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" - -using namespace clang; -using namespace ento; - -void ento::RegisterExperimentalChecks(ExprEngine &Eng) { - // These are checks that never belong as internal checks - // within ExprEngine. - RegisterMallocChecker(Eng); // ArrayBoundChecker depends on this. -} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.h deleted file mode 100644 index 1f38ad77ebde..000000000000 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.h +++ /dev/null @@ -1,31 +0,0 @@ -//=-- ExperimentalChecks.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 defines functions to instantiate and register experimental -// checks in ExprEngine. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_GR_ExprEngine_EXPERIMENTAL_CHECKS -#define LLVM_CLANG_GR_ExprEngine_EXPERIMENTAL_CHECKS - -namespace clang { - -namespace ento { - -class ExprEngine; - -void RegisterAnalyzerStatsChecker(ExprEngine &Eng); -void RegisterMallocChecker(ExprEngine &Eng); - -} // end GR namespace - -} // end clang namespace - -#endif diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp index d7b27b563784..d699deecd768 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp @@ -14,7 +14,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -24,7 +24,7 @@ using namespace ento; namespace { class FixedAddressChecker - : public CheckerV2< check::PreStmt > { + : public Checker< check::PreStmt > { mutable llvm::OwningPtr BT; public: diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp index 83d9668c48fa..b0c07fc7d264 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp @@ -46,7 +46,7 @@ #include "clang/Analysis/CFGStmtMap.h" #include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -59,14 +59,13 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/BitVector.h" #include "llvm/Support/ErrorHandling.h" -#include using namespace clang; using namespace ento; namespace { class IdempotentOperationChecker - : public CheckerV2, + : public Checker, check::PostStmt, check::EndAnalysis> { public: @@ -336,10 +335,9 @@ void IdempotentOperationChecker::checkPostStmt(const BinaryOperator *B, = cast(C.getPredecessor()->getLocation()).getStmt(); // Ignore implicit calls to setters. - if (isa(predStmt)) + if (!isa(predStmt)) return; - - assert(isa(predStmt)); + Data.explodedNodes.Add(C.getPredecessor()); } @@ -532,12 +530,12 @@ IdempotentOperationChecker::pathWasCompletelyAnalyzed(AnalysisContext *AC, const CFGBlock *CB, const CoreEngine &CE) { - CFGReachabilityAnalysis *CRA = AC->getCFGReachablityAnalysis(); + CFGReverseBlockReachabilityAnalysis *CRA = AC->getCFGReachablityAnalysis(); // Test for reachability from any aborted blocks to this block - typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator; - for (AbortedIterator I = CE.blocks_aborted_begin(), - E = CE.blocks_aborted_end(); I != E; ++I) { + typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator; + for (ExhaustedIterator I = CE.blocks_exhausted_begin(), + E = CE.blocks_exhausted_end(); I != E; ++I) { const BlockEdge &BE = I->first; // The destination block on the BlockEdge is the first block that was not @@ -551,16 +549,25 @@ IdempotentOperationChecker::pathWasCompletelyAnalyzed(AnalysisContext *AC, if (destBlock == CB || CRA->isReachable(destBlock, CB)) return false; } + + // Test for reachability from blocks we just gave up on. + typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator; + for (AbortedIterator I = CE.blocks_aborted_begin(), + E = CE.blocks_aborted_end(); I != E; ++I) { + const CFGBlock *destBlock = I->first; + if (destBlock == CB || CRA->isReachable(destBlock, CB)) + return false; + } // For the items still on the worklist, see if they are in blocks that // can eventually reach 'CB'. class VisitWL : public WorkList::Visitor { const CFGStmtMap *CBM; const CFGBlock *TargetBlock; - CFGReachabilityAnalysis &CRA; + CFGReverseBlockReachabilityAnalysis &CRA; public: VisitWL(const CFGStmtMap *cbm, const CFGBlock *targetBlock, - CFGReachabilityAnalysis &cra) + CFGReverseBlockReachabilityAnalysis &cra) : CBM(cbm), TargetBlock(targetBlock), CRA(cra) {} virtual bool visit(const WorkListUnit &U) { ProgramPoint P = U.getNode()->getLocation(); @@ -580,7 +587,7 @@ IdempotentOperationChecker::pathWasCompletelyAnalyzed(AnalysisContext *AC, if (!B) return true; - return CRA.isReachable(B, TargetBlock); + return B == TargetBlock || CRA.isReachable(B, TargetBlock); } }; VisitWL visitWL(AC->getCFGStmtMap(), CB, *CRA); @@ -641,9 +648,10 @@ bool IdempotentOperationChecker::CanVary(const Expr *Ex, return false; // Cases requiring custom logic - case Stmt::SizeOfAlignOfExprClass: { - const SizeOfAlignOfExpr *SE = cast(Ex); - if (!SE->isSizeOf()) + case Stmt::UnaryExprOrTypeTraitExprClass: { + const UnaryExprOrTypeTraitExpr *SE = + cast(Ex); + if (SE->getKind() != UETT_SizeOf) return false; return SE->getTypeOfArgument()->isVariableArrayType(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h deleted file mode 100644 index e7c38ee25d8f..000000000000 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h +++ /dev/null @@ -1,48 +0,0 @@ -//=-- InternalChecks.h- Builtin ExprEngine Checks -------------------*- C++ -*-= -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines functions to instantiate and register the "built-in" -// checks in ExprEngine. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_GR_ExprEngine_INTERNAL_CHECKS -#define LLVM_CLANG_GR_ExprEngine_INTERNAL_CHECKS - -namespace clang { - -namespace ento { - -class ExprEngine; - -// Foundational checks that handle basic semantics. -void RegisterAdjustedReturnValueChecker(ExprEngine &Eng); -void RegisterArrayBoundCheckerV2(ExprEngine &Eng); -void RegisterAttrNonNullChecker(ExprEngine &Eng); -void RegisterBuiltinFunctionChecker(ExprEngine &Eng); -void RegisterCallAndMessageChecker(ExprEngine &Eng); -void RegisterDereferenceChecker(ExprEngine &Eng); -void RegisterDivZeroChecker(ExprEngine &Eng); -void RegisterNoReturnFunctionChecker(ExprEngine &Eng); -void RegisterReturnUndefChecker(ExprEngine &Eng); -void RegisterUndefBranchChecker(ExprEngine &Eng); -void RegisterUndefCapturedBlockVarChecker(ExprEngine &Eng); -void RegisterUndefResultChecker(ExprEngine &Eng); -void RegisterUndefinedArraySubscriptChecker(ExprEngine &Eng); -void RegisterUndefinedAssignmentChecker(ExprEngine &Eng); -void RegisterVLASizeChecker(ExprEngine &Eng); - -// API checks. -void RegisterOSAtomicChecker(ExprEngine &Eng); - -} // end GR namespace - -} // end clang namespace - -#endif diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp new file mode 100644 index 000000000000..e4e5f54770b3 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp @@ -0,0 +1,582 @@ +//=== IteratorsChecker.cpp - Check for Invalidated Iterators ------*- C++ -*---- +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines IteratorsChecker, a number of small checks for conditions +// leading to invalid iterators being used. +// FIXME: Currently only supports 'vector' and 'deque' +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/DeclTemplate.h" +#include "clang/Basic/SourceManager.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Type.h" +#include "clang/AST/PrettyPrinter.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringSwitch.h" + + +using namespace clang; +using namespace ento; + +// This is the state associated with each iterator which includes both the +// kind of state and the instance used to initialize it. +// FIXME: add location where invalidated for better error reporting. +namespace { +class RefState { + enum Kind { BeginValid, EndValid, Invalid, Undefined, Unknown } K; + const void *VR; + +public: + RefState(Kind k, const void *vr) : K(k), VR(vr) {} + + bool isValid() const { return K == BeginValid || K == EndValid; } + bool isInvalid() const { return K == Invalid; } + bool isUndefined() const { return K == Undefined; } + bool isUnknown() const { return K == Unknown; } + const MemRegion *getMemRegion() const { + if (K == BeginValid || K == EndValid) + return(const MemRegion *)VR; + return 0; + } + const MemberExpr *getMemberExpr() const { + if (K == Invalid) + return(const MemberExpr *)VR; + return 0; + } + + bool operator==(const RefState &X) const { + return K == X.K && VR == X.VR; + } + + static RefState getBeginValid(const MemRegion *vr) { + assert(vr); + return RefState(BeginValid, vr); + } + static RefState getEndValid(const MemRegion *vr) { + assert(vr); + return RefState(EndValid, vr); + } + static RefState getInvalid( const MemberExpr *ME ) { + return RefState(Invalid, ME); + } + static RefState getUndefined( void ) { + return RefState(Undefined, 0); + } + static RefState getUnknown( void ) { + return RefState(Unknown, 0); + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(K); + ID.AddPointer(VR); + } +}; + +enum RefKind { NoKind, VectorKind, VectorIteratorKind }; + +class IteratorsChecker : + public Checker, + check::PreStmt, + check::PreStmt, + check::PreStmt > + { + // Used when parsing iterators and vectors and deques. + BuiltinBug *BT_Invalid, *BT_Undefined, *BT_Incompatible; + +public: + IteratorsChecker() : + BT_Invalid(0), BT_Undefined(0), BT_Incompatible(0) + {} + static void *getTag() { static int tag; return &tag; } + + // Checker entry points. + void checkPreStmt(const CXXOperatorCallExpr *OCE, + CheckerContext &C) const; + + void checkPreStmt(const DeclStmt *DS, + CheckerContext &C) const; + + void checkPreStmt(const CXXMemberCallExpr *MCE, + CheckerContext &C) const; + + void checkPreStmt(const CallExpr *CE, + CheckerContext &C) const; + +private: + const GRState *handleAssign(const GRState *state, const Expr *lexp, + const Expr *rexp, const LocationContext *LC) const; + const GRState *handleAssign(const GRState *state, const MemRegion *MR, + const Expr *rexp, const LocationContext *LC) const; + const GRState *invalidateIterators(const GRState *state, const MemRegion *MR, + const MemberExpr *ME) const; + void checkExpr(CheckerContext &C, const Expr *E) const; + void checkArgs(CheckerContext &C, const CallExpr *CE) const; + const MemRegion *getRegion(const GRState *state, const Expr *E, + const LocationContext *LC) const; + const DeclRefExpr *getDeclRefExpr(const Expr *E) const; +}; + +class IteratorState { +public: + typedef llvm::ImmutableMap EntryMap; +}; +} //end anonymous namespace + +namespace clang { + namespace ento { + template <> + struct GRStateTrait + : public GRStatePartialTrait { + static void *GDMIndex() { return IteratorsChecker::getTag(); } + }; + } +} + +void ento::registerIteratorsChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} + +// =============================================== +// Utility functions used by visitor functions +// =============================================== + +// check a templated type for std::vector or std::deque +static RefKind getTemplateKind(const NamedDecl *td) { + const DeclContext *dc = td->getDeclContext(); + const NamespaceDecl *nameSpace = dyn_cast(dc); + if (!nameSpace || !isa(nameSpace->getDeclContext()) + || nameSpace->getName() != "std") + return NoKind; + + llvm::StringRef name = td->getName(); + return llvm::StringSwitch(name) + .Cases("vector", "deque", VectorKind) + .Default(NoKind); +} + +static RefKind getTemplateKind(const DeclContext *dc) { + if (const ClassTemplateSpecializationDecl *td = + dyn_cast(dc)) + return getTemplateKind(cast(td)); + return NoKind; +} + +static RefKind getTemplateKind(const TypedefType *tdt) { + const TypedefNameDecl *td = tdt->getDecl(); + RefKind parentKind = getTemplateKind(td->getDeclContext()); + if (parentKind == VectorKind) { + return llvm::StringSwitch(td->getName()) + .Cases("iterator", + "const_iterator", + "reverse_iterator", VectorIteratorKind) + .Default(NoKind); + } + return NoKind; +} + +static RefKind getTemplateKind(const TemplateSpecializationType *tsp) { + const TemplateName &tname = tsp->getTemplateName(); + TemplateDecl *td = tname.getAsTemplateDecl(); + if (!td) + return NoKind; + return getTemplateKind(td); +} + +static RefKind getTemplateKind(QualType T) { + if (const TemplateSpecializationType *tsp = + T->getAs()) { + return getTemplateKind(tsp); + } + if (const ElaboratedType *ET = dyn_cast(T)) { + QualType namedType = ET->getNamedType(); + if (const TypedefType *tdt = namedType->getAs()) + return getTemplateKind(tdt); + if (const TemplateSpecializationType *tsp = + namedType->getAs()) { + return getTemplateKind(tsp); + } + } + return NoKind; +} + +// Iterate through our map and invalidate any iterators that were +// initialized fromt the specified instance MemRegion. +const GRState *IteratorsChecker::invalidateIterators(const GRState *state, + const MemRegion *MR, const MemberExpr *ME) const { + IteratorState::EntryMap Map = state->get(); + if (Map.isEmpty()) + return state; + + // Loop over the entries in the current state. + // The key doesn't change, so the map iterators won't change. + for (IteratorState::EntryMap::iterator I = Map.begin(), E = Map.end(); + I != E; ++I) { + RefState RS = I.getData(); + if (RS.getMemRegion() == MR) + state = state->set(I.getKey(), RefState::getInvalid(ME)); + } + + return state; +} + +// Handle assigning to an iterator where we don't have the LValue MemRegion. +const GRState *IteratorsChecker::handleAssign(const GRState *state, + const Expr *lexp, const Expr *rexp, const LocationContext *LC) const { + // Skip the cast if present. + if (isa(lexp)) + lexp = dyn_cast(lexp)->getSubExpr(); + SVal sv = state->getSVal(lexp); + const MemRegion *MR = sv.getAsRegion(); + if (!MR) + return state; + RefKind kind = getTemplateKind(lexp->getType()); + + // If assigning to a vector, invalidate any iterators currently associated. + if (kind == VectorKind) + return invalidateIterators(state, MR, 0); + + // Make sure that we are assigning to an iterator. + if (getTemplateKind(lexp->getType()) != VectorIteratorKind) + return state; + return handleAssign(state, MR, rexp, LC); +} + +// handle assigning to an iterator +const GRState *IteratorsChecker::handleAssign(const GRState *state, + const MemRegion *MR, const Expr *rexp, const LocationContext *LC) const { + // Assume unknown until we find something definite. + state = state->set(MR, RefState::getUnknown()); + if (isa(rexp)) + rexp = dyn_cast(rexp)->getSubExpr(); + // Need to handle three cases: MemberCall, copy, copy with addition. + if (const CallExpr *CE = dyn_cast(rexp)) { + // Handle MemberCall. + if (const MemberExpr *ME = dyn_cast(CE->getCallee())) { + const DeclRefExpr *DRE = dyn_cast(ME->getBase()); + if (!DRE) + return state; + // Verify that the type is std::vector. + if (getTemplateKind(DRE->getType()) != VectorKind) + return state; + // Now get the MemRegion associated with the instance. + const VarDecl *VD = dyn_cast(DRE->getDecl()); + if (!VD) + return state; + const MemRegion *IMR = state->getRegion(VD, LC); + if (!IMR) + return state; + // Finally, see if it is one of the calls that will create + // a valid iterator and mark it if so, else mark as Unknown. + llvm::StringRef mName = ME->getMemberDecl()->getName(); + + if (llvm::StringSwitch(mName) + .Cases("begin", "insert", "erase", true).Default(false)) { + return state->set(MR, RefState::getBeginValid(IMR)); + } + if (mName == "end") + return state->set(MR, RefState::getEndValid(IMR)); + + return state->set(MR, RefState::getUnknown()); + } + } + // Handle straight copy from another iterator. + if (const DeclRefExpr *DRE = dyn_cast(rexp)) { + if (getTemplateKind(DRE->getType()) != VectorIteratorKind) + return state; + // Now get the MemRegion associated with the instance. + const VarDecl *VD = dyn_cast(DRE->getDecl()); + if (!VD) + return state; + const MemRegion *IMR = state->getRegion(VD, LC); + if (!IMR) + return state; + // Get the RefState of the iterator being copied. + const RefState *RS = state->get(IMR); + if (!RS) + return state; + // Use it to set the state of the LValue. + return state->set(MR, *RS); + } + // If we have operator+ or operator- ... + if (const CXXOperatorCallExpr *OCE = dyn_cast(rexp)) { + OverloadedOperatorKind Kind = OCE->getOperator(); + if (Kind == OO_Plus || Kind == OO_Minus) { + // Check left side of tree for a valid value. + state = handleAssign( state, MR, OCE->getArg(0), LC); + const RefState *RS = state->get(MR); + // If found, return it. + if (!RS->isUnknown()) + return state; + // Otherwise return what we find in the right side. + return handleAssign(state, MR, OCE->getArg(1), LC); + } + } + // Fall through if nothing matched. + return state; +} + +// Iterate through the arguments looking for an Invalid or Undefined iterator. +void IteratorsChecker::checkArgs(CheckerContext &C, const CallExpr *CE) const { + for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end(); + I != E; ++I) { + checkExpr(C, *I); + } +} + +// Get the DeclRefExpr associated with the expression. +const DeclRefExpr *IteratorsChecker::getDeclRefExpr(const Expr *E) const { + // If it is a CXXConstructExpr, need to get the subexpression. + if (const CXXConstructExpr *CE = dyn_cast(E)) { + if (CE->getNumArgs()== 1) { + CXXConstructorDecl *CD = CE->getConstructor(); + if (CD->isTrivial()) + E = CE->getArg(0); + } + } + if (isa(E)) + E = dyn_cast(E)->getSubExpr(); + // If it isn't one of our types, don't do anything. + if (getTemplateKind(E->getType()) != VectorIteratorKind) + return NULL; + return dyn_cast(E); +} + +// Get the MemRegion associated with the expresssion. +const MemRegion *IteratorsChecker::getRegion(const GRState *state, + const Expr *E, const LocationContext *LC) const { + const DeclRefExpr *DRE = getDeclRefExpr(E); + if (!DRE) + return NULL; + const VarDecl *VD = dyn_cast(DRE->getDecl()); + if (!VD) + return NULL; + // return the MemRegion associated with the iterator + return state->getRegion(VD, LC); +} + +// Check the expression and if it is an iterator, generate a diagnostic +// if the iterator is not valid. +// FIXME: this method can generate new nodes, and subsequent logic should +// use those nodes. We also cannot create multiple nodes at one ProgramPoint +// with the same tag. +void IteratorsChecker::checkExpr(CheckerContext &C, const Expr *E) const { + const GRState *state = C.getState(); + const MemRegion *MR = getRegion(state, E, + C.getPredecessor()->getLocationContext()); + if (!MR) + return; + + // Get the state associated with the iterator. + const RefState *RS = state->get(MR); + if (!RS) + return; + if (RS->isInvalid()) { + if (ExplodedNode *N = C.generateNode()) { + if (!BT_Invalid) + // FIXME: We are eluding constness here. + const_cast(this)->BT_Invalid = new BuiltinBug(""); + + std::string msg; + const MemberExpr *ME = RS->getMemberExpr(); + if (ME) { + std::string name = ME->getMemberNameInfo().getAsString(); + msg = "Attempt to use an iterator made invalid by call to '" + + name + "'"; + } + else { + msg = "Attempt to use an iterator made invalid by copying another " + "container to its container"; + } + + EnhancedBugReport *R = new EnhancedBugReport(*BT_Invalid, msg, N); + R->addRange(getDeclRefExpr(E)->getSourceRange()); + C.EmitReport(R); + } + } + else if (RS->isUndefined()) { + if (ExplodedNode *N = C.generateNode()) { + if (!BT_Undefined) + // FIXME: We are eluding constness here. + const_cast(this)->BT_Undefined = + new BuiltinBug("Use of iterator that is not defined"); + + EnhancedBugReport *R = new EnhancedBugReport(*BT_Undefined, + BT_Undefined->getDescription(), N); + R->addRange(getDeclRefExpr(E)->getSourceRange()); + C.EmitReport(R); + } + } +} + +// =============================================== +// Path analysis visitor functions +// =============================================== + +// For a generic Call, just check the args for bad iterators. +void IteratorsChecker::checkPreStmt(const CallExpr *CE, + CheckerContext &C) const{ + + // FIXME: These checks are to currently work around a bug + // in CheckerManager. + if (isa(CE)) + return; + if (isa(CE)) + return; + + checkArgs(C, CE); +} + +// Handle operator calls. First, if it is operator=, check the argument, +// and handle assigning and set target state appropriately. Otherwise, for +// other operators, check the args for bad iterators and handle comparisons. +void IteratorsChecker::checkPreStmt(const CXXOperatorCallExpr *OCE, + CheckerContext &C) const +{ + const LocationContext *LC = C.getPredecessor()->getLocationContext(); + const GRState *state = C.getState(); + OverloadedOperatorKind Kind = OCE->getOperator(); + if (Kind == OO_Equal) { + checkExpr(C, OCE->getArg(1)); + state = handleAssign(state, OCE->getArg(0), OCE->getArg(1), LC); + C.addTransition(state); + return; + } + else { + checkArgs(C, OCE); + // If it is a compare and both are iterators, ensure that they are for + // the same container. + if (Kind == OO_EqualEqual || Kind == OO_ExclaimEqual || + Kind == OO_Less || Kind == OO_LessEqual || + Kind == OO_Greater || Kind == OO_GreaterEqual) { + const MemRegion *MR0, *MR1; + MR0 = getRegion(state, OCE->getArg(0), LC); + if (!MR0) + return; + MR1 = getRegion(state, OCE->getArg(1), LC); + if (!MR1) + return; + const RefState *RS0, *RS1; + RS0 = state->get(MR0); + if (!RS0) + return; + RS1 = state->get(MR1); + if (!RS1) + return; + if (RS0->getMemRegion() != RS1->getMemRegion()) { + if (ExplodedNode *N = C.generateNode()) { + if (!BT_Incompatible) + const_cast(this)->BT_Incompatible = + new BuiltinBug( + "Cannot compare iterators from different containers"); + + EnhancedBugReport *R = new EnhancedBugReport(*BT_Incompatible, + BT_Incompatible->getDescription(), N); + R->addRange(OCE->getSourceRange()); + C.EmitReport(R); + } + } + } + } +} + +// Need to handle DeclStmts to pick up initializing of iterators and to mark +// uninitialized ones as Undefined. +void IteratorsChecker::checkPreStmt(const DeclStmt *DS, + CheckerContext &C) const { + const Decl* D = *DS->decl_begin(); + const VarDecl* VD = dyn_cast(D); + // Only care about iterators. + if (getTemplateKind(VD->getType()) != VectorIteratorKind) + return; + + // Get the MemRegion associated with the iterator and mark it as Undefined. + const GRState *state = C.getState(); + Loc VarLoc = state->getLValue(VD, C.getPredecessor()->getLocationContext()); + const MemRegion *MR = VarLoc.getAsRegion(); + if (!MR) + return; + state = state->set(MR, RefState::getUndefined()); + + // if there is an initializer, handle marking Valid if a proper initializer + const Expr* InitEx = VD->getInit(); + if (InitEx) { + // FIXME: This is too syntactic. Since 'InitEx' will be analyzed first + // it should resolve to an SVal that we can check for validity + // *semantically* instead of walking through the AST. + if (const CXXConstructExpr *CE = dyn_cast(InitEx)) { + if (CE->getNumArgs() == 1) { + const Expr *E = CE->getArg(0); + if (isa(E)) + InitEx = dyn_cast(E)->getSubExpr(); + state = handleAssign(state, MR, InitEx, + C.getPredecessor()->getLocationContext()); + } + } + } + C.addTransition(state); +} + + +namespace { struct CalledReserved {}; } +namespace clang { namespace ento { +template<> struct GRStateTrait + : public GRStatePartialTrait > { + static void *GDMIndex() { static int index = 0; return &index; } +}; +}} + +// on a member call, first check the args for any bad iterators +// then, check to see if it is a call to a function that will invalidate +// the iterators +void IteratorsChecker::checkPreStmt(const CXXMemberCallExpr *MCE, + CheckerContext &C) const { + // Check the arguments. + checkArgs(C, MCE); + const MemberExpr *ME = dyn_cast(MCE->getCallee()); + if (!ME) + return; + // Make sure we have the right kind of container. + const DeclRefExpr *DRE = dyn_cast(ME->getBase()); + if (!DRE || getTemplateKind(DRE->getType()) != VectorKind) + return; + SVal tsv = C.getState()->getSVal(DRE); + // Get the MemRegion associated with the container instance. + const MemRegion *MR = tsv.getAsRegion(); + if (!MR) + return; + // If we are calling a function that invalidates iterators, mark them + // appropriately by finding matching instances. + const GRState *state = C.getState(); + llvm::StringRef mName = ME->getMemberDecl()->getName(); + if (llvm::StringSwitch(mName) + .Cases("insert", "reserve", "push_back", true) + .Cases("erase", "pop_back", "clear", "resize", true) + .Default(false)) { + // If there was a 'reserve' call, assume iterators are good. + if (!state->contains(MR)) + state = invalidateIterators(state, MR, ME); + } + // Keep track of instances that have called 'reserve' + // note: do this after we invalidate any iterators by calling + // 'reserve' itself. + if (mName == "reserve") + state = state->add(MR); + + if (state != C.getState()) + C.addTransition(state); +} + diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp index 9e3adc804f67..3d1b5e2d1051 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp @@ -13,8 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" -#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/StmtVisitor.h" @@ -57,7 +56,7 @@ static bool IsStdString(QualType T) { if (!TT) return false; - const TypedefDecl *TD = TT->getDecl(); + const TypedefNameDecl *TD = TT->getDecl(); if (!InNamespace(TD, "std")) return false; @@ -289,7 +288,7 @@ void ASTFieldVisitor::ReportError(QualType T) { //===----------------------------------------------------------------------===// namespace { -class LLVMConventionsChecker : public CheckerV2< +class LLVMConventionsChecker : public Checker< check::ASTDecl, check::ASTCodeBody > { public: diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp index d70c65ae3073..12ce86613ddc 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp @@ -16,7 +16,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -30,7 +30,7 @@ using namespace clang; using namespace ento; namespace { -class MacOSXAPIChecker : public CheckerV2< check::PreStmt > { +class MacOSXAPIChecker : public Checker< check::PreStmt > { enum SubChecks { DispatchOnce = 0, DispatchOnceF, diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 794740ab7203..91002158c57f 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -12,9 +12,11 @@ // //===----------------------------------------------------------------------===// -#include "ExperimentalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" @@ -62,55 +64,52 @@ class RefState { class RegionState {}; -class MallocChecker : public CheckerVisitor { - BuiltinBug *BT_DoubleFree; - BuiltinBug *BT_Leak; - BuiltinBug *BT_UseFree; - BuiltinBug *BT_UseRelinquished; - BuiltinBug *BT_BadFree; - IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc; +class MallocChecker : public Checker, check::Location, + check::Bind, eval::Assume> { + mutable llvm::OwningPtr BT_DoubleFree; + mutable llvm::OwningPtr BT_Leak; + mutable llvm::OwningPtr BT_UseFree; + mutable llvm::OwningPtr BT_UseRelinquished; + mutable llvm::OwningPtr BT_BadFree; + mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc; public: - MallocChecker() - : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), BT_UseRelinquished(0), - BT_BadFree(0), - II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {} - static void *getTag(); - bool evalCallExpr(CheckerContext &C, const CallExpr *CE); - void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper); - void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng); - void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S); - const GRState *evalAssume(const GRState *state, SVal Cond, bool Assumption, - bool *respondsToCallback); - void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad); - virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE, - SVal location, SVal val); + MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {} + + bool evalCall(const CallExpr *CE, CheckerContext &C) const; + void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; + void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const; + void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; + const GRState *evalAssume(const GRState *state, SVal Cond, + bool Assumption) const; + void checkLocation(SVal l, bool isLoad, CheckerContext &C) const; + void checkBind(SVal location, SVal val, CheckerContext &C) const; private: - void MallocMem(CheckerContext &C, const CallExpr *CE); - void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, - const OwnershipAttr* Att); - const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE, - const Expr *SizeEx, SVal Init, - const GRState *state) { + static void MallocMem(CheckerContext &C, const CallExpr *CE); + static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, + const OwnershipAttr* Att); + static const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE, + const Expr *SizeEx, SVal Init, + const GRState *state) { return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, state); } - const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE, - SVal SizeEx, SVal Init, - const GRState *state); + static const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE, + SVal SizeEx, SVal Init, + const GRState *state); - void FreeMem(CheckerContext &C, const CallExpr *CE); + void FreeMem(CheckerContext &C, const CallExpr *CE) const; void FreeMemAttr(CheckerContext &C, const CallExpr *CE, - const OwnershipAttr* Att); + const OwnershipAttr* Att) const; const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE, - const GRState *state, unsigned Num, bool Hold); + const GRState *state, unsigned Num, bool Hold) const; - void ReallocMem(CheckerContext &C, const CallExpr *CE); - void CallocMem(CheckerContext &C, const CallExpr *CE); + void ReallocMem(CheckerContext &C, const CallExpr *CE) const; + static void CallocMem(CheckerContext &C, const CallExpr *CE); - bool SummarizeValue(llvm::raw_ostream& os, SVal V); - bool SummarizeRegion(llvm::raw_ostream& os, const MemRegion *MR); - void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range); + static bool SummarizeValue(llvm::raw_ostream& os, SVal V); + static bool SummarizeRegion(llvm::raw_ostream& os, const MemRegion *MR); + void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const; }; } // end anonymous namespace @@ -121,21 +120,12 @@ namespace ento { template <> struct GRStateTrait : public GRStatePartialTrait { - static void *GDMIndex() { return MallocChecker::getTag(); } + static void *GDMIndex() { static int x; return &x; } }; } } -void ento::RegisterMallocChecker(ExprEngine &Eng) { - Eng.registerCheck(new MallocChecker()); -} - -void *MallocChecker::getTag() { - static int x; - return &x; -} - -bool MallocChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { +bool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); SVal L = state->getSVal(Callee); @@ -256,7 +246,7 @@ const GRState *MallocChecker::MallocMemAux(CheckerContext &C, return state->set(Sym, RefState::getAllocateUnchecked(CE)); } -void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) { +void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) const { const GRState *state = FreeMemAux(C, CE, C.getState(), 0, false); if (state) @@ -264,7 +254,7 @@ void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) { } void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE, - const OwnershipAttr* Att) { + const OwnershipAttr* Att) const { if (Att->getModule() != "malloc") return; @@ -279,7 +269,7 @@ void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE, const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE, const GRState *state, unsigned Num, - bool Hold) { + bool Hold) const { const Expr *ArgExpr = CE->getArg(Num); SVal ArgVal = state->getSVal(ArgExpr); @@ -357,9 +347,9 @@ const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE, if (RS->isReleased()) { if (ExplodedNode *N = C.generateSink()) { if (!BT_DoubleFree) - BT_DoubleFree - = new BuiltinBug("Double free", - "Try to free a memory block that has been released"); + BT_DoubleFree.reset( + new BuiltinBug("Double free", + "Try to free a memory block that has been released")); // FIXME: should find where it's freed last time. BugReport *R = new BugReport(*BT_DoubleFree, BT_DoubleFree->getDescription(), N); @@ -463,10 +453,10 @@ bool MallocChecker::SummarizeRegion(llvm::raw_ostream& os, } void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, - SourceRange range) { + SourceRange range) const { if (ExplodedNode *N = C.generateSink()) { if (!BT_BadFree) - BT_BadFree = new BuiltinBug("Bad free"); + BT_BadFree.reset(new BuiltinBug("Bad free")); llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); @@ -500,7 +490,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, } } -void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) { +void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); const Expr *arg0Expr = CE->getArg(0); DefinedOrUnknownSVal arg0Val @@ -511,8 +501,24 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) { DefinedOrUnknownSVal PtrEQ = svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull()); - // If the ptr is NULL, the call is equivalent to malloc(size). - if (const GRState *stateEqual = state->assume(PtrEQ, true)) { + // Get the size argument. If there is no size arg then give up. + const Expr *Arg1 = CE->getArg(1); + if (!Arg1) + return; + + // Get the value of the size argument. + DefinedOrUnknownSVal Arg1Val = + cast(state->getSVal(Arg1)); + + // Compare the size argument to 0. + DefinedOrUnknownSVal SizeZero = + svalBuilder.evalEQ(state, Arg1Val, + svalBuilder.makeIntValWithPtrWidth(0, false)); + + // If the ptr is NULL and the size is not 0, the call is equivalent to + // malloc(size). + const GRState *stateEqual = state->assume(PtrEQ, true); + if (stateEqual && state->assume(SizeZero, false)) { // Hack: set the NULL symbolic region to released to suppress false warning. // In the future we should add more states for allocated regions, e.g., // CheckedNull, CheckedNonNull. @@ -527,17 +533,17 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) { } if (const GRState *stateNotEqual = state->assume(PtrEQ, false)) { - const Expr *Arg1 = CE->getArg(1); - DefinedOrUnknownSVal Arg1Val = - cast(stateNotEqual->getSVal(Arg1)); - DefinedOrUnknownSVal SizeZero = - svalBuilder.evalEQ(stateNotEqual, Arg1Val, - svalBuilder.makeIntValWithPtrWidth(0, false)); - + // If the size is 0, free the memory. if (const GRState *stateSizeZero = stateNotEqual->assume(SizeZero, true)) - if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeZero, 0, false)) - C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true)); + if (const GRState *stateFree = + FreeMemAux(C, CE, stateSizeZero, 0, false)) { + // Add the state transition to set input pointer argument to be free. + C.addTransition(stateFree); + + // Bind the return value to UndefinedVal because it is now free. + C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true)); + } if (const GRState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false)) if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero, 0, false)) { @@ -562,7 +568,8 @@ void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) { C.addTransition(MallocMemAux(C, CE, TotalSize, zeroVal, state)); } -void MallocChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) +void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper, + CheckerContext &C) const { if (!SymReaper.hasDeadSymbols()) return; @@ -576,8 +583,8 @@ void MallocChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) if (I->second.isAllocated()) { if (ExplodedNode *N = C.generateNode()) { if (!BT_Leak) - BT_Leak = new BuiltinBug("Memory leak", - "Allocated memory never released. Potential memory leak."); + BT_Leak.reset(new BuiltinBug("Memory leak", + "Allocated memory never released. Potential memory leak.")); // FIXME: where it is allocated. BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N); C.EmitReport(R); @@ -591,8 +598,8 @@ void MallocChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) C.generateNode(state->set(RS)); } -void MallocChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, - ExprEngine &Eng) { +void MallocChecker::checkEndPath(EndOfFunctionNodeBuilder &B, + ExprEngine &Eng) const { const GRState *state = B.getState(); RegionStateTy M = state->get(); @@ -602,8 +609,8 @@ void MallocChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExplodedNode *N = B.generateNode(state); if (N) { if (!BT_Leak) - BT_Leak = new BuiltinBug("Memory leak", - "Allocated memory never released. Potential memory leak."); + BT_Leak.reset(new BuiltinBug("Memory leak", + "Allocated memory never released. Potential memory leak.")); BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N); Eng.getBugReporter().EmitReport(R); } @@ -611,7 +618,7 @@ void MallocChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, } } -void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) { +void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { const Expr *retExpr = S->getRetValue(); if (!retExpr) return; @@ -634,14 +641,14 @@ void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) { } const GRState *MallocChecker::evalAssume(const GRState *state, SVal Cond, - bool Assumption, - bool * /* respondsToCallback */) { + bool Assumption) const { // If a symblic region is assumed to NULL, set its state to AllocateFailed. // FIXME: should also check symbols assumed to non-null. RegionStateTy RS = state->get(); for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { + // If the symbol is assumed to NULL, this will return an APSInt*. if (state->getSymVal(I.getKey())) state = state->set(I.getKey(),RefState::getAllocateFailed()); } @@ -650,16 +657,15 @@ const GRState *MallocChecker::evalAssume(const GRState *state, SVal Cond, } // Check if the location is a freed symbolic region. -void MallocChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l, - bool isLoad) { +void MallocChecker::checkLocation(SVal l, bool isLoad,CheckerContext &C) const { SymbolRef Sym = l.getLocSymbolInBase(); if (Sym) { const RefState *RS = C.getState()->get(Sym); if (RS && RS->isReleased()) { if (ExplodedNode *N = C.generateNode()) { if (!BT_UseFree) - BT_UseFree = new BuiltinBug("Use dynamically allocated memory after" - " it is freed."); + BT_UseFree.reset(new BuiltinBug("Use dynamically allocated memory " + "after it is freed.")); BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(), N); @@ -669,10 +675,7 @@ void MallocChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l, } } -void MallocChecker::PreVisitBind(CheckerContext &C, - const Stmt *StoreE, - SVal location, - SVal val) { +void MallocChecker::checkBind(SVal location, SVal val,CheckerContext &C) const { // The PreVisitBind implements the same algorithm as already used by the // Objective C ownership checker: if the pointer escaped from this scope by // assignment, let it go. However, assigning to fields of a stack-storage @@ -721,7 +724,7 @@ void MallocChecker::PreVisitBind(CheckerContext &C, // We no longer own this pointer. notNullState = notNullState->set(Sym, - RefState::getRelinquished(StoreE)); + RefState::getRelinquished(C.getStmt())); } while (false); } @@ -729,3 +732,7 @@ void MallocChecker::PreVisitBind(CheckerContext &C, } } } + +void ento::registerMallocChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp index fed6a99c89a2..f11db6458cc0 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp @@ -16,7 +16,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -29,7 +29,7 @@ using namespace ento; namespace { class NSAutoreleasePoolChecker - : public CheckerV2 { + : public Checker { mutable Selector releaseS; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp index 7a1b9787754d..63a591729944 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp @@ -1,4 +1,4 @@ -//=- NSErrorCheckerer.cpp - Coding conventions for uses of NSError -*- C++ -*-==// +//=- NSErrorChecker.cpp - Coding conventions for uses of NSError -*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -15,11 +15,12 @@ // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" -#include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h" -#include "BasicObjCFoundationChecks.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Decl.h" #include "llvm/ADT/SmallVector.h" @@ -27,142 +28,263 @@ using namespace clang; using namespace ento; +static bool IsNSError(QualType T, IdentifierInfo *II); +static bool IsCFError(QualType T, IdentifierInfo *II); + +//===----------------------------------------------------------------------===// +// NSErrorMethodChecker +//===----------------------------------------------------------------------===// + namespace { -class NSErrorChecker : public BugType { - const Decl &CodeDecl; - const bool isNSErrorWarning; - IdentifierInfo * const II; - ExprEngine &Eng; - - void CheckSignature(const ObjCMethodDecl& MD, QualType& ResultTy, - llvm::SmallVectorImpl& ErrorParams); - - void CheckSignature(const FunctionDecl& MD, QualType& ResultTy, - llvm::SmallVectorImpl& ErrorParams); - - bool CheckNSErrorArgument(QualType ArgTy); - bool CheckCFErrorArgument(QualType ArgTy); - - void CheckParamDeref(const VarDecl *V, const LocationContext *LC, - const GRState *state, BugReporter& BR); - - void EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl); +class NSErrorMethodChecker + : public Checker< check::ASTDecl > { + mutable IdentifierInfo *II; public: - NSErrorChecker(const Decl &D, bool isNSError, ExprEngine& eng) - : BugType(isNSError ? "NSError** null dereference" - : "CFErrorRef* null dereference", - "Coding conventions (Apple)"), - CodeDecl(D), - isNSErrorWarning(isNSError), - II(&eng.getContext().Idents.get(isNSErrorWarning ? "NSError":"CFErrorRef")), - Eng(eng) {} + NSErrorMethodChecker() : II(0) { } - void FlushReports(BugReporter& BR); + void checkASTDecl(const ObjCMethodDecl *D, + AnalysisManager &mgr, BugReporter &BR) const; +}; +} + +void NSErrorMethodChecker::checkASTDecl(const ObjCMethodDecl *D, + AnalysisManager &mgr, + BugReporter &BR) const { + if (!D->isThisDeclarationADefinition()) + return; + if (!D->getResultType()->isVoidType()) + return; + + if (!II) + II = &D->getASTContext().Idents.get("NSError"); + + bool hasNSError = false; + for (ObjCMethodDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) { + if (IsNSError((*I)->getType(), II)) { + hasNSError = true; + break; + } + } + + if (hasNSError) { + const char *err = "Method accepting NSError** " + "should have a non-void return value to indicate whether or not an " + "error occurred"; + BR.EmitBasicReport("Bad return type when passing NSError**", + "Coding conventions (Apple)", err, D->getLocation()); + } +} + +//===----------------------------------------------------------------------===// +// CFErrorFunctionChecker +//===----------------------------------------------------------------------===// + +namespace { +class CFErrorFunctionChecker + : public Checker< check::ASTDecl > { + mutable IdentifierInfo *II; + +public: + CFErrorFunctionChecker() : II(0) { } + + void checkASTDecl(const FunctionDecl *D, + AnalysisManager &mgr, BugReporter &BR) const; +}; +} + +void CFErrorFunctionChecker::checkASTDecl(const FunctionDecl *D, + AnalysisManager &mgr, + BugReporter &BR) const { + if (!D->isThisDeclarationADefinition()) + return; + if (!D->getResultType()->isVoidType()) + return; + + if (!II) + II = &D->getASTContext().Idents.get("CFErrorRef"); + + bool hasCFError = false; + for (FunctionDecl::param_const_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) { + if (IsCFError((*I)->getType(), II)) { + hasCFError = true; + break; + } + } + + if (hasCFError) { + const char *err = "Function accepting CFErrorRef* " + "should have a non-void return value to indicate whether or not an " + "error occurred"; + BR.EmitBasicReport("Bad return type when passing CFErrorRef*", + "Coding conventions (Apple)", err, D->getLocation()); + } +} + +//===----------------------------------------------------------------------===// +// NSOrCFErrorDerefChecker +//===----------------------------------------------------------------------===// + +namespace { + +class NSErrorDerefBug : public BugType { +public: + NSErrorDerefBug() : BugType("NSError** null dereference", + "Coding conventions (Apple)") {} }; -} // end anonymous namespace +class CFErrorDerefBug : public BugType { +public: + CFErrorDerefBug() : BugType("CFErrorRef* null dereference", + "Coding conventions (Apple)") {} +}; -void ento::RegisterNSErrorChecks(BugReporter& BR, ExprEngine &Eng, - const Decl &D) { - BR.Register(new NSErrorChecker(D, true, Eng)); - BR.Register(new NSErrorChecker(D, false, Eng)); } -void NSErrorChecker::FlushReports(BugReporter& BR) { - // Get the analysis engine and the exploded analysis graph. - ExplodedGraph& G = Eng.getGraph(); +namespace { +class NSOrCFErrorDerefChecker + : public Checker< check::Location, + check::Event > { + mutable IdentifierInfo *NSErrorII, *CFErrorII; +public: + bool ShouldCheckNSError, ShouldCheckCFError; + NSOrCFErrorDerefChecker() : NSErrorII(0), CFErrorII(0), + ShouldCheckNSError(0), ShouldCheckCFError(0) { } - // Get the ASTContext, which is useful for querying type information. - ASTContext &Ctx = BR.getContext(); + void checkLocation(SVal loc, bool isLoad, CheckerContext &C) const; + void checkEvent(ImplicitNullDerefEvent event) const; +}; +} - QualType ResultTy; - llvm::SmallVector ErrorParams; +namespace { struct NSErrorOut {}; } +namespace { struct CFErrorOut {}; } - if (const ObjCMethodDecl* MD = dyn_cast(&CodeDecl)) - CheckSignature(*MD, ResultTy, ErrorParams); - else if (const FunctionDecl* FD = dyn_cast(&CodeDecl)) - CheckSignature(*FD, ResultTy, ErrorParams); - else +typedef llvm::ImmutableMap ErrorOutFlag; + +namespace clang { +namespace ento { + template <> + struct GRStateTrait : public GRStatePartialTrait { + static void *GDMIndex() { static int index = 0; return &index; } + }; + template <> + struct GRStateTrait : public GRStatePartialTrait { + static void *GDMIndex() { static int index = 0; return &index; } + }; +} +} + +template +static bool hasFlag(SVal val, const GRState *state) { + if (SymbolRef sym = val.getAsSymbol()) + if (const unsigned *attachedFlags = state->get(sym)) + return *attachedFlags; + return false; +} + +template +static void setFlag(const GRState *state, SVal val, CheckerContext &C) { + // We tag the symbol that the SVal wraps. + if (SymbolRef sym = val.getAsSymbol()) + C.addTransition(state->set(sym, true)); +} + +static QualType parameterTypeFromSVal(SVal val, CheckerContext &C) { + const StackFrameContext * + SFC = C.getPredecessor()->getLocationContext()->getCurrentStackFrame(); + if (const loc::MemRegionVal* X = dyn_cast(&val)) { + const MemRegion* R = X->getRegion(); + if (const VarRegion *VR = R->getAs()) + if (const StackArgumentsSpaceRegion * + stackReg = dyn_cast(VR->getMemorySpace())) + if (stackReg->getStackFrame() == SFC) + return VR->getValueType(); + } + + return QualType(); +} + +void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad, + CheckerContext &C) const { + if (!isLoad) + return; + if (loc.isUndef() || !isa(loc)) return; - if (ErrorParams.empty()) + ASTContext &Ctx = C.getASTContext(); + const GRState *state = C.getState(); + + // If we are loading from NSError**/CFErrorRef* parameter, mark the resulting + // SVal so that we can later check it when handling the + // ImplicitNullDerefEvent event. + // FIXME: Cumbersome! Maybe add hook at construction of SVals at start of + // function ? + + QualType parmT = parameterTypeFromSVal(loc, C); + if (parmT.isNull()) return; - if (ResultTy == Ctx.VoidTy) EmitRetTyWarning(BR, CodeDecl); + if (!NSErrorII) + NSErrorII = &Ctx.Idents.get("NSError"); + if (!CFErrorII) + CFErrorII = &Ctx.Idents.get("CFErrorRef"); - for (ExplodedGraph::roots_iterator RI=G.roots_begin(), RE=G.roots_end(); - RI!=RE; ++RI) { - // Scan the parameters for an implicit null dereference. - for (llvm::SmallVectorImpl::iterator I=ErrorParams.begin(), - E=ErrorParams.end(); I!=E; ++I) - CheckParamDeref(*I, (*RI)->getLocationContext(), (*RI)->getState(), BR); + if (ShouldCheckNSError && IsNSError(parmT, NSErrorII)) { + setFlag(state, state->getSVal(cast(loc)), C); + return; + } + + if (ShouldCheckCFError && IsCFError(parmT, CFErrorII)) { + setFlag(state, state->getSVal(cast(loc)), C); + return; } } -void NSErrorChecker::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) { - std::string sbuf; - llvm::raw_string_ostream os(sbuf); +void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const { + if (event.IsLoad) + return; - if (isa(CodeDecl)) - os << "Method"; + SVal loc = event.Location; + const GRState *state = event.SinkNode->getState(); + BugReporter &BR = *event.BR; + + bool isNSError = hasFlag(loc, state); + bool isCFError = false; + if (!isNSError) + isCFError = hasFlag(loc, state); + + if (!(isNSError || isCFError)) + return; + + // Storing to possible null NSError/CFErrorRef out parameter. + + // Emit an error. + std::string err; + llvm::raw_string_ostream os(err); + os << "Potential null dereference. According to coding standards "; + + if (isNSError) + os << "in 'Creating and Returning NSError Objects' the parameter '"; else - os << "Function"; + os << "documented in CoreFoundation/CFError.h the parameter '"; - os << " accepting "; - os << (isNSErrorWarning ? "NSError**" : "CFErrorRef*"); - os << " should have a non-void return value to indicate whether or not an " - "error occurred"; + os << "' may be null."; - BR.EmitBasicReport(isNSErrorWarning - ? "Bad return type when passing NSError**" - : "Bad return type when passing CFError*", - getCategory(), os.str(), - CodeDecl.getLocation()); + BugType *bug = 0; + if (isNSError) + bug = new NSErrorDerefBug(); + else + bug = new CFErrorDerefBug(); + EnhancedBugReport *report = new EnhancedBugReport(*bug, os.str(), + event.SinkNode); + BR.EmitReport(report); } -void -NSErrorChecker::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy, - llvm::SmallVectorImpl& ErrorParams) { +static bool IsNSError(QualType T, IdentifierInfo *II) { - ResultTy = M.getResultType(); - - for (ObjCMethodDecl::param_iterator I=M.param_begin(), - E=M.param_end(); I!=E; ++I) { - - QualType T = (*I)->getType(); - - if (isNSErrorWarning) { - if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I); - } - else if (CheckCFErrorArgument(T)) - ErrorParams.push_back(*I); - } -} - -void -NSErrorChecker::CheckSignature(const FunctionDecl& F, QualType& ResultTy, - llvm::SmallVectorImpl& ErrorParams) { - - ResultTy = F.getResultType(); - - for (FunctionDecl::param_const_iterator I = F.param_begin(), - E = F.param_end(); I != E; ++I) { - - QualType T = (*I)->getType(); - - if (isNSErrorWarning) { - if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I); - } - else if (CheckCFErrorArgument(T)) - ErrorParams.push_back(*I); - } -} - - -bool NSErrorChecker::CheckNSErrorArgument(QualType ArgTy) { - - const PointerType* PPT = ArgTy->getAs(); + const PointerType* PPT = T->getAs(); if (!PPT) return false; @@ -181,9 +303,8 @@ bool NSErrorChecker::CheckNSErrorArgument(QualType ArgTy) { return false; } -bool NSErrorChecker::CheckCFErrorArgument(QualType ArgTy) { - - const PointerType* PPT = ArgTy->getAs(); +static bool IsCFError(QualType T, IdentifierInfo *II) { + const PointerType* PPT = T->getAs(); if (!PPT) return false; const TypedefType* TT = PPT->getPointeeType()->getAs(); @@ -192,47 +313,16 @@ bool NSErrorChecker::CheckCFErrorArgument(QualType ArgTy) { return TT->getDecl()->getIdentifier() == II; } -void NSErrorChecker::CheckParamDeref(const VarDecl *Param, - const LocationContext *LC, - const GRState *rootState, - BugReporter& BR) { - - SVal ParamL = rootState->getLValue(Param, LC); - const MemRegion* ParamR = cast(ParamL).getRegionAs(); - assert (ParamR && "Parameters always have VarRegions."); - SVal ParamSVal = rootState->getSVal(ParamR); - - // FIXME: For now assume that ParamSVal is symbolic. We need to generalize - // this later. - SymbolRef ParamSym = ParamSVal.getAsLocSymbol(); - if (!ParamSym) - return; - - // Iterate over the implicit-null dereferences. - ExplodedNode *const* I, *const* E; - llvm::tie(I, E) = GetImplicitNullDereferences(Eng); - for ( ; I != E; ++I) { - const GRState *state = (*I)->getState(); - SVal location = state->getSVal((*I)->getLocationAs()->getStmt()); - if (location.getAsSymbol() != ParamSym) - continue; - - // Emit an error. - std::string sbuf; - llvm::raw_string_ostream os(sbuf); - os << "Potential null dereference. According to coding standards "; - - if (isNSErrorWarning) - os << "in 'Creating and Returning NSError Objects' the parameter '"; - else - os << "documented in CoreFoundation/CFError.h the parameter '"; - - os << Param << "' may be null."; - - BugReport *report = new BugReport(*this, os.str(), *I); - // FIXME: Notable symbols are now part of the report. We should - // add support for notable symbols in BugReport. - // BR.addNotableSymbol(SV->getSymbol()); - BR.EmitReport(report); - } +void ento::registerNSErrorChecker(CheckerManager &mgr) { + mgr.registerChecker(); + NSOrCFErrorDerefChecker * + checker = mgr.registerChecker(); + checker->ShouldCheckNSError = true; +} + +void ento::registerCFErrorChecker(CheckerManager &mgr) { + mgr.registerChecker(); + NSOrCFErrorDerefChecker * + checker = mgr.registerChecker(); + checker->ShouldCheckCFError = true; } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp index 40040eada7b0..2d0af9c978dc 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp @@ -12,8 +12,10 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "llvm/ADT/StringSwitch.h" using namespace clang; @@ -21,20 +23,15 @@ using namespace ento; namespace { -class NoReturnFunctionChecker : public CheckerVisitor { +class NoReturnFunctionChecker : public Checker< check::PostStmt > { public: - static void *getTag() { static int tag = 0; return &tag; } - void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE); + void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; }; } -void ento::RegisterNoReturnFunctionChecker(ExprEngine &Eng) { - Eng.registerCheck(new NoReturnFunctionChecker()); -} - -void NoReturnFunctionChecker::PostVisitCallExpr(CheckerContext &C, - const CallExpr *CE) { +void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE, + CheckerContext &C) const { const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); @@ -78,3 +75,7 @@ void NoReturnFunctionChecker::PostVisitCallExpr(CheckerContext &C, if (BuildSinks) C.generateSink(CE); } + +void ento::registerNoReturnFunctionChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp index e1126b617b7c..7262bc36404d 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp @@ -11,8 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/Basic/Builtins.h" using namespace clang; @@ -20,22 +22,17 @@ using namespace ento; namespace { -class OSAtomicChecker : public Checker { +class OSAtomicChecker : public Checker { public: - static void *getTag() { static int tag = 0; return &tag; } - virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE); + bool evalCall(const CallExpr *CE, CheckerContext &C) const; private: - bool evalOSAtomicCompareAndSwap(CheckerContext &C, const CallExpr *CE); + static bool evalOSAtomicCompareAndSwap(CheckerContext &C, const CallExpr *CE); }; } -void ento::RegisterOSAtomicChecker(ExprEngine &Eng) { - Eng.registerCheck(new OSAtomicChecker()); -} - -bool OSAtomicChecker::evalCallExpr(CheckerContext &C,const CallExpr *CE) { +bool OSAtomicChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); SVal L = state->getSVal(Callee); @@ -130,7 +127,12 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C, ExplodedNode *N = *I; const GRState *stateLoad = N->getState(); - SVal theValueVal_untested = stateLoad->getSVal(theValueExpr); + + // Use direct bindings from the environment since we are forcing a load + // from a location that the Environment would typically not be used + // to bind a value. + SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, true); + SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr); // FIXME: Issue an error. @@ -201,3 +203,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C, return true; } + +void ento::registerOSAtomicChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp index 77467190db73..a1180492a937 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -25,7 +25,7 @@ using namespace ento; namespace { class ObjCAtSyncChecker - : public CheckerV2< check::PreStmt > { + : public Checker< check::PreStmt > { mutable llvm::OwningPtr BT_null; mutable llvm::OwningPtr BT_undef; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index 5f32bb8f53a2..4c05867631f3 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -16,7 +16,7 @@ // result of an initialization call (e.g. [super init], or [self initWith..]) // before using 'self' or any instance variable. // -// To perform the required checking, values are tagged wih flags that indicate +// To perform the required checking, values are tagged with flags that indicate // 1) if the object is the one pointed to by 'self', and 2) if the object // is the result of an initializer (e.g. [super init]). // @@ -47,12 +47,11 @@ // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/Analysis/DomainSpecific/CocoaConventions.h" #include "clang/AST/ParentMap.h" using namespace clang; @@ -64,7 +63,7 @@ static bool isInitMessage(const ObjCMessage &msg); static bool isSelfVar(SVal location, CheckerContext &C); namespace { -class ObjCSelfInitChecker : public CheckerV2< +class ObjCSelfInitChecker : public Checker< check::PostObjCMessage, check::PostStmt, check::PreStmt, @@ -347,15 +346,11 @@ static bool isSelfVar(SVal location, CheckerContext &C) { } static bool isInitializationMethod(const ObjCMethodDecl *MD) { - // Init methods with prefix like '-(id)_init' are private and the requirements - // are less strict so we don't check those. - return MD->isInstanceMethod() && - cocoa::deriveNamingConvention(MD->getSelector(), - /*ignorePrefix=*/false) == cocoa::InitRule; + return MD->getMethodFamily() == OMF_init; } static bool isInitMessage(const ObjCMessage &msg) { - return cocoa::deriveNamingConvention(msg.getSelector()) == cocoa::InitRule; + return msg.getMethodFamily() == OMF_init; } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp index 6e92498769f7..d78e5ceb533d 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp @@ -14,7 +14,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/AST/ExprObjC.h" @@ -169,7 +169,7 @@ static void checkObjCUnusedIvar(const ObjCImplementationDecl *D, //===----------------------------------------------------------------------===// namespace { -class ObjCUnusedIvarsChecker : public CheckerV2< +class ObjCUnusedIvarsChecker : public Checker< check::ASTDecl > { public: void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& mgr, diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp index 034a2aaef74e..7c21acc5bee7 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -23,7 +23,7 @@ using namespace ento; namespace { class PointerArithChecker - : public CheckerV2< check::PreStmt > { + : public Checker< check::PreStmt > { mutable llvm::OwningPtr BT; public: diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp index bf85b959c9ee..16ede2095eae 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp @@ -14,7 +14,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -24,7 +24,7 @@ using namespace ento; namespace { class PointerSubChecker - : public CheckerV2< check::PreStmt > { + : public Checker< check::PreStmt > { mutable llvm::OwningPtr BT; public: diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index 6c6901f41263..74199bb1f6db 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -25,7 +25,7 @@ using namespace ento; namespace { class PthreadLockChecker - : public CheckerV2< check::PostStmt > { + : public Checker< check::PostStmt > { public: void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp index 298515609cd0..1729b25a2979 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -24,7 +24,7 @@ using namespace ento; namespace { class ReturnPointerRangeChecker : - public CheckerV2< check::PreStmt > { + public Checker< check::PreStmt > { mutable llvm::OwningPtr BT; public: void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp index 555eaf41282b..7c215b7cf318 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp @@ -13,35 +13,26 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" using namespace clang; using namespace ento; namespace { class ReturnUndefChecker : - public CheckerVisitor { - BuiltinBug *BT; + public Checker< check::PreStmt > { + mutable llvm::OwningPtr BT; public: - ReturnUndefChecker() : BT(0) {} - static void *getTag(); - void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS); + void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; }; } -void ento::RegisterReturnUndefChecker(ExprEngine &Eng) { - Eng.registerCheck(new ReturnUndefChecker()); -} - -void *ReturnUndefChecker::getTag() { - static int x = 0; return &x; -} - -void ReturnUndefChecker::PreVisitReturnStmt(CheckerContext &C, - const ReturnStmt *RS) { +void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS, + CheckerContext &C) const { const Expr *RetE = RS->getRetValue(); if (!RetE) @@ -56,8 +47,8 @@ void ReturnUndefChecker::PreVisitReturnStmt(CheckerContext &C, return; if (!BT) - BT = new BuiltinBug("Garbage return value", - "Undefined or garbage value returned to caller"); + BT.reset(new BuiltinBug("Garbage return value", + "Undefined or garbage value returned to caller")); EnhancedBugReport *report = new EnhancedBugReport(*BT, BT->getDescription(), N); @@ -67,3 +58,7 @@ void ReturnUndefChecker::PreVisitReturnStmt(CheckerContext &C, C.EmitReport(report); } + +void ento::registerReturnUndefChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index 6a9a37d955bf..07de8706df24 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -24,7 +24,7 @@ using namespace clang; using namespace ento; namespace { -class StackAddrEscapeChecker : public CheckerV2< check::PreStmt, +class StackAddrEscapeChecker : public Checker< check::PreStmt, check::EndPath > { mutable llvm::OwningPtr BT_stackleak; mutable llvm::OwningPtr BT_returnstack; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index d0626b8cef83..711c672c1448 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -56,7 +56,7 @@ struct StreamState { } }; -class StreamChecker : public CheckerV2 > { diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp index 14ae9edc7b7e..1fb181591b42 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -12,17 +12,19 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" using namespace clang; using namespace ento; namespace { -class UndefBranchChecker : public Checker { - BuiltinBug *BT; +class UndefBranchChecker : public Checker { + mutable llvm::OwningPtr BT; struct FindUndefExpr { GRStateManager& VM; @@ -48,26 +50,15 @@ class UndefBranchChecker : public Checker { }; public: - UndefBranchChecker() : BT(0) {} - static void *getTag(); - void VisitBranchCondition(BranchNodeBuilder &Builder, ExprEngine &Eng, - const Stmt *Condition, void *tag); + void checkBranchCondition(const Stmt *Condition, BranchNodeBuilder &Builder, + ExprEngine &Eng) const; }; } -void ento::RegisterUndefBranchChecker(ExprEngine &Eng) { - Eng.registerCheck(new UndefBranchChecker()); -} - -void *UndefBranchChecker::getTag() { - static int x; - return &x; -} - -void UndefBranchChecker::VisitBranchCondition(BranchNodeBuilder &Builder, - ExprEngine &Eng, - const Stmt *Condition, void *tag){ +void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, + BranchNodeBuilder &Builder, + ExprEngine &Eng) const { const GRState *state = Builder.getState(); SVal X = state->getSVal(Condition); if (X.isUndef()) { @@ -75,7 +66,8 @@ void UndefBranchChecker::VisitBranchCondition(BranchNodeBuilder &Builder, if (N) { N->markAsSink(); if (!BT) - BT = new BuiltinBug("Branch condition evaluates to a garbage value"); + BT.reset( + new BuiltinBug("Branch condition evaluates to a garbage value")); // What's going on here: we want to highlight the subexpression of the // condition that is the most likely source of the "uninitialized @@ -118,3 +110,7 @@ void UndefBranchChecker::VisitBranchCondition(BranchNodeBuilder &Builder, Builder.markInfeasible(false); } } + +void ento::registerUndefBranchChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp index 6d3c966e6db1..69958d11f717 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp @@ -11,8 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "llvm/Support/raw_ostream.h" @@ -22,20 +24,14 @@ using namespace ento; namespace { class UndefCapturedBlockVarChecker - : public CheckerVisitor { - BugType *BT; + : public Checker< check::PostStmt > { + mutable llvm::OwningPtr BT; public: - UndefCapturedBlockVarChecker() : BT(0) {} - static void *getTag() { static int tag = 0; return &tag; } - void PostVisitBlockExpr(CheckerContext &C, const BlockExpr *BE); + void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const; }; } // end anonymous namespace -void ento::RegisterUndefCapturedBlockVarChecker(ExprEngine &Eng) { - Eng.registerCheck(new UndefCapturedBlockVarChecker()); -} - static const BlockDeclRefExpr *FindBlockDeclRefExpr(const Stmt *S, const VarDecl *VD){ if (const BlockDeclRefExpr *BR = dyn_cast(S)) @@ -54,8 +50,8 @@ static const BlockDeclRefExpr *FindBlockDeclRefExpr(const Stmt *S, } void -UndefCapturedBlockVarChecker::PostVisitBlockExpr(CheckerContext &C, - const BlockExpr *BE) { +UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE, + CheckerContext &C) const { if (!BE->getBlockDecl()->hasCaptures()) return; @@ -82,7 +78,7 @@ UndefCapturedBlockVarChecker::PostVisitBlockExpr(CheckerContext &C, if (state->getSVal(VR).isUndef()) if (ExplodedNode *N = C.generateSink()) { if (!BT) - BT = new BuiltinBug("uninitialized variable captured by block"); + BT.reset(new BuiltinBug("uninitialized variable captured by block")); // Generate a bug report. llvm::SmallString<128> buf; @@ -100,3 +96,7 @@ UndefCapturedBlockVarChecker::PostVisitBlockExpr(CheckerContext &C, } } } + +void ento::registerUndefCapturedBlockVarChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp index 64a3567bc342..7fa3804639d6 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -12,9 +12,11 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" using namespace clang; @@ -22,23 +24,17 @@ using namespace ento; namespace { class UndefResultChecker - : public CheckerVisitor { + : public Checker< check::PostStmt > { - BugType *BT; + mutable llvm::OwningPtr BT; public: - UndefResultChecker() : BT(0) {} - static void *getTag() { static int tag = 0; return &tag; } - void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); + void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const; }; } // end anonymous namespace -void ento::RegisterUndefResultChecker(ExprEngine &Eng) { - Eng.registerCheck(new UndefResultChecker()); -} - -void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C, - const BinaryOperator *B) { +void UndefResultChecker::checkPostStmt(const BinaryOperator *B, + CheckerContext &C) const { const GRState *state = C.getState(); if (state->getSVal(B).isUndef()) { // Generate an error node. @@ -47,7 +43,7 @@ void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C, return; if (!BT) - BT = new BuiltinBug("Result of operation is garbage or undefined"); + BT.reset(new BuiltinBug("Result of operation is garbage or undefined")); llvm::SmallString<256> sbuf; llvm::raw_svector_ostream OS(sbuf); @@ -85,3 +81,7 @@ void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C, C.EmitReport(report); } } + +void ento::registerUndefResultChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp index ff0344802d90..e51ab20d2f30 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp @@ -12,39 +12,32 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { class UndefinedArraySubscriptChecker - : public CheckerVisitor { - BugType *BT; + : public Checker< check::PreStmt > { + mutable llvm::OwningPtr BT; + public: - UndefinedArraySubscriptChecker() : BT(0) {} - static void *getTag() { - static int x = 0; - return &x; - } - void PreVisitArraySubscriptExpr(CheckerContext &C, - const ArraySubscriptExpr *A); + void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const; }; } // end anonymous namespace -void ento::RegisterUndefinedArraySubscriptChecker(ExprEngine &Eng) { - Eng.registerCheck(new UndefinedArraySubscriptChecker()); -} - void -UndefinedArraySubscriptChecker::PreVisitArraySubscriptExpr(CheckerContext &C, - const ArraySubscriptExpr *A) { +UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A, + CheckerContext &C) const { if (C.getState()->getSVal(A->getIdx()).isUndef()) { if (ExplodedNode *N = C.generateSink()) { if (!BT) - BT = new BuiltinBug("Array subscript is undefined"); + BT.reset(new BuiltinBug("Array subscript is undefined")); // Generate a report for this bug. EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N); @@ -55,3 +48,7 @@ UndefinedArraySubscriptChecker::PreVisitArraySubscriptExpr(CheckerContext &C, } } } + +void ento::registerUndefinedArraySubscriptChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp index e53cbba41cbc..28806e3db917 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -7,43 +7,32 @@ // //===----------------------------------------------------------------------===// // -// This defines UndefinedAssginmentChecker, a builtin check in ExprEngine that +// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that // checks for assigning undefined values. // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { class UndefinedAssignmentChecker - : public CheckerVisitor { - BugType *BT; + : public Checker { + mutable llvm::OwningPtr BT; + public: - UndefinedAssignmentChecker() : BT(0) {} - static void *getTag(); - virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE, - SVal location, SVal val); + void checkBind(SVal location, SVal val, CheckerContext &C) const; }; } -void ento::RegisterUndefinedAssignmentChecker(ExprEngine &Eng){ - Eng.registerCheck(new UndefinedAssignmentChecker()); -} - -void *UndefinedAssignmentChecker::getTag() { - static int x = 0; - return &x; -} - -void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C, - const Stmt *StoreE, - SVal location, - SVal val) { +void UndefinedAssignmentChecker::checkBind(SVal location, SVal val, + CheckerContext &C) const { if (!val.isUndef()) return; @@ -55,11 +44,12 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C, const char *str = "Assigned value is garbage or undefined"; if (!BT) - BT = new BuiltinBug(str); + BT.reset(new BuiltinBug(str)); // Generate a report for this bug. const Expr *ex = 0; + const Stmt *StoreE = C.getStmt(); while (StoreE) { if (const BinaryOperator *B = dyn_cast(StoreE)) { if (B->isCompoundAssignmentOp()) { @@ -92,3 +82,6 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C, C.EmitReport(R); } +void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index be4fbf60eb2e..48d7c367a96d 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -27,7 +27,7 @@ using namespace ento; using llvm::Optional; namespace { -class UnixAPIChecker : public CheckerV2< check::PreStmt > { +class UnixAPIChecker : public Checker< check::PreStmt > { enum SubChecks { OpenFn = 0, PthreadOnceFn = 1, diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp index 1bc487a49c1e..b540bce98170 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp @@ -14,7 +14,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" @@ -34,7 +34,7 @@ using namespace clang; using namespace ento; namespace { -class UnreachableCodeChecker : public CheckerV2 { +class UnreachableCodeChecker : public Checker { public: void checkEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng) const; @@ -112,8 +112,8 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G, // such as llvm_unreachable. if (!CB->empty()) { CFGElement First = CB->front(); - if (CFGStmt S = First.getAs()) { - if (const CallExpr *CE = dyn_cast(S.getStmt())) { + if (const CFGStmt *S = First.getAs()) { + if (const CallExpr *CE = dyn_cast(S->getStmt())) { if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable) continue; } @@ -164,8 +164,8 @@ void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB, // Find the Stmt* in a CFGBlock for reporting a warning const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) { for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) { - if (CFGStmt S = I->getAs()) - return S; + if (const CFGStmt *S = I->getAs()) + return S->getStmt(); } if (const Stmt *S = CB->getTerminator()) return S; @@ -204,7 +204,7 @@ bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB, // Run each of the checks on the conditions if (containsMacro(cond) || containsEnum(cond) || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond) - || containsStmt(cond)) + || containsStmt(cond)) return true; return false; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index ba46e177f822..875dce2e994a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -14,32 +14,27 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" -#include "clang/AST/CharUnits.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" +#include "clang/AST/CharUnits.h" using namespace clang; using namespace ento; namespace { -class VLASizeChecker : public CheckerVisitor { - BugType *BT_zero; - BugType *BT_undef; +class VLASizeChecker : public Checker< check::PreStmt > { + mutable llvm::OwningPtr BT_zero; + mutable llvm::OwningPtr BT_undef; public: - VLASizeChecker() : BT_zero(0), BT_undef(0) {} - static void *getTag() { static int tag = 0; return &tag; } - void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS); + void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const; }; } // end anonymous namespace -void ento::RegisterVLASizeChecker(ExprEngine &Eng) { - Eng.registerCheck(new VLASizeChecker()); -} - -void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { +void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { if (!DS->isSingleDecl()) return; @@ -64,8 +59,8 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { return; if (!BT_undef) - BT_undef = new BuiltinBug("Declared variable-length array (VLA) uses a " - "garbage value as its size"); + BT_undef.reset(new BuiltinBug("Declared variable-length array (VLA) " + "uses a garbage value as its size")); EnhancedBugReport *report = new EnhancedBugReport(*BT_undef, BT_undef->getName(), N); @@ -89,8 +84,8 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { if (stateZero && !stateNotZero) { ExplodedNode* N = C.generateSink(stateZero); if (!BT_zero) - BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero " - "size"); + BT_zero.reset(new BuiltinBug("Declared variable-length array (VLA) has " + "zero size")); EnhancedBugReport *report = new EnhancedBugReport(*BT_zero, BT_zero->getName(), N); @@ -136,3 +131,7 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { // Remember our assumptions! C.addTransition(state); } + +void ento::registerVLASizeChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AggExprVisitor.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AggExprVisitor.cpp index e80cf9b4a331..901190d901dd 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AggExprVisitor.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AggExprVisitor.cpp @@ -60,7 +60,7 @@ void AggExprVisitor::VisitCXXConstructExpr(CXXConstructExpr *E) { } void AggExprVisitor::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { - Eng.VisitCXXMemberCallExpr(E, Pred, DstSet); + Eng.Visit(E, Pred, DstSet); } void ExprEngine::VisitAggExpr(const Expr *E, const MemRegion *Dest, diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicStore.cpp index 98365e7f4e62..4faa84ca2660 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicStore.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicStore.cpp @@ -429,12 +429,15 @@ StoreRef BasicStoreManager::getInitialStore(const LocationContext *InitLoc) { } if (const CXXMethodDecl *MD = dyn_cast(InitLoc->getDecl())) { - // For C++ methods add symbolic region for 'this' in initial stack frame. - QualType ThisT = MD->getThisType(StateMgr.getContext()); - MemRegionManager &RegMgr = svalBuilder.getRegionManager(); - const CXXThisRegion *ThisR = RegMgr.getCXXThisRegion(ThisT, InitLoc); - SVal ThisV = svalBuilder.getRegionValueSymbolVal(ThisR); - St = Bind(St.getStore(), svalBuilder.makeLoc(ThisR), ThisV); + // For C++ non-static member variables, add a symbolic region for 'this' in + // the initial stack frame. + if (MD->isInstance()) { + QualType ThisT = MD->getThisType(StateMgr.getContext()); + MemRegionManager &RegMgr = svalBuilder.getRegionManager(); + const CXXThisRegion *ThisR = RegMgr.getCXXThisRegion(ThisT, InitLoc); + SVal ThisV = svalBuilder.getRegionValueSymbolVal(ThisR); + St = Bind(St.getStore(), svalBuilder.makeLoc(ThisR), ThisV); + } } return St; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp index 6315d83d894d..ae8a04ce439f 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" using namespace clang; using namespace ento; @@ -25,8 +26,9 @@ void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T, } void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID, - const void *store,const TypedRegion *region) { - ID.AddPointer(store); + const StoreRef &store, + const TypedRegion *region) { + ID.AddPointer(store.getStore()); ID.AddPointer(region); } @@ -124,7 +126,7 @@ BasicValueFactory::getCompoundValData(QualType T, } const LazyCompoundValData* -BasicValueFactory::getLazyCompoundValData(const void *store, +BasicValueFactory::getLazyCompoundValData(const StoreRef &store, const TypedRegion *region) { llvm::FoldingSetNodeID ID; LazyCompoundValData::Profile(ID, store, region); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 672982a3c025..8b5d383ed07f 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -432,7 +432,7 @@ class NotableSymbolHandler else if (const DeclStmt* DS = dyn_cast(S)) { // FIXME: Eventually CFGs won't have DeclStmts. Right now we // assume that each DeclStmt has a single Decl. This invariant - // holds by contruction in the CFG. + // holds by construction in the CFG. VD = dyn_cast(*DS->decl_begin()); } @@ -859,7 +859,8 @@ class EdgeBuilder { default: break; case Stmt::ParenExprClass: - S = cast(S)->IgnoreParens(); + case Stmt::GenericSelectionExprClass: + S = cast(S)->IgnoreParens(); firstCharOnly = true; continue; case Stmt::BinaryConditionalOperatorClass: @@ -1170,13 +1171,14 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, } if (const BlockEntrance *BE = dyn_cast(&P)) { - if (CFGStmt S = BE->getFirstElement().getAs()) { - if (IsControlFlowExpr(S)) { + if (const CFGStmt *S = BE->getFirstElement().getAs()) { + const Stmt *stmt = S->getStmt(); + if (IsControlFlowExpr(stmt)) { // Add the proper context for '&&', '||', and '?'. - EB.addContext(S); + EB.addContext(stmt); } else - EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); + EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); } break; diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp index b3721d7659fe..d9b1ce825cea 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" @@ -20,7 +24,6 @@ #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h" @@ -1198,7 +1201,7 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, // Effects on the parameters. unsigned parm_idx = 0; for (FunctionDecl::param_const_iterator pi = FD->param_begin(), - pe = FD->param_end(); pi != pe; ++pi) { + pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) { const ParmVarDecl *pd = *pi; if (pd->getAttr()) { if (!GCEnabled) @@ -2428,7 +2431,7 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug& D, const CFRefCount &tf, SymbolRef sym, ExprEngine& Eng) : CFRefReport(D, tf, n, sym) { - // Most bug reports are cached at the location where they occured. + // Most bug reports are cached at the location where they occurred. // With leaks, we want to unique them by the location where they were // allocated, and only report a single path. To do this, we need to find // the allocation site of a piece of tracked memory, which we do via a @@ -2526,6 +2529,14 @@ void CFRefCount::evalSummary(ExplodedNodeSet& Dst, RegionsToInvalidate.push_back(region); } + // Invalidate all instance variables for the callee of a C++ method call. + // FIXME: We should be able to do better with inter-procedural analysis. + // FIXME: we can probably do better for const versus non-const methods. + if (callOrMsg.isCXXCall()) { + if (const MemRegion *callee = callOrMsg.getCXXCallee().getAsRegion()) + RegionsToInvalidate.push_back(callee); + } + for (unsigned idx = 0, e = callOrMsg.getNumArgs(); idx != e; ++idx) { SVal V = callOrMsg.getArgSValAsScalarOrLoc(idx); SymbolRef Sym = V.getAsLocSymbol(); @@ -2678,11 +2689,14 @@ void CFRefCount::evalSummary(ExplodedNodeSet& Dst, // FIXME: We eventually should handle structs and other compound types // that are returned by value. - QualType T = callOrMsg.getResultType(Eng.getContext()); - if (Loc::isLocType(T) || (T->isIntegerType() && T->isScalarType())) { + // Use the result type from callOrMsg as it automatically adjusts + // for methods/functions that return references. + QualType resultTy = callOrMsg.getResultType(Eng.getContext()); + if (Loc::isLocType(resultTy) || + (resultTy->isIntegerType() && resultTy->isScalarType())) { unsigned Count = Builder.getCurrentBlockCount(); SValBuilder &svalBuilder = Eng.getSValBuilder(); - SVal X = svalBuilder.getConjuredSymbolVal(NULL, Ex, T, Count); + SVal X = svalBuilder.getConjuredSymbolVal(NULL, Ex, resultTy, Count); state = state->BindExpr(Ex, X, false); } @@ -2709,9 +2723,12 @@ void CFRefCount::evalSummary(ExplodedNodeSet& Dst, unsigned Count = Builder.getCurrentBlockCount(); SValBuilder &svalBuilder = Eng.getSValBuilder(); SymbolRef Sym = svalBuilder.getConjuredSymbol(Ex, Count); - QualType RetT = GetReturnType(Ex, svalBuilder.getContext()); + + // Use the result type from callOrMsg as it automatically adjusts + // for methods/functions that return references. + QualType resultTy = callOrMsg.getResultType(Eng.getContext()); state = state->set(Sym, RefVal::makeOwned(RE.getObjKind(), - RetT)); + resultTy)); state = state->BindExpr(Ex, svalBuilder.makeLoc(Sym), false); // FIXME: Add a flag to the checker where allocations are assumed to @@ -2764,11 +2781,17 @@ void CFRefCount::evalCall(ExplodedNodeSet& Dst, if (dyn_cast_or_null(L.getAsRegion())) { Summ = Summaries.getPersistentStopSummary(); } - else { - const FunctionDecl* FD = L.getAsFunctionDecl(); - Summ = !FD ? Summaries.getDefaultSummary() : - Summaries.getSummary(FD); + else if (const FunctionDecl* FD = L.getAsFunctionDecl()) { + Summ = Summaries.getSummary(FD); } + else if (const CXXMemberCallExpr *me = dyn_cast(CE)) { + if (const CXXMethodDecl *MD = me->getMethodDecl()) + Summ = Summaries.getSummary(MD); + else + Summ = Summaries.getDefaultSummary(); + } + else + Summ = Summaries.getDefaultSummary(); assert(Summ); evalSummary(Dst, Eng, Builder, CE, @@ -3395,19 +3418,15 @@ void CFRefCount::ProcessNonLeakError(ExplodedNodeSet& Dst, namespace { class RetainReleaseChecker - : public CheckerVisitor { - CFRefCount *TF; + : public Checker< check::PostStmt > { public: - RetainReleaseChecker(CFRefCount *tf) : TF(tf) {} - static void* getTag() { static int x = 0; return &x; } - - void PostVisitBlockExpr(CheckerContext &C, const BlockExpr *BE); + void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const; }; } // end anonymous namespace -void RetainReleaseChecker::PostVisitBlockExpr(CheckerContext &C, - const BlockExpr *BE) { +void RetainReleaseChecker::checkPostStmt(const BlockExpr *BE, + CheckerContext &C) const { // Scan the BlockDecRefExprs for any object the retain/release checker // may be tracking. @@ -3510,7 +3529,9 @@ void CFRefCount::RegisterChecks(ExprEngine& Eng) { // Register the RetainReleaseChecker with the ExprEngine object. // Functionality in CFRefCount will be migrated to RetainReleaseChecker // over time. - Eng.registerCheck(new RetainReleaseChecker(this)); + // FIXME: HACK! Remove TransferFuncs and turn all of CFRefCount into fully + // using the checker mechanism. + Eng.getCheckerManager().registerChecker(); } TransferFuncs* ento::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled, diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CXXExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CXXExprEngine.cpp index 56dfe8cb04a9..54cbca08b981 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CXXExprEngine.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CXXExprEngine.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/AST/DeclCXX.h" @@ -61,6 +62,34 @@ void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE, } } +void ExprEngine::evalCallee(const CallExpr *callExpr, + const ExplodedNodeSet &src, + ExplodedNodeSet &dest) { + + const Expr *callee = 0; + + switch (callExpr->getStmtClass()) { + case Stmt::CXXMemberCallExprClass: { + // Evaluate the implicit object argument that is the recipient of the + // call. + callee = cast(callExpr)->getImplicitObjectArgument(); + + // FIXME: handle member pointers. + if (!callee) + return; + + break; + } + default: { + callee = callExpr->getCallee()->IgnoreParens(); + break; + } + } + + for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i) + Visit(callee, *i, dest); +} + const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D, const StackFrameContext *SFC) { const Type *T = D->getTypeForDecl(); @@ -95,50 +124,121 @@ void ExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred, } void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, - const MemRegion *Dest, - ExplodedNode *Pred, - ExplodedNodeSet &Dst) { - if (!Dest) - Dest = svalBuilder.getRegionManager().getCXXTempObjectRegion(E, - Pred->getLocationContext()); - - if (E->isElidable()) { - VisitAggExpr(E->getArg(0), Dest, Pred, Dst); - return; - } + const MemRegion *Dest, + ExplodedNode *Pred, + ExplodedNodeSet &destNodes) { const CXXConstructorDecl *CD = E->getConstructor(); assert(CD); - + +#if 0 if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) // FIXME: invalidate the object. return; - +#endif // Evaluate other arguments. ExplodedNodeSet argsEvaluated; const FunctionProtoType *FnType = CD->getType()->getAs(); evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated); - // The callee stack frame context used to create the 'this' parameter region. - const StackFrameContext *SFC = AMgr.getStackFrame(CD, - Pred->getLocationContext(), - E, Builder->getBlock(), - Builder->getIndex()); - const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(), - SFC); - - CallEnter Loc(E, SFC, Pred->getLocationContext()); - for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(), - NE = argsEvaluated.end(); NI != NE; ++NI) { - const GRState *state = GetState(*NI); - // Setup 'this' region, so that the ctor is evaluated on the object pointed - // by 'Dest'. - state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); - ExplodedNode *N = Builder->generateNode(Loc, state, Pred); - if (N) - Dst.Add(N); +#if 0 + // Is the constructor elidable? + if (E->isElidable()) { + VisitAggExpr(E->getArg(0), destNodes, Pred, Dst); + // FIXME: this is here to force propagation if VisitAggExpr doesn't + if (destNodes.empty()) + destNodes.Add(Pred); + return; } +#endif + + // Perform the previsit of the constructor. + ExplodedNodeSet destPreVisit; + getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E, + *this); + + // Evaluate the constructor. Currently we don't now allow checker-specific + // implementations of specific constructors (as we do with ordinary + // function calls. We can re-evaluate this in the future. + +#if 0 + // Inlining currently isn't fully implemented. + + if (AMgr.shouldInlineCall()) { + if (!Dest) + Dest = + svalBuilder.getRegionManager().getCXXTempObjectRegion(E, + Pred->getLocationContext()); + + // The callee stack frame context used to create the 'this' + // parameter region. + const StackFrameContext *SFC = + AMgr.getStackFrame(CD, Pred->getLocationContext(), + E, Builder->getBlock(), Builder->getIndex()); + + // Create the 'this' region. + const CXXThisRegion *ThisR = + getCXXThisRegion(E->getConstructor()->getParent(), SFC); + + CallEnter Loc(E, SFC, Pred->getLocationContext()); + + + for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(), + NE = argsEvaluated.end(); NI != NE; ++NI) { + const GRState *state = GetState(*NI); + // Setup 'this' region, so that the ctor is evaluated on the object pointed + // by 'Dest'. + state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); + if (ExplodedNode *N = Builder->generateNode(Loc, state, *NI)) + destNodes.Add(N); + } + } +#endif + + // Default semantics: invalidate all regions passed as arguments. + llvm::SmallVector regionsToInvalidate; + + // FIXME: We can have collisions on the conjured symbol if the + // expression *I also creates conjured symbols. We probably want + // to identify conjured symbols by an expression pair: the enclosing + // expression (the context) and the expression itself. This should + // disambiguate conjured symbols. + unsigned blockCount = Builder->getCurrentBlockCount(); + + // NOTE: Even if RegionsToInvalidate is empty, we must still invalidate + // global variables. + ExplodedNodeSet destCall; + + for (ExplodedNodeSet::iterator + i = destPreVisit.begin(), e = destPreVisit.end(); + i != e; ++i) + { + ExplodedNode *Pred = *i; + const GRState *state = GetState(Pred); + + // Accumulate list of regions that are invalidated. + for (CXXConstructExpr::const_arg_iterator + ai = E->arg_begin(), ae = E->arg_end(); + ai != ae; ++ai) + { + SVal val = state->getSVal(*ai); + if (const MemRegion *region = val.getAsRegion()) + regionsToInvalidate.push_back(region); + } + + // Invalidate the regions. + state = state->invalidateRegions(regionsToInvalidate.data(), + regionsToInvalidate.data() + + regionsToInvalidate.size(), + E, blockCount, 0, + /* invalidateGlobals = */ true); + + Builder->MakeNode(destCall, E, Pred, state); + } + + // Do the post visit. + getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this); } void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, @@ -165,106 +265,26 @@ void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, Dst.Add(N); } -void ExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, - ExplodedNode *Pred, - ExplodedNodeSet &Dst) { - // Get the method type. - const FunctionProtoType *FnType = - MCE->getCallee()->getType()->getAs(); - assert(FnType && "Method type not available"); - - // Evaluate explicit arguments with a worklist. - ExplodedNodeSet argsEvaluated; - evalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, argsEvaluated); - - // Evaluate the implicit object argument. - ExplodedNodeSet AllargsEvaluated; - const MemberExpr *ME = dyn_cast(MCE->getCallee()->IgnoreParens()); - if (!ME) - return; - Expr *ObjArgExpr = ME->getBase(); - for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), - E = argsEvaluated.end(); I != E; ++I) { - Visit(ObjArgExpr, *I, AllargsEvaluated); - } - - // Now evaluate the call itself. - const CXXMethodDecl *MD = cast(ME->getMemberDecl()); - assert(MD && "not a CXXMethodDecl?"); - evalMethodCall(MCE, MD, ObjArgExpr, Pred, AllargsEvaluated, Dst); -} - -void ExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C, - ExplodedNode *Pred, - ExplodedNodeSet &Dst) { - const CXXMethodDecl *MD = dyn_cast_or_null(C->getCalleeDecl()); - if (!MD) { - // If the operator doesn't represent a method call treat as regural call. - VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst); - return; - } - - // Determine the type of function we're calling (if available). - const FunctionProtoType *Proto = NULL; - QualType FnType = C->getCallee()->IgnoreParens()->getType(); - if (const PointerType *FnTypePtr = FnType->getAs()) - Proto = FnTypePtr->getPointeeType()->getAs(); - - // Evaluate arguments treating the first one (object method is called on) - // as alvalue. - ExplodedNodeSet argsEvaluated; - evalArguments(C->arg_begin(), C->arg_end(), Proto, Pred, argsEvaluated, true); - - // Now evaluate the call itself. - evalMethodCall(C, MD, C->getArg(0), Pred, argsEvaluated, Dst); -} - -void ExprEngine::evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD, - const Expr *ThisExpr, ExplodedNode *Pred, - ExplodedNodeSet &Src, ExplodedNodeSet &Dst) { - // Allow checkers to pre-visit the member call. - ExplodedNodeSet PreVisitChecks; - CheckerVisit(MCE, PreVisitChecks, Src, PreVisitStmtCallback); - - if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) { - // FIXME: conservative method call evaluation. - CheckerVisit(MCE, Dst, PreVisitChecks, PostVisitStmtCallback); - return; - } - - const StackFrameContext *SFC = AMgr.getStackFrame(MD, - Pred->getLocationContext(), - MCE, - Builder->getBlock(), - Builder->getIndex()); - const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC); - CallEnter Loc(MCE, SFC, Pred->getLocationContext()); - for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(), - E = PreVisitChecks.end(); I != E; ++I) { - // Set up 'this' region. - const GRState *state = GetState(*I); - state = state->bindLoc(loc::MemRegionVal(ThisR), state->getSVal(ThisExpr)); - Dst.Add(Builder->generateNode(Loc, state, *I)); - } -} - void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { + + unsigned blockCount = Builder->getCurrentBlockCount(); + DefinedOrUnknownSVal symVal = + svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount); + const MemRegion *NewReg = cast(symVal).getRegion(); + QualType ObjTy = CNE->getType()->getAs()->getPointeeType(); + const ElementRegion *EleReg = + getStoreManager().GetElementZeroRegion(NewReg, ObjTy); + if (CNE->isArray()) { - // FIXME: allocating an array has not been handled. + // FIXME: allocating an array requires simulating the constructors. + // For now, just return a symbolicated region. + const GRState *state = GetState(Pred); + state = state->BindExpr(CNE, loc::MemRegionVal(EleReg)); + MakeNode(Dst, CNE, Pred, state); return; } - unsigned Count = Builder->getCurrentBlockCount(); - DefinedOrUnknownSVal symVal = - svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), Count); - const MemRegion *NewReg = cast(symVal).getRegion(); - - QualType ObjTy = CNE->getType()->getAs()->getPointeeType(); - - const ElementRegion *EleReg = - getStoreManager().GetElementZeroRegion(NewReg, ObjTy); - // Evaluate constructor arguments. const FunctionProtoType *FnType = NULL; const CXXConstructorDecl *CD = CNE->getConstructor(); @@ -277,11 +297,39 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // Initialize the object region and bind the 'new' expression. for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), E = argsEvaluated.end(); I != E; ++I) { + const GRState *state = GetState(*I); + + // Accumulate list of regions that are invalidated. + // FIXME: Eventually we should unify the logic for constructor + // processing in one place. + llvm::SmallVector regionsToInvalidate; + for (CXXNewExpr::const_arg_iterator + ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); + ai != ae; ++ai) + { + SVal val = state->getSVal(*ai); + if (const MemRegion *region = val.getAsRegion()) + regionsToInvalidate.push_back(region); + } if (ObjTy->isRecordType()) { - state = state->invalidateRegion(EleReg, CNE, Count); + regionsToInvalidate.push_back(EleReg); + // Invalidate the regions. + state = state->invalidateRegions(regionsToInvalidate.data(), + regionsToInvalidate.data() + + regionsToInvalidate.size(), + CNE, blockCount, 0, + /* invalidateGlobals = */ true); + } else { + // Invalidate the regions. + state = state->invalidateRegions(regionsToInvalidate.data(), + regionsToInvalidate.data() + + regionsToInvalidate.size(), + CNE, blockCount, 0, + /* invalidateGlobals = */ true); + if (CNE->hasInitializer()) { SVal V = state->getSVal(*CNE->constructor_arg_begin()); state = state->bindLoc(loc::MemRegionVal(EleReg), V); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp similarity index 78% rename from contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp rename to contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index a014eec76bd4..f6fb8f256c01 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -1,4 +1,4 @@ -//== Checker.h - Abstract interface for checkers -----------------*- C++ -*--=// +//== CheckerContext.cpp - Context info for path-sensitive checkers-----------=// // // The LLVM Compiler Infrastructure // @@ -7,17 +7,15 @@ // //===----------------------------------------------------------------------===// // -// This file defines Checker and CheckerVisitor, classes used for creating -// domain-specific checks. +// This file defines CheckerContext that provides contextual info for +// path-sensitive checkers. // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" using namespace clang; using namespace ento; -Checker::~Checker() {} - CheckerContext::~CheckerContext() { // Do we need to autotransition? 'Dst' can get populated in a variety of // ways, including 'addTransition()' adding the predecessor node to Dst diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp index 75d331a131a8..4a2549091cb4 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -20,6 +20,32 @@ using namespace clang; using namespace ento; +bool CheckerManager::hasPathSensitiveCheckers() const { + return !StmtCheckers.empty() || + !PreObjCMessageCheckers.empty() || + !PostObjCMessageCheckers.empty() || + !LocationCheckers.empty() || + !BindCheckers.empty() || + !EndAnalysisCheckers.empty() || + !EndPathCheckers.empty() || + !BranchConditionCheckers.empty() || + !LiveSymbolsCheckers.empty() || + !DeadSymbolsCheckers.empty() || + !RegionChangesCheckers.empty() || + !EvalAssumeCheckers.empty() || + !EvalCallCheckers.empty(); +} + +void CheckerManager::finishedCheckerRegistration() { +#ifndef NDEBUG + // Make sure that for every event that has listeners, there is at least + // one dispatcher registered for it. + for (llvm::DenseMap::iterator + I = Events.begin(), E = Events.end(); I != E; ++I) + assert(I->second.HasDispatcher && "No dispatcher registered for an event"); +#endif +} + //===----------------------------------------------------------------------===// // Functions for running checkers for AST traversing.. //===----------------------------------------------------------------------===// @@ -205,6 +231,40 @@ void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, expandGraphWithCheckers(C, Dst, Src); } +namespace { + struct CheckBindContext { + typedef std::vector CheckersTy; + const CheckersTy &Checkers; + SVal Loc; + SVal Val; + const Stmt *S; + ExprEngine &Eng; + + CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } + CheckersTy::const_iterator checkers_end() { return Checkers.end(); } + + CheckBindContext(const CheckersTy &checkers, + SVal loc, SVal val, const Stmt *s, ExprEngine &eng) + : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { } + + void runChecker(CheckerManager::CheckBindFunc checkFn, + ExplodedNodeSet &Dst, ExplodedNode *Pred) { + CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, + ProgramPoint::PreStmtKind, 0, S); + checkFn(Loc, Val, C); + } + }; +} + +/// \brief Run checkers for binding of a value to a location. +void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + SVal location, SVal val, + const Stmt *S, ExprEngine &Eng) { + CheckBindContext C(BindCheckers, location, val, S, Eng); + expandGraphWithCheckers(C, Dst, Src); +} + void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng) { @@ -222,6 +282,16 @@ void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B, } } +/// \brief Run checkers for branch condition. +void CheckerManager::runCheckersForBranchCondition(const Stmt *condition, + BranchNodeBuilder &B, + ExprEngine &Eng) { + for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) { + CheckBranchConditionFunc fn = BranchConditionCheckers[i]; + fn(condition, B, Eng); + } +} + /// \brief Run checkers for live symbols. void CheckerManager::runCheckersForLiveSymbols(const GRState *state, SymbolReaper &SymReaper) { @@ -287,6 +357,20 @@ CheckerManager::runCheckersForRegionChanges(const GRState *state, return state; } +/// \brief Run checkers for handling assumptions on symbolic values. +const GRState * +CheckerManager::runCheckersForEvalAssume(const GRState *state, + SVal Cond, bool Assumption) { + for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { + // If any checker declares the state infeasible (or if it starts that way), + // bail out. + if (!state) + return NULL; + state = EvalAssumeCheckers[i](state, Cond, Assumption); + } + return state; +} + /// \brief Run checkers for evaluating a call. /// Only one checker will evaluate the call. void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, @@ -371,6 +455,10 @@ void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { LocationCheckers.push_back(checkfn); } +void CheckerManager::_registerForBind(CheckBindFunc checkfn) { + BindCheckers.push_back(checkfn); +} + void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { EndAnalysisCheckers.push_back(checkfn); } @@ -379,6 +467,11 @@ void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { EndPathCheckers.push_back(checkfn); } +void CheckerManager::_registerForBranchCondition( + CheckBranchConditionFunc checkfn) { + BranchConditionCheckers.push_back(checkfn); +} + void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { LiveSymbolsCheckers.push_back(checkfn); } @@ -393,6 +486,10 @@ void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, RegionChangesCheckers.push_back(info); } +void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { + EvalAssumeCheckers.push_back(checkfn); +} + void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { EvalCallCheckers.push_back(checkfn); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index 08a2068c0106..34cd6e8884a0 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -19,8 +19,6 @@ #include "clang/AST/Expr.h" #include "llvm/Support/Casting.h" #include "llvm/ADT/DenseMap.h" -#include -#include using llvm::cast; using llvm::isa; @@ -310,7 +308,7 @@ void CoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) { for (llvm::SmallVectorImpl::const_iterator I = nodeBuilder.sinks().begin(), E = nodeBuilder.sinks().end(); I != E; ++I) { - blocksAborted.push_back(std::make_pair(L, *I)); + blocksExhausted.push_back(std::make_pair(L, *I)); } } @@ -602,6 +600,25 @@ StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc, return NULL; } +// This function generate a new ExplodedNode but not a new branch(block edge). +ExplodedNode* BranchNodeBuilder::generateNode(const Stmt* Condition, + const GRState* State) { + bool IsNew; + + ExplodedNode* Succ + = Eng.G->getNode(PostCondition(Condition, Pred->getLocationContext()), State, + &IsNew); + + Succ->addPredecessor(Pred, *Eng.G); + + Pred = Succ; + + if (IsNew) + return Succ; + + return NULL; +} + ExplodedNode* BranchNodeBuilder::generateNode(const GRState* State, bool branch) { diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp index 1bffa3022e43..a00f9dc10b68 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp @@ -27,7 +27,17 @@ SVal Environment::lookupExpr(const Stmt* E) const { return UnknownVal(); } -SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const { +SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder, + bool useOnlyDirectBindings) const { + + if (useOnlyDirectBindings) { + // This branch is rarely taken, but can be exercised by + // checkers that explicitly bind values to arbitrary + // expressions. It is crucial that we do not ignore any + // expression here, and do a direct lookup. + return lookupExpr(E); + } + for (;;) { switch (E->getStmtClass()) { case Stmt::AddrLabelExprClass: @@ -41,6 +51,10 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const { // ParenExprs are no-ops. E = cast(E)->getSubExpr(); continue; + case Stmt::GenericSelectionExprClass: + // GenericSelectionExprs are no-ops. + E = cast(E)->getResultExpr(); + continue; case Stmt::CharacterLiteralClass: { const CharacterLiteral* C = cast(E); return svalBuilder.makeIntVal(C->getValue(), C->getType()); @@ -60,6 +74,9 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const { else return svalBuilder.makeIntVal(cast(E)); } + // For special C0xx nullptr case, make a null pointer SVal. + case Stmt::CXXNullPtrLiteralExprClass: + return svalBuilder.makeNull(); case Stmt::ImplicitCastExprClass: case Stmt::CXXFunctionalCastExprClass: case Stmt::CStyleCastExprClass: { diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp index 2a8364d4117f..fa16fead9f1d 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp @@ -374,7 +374,7 @@ ExplodedGraph::TrimInternal(const ExplodedNode* const* BeginSources, WL2.push_back(*I); } - // Finally, explictly mark all nodes without any successors as sinks. + // Finally, explicitly mark all nodes without any successors as sinks. if (N->isSink()) NewN->markAsSink(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp similarity index 79% rename from contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp rename to contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index c1b1e656989b..657420d06f06 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -13,15 +13,11 @@ // //===----------------------------------------------------------------------===// -// FIXME: Restructure checker registration. -#include "InternalChecks.h" - #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" #include "clang/AST/CharUnits.h" #include "clang/AST/ParentMap.h" #include "clang/AST/StmtObjC.h" @@ -62,279 +58,10 @@ static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { return Ctx.Selectors.getSelector(0, &II); } -//===----------------------------------------------------------------------===// -// Checker worklist routines. -//===----------------------------------------------------------------------===// - -void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, - ExplodedNodeSet &Src, CallbackKind Kind) { - - // Determine if we already have a cached 'CheckersOrdered' vector - // specifically tailored for the provided . This - // can reduce the number of checkers actually called. - CheckersOrdered *CO = &Checkers; - llvm::OwningPtr NewCO; - - // The cache key is made up of the and the callback kind (pre- or post-visit) - // and the statement kind. - CallbackTag K = GetCallbackTag(Kind, S->getStmtClass()); - - CheckersOrdered *& CO_Ref = COCache[K]; - - if (!CO_Ref) { - // If we have no previously cached CheckersOrdered vector for this - // statement kind, then create one. - NewCO.reset(new CheckersOrdered); - } - else { - // Use the already cached set. - CO = CO_Ref; - } - - if (CO->empty()) { - // If there are no checkers, just delegate to the checker manager. - getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback, - Dst, Src, S, *this); - return; - } - - ExplodedNodeSet CheckersV1Dst; - ExplodedNodeSet Tmp; - ExplodedNodeSet *PrevSet = &Src; - unsigned checkersEvaluated = 0; - - for (CheckersOrdered::iterator I=CO->begin(), E=CO->end(); I!=E; ++I) { - // If all nodes are sunk, bail out early. - if (PrevSet->empty()) - break; - ExplodedNodeSet *CurrSet = 0; - if (I+1 == E) - CurrSet = &CheckersV1Dst; - else { - CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp; - CurrSet->clear(); - } - void *tag = I->first; - Checker *checker = I->second; - bool respondsToCallback = true; - - for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); - NI != NE; ++NI) { - - checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag, - Kind == PreVisitStmtCallback, respondsToCallback); - - } - - PrevSet = CurrSet; - - if (NewCO.get()) { - ++checkersEvaluated; - if (respondsToCallback) - NewCO->push_back(*I); - } - } - - // If we built NewCO, check if we called all the checkers. This is important - // so that we know that we accurately determined the entire set of checkers - // that responds to this callback. Note that 'checkersEvaluated' might - // not be the same as Checkers.size() if one of the Checkers generates - // a sink node. - if (NewCO.get() && checkersEvaluated == Checkers.size()) - CO_Ref = NewCO.take(); - - // Don't autotransition. The CheckerContext objects should do this - // automatically. - - getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback, - Dst, CheckersV1Dst, S, *this); -} - -void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg, - ExplodedNodeSet &Dst, - ExplodedNodeSet &Src, - bool isPrevisit) { - - if (Checkers.empty()) { - getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, Src, msg, - *this); - return; - } - - ExplodedNodeSet CheckersV1Dst; - ExplodedNodeSet Tmp; - ExplodedNodeSet *PrevSet = &Src; - - for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I) - { - ExplodedNodeSet *CurrSet = 0; - if (I+1 == E) - CurrSet = &CheckersV1Dst; - else { - CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp; - CurrSet->clear(); - } - - void *tag = I->first; - Checker *checker = I->second; - - for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); - NI != NE; ++NI) - checker->GR_visitObjCMessage(*CurrSet, *Builder, *this, msg, - *NI, tag, isPrevisit); - - // Update which NodeSet is the current one. - PrevSet = CurrSet; - } - - getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, CheckersV1Dst, - msg, *this); -} - -void ExprEngine::CheckerEvalNilReceiver(const ObjCMessage &msg, - ExplodedNodeSet &Dst, - const GRState *state, - ExplodedNode *Pred) { - bool evaluated = false; - ExplodedNodeSet DstTmp; - - for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) { - void *tag = I->first; - Checker *checker = I->second; - - if (checker->GR_evalNilReceiver(DstTmp, *Builder, *this, msg, Pred, state, - tag)) { - evaluated = true; - break; - } else - // The checker didn't evaluate the expr. Restore the Dst. - DstTmp.clear(); - } - - if (evaluated) - Dst.insert(DstTmp); - else - Dst.insert(Pred); -} - -// CheckerEvalCall returns true if one of the checkers processed the node. -// This may return void when all call evaluation logic goes to some checker -// in the future. -bool ExprEngine::CheckerEvalCall(const CallExpr *CE, - ExplodedNodeSet &Dst, - ExplodedNode *Pred) { - bool evaluated = false; - ExplodedNodeSet DstTmp; - - for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) { - void *tag = I->first; - Checker *checker = I->second; - - if (checker->GR_evalCallExpr(DstTmp, *Builder, *this, CE, Pred, tag)) { - evaluated = true; - break; - } else - // The checker didn't evaluate the expr. Restore the DstTmp set. - DstTmp.clear(); - } - - if (evaluated) { - Dst.insert(DstTmp); - return evaluated; - } - - class DefaultEval : public GraphExpander { - bool &Evaluated; - public: - DefaultEval(bool &evaluated) : Evaluated(evaluated) { } - virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) { - Evaluated = false; - Dst.insert(Pred); - } - }; - - evaluated = true; - DefaultEval defaultEval(evaluated); - getCheckerManager().runCheckersForEvalCall(Dst, Pred, CE, *this, - &defaultEval); - return evaluated; -} - -// FIXME: This is largely copy-paste from CheckerVisit(). Need to -// unify. -void ExprEngine::CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst, - ExplodedNodeSet &Src, SVal location, - SVal val, bool isPrevisit) { - - if (Checkers.empty()) { - Dst.insert(Src); - return; - } - - ExplodedNodeSet Tmp; - ExplodedNodeSet *PrevSet = &Src; - - for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I) - { - ExplodedNodeSet *CurrSet = 0; - if (I+1 == E) - CurrSet = &Dst; - else { - CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp; - CurrSet->clear(); - } - - void *tag = I->first; - Checker *checker = I->second; - - for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); - NI != NE; ++NI) - checker->GR_VisitBind(*CurrSet, *Builder, *this, StoreE, - *NI, tag, location, val, isPrevisit); - - // Update which NodeSet is the current one. - PrevSet = CurrSet; - } - - // Don't autotransition. The CheckerContext objects should do this - // automatically. -} //===----------------------------------------------------------------------===// // Engine construction and deletion. //===----------------------------------------------------------------------===// -static void RegisterInternalChecks(ExprEngine &Eng) { - // Register internal "built-in" BugTypes with the BugReporter. These BugTypes - // are different than what probably many checks will do since they don't - // create BugReports on-the-fly but instead wait until ExprEngine finishes - // analyzing a function. Generation of BugReport objects is done via a call - // to 'FlushReports' from BugReporter. - // The following checks do not need to have their associated BugTypes - // explicitly registered with the BugReporter. If they issue any BugReports, - // their associated BugType will get registered with the BugReporter - // automatically. Note that the check itself is owned by the ExprEngine - // object. - RegisterAdjustedReturnValueChecker(Eng); - // CallAndMessageChecker should be registered before AttrNonNullChecker, - // where we assume arguments are not undefined. - RegisterCallAndMessageChecker(Eng); - RegisterAttrNonNullChecker(Eng); - RegisterDereferenceChecker(Eng); - RegisterVLASizeChecker(Eng); - RegisterDivZeroChecker(Eng); - RegisterReturnUndefChecker(Eng); - RegisterUndefinedArraySubscriptChecker(Eng); - RegisterUndefinedAssignmentChecker(Eng); - RegisterUndefBranchChecker(Eng); - RegisterUndefCapturedBlockVarChecker(Eng); - RegisterUndefResultChecker(Eng); - - // This is not a checker yet. - RegisterNoReturnFunctionChecker(Eng); - RegisterBuiltinFunctionChecker(Eng); - RegisterOSAtomicChecker(Eng); -} - ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf) : AMgr(mgr), Engine(*this), @@ -349,8 +76,6 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf) NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), RaiseSel(GetNullarySelector("raise", getContext())), BR(mgr, *this), TF(tf) { - // Register internal checks. - RegisterInternalChecks(*this); // FIXME: Eventually remove the TF object entirely. TF->RegisterChecks(*this); @@ -365,14 +90,6 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf) ExprEngine::~ExprEngine() { BR.FlushReports(); delete [] NSExceptionInstanceRaiseSelectors; - - // Delete the set of checkers. - for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I) - delete I->second; - - for (CheckersOrderedCache::iterator I=COCache.begin(), E=COCache.end(); - I!=E;++I) - delete I->second; } //===----------------------------------------------------------------------===// @@ -447,51 +164,7 @@ const GRState* ExprEngine::getInitialState(const LocationContext *InitLoc) { /// logic for handling assumptions on symbolic values. const GRState *ExprEngine::processAssume(const GRState *state, SVal cond, bool assumption) { - // Determine if we already have a cached 'CheckersOrdered' vector - // specifically tailored for processing assumptions. This - // can reduce the number of checkers actually called. - CheckersOrdered *CO = &Checkers; - llvm::OwningPtr NewCO; - - CallbackTag K = GetCallbackTag(processAssumeCallback); - CheckersOrdered *& CO_Ref = COCache[K]; - - if (!CO_Ref) { - // If we have no previously cached CheckersOrdered vector for this - // statement kind, then create one. - NewCO.reset(new CheckersOrdered); - } - else { - // Use the already cached set. - CO = CO_Ref; - } - - if (!CO->empty()) { - // Let the checkers have a crack at the assume before the transfer functions - // get their turn. - for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I!=E; ++I) { - - // If any checker declares the state infeasible (or if it starts that - // way), bail out. - if (!state) - return NULL; - - Checker *C = I->second; - bool respondsToCallback = true; - - state = C->evalAssume(state, cond, assumption, &respondsToCallback); - - // Check if we're building the cache of checkers that care about - // assumptions. - if (NewCO.get() && respondsToCallback) - NewCO->push_back(*I); - } - - // If we got through all the checkers, and we built a list of those that - // care about assumptions, save it. - if (NewCO.get()) - CO_Ref = NewCO.take(); - } + state = getCheckerManager().runCheckersForEvalAssume(state, cond, assumption); // If the state is infeasible at this point, bail out. if (!state) @@ -501,18 +174,6 @@ const GRState *ExprEngine::processAssume(const GRState *state, SVal cond, } bool ExprEngine::wantsRegionChangeUpdate(const GRState* state) { - CallbackTag K = GetCallbackTag(EvalRegionChangesCallback); - CheckersOrdered *CO = COCache[K]; - - if (!CO) - CO = &Checkers; - - for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) { - Checker *C = I->second; - if (C->wantsRegionChangeUpdate(state)) - return true; - } - return getCheckerManager().wantsRegionChangeUpdate(state); } @@ -520,78 +181,30 @@ const GRState * ExprEngine::processRegionChanges(const GRState *state, const MemRegion * const *Begin, const MemRegion * const *End) { - // FIXME: Most of this method is copy-pasted from processAssume. - - // Determine if we already have a cached 'CheckersOrdered' vector - // specifically tailored for processing region changes. This - // can reduce the number of checkers actually called. - CheckersOrdered *CO = &Checkers; - llvm::OwningPtr NewCO; - - CallbackTag K = GetCallbackTag(EvalRegionChangesCallback); - CheckersOrdered *& CO_Ref = COCache[K]; - - if (!CO_Ref) { - // If we have no previously cached CheckersOrdered vector for this - // callback, then create one. - NewCO.reset(new CheckersOrdered); - } - else { - // Use the already cached set. - CO = CO_Ref; - } - - // If there are no checkers, just delegate to the checker manager. - if (CO->empty()) - return getCheckerManager().runCheckersForRegionChanges(state, Begin, End); - - for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) { - // If any checker declares the state infeasible (or if it starts that way), - // bail out. - if (!state) - return NULL; - - Checker *C = I->second; - bool respondsToCallback = true; - - state = C->EvalRegionChanges(state, Begin, End, &respondsToCallback); - - // See if we're building a cache of checkers that care about region changes. - if (NewCO.get() && respondsToCallback) - NewCO->push_back(*I); - } - - // If we got through all the checkers, and we built a list of those that - // care about region changes, save it. - if (NewCO.get()) - CO_Ref = NewCO.take(); - return getCheckerManager().runCheckersForRegionChanges(state, Begin, End); } void ExprEngine::processEndWorklist(bool hasWorkRemaining) { - for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end(); - I != E; ++I) { - I->second->VisitEndAnalysis(G, BR, *this); - } getCheckerManager().runCheckersForEndAnalysis(G, BR, *this); } void ExprEngine::processCFGElement(const CFGElement E, StmtNodeBuilder& builder) { switch (E.getKind()) { - case CFGElement::Statement: - ProcessStmt(E.getAs(), builder); - break; - case CFGElement::Initializer: - ProcessInitializer(E.getAs(), builder); - break; - case CFGElement::ImplicitDtor: - ProcessImplicitDtor(E.getAs(), builder); - break; - default: - // Suppress compiler warning. - llvm_unreachable("Unexpected CFGElement kind."); + case CFGElement::Invalid: + llvm_unreachable("Unexpected CFGElement kind."); + case CFGElement::Statement: + ProcessStmt(E.getAs()->getStmt(), builder); + return; + case CFGElement::Initializer: + ProcessInitializer(E.getAs()->getInitializer(), builder); + return; + case CFGElement::AutomaticObjectDtor: + case CFGElement::BaseDtor: + case CFGElement::MemberDtor: + case CFGElement::TemporaryDtor: + ProcessImplicitDtor(*E.getAs(), builder); + return; } } @@ -615,13 +228,6 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) { if (AMgr.shouldPurgeDead()) { const GRState *St = EntryNode->getState(); - - for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end(); - I != E; ++I) { - Checker *checker = I->second; - checker->MarkLiveSymbols(St, SymReaper); - } - getCheckerManager().runCheckersForLiveSymbols(St, SymReaper); const StackFrameContext *SFC = LC->getCurrentStackFrame(); @@ -647,33 +253,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) { getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode, CleanedState, SymReaper); - ExplodedNodeSet checkersV1Tmp; - if (Checkers.empty()) - checkersV1Tmp.insert(Tmp2); - else { - ExplodedNodeSet Tmp3; - ExplodedNodeSet *SrcSet = &Tmp2; - for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end(); - I != E; ++I) { - ExplodedNodeSet *DstSet = 0; - if (I+1 == E) - DstSet = &checkersV1Tmp; - else { - DstSet = (SrcSet == &Tmp2) ? &Tmp3 : &Tmp2; - DstSet->clear(); - } - - void *tag = I->first; - Checker *checker = I->second; - for (ExplodedNodeSet::iterator NI = SrcSet->begin(), NE = SrcSet->end(); - NI != NE; ++NI) - checker->GR_evalDeadSymbols(*DstSet, *Builder, *this, currentStmt, - *NI, SymReaper, tag); - SrcSet = DstSet; - } - } - - getCheckerManager().runCheckersForDeadSymbols(Tmp, checkersV1Tmp, + getCheckerManager().runCheckersForDeadSymbols(Tmp, Tmp2, SymReaper, currentStmt, *this); if (!Builder->BuildSinks && !Builder->hasGeneratedNode) @@ -767,7 +347,7 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D, StmtNodeBuilder &builder) { Builder = &builder; - switch (D.getDtorKind()) { + switch (D.getKind()) { case CFGElement::AutomaticObjectDtor: ProcessAutomaticObjDtor(cast(D), builder); break; @@ -842,10 +422,8 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, // C++ stuff we don't support yet. case Stmt::CXXBindTemporaryExprClass: case Stmt::CXXCatchStmtClass: - case Stmt::CXXDefaultArgExprClass: case Stmt::CXXDependentScopeMemberExprClass: - case Stmt::ExprWithCleanupsClass: - case Stmt::CXXNullPtrLiteralExprClass: + case Stmt::CXXForRangeStmtClass: case Stmt::CXXPseudoDestructorExprClass: case Stmt::CXXTemporaryObjectExprClass: case Stmt::CXXThrowExprClass: @@ -857,20 +435,35 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, case Stmt::DependentScopeDeclRefExprClass: case Stmt::UnaryTypeTraitExprClass: case Stmt::BinaryTypeTraitExprClass: + case Stmt::ArrayTypeTraitExprClass: + case Stmt::ExpressionTraitExprClass: case Stmt::UnresolvedLookupExprClass: case Stmt::UnresolvedMemberExprClass: case Stmt::CXXNoexceptExprClass: case Stmt::PackExpansionExprClass: case Stmt::SubstNonTypeTemplateParmPackExprClass: + case Stmt::SEHTryStmtClass: + case Stmt::SEHExceptStmtClass: + case Stmt::SEHFinallyStmtClass: { SaveAndRestore OldSink(Builder->BuildSinks); Builder->BuildSinks = true; - MakeNode(Dst, S, Pred, GetState(Pred)); + const ExplodedNode *node = MakeNode(Dst, S, Pred, GetState(Pred)); + Engine.addAbortedBlock(node, Builder->getBlock()); break; } - + + // We don't handle default arguments either yet, but we can fake it + // for now by just skipping them. + case Stmt::CXXDefaultArgExprClass: { + Dst.Add(Pred); + break; + } + case Stmt::ParenExprClass: llvm_unreachable("ParenExprs already handled."); + case Stmt::GenericSelectionExprClass: + llvm_unreachable("GenericSelectionExprs already handled."); // Cases that should never be evaluated simply because they shouldn't // appear in the CFG. case Stmt::BreakStmtClass: @@ -879,11 +472,15 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, case Stmt::ContinueStmtClass: case Stmt::DefaultStmtClass: case Stmt::DoStmtClass: + case Stmt::ForStmtClass: case Stmt::GotoStmtClass: + case Stmt::IfStmtClass: case Stmt::IndirectGotoStmtClass: case Stmt::LabelStmtClass: case Stmt::NoStmtClass: case Stmt::NullStmtClass: + case Stmt::SwitchStmtClass: + case Stmt::WhileStmtClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); break; @@ -927,8 +524,10 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, case Stmt::IntegerLiteralClass: case Stmt::CharacterLiteralClass: case Stmt::CXXBoolLiteralExprClass: + case Stmt::ExprWithCleanupsClass: case Stmt::FloatingLiteralClass: case Stmt::SizeOfPackExprClass: + case Stmt::CXXNullPtrLiteralExprClass: Dst.Add(Pred); // No-op. Simply propagate the current state unchanged. break; @@ -974,9 +573,10 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, break; } - case Stmt::CallExprClass: { - const CallExpr* C = cast(S); - VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst); + case Stmt::CallExprClass: + case Stmt::CXXOperatorCallExprClass: + case Stmt::CXXMemberCallExprClass: { + VisitCallExpr(cast(S), Pred, Dst); break; } @@ -988,18 +588,6 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, break; } - case Stmt::CXXMemberCallExprClass: { - const CXXMemberCallExpr *MCE = cast(S); - VisitCXXMemberCallExpr(MCE, Pred, Dst); - break; - } - - case Stmt::CXXOperatorCallExprClass: { - const CXXOperatorCallExpr *C = cast(S); - VisitCXXOperatorCallExpr(C, Pred, Dst); - break; - } - case Stmt::CXXNewExprClass: { const CXXNewExpr *NE = cast(S); VisitCXXNewExpr(NE, Pred, Dst); @@ -1050,12 +638,6 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, VisitDeclStmt(cast(S), Pred, Dst); break; - case Stmt::ForStmtClass: - // This case isn't for branch processing, but for handling the - // initialization of a condition variable. - VisitCondInit(cast(S)->getConditionVariable(), S, Pred, Dst); - break; - case Stmt::ImplicitCastExprClass: case Stmt::CStyleCastExprClass: case Stmt::CXXStaticCastExprClass: @@ -1068,12 +650,6 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, break; } - case Stmt::IfStmtClass: - // This case isn't for branch processing, but for handling the - // initialization of a condition variable. - VisitCondInit(cast(S)->getConditionVariable(), S, Pred, Dst); - break; - case Stmt::InitListExprClass: VisitInitListExpr(cast(S), Pred, Dst); break; @@ -1110,8 +686,9 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, VisitOffsetOfExpr(cast(S), Pred, Dst); break; - case Stmt::SizeOfAlignOfExprClass: - VisitSizeOfAlignOfExpr(cast(S), Pred, Dst); + case Stmt::UnaryExprOrTypeTraitExprClass: + VisitUnaryExprOrTypeTraitExpr(cast(S), + Pred, Dst); break; case Stmt::StmtExprClass: { @@ -1142,12 +719,6 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, return; } - case Stmt::SwitchStmtClass: - // This case isn't for branch processing, but for handling the - // initialization of a condition variable. - VisitCondInit(cast(S)->getConditionVariable(), S, Pred, Dst); - break; - case Stmt::UnaryOperatorClass: { const UnaryOperator *U = cast(S); if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UO_LNot)) { @@ -1159,12 +730,6 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, VisitUnaryOperator(U, Pred, Dst); break; } - - case Stmt::WhileStmtClass: - // This case isn't for branch processing, but for handling the - // initialization of a condition variable. - VisitCondInit(cast(S)->getConditionVariable(), S, Pred, Dst); - break; } } @@ -1313,11 +878,7 @@ void ExprEngine::processBranch(const Stmt* Condition, const Stmt* Term, Condition->getLocStart(), "Error evaluating branch"); - for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) { - void *tag = I->first; - Checker *checker = I->second; - checker->VisitBranchCondition(builder, *this, Condition, tag); - } + getCheckerManager().runCheckersForBranchCondition(Condition, builder, *this); // If the branch condition is undefined, return; if (!builder.isFeasible(true) && !builder.isFeasible(false)) @@ -1326,7 +887,7 @@ void ExprEngine::processBranch(const Stmt* Condition, const Stmt* Term, const GRState* PrevState = builder.getState(); SVal X = PrevState->getSVal(Condition); - if (X.isUnknown()) { + if (X.isUnknownOrUndef()) { // Give it a chance to recover from unknown. if (const Expr *Ex = dyn_cast(Condition)) { if (Ex->getType()->isIntegerType()) { @@ -1344,7 +905,7 @@ void ExprEngine::processBranch(const Stmt* Condition, const Stmt* Term, } } // If the condition is still unknown, give up. - if (X.isUnknown()) { + if (X.isUnknownOrUndef()) { builder.generateNode(MarkBranch(PrevState, Term, true), true); builder.generateNode(MarkBranch(PrevState, Term, false), false); return; @@ -1441,12 +1002,6 @@ void ExprEngine::VisitGuardedExpr(const Expr* Ex, const Expr* L, void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) { getTF().evalEndPath(*this, builder); StateMgr.EndPath(builder.getState()); - for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){ - void *tag = I->first; - Checker *checker = I->second; - EndOfFunctionNodeBuilder B = builder.withCheckerTag(tag); - checker->evalEndPath(B, tag, *this); - } getCheckerManager().runCheckersForEndPath(builder, *this); } @@ -1473,6 +1028,10 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) { bool defaultIsFeasible = I == EI; for ( ; I != EI; ++I) { + // Successor may be pruned out during CFG construction. + if (!I.getBlock()) + continue; + const CaseStmt* Case = I.getCase(); // Evaluate the LHS of the case value. @@ -1666,7 +1225,7 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ProgramPoint::PostLValueKind); // Post-visit the BlockExpr. - CheckerVisit(BE, Dst, Tmp, PostVisitStmtCallback); + getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this); } void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, @@ -1723,7 +1282,7 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr* A, ExplodedNodeSet Tmp2; Visit(Idx, *I1, Tmp2); // Evaluate the index. ExplodedNodeSet Tmp3; - CheckerVisit(A, Tmp3, Tmp2, PreVisitStmtCallback); + getCheckerManager().runCheckersForPreStmt(Tmp3, Tmp2, A, *this); for (ExplodedNodeSet::iterator I2=Tmp3.begin(),E2=Tmp3.end();I2!=E2; ++I2) { const GRState* state = GetState(*I2); @@ -1784,7 +1343,8 @@ void ExprEngine::evalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, // Do a previsit of the bind. ExplodedNodeSet CheckedSet, Src; Src.Add(Pred); - CheckerVisitBind(StoreE, CheckedSet, Src, location, Val, true); + getCheckerManager().runCheckersForBind(CheckedSet, Src, location, Val, StoreE, + *this); for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); I!=E; ++I) { @@ -1862,7 +1422,8 @@ void ExprEngine::evalStore(ExplodedNodeSet& Dst, const Expr *AssignE, if (Tmp.empty()) return; - assert(!location.isUndef()); + if (location.isUndef()) + return; SaveAndRestore OldSPointKind(Builder->PointKind, ProgramPoint::PostStoreKind); @@ -1922,7 +1483,8 @@ void ExprEngine::evalLoadCommon(ExplodedNodeSet& Dst, const Expr *Ex, if (Tmp.empty()) return; - assert(!location.isUndef()); + if (location.isUndef()) + return; SaveAndRestore OldSPointKind(Builder->PointKind); @@ -1955,57 +1517,36 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S, return; } - if (Checkers.empty()) { - ExplodedNodeSet Src; - if (Builder->GetState(Pred) == state) { - Src.Add(Pred); - } else { - // Associate this new state with an ExplodedNode. - Src.Add(Builder->generateNode(S, state, Pred)); - } - getCheckerManager().runCheckersForLocation(Dst, Src, location, isLoad, S, - *this); - return; - } - ExplodedNodeSet Src; - Src.Add(Pred); - ExplodedNodeSet CheckersV1Dst; - ExplodedNodeSet Tmp; - ExplodedNodeSet *PrevSet = &Src; - - for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I) - { - ExplodedNodeSet *CurrSet = 0; - if (I+1 == E) - CurrSet = &CheckersV1Dst; - else { - CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp; - CurrSet->clear(); - } - - void *tag = I->first; - Checker *checker = I->second; - - for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); - NI != NE; ++NI) { - // Use the 'state' argument only when the predecessor node is the - // same as Pred. This allows us to catch updates to the state. - checker->GR_visitLocation(*CurrSet, *Builder, *this, S, *NI, - *NI == Pred ? state : GetState(*NI), - location, tag, isLoad); - } - - // Update which NodeSet is the current one. - PrevSet = CurrSet; + if (Builder->GetState(Pred) == state) { + Src.Add(Pred); + } else { + // Associate this new state with an ExplodedNode. + // FIXME: If I pass null tag, the graph is incorrect, e.g for + // int *p; + // p = 0; + // *p = 0xDEADBEEF; + // "p = 0" is not noted as "Null pointer value stored to 'p'" but + // instead "int *p" is noted as + // "Variable 'p' initialized to a null pointer value" + ExplodedNode *N = Builder->generateNode(S, state, Pred, this); + Src.Add(N ? N : Pred); } - - getCheckerManager().runCheckersForLocation(Dst, CheckersV1Dst, location, - isLoad, S, *this); + getCheckerManager().runCheckersForLocation(Dst, Src, location, isLoad, S, + *this); } bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred) { + return false; + + // Inlining isn't correct right now because we: + // (a) don't generate CallExit nodes. + // (b) we need a way to postpone doing post-visits of CallExprs until + // the CallExit. This means we need CallExits for the non-inline + // cases as well. + +#if 0 const GRState *state = GetState(Pred); const Expr *Callee = CE->getCallee(); SVal L = state->getSVal(Callee); @@ -2014,6 +1555,29 @@ bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, if (!FD) return false; + // Specially handle CXXMethods. + const CXXMethodDecl *methodDecl = 0; + + switch (CE->getStmtClass()) { + default: break; + case Stmt::CXXOperatorCallExprClass: { + const CXXOperatorCallExpr *opCall = cast(CE); + methodDecl = + llvm::dyn_cast_or_null(opCall->getCalleeDecl()); + break; + } + case Stmt::CXXMemberCallExprClass: { + const CXXMemberCallExpr *memberCall = cast(CE); + const MemberExpr *memberExpr = + cast(memberCall->getCallee()->IgnoreParens()); + methodDecl = cast(memberExpr->getMemberDecl()); + break; + } + } + + + + // Check if the function definition is in the same translation unit. if (FD->hasBody(FD)) { const StackFrameContext *stackFrame = @@ -2041,14 +1605,15 @@ bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, Dst.Add(N); return true; } + + // Generate the CallExit node. return false; +#endif } -void ExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred, - CallExpr::const_arg_iterator AI, - CallExpr::const_arg_iterator AE, - ExplodedNodeSet& Dst) { +void ExprEngine::VisitCallExpr(const CallExpr* CE, ExplodedNode* Pred, + ExplodedNodeSet& dst) { // Determine the type of function we're calling (if available). const FunctionProtoType *Proto = NULL; @@ -2056,72 +1621,78 @@ void ExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred, if (const PointerType *FnTypePtr = FnType->getAs()) Proto = FnTypePtr->getPointeeType()->getAs(); - // Evaluate the arguments. - ExplodedNodeSet ArgsEvaluated; - evalArguments(CE->arg_begin(), CE->arg_end(), Proto, Pred, ArgsEvaluated); - - // Now process the call itself. - ExplodedNodeSet DstTmp; - const Expr* Callee = CE->getCallee()->IgnoreParens(); - - for (ExplodedNodeSet::iterator NI=ArgsEvaluated.begin(), - NE=ArgsEvaluated.end(); NI != NE; ++NI) { - // Evaluate the callee. - ExplodedNodeSet DstTmp2; - Visit(Callee, *NI, DstTmp2); - // Perform the previsit of the CallExpr, storing the results in DstTmp. - CheckerVisit(CE, DstTmp, DstTmp2, PreVisitStmtCallback); + // Should the first argument be evaluated as an lvalue? + bool firstArgumentAsLvalue = false; + switch (CE->getStmtClass()) { + case Stmt::CXXOperatorCallExprClass: + firstArgumentAsLvalue = true; + break; + default: + break; } + + // Evaluate the arguments. + ExplodedNodeSet dstArgsEvaluated; + evalArguments(CE->arg_begin(), CE->arg_end(), Proto, Pred, dstArgsEvaluated, + firstArgumentAsLvalue); + + // Evaluate the callee. + ExplodedNodeSet dstCalleeEvaluated; + evalCallee(CE, dstArgsEvaluated, dstCalleeEvaluated); + + // Perform the previsit of the CallExpr. + ExplodedNodeSet dstPreVisit; + getCheckerManager().runCheckersForPreStmt(dstPreVisit, dstCalleeEvaluated, + CE, *this); + + // Now evaluate the call itself. + class DefaultEval : public GraphExpander { + ExprEngine &Eng; + const CallExpr *CE; + public: + + DefaultEval(ExprEngine &eng, const CallExpr *ce) + : Eng(eng), CE(ce) {} + virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) { + // Should we inline the call? + if (Eng.getAnalysisManager().shouldInlineCall() && + Eng.InlineCall(Dst, CE, Pred)) { + return; + } + + StmtNodeBuilder &Builder = Eng.getBuilder(); + assert(&Builder && "StmtNodeBuilder must be defined."); + + // Dispatch to the plug-in transfer function. + unsigned oldSize = Dst.size(); + SaveOr OldHasGen(Builder.hasGeneratedNode); + + // Dispatch to transfer function logic to handle the call itself. + const Expr* Callee = CE->getCallee()->IgnoreParens(); + const GRState* state = Eng.GetState(Pred); + SVal L = state->getSVal(Callee); + Eng.getTF().evalCall(Dst, Eng, Builder, CE, L, Pred); + + // Handle the case where no nodes where generated. Auto-generate that + // contains the updated state if we aren't generating sinks. + if (!Builder.BuildSinks && Dst.size() == oldSize && + !Builder.hasGeneratedNode) + Eng.MakeNode(Dst, CE, Pred, state); + } + }; // Finally, evaluate the function call. We try each of the checkers // to see if the can evaluate the function call. - ExplodedNodeSet DstTmp3; - - for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); - DI != DE; ++DI) { - - const GRState* state = GetState(*DI); - SVal L = state->getSVal(Callee); - - // FIXME: Add support for symbolic function calls (calls involving - // function pointer values that are symbolic). - SaveAndRestore OldSink(Builder->BuildSinks); - ExplodedNodeSet DstChecker; - - // If the callee is processed by a checker, skip the rest logic. - if (CheckerEvalCall(CE, DstChecker, *DI)) - DstTmp3.insert(DstChecker); - else if (AMgr.shouldInlineCall() && InlineCall(Dst, CE, *DI)) { - // Callee is inlined. We shouldn't do post call checking. - return; - } - else { - for (ExplodedNodeSet::iterator DI_Checker = DstChecker.begin(), - DE_Checker = DstChecker.end(); - DI_Checker != DE_Checker; ++DI_Checker) { - - // Dispatch to the plug-in transfer function. - unsigned oldSize = DstTmp3.size(); - SaveOr OldHasGen(Builder->hasGeneratedNode); - Pred = *DI_Checker; - - // Dispatch to transfer function logic to handle the call itself. - // FIXME: Allow us to chain together transfer functions. - assert(Builder && "StmtNodeBuilder must be defined."); - getTF().evalCall(DstTmp3, *this, *Builder, CE, L, Pred); - - // Handle the case where no nodes where generated. Auto-generate that - // contains the updated state if we aren't generating sinks. - if (!Builder->BuildSinks && DstTmp3.size() == oldSize && - !Builder->hasGeneratedNode) - MakeNode(DstTmp3, CE, Pred, state); - } - } - } + ExplodedNodeSet dstCallEvaluated; + DefaultEval defEval(*this, CE); + getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, + dstPreVisit, + CE, *this, &defEval); // Finally, perform the post-condition check of the CallExpr and store // the created nodes in 'Dst'. - CheckerVisit(CE, Dst, DstTmp3, PostVisitStmtCallback); + getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE, + *this); } //===----------------------------------------------------------------------===// @@ -2213,7 +1784,7 @@ void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, // Pre-visit the ObjCAtSynchronizedStmt. ExplodedNodeSet Tmp; Tmp.Add(Pred); - CheckerVisit(S, Dst, Tmp, PreVisitStmtCallback); + getCheckerManager().runCheckersForPreStmt(Dst, Tmp, S, *this); } //===----------------------------------------------------------------------===// @@ -2244,7 +1815,7 @@ void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr* Ex, // Perform the post-condition check of the ObjCIvarRefExpr and store // the created nodes in 'Dst'. - CheckerVisit(Ex, Dst, dstIvar, PostVisitStmtCallback); + getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this); } //===----------------------------------------------------------------------===// @@ -2414,7 +1985,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, // Handle the previsits checks. ExplodedNodeSet DstPrevisit; - CheckerVisitObjCMessage(msg, DstPrevisit, Src, /*isPreVisit=*/true); + getCheckerManager().runCheckersForPreObjCMessage(DstPrevisit, Src, msg,*this); // Proceed with evaluate the message expression. ExplodedNodeSet dstEval; @@ -2430,33 +2001,34 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, if (const Expr *Receiver = msg.getInstanceReceiver()) { const GRState *state = GetState(Pred); - - // Bifurcate the state into nil and non-nil ones. - DefinedOrUnknownSVal receiverVal = - cast(state->getSVal(Receiver)); - - const GRState *notNilState, *nilState; - llvm::tie(notNilState, nilState) = state->assume(receiverVal); - - // There are three cases: can be nil or non-nil, must be nil, must be - // non-nil. We handle must be nil, and merge the rest two into non-nil. - if (nilState && !notNilState) { - CheckerEvalNilReceiver(msg, dstEval, nilState, Pred); - continue; + SVal recVal = state->getSVal(Receiver); + if (!recVal.isUndef()) { + // Bifurcate the state into nil and non-nil ones. + DefinedOrUnknownSVal receiverVal = cast(recVal); + + const GRState *notNilState, *nilState; + llvm::tie(notNilState, nilState) = state->assume(receiverVal); + + // There are three cases: can be nil or non-nil, must be nil, must be + // non-nil. We ignore must be nil, and merge the rest two into non-nil. + if (nilState && !notNilState) { + dstEval.insert(Pred); + continue; + } + + // Check if the "raise" message was sent. + assert(notNilState); + if (msg.getSelector() == RaiseSel) + RaisesException = true; + + // Check if we raise an exception. For now treat these as sinks. + // Eventually we will want to handle exceptions properly. + if (RaisesException) + Builder->BuildSinks = true; + + // Dispatch to plug-in transfer function. + evalObjCMessage(dstEval, msg, Pred, notNilState); } - - // Check if the "raise" message was sent. - assert(notNilState); - if (msg.getSelector() == RaiseSel) - RaisesException = true; - - // Check if we raise an exception. For now treat these as sinks. - // Eventually we will want to handle exceptions properly. - if (RaisesException) - Builder->BuildSinks = true; - - // Dispatch to plug-in transfer function. - evalObjCMessage(dstEval, msg, Pred, notNilState); } else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) { IdentifierInfo* ClsName = Iface->getIdentifier(); @@ -2516,7 +2088,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, // Finally, perform the post-condition check of the ObjCMessageExpr and store // the created nodes in 'Dst'. - CheckerVisitObjCMessage(msg, Dst, dstEval, /*isPreVisit=*/false); + getCheckerManager().runCheckersForPostObjCMessage(Dst, dstEval, msg, *this); } //===----------------------------------------------------------------------===// @@ -2529,7 +2101,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNodeSet S1; Visit(Ex, Pred, S1); ExplodedNodeSet S2; - CheckerVisit(CastE, S2, S1, PreVisitStmtCallback); + getCheckerManager().runCheckersForPreStmt(S2, S1, CastE, *this); if (CastE->getCastKind() == CK_LValueToRValue || CastE->getCastKind() == CK_GetObjCProperty) { @@ -2547,106 +2119,95 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, if (const ExplicitCastExpr *ExCast=dyn_cast_or_null(CastE)) T = ExCast->getTypeAsWritten(); - -#if 0 - // If we are evaluating the cast in an lvalue context, we implicitly want - // the cast to evaluate to a location. - if (asLValue) { - ASTContext &Ctx = getContext(); - T = Ctx.getPointerType(Ctx.getCanonicalType(T)); - ExTy = Ctx.getPointerType(Ctx.getCanonicalType(ExTy)); - } -#endif - switch (CastE->getCastKind()) { - case CK_ToVoid: - for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) - Dst.Add(*I); - return; + for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) { + Pred = *I; - case CK_LValueToRValue: - case CK_NoOp: - case CK_FunctionToPointerDecay: - for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) { - // Copy the SVal of Ex to CastE. - ExplodedNode *N = *I; - const GRState *state = GetState(N); - SVal V = state->getSVal(Ex); - state = state->BindExpr(CastE, V); - MakeNode(Dst, CastE, N, state); + switch (CastE->getCastKind()) { + case CK_ToVoid: + Dst.Add(Pred); + continue; + case CK_LValueToRValue: + case CK_NoOp: + case CK_FunctionToPointerDecay: { + // Copy the SVal of Ex to CastE. + const GRState *state = GetState(Pred); + SVal V = state->getSVal(Ex); + state = state->BindExpr(CastE, V); + MakeNode(Dst, CastE, Pred, state); + continue; + } + case CK_GetObjCProperty: + case CK_Dependent: + case CK_ArrayToPointerDecay: + case CK_BitCast: + case CK_LValueBitCast: + case CK_IntegralCast: + case CK_NullToPointer: + case CK_IntegralToPointer: + case CK_PointerToIntegral: + case CK_PointerToBoolean: + case CK_IntegralToBoolean: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingToBoolean: + case CK_FloatingCast: + case CK_FloatingRealToComplex: + case CK_FloatingComplexToReal: + case CK_FloatingComplexToBoolean: + case CK_FloatingComplexCast: + case CK_FloatingComplexToIntegralComplex: + case CK_IntegralRealToComplex: + case CK_IntegralComplexToReal: + case CK_IntegralComplexToBoolean: + case CK_IntegralComplexCast: + case CK_IntegralComplexToFloatingComplex: + case CK_AnyPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + case CK_ObjCObjectLValueCast: { + // Delegate to SValBuilder to process. + const GRState* state = GetState(Pred); + SVal V = state->getSVal(Ex); + V = svalBuilder.evalCast(V, T, ExTy); + state = state->BindExpr(CastE, V); + MakeNode(Dst, CastE, Pred, state); + continue; + } + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: { + // For DerivedToBase cast, delegate to the store manager. + const GRState *state = GetState(Pred); + SVal val = state->getSVal(Ex); + val = getStoreManager().evalDerivedToBase(val, T); + state = state->BindExpr(CastE, val); + MakeNode(Dst, CastE, Pred, state); + continue; + } + // Various C++ casts that are not handled yet. + case CK_Dynamic: + case CK_ToUnion: + case CK_BaseToDerived: + case CK_NullToMemberPointer: + case CK_BaseToDerivedMemberPointer: + case CK_DerivedToBaseMemberPointer: + case CK_UserDefinedConversion: + case CK_ConstructorConversion: + case CK_VectorSplat: + case CK_MemberPointerToBoolean: { + // Recover some path-sensitivty by conjuring a new value. + QualType resultType = CastE->getType(); + if (CastE->isLValue()) + resultType = getContext().getPointerType(resultType); + + SVal result = + svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType, + Builder->getCurrentBlockCount()); + + const GRState *state = GetState(Pred)->BindExpr(CastE, result); + MakeNode(Dst, CastE, Pred, state); + continue; + } } - return; - - case CK_GetObjCProperty: - case CK_Dependent: - case CK_ArrayToPointerDecay: - case CK_BitCast: - case CK_LValueBitCast: - case CK_IntegralCast: - case CK_NullToPointer: - case CK_IntegralToPointer: - case CK_PointerToIntegral: - case CK_PointerToBoolean: - case CK_IntegralToBoolean: - case CK_IntegralToFloating: - case CK_FloatingToIntegral: - case CK_FloatingToBoolean: - case CK_FloatingCast: - case CK_FloatingRealToComplex: - case CK_FloatingComplexToReal: - case CK_FloatingComplexToBoolean: - case CK_FloatingComplexCast: - case CK_FloatingComplexToIntegralComplex: - case CK_IntegralRealToComplex: - case CK_IntegralComplexToReal: - case CK_IntegralComplexToBoolean: - case CK_IntegralComplexCast: - case CK_IntegralComplexToFloatingComplex: - case CK_AnyPointerToObjCPointerCast: - case CK_AnyPointerToBlockPointerCast: - - case CK_ObjCObjectLValueCast: { - // Delegate to SValBuilder to process. - for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) { - ExplodedNode* N = *I; - const GRState* state = GetState(N); - SVal V = state->getSVal(Ex); - V = svalBuilder.evalCast(V, T, ExTy); - state = state->BindExpr(CastE, V); - MakeNode(Dst, CastE, N, state); - } - return; - } - - case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: - // For DerivedToBase cast, delegate to the store manager. - for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) { - ExplodedNode *node = *I; - const GRState *state = GetState(node); - SVal val = state->getSVal(Ex); - val = getStoreManager().evalDerivedToBase(val, T); - state = state->BindExpr(CastE, val); - MakeNode(Dst, CastE, node, state); - } - return; - - // Various C++ casts that are not handled yet. - case CK_Dynamic: - case CK_ToUnion: - case CK_BaseToDerived: - case CK_NullToMemberPointer: - case CK_BaseToDerivedMemberPointer: - case CK_DerivedToBaseMemberPointer: - case CK_UserDefinedConversion: - case CK_ConstructorConversion: - case CK_VectorSplat: - case CK_MemberPointerToBoolean: { - SaveAndRestore OldSink(Builder->BuildSinks); - Builder->BuildSinks = true; - MakeNode(Dst, CastE, Pred, GetState(Pred)); - return; - } } } @@ -2702,7 +2263,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, Tmp.Add(Pred); ExplodedNodeSet Tmp2; - CheckerVisit(DS, Tmp2, Tmp, PreVisitStmtCallback); + getCheckerManager().runCheckersForPreStmt(Tmp2, Tmp, DS, *this); for (ExplodedNodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I) { ExplodedNode *N = *I; @@ -2741,33 +2302,6 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, } } -void ExprEngine::VisitCondInit(const VarDecl *VD, const Stmt *S, - ExplodedNode *Pred, ExplodedNodeSet& Dst) { - - const Expr* InitEx = VD->getInit(); - ExplodedNodeSet Tmp; - Visit(InitEx, Pred, Tmp); - - for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ExplodedNode *N = *I; - const GRState *state = GetState(N); - - const LocationContext *LC = N->getLocationContext(); - SVal InitVal = state->getSVal(InitEx); - - // Recover some path-sensitivity if a scalar value evaluated to - // UnknownVal. - if (InitVal.isUnknown() || - !getConstraintManager().canReasonAbout(InitVal)) { - InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx, - Builder->getCurrentBlockCount()); - } - - evalBind(Dst, S, N, state, - loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true); - } -} - namespace { // This class is used by VisitInitListExpr as an item in a worklist // for processing the values contained in an InitListExpr. @@ -2861,19 +2395,15 @@ void ExprEngine::VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred, assert(0 && "unprocessed InitListExpr type"); } -/// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type). -void ExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, +/// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof(type). +void ExprEngine::VisitUnaryExprOrTypeTraitExpr( + const UnaryExprOrTypeTraitExpr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst) { QualType T = Ex->getTypeOfArgument(); - CharUnits amt; - if (Ex->isSizeOf()) { - if (T == getContext().VoidTy) { - // sizeof(void) == 1 byte. - amt = CharUnits::One(); - } - else if (!T->isConstantSizeType()) { + if (Ex->getKind() == UETT_SizeOf) { + if (!T->isIncompleteType() && !T->isConstantSizeType()) { assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); // FIXME: Add support for VLA type arguments, not just VLA expressions. @@ -2914,13 +2444,11 @@ void ExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, Dst.Add(Pred); return; } - else { - // All other cases. - amt = getContext().getTypeSizeInChars(T); - } } - else // Get alignment of the type. - amt = getContext().getTypeAlignInChars(T); + + Expr::EvalResult Result; + Ex->Evaluate(Result, getContext()); + CharUnits amt = CharUnits::fromQuantity(Result.Val.getInt().getZExtValue()); MakeNode(Dst, Ex, Pred, GetState(Pred)->BindExpr(Ex, @@ -3263,7 +2791,7 @@ void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred, } ExplodedNodeSet CheckedSet; - CheckerVisit(RS, CheckedSet, Src, PreVisitStmtCallback); + getCheckerManager().runCheckersForPreStmt(CheckedSet, Src, RS, *this); for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); I != E; ++I) { @@ -3305,7 +2833,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, Visit(RHS, *I1, Tmp2); ExplodedNodeSet CheckedSet; - CheckerVisit(B, CheckedSet, Tmp2, PreVisitStmtCallback); + getCheckerManager().runCheckersForPreStmt(CheckedSet, Tmp2, B, *this); // With both the LHS and RHS evaluated, process the operation itself. @@ -3432,16 +2960,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, } } - CheckerVisit(B, Dst, Tmp3, PostVisitStmtCallback); -} - -//===----------------------------------------------------------------------===// -// Checker registration/lookup. -//===----------------------------------------------------------------------===// - -Checker *ExprEngine::lookupChecker(void *tag) const { - CheckerMap::const_iterator I = CheckerM.find(tag); - return (I == CheckerM.end()) ? NULL : Checkers[I->second].second; + getCheckerManager().runCheckersForPostStmt(Dst, Tmp3, B, *this); } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FlatStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FlatStore.cpp index 99a5eadaca20..7bdca6b7f17d 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FlatStore.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FlatStore.cpp @@ -90,6 +90,19 @@ StoreManager *ento::CreateFlatStoreManager(GRStateManager &StMgr) { } SVal FlatStoreManager::Retrieve(Store store, Loc L, QualType T) { + // For access to concrete addresses, return UnknownVal. Checks + // for null dereferences (and similar errors) are done by checkers, not + // the Store. + // FIXME: We can consider lazily symbolicating such memory, but we really + // should defer this when we can reason easily about symbolicating arrays + // of bytes. + if (isa(L)) { + return UnknownVal(); + } + if (!isa(L)) { + return UnknownVal(); + } + const MemRegion *R = cast(L).getRegion(); RegionInterval RI = RegionToInterval(R); // FIXME: FlatStore should handle regions with unknown intervals. diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp index 2e370d62e440..c005819c9c96 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp @@ -37,6 +37,35 @@ Selector ObjCMessage::getSelector() const { return propE->getGetterSelector(); } +ObjCMethodFamily ObjCMessage::getMethodFamily() const { + assert(isValid() && "This ObjCMessage is uninitialized!"); + // Case 1. Explicit message send. + if (const ObjCMessageExpr *msgE = dyn_cast(MsgOrPropE)) + return msgE->getMethodFamily(); + + const ObjCPropertyRefExpr *propE = cast(MsgOrPropE); + + // Case 2. Reference to implicit property. + if (propE->isImplicitProperty()) { + if (isPropertySetter()) + return propE->getImplicitPropertySetter()->getMethodFamily(); + else + return propE->getImplicitPropertyGetter()->getMethodFamily(); + } + + // Case 3. Reference to explicit property. + const ObjCPropertyDecl *prop = propE->getExplicitProperty(); + if (isPropertySetter()) { + if (prop->getSetterMethodDecl()) + return prop->getSetterMethodDecl()->getMethodFamily(); + return prop->getSetterName().getMethodFamily(); + } else { + if (prop->getGetterMethodDecl()) + return prop->getGetterMethodDecl()->getMethodFamily(); + return prop->getGetterName().getMethodFamily(); + } +} + const ObjCMethodDecl *ObjCMessage::getMethodDecl() const { assert(isValid() && "This ObjCMessage is uninitialized!"); if (const ObjCMessageExpr *msgE = dyn_cast(MsgOrPropE)) @@ -80,13 +109,27 @@ const Expr *ObjCMessage::getArgExpr(unsigned i) const { } QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const { + QualType resultTy; + bool isLVal = false; + if (CallE) { + isLVal = CallE->isLValue(); const Expr *Callee = CallE->getCallee(); if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl()) - return FD->getResultType(); - return CallE->getType(); + resultTy = FD->getResultType(); + else + resultTy = CallE->getType(); } - return Msg.getResultType(ctx); + else { + isLVal = isa(Msg.getOriginExpr()) && + Msg.getOriginExpr()->isLValue(); + resultTy = Msg.getResultType(ctx); + } + + if (isLVal) + resultTy = ctx.getPointerType(resultTy); + + return resultTy; } SVal CallOrObjCMessage::getArgSValAsScalarOrLoc(unsigned i) const { @@ -97,3 +140,10 @@ SVal CallOrObjCMessage::getArgSValAsScalarOrLoc(unsigned i) const { return Msg.getArgSVal(i, State); return UnknownVal(); } + +SVal CallOrObjCMessage::getCXXCallee() const { + assert(isCXXCall()); + const Expr *callee = + cast(CallE)->getImplicitObjectArgument(); + return State->getSVal(callee); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 19e0e1257215..4522f976e648 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -337,6 +337,9 @@ class RegionStoreManager : public StoreManager { SVal RetrieveFieldOrElementCommon(Store store, const TypedRegion *R, QualType Ty, const MemRegion *superR); + + SVal RetrieveLazyBinding(const MemRegion *lazyBindingRegion, + Store lazyBindingStore); /// Retrieve the values in a struct and return a CompoundVal, used when doing /// struct copy: @@ -355,7 +358,8 @@ class RegionStoreManager : public StoreManager { /// Get the state and region whose binding this region R corresponds to. std::pair - GetLazyBinding(RegionBindings B, const MemRegion *R); + GetLazyBinding(RegionBindings B, const MemRegion *R, + const MemRegion *originalRegion); StoreRef CopyLazyBindings(nonloc::LazyCompoundVal V, Store store, const TypedRegion *R); @@ -684,11 +688,11 @@ void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) { QualType T = TR->getValueType(); // Invalidate the binding. - if (T->isStructureType()) { + if (T->isStructureOrClassType()) { // Invalidate the region by setting its default value to // conjured symbol. The type of the symbol is irrelavant. - DefinedOrUnknownSVal V = svalBuilder.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy, - Count); + DefinedOrUnknownSVal V = + svalBuilder.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy, Count); B = RM.addBinding(B, baseR, BindingKey::Default, V); return; } @@ -976,15 +980,20 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { } std::pair -RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R) { - if (Optional OV = getDirectBinding(B, R)) - if (const nonloc::LazyCompoundVal *V = - dyn_cast(OV.getPointer())) - return std::make_pair(V->getStore(), V->getRegion()); - +RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R, + const MemRegion *originalRegion) { + + if (originalRegion != R) { + if (Optional OV = getDefaultBinding(B, R)) { + if (const nonloc::LazyCompoundVal *V = + dyn_cast(OV.getPointer())) + return std::make_pair(V->getStore(), V->getRegion()); + } + } + if (const ElementRegion *ER = dyn_cast(R)) { const std::pair &X = - GetLazyBinding(B, ER->getSuperRegion()); + GetLazyBinding(B, ER->getSuperRegion(), originalRegion); if (X.second) return std::make_pair(X.first, @@ -992,7 +1001,7 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R) { } else if (const FieldRegion *FR = dyn_cast(R)) { const std::pair &X = - GetLazyBinding(B, FR->getSuperRegion()); + GetLazyBinding(B, FR->getSuperRegion(), originalRegion); if (X.second) return std::make_pair(X.first, @@ -1003,12 +1012,13 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R) { else if (const CXXBaseObjectRegion *baseReg = dyn_cast(R)) { const std::pair &X = - GetLazyBinding(B, baseReg->getSuperRegion()); + GetLazyBinding(B, baseReg->getSuperRegion(), originalRegion); if (X.second) return std::make_pair(X.first, MRMgr.getCXXBaseObjectRegionWithSuper(baseReg, X.second)); } + // The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is // possible for a valid lazy binding. return std::make_pair((Store) 0, (const MemRegion *) 0); @@ -1098,14 +1108,19 @@ RegionStoreManager::RetrieveDerivedDefaultValue(RegionBindings B, QualType Ty) { if (const Optional &D = getDefaultBinding(B, superR)) { - if (SymbolRef parentSym = D->getAsSymbol()) + const SVal &val = D.getValue(); + if (SymbolRef parentSym = val.getAsSymbol()) return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R); - if (D->isZeroConstant()) + if (val.isZeroConstant()) return svalBuilder.makeZeroVal(Ty); - if (D->isUnknownOrUndef()) - return *D; + if (val.isUnknownOrUndef()) + return val; + + // Lazy bindings are handled later. + if (isa(val)) + return Optional(); assert(0 && "Unknown default value"); } @@ -1113,6 +1128,15 @@ RegionStoreManager::RetrieveDerivedDefaultValue(RegionBindings B, return Optional(); } +SVal RegionStoreManager::RetrieveLazyBinding(const MemRegion *lazyBindingRegion, + Store lazyBindingStore) { + if (const ElementRegion *ER = dyn_cast(lazyBindingRegion)) + return RetrieveElement(lazyBindingStore, ER); + + return RetrieveField(lazyBindingStore, + cast(lazyBindingRegion)); +} + SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store, const TypedRegion *R, QualType Ty, @@ -1140,14 +1164,10 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store, // Lazy binding? Store lazyBindingStore = NULL; const MemRegion *lazyBindingRegion = NULL; - llvm::tie(lazyBindingStore, lazyBindingRegion) = GetLazyBinding(B, R); + llvm::tie(lazyBindingStore, lazyBindingRegion) = GetLazyBinding(B, R, R); - if (lazyBindingRegion) { - if (const ElementRegion *ER = dyn_cast(lazyBindingRegion)) - return RetrieveElement(lazyBindingStore, ER); - return RetrieveField(lazyBindingStore, - cast(lazyBindingRegion)); - } + if (lazyBindingRegion) + return RetrieveLazyBinding(lazyBindingRegion, lazyBindingStore); if (R->hasStackNonParametersStorage()) { if (const ElementRegion *ER = dyn_cast(R)) { @@ -1250,12 +1270,12 @@ SVal RegionStoreManager::RetrieveLazySymbol(const TypedRegion *R) { SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) { QualType T = R->getValueType(); assert(T->isStructureOrClassType()); - return svalBuilder.makeLazyCompoundVal(store, R); + return svalBuilder.makeLazyCompoundVal(StoreRef(store, *this), R); } SVal RegionStoreManager::RetrieveArray(Store store, const TypedRegion * R) { assert(Ctx.getAsConstantArrayType(R->getValueType())); - return svalBuilder.makeLazyCompoundVal(store, R); + return svalBuilder.makeLazyCompoundVal(StoreRef(store, *this), R); } //===----------------------------------------------------------------------===// @@ -1378,7 +1398,8 @@ StoreRef RegionStoreManager::BindArray(Store store, const TypedRegion* R, // Treat the string as a lazy compound value. nonloc::LazyCompoundVal LCV = - cast(svalBuilder.makeLazyCompoundVal(store, S)); + cast(svalBuilder. + makeLazyCompoundVal(StoreRef(store, *this), S)); return CopyLazyBindings(LCV, store, R); } @@ -1529,7 +1550,7 @@ StoreRef RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V, // Now copy the bindings. This amounts to just binding 'V' to 'R'. This // results in a zero-copy algorithm. - return StoreRef(addBinding(B, R, BindingKey::Direct, + return StoreRef(addBinding(B, R, BindingKey::Default, V).getRootWithoutRetain(), *this); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index b0fd497e5719..71f2b4abb9c3 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -25,12 +25,12 @@ using namespace ento; // Basic SVal creation. //===----------------------------------------------------------------------===// -DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType T) { - if (Loc::isLocType(T)) +DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) { + if (Loc::isLocType(type)) return makeNull(); - if (T->isIntegerType()) - return makeIntVal(0, T); + if (type->isIntegerType()) + return makeIntVal(0, type); // FIXME: Handle floats. // FIXME: Handle structs. @@ -39,44 +39,44 @@ DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType T) { NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt& v, QualType T) { + const llvm::APSInt& rhs, QualType type) { // The Environment ensures we always get a persistent APSInt in // BasicValueFactory, so we don't need to get the APSInt from // BasicValueFactory again. - assert(!Loc::isLocType(T)); - return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T)); + assert(!Loc::isLocType(type)); + return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, rhs, type)); } NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, - const SymExpr *rhs, QualType T) { + const SymExpr *rhs, QualType type) { assert(SymMgr.getType(lhs) == SymMgr.getType(rhs)); - assert(!Loc::isLocType(T)); - return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T)); + assert(!Loc::isLocType(type)); + return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, type)); } -SVal SValBuilder::convertToArrayIndex(SVal V) { - if (V.isUnknownOrUndef()) - return V; +SVal SValBuilder::convertToArrayIndex(SVal val) { + if (val.isUnknownOrUndef()) + return val; // Common case: we have an appropriately sized integer. - if (nonloc::ConcreteInt* CI = dyn_cast(&V)) { + if (nonloc::ConcreteInt* CI = dyn_cast(&val)) { const llvm::APSInt& I = CI->getValue(); if (I.getBitWidth() == ArrayIndexWidth && I.isSigned()) - return V; + return val; } - return evalCastNL(cast(V), ArrayIndexTy); + return evalCastFromNonLoc(cast(val), ArrayIndexTy); } DefinedOrUnknownSVal -SValBuilder::getRegionValueSymbolVal(const TypedRegion* R) { - QualType T = R->getValueType(); +SValBuilder::getRegionValueSymbolVal(const TypedRegion* region) { + QualType T = region->getValueType(); if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); - SymbolRef sym = SymMgr.getRegionValueSymbol(R); + SymbolRef sym = SymMgr.getRegionValueSymbol(region); if (Loc::isLocType(T)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); @@ -84,15 +84,15 @@ SValBuilder::getRegionValueSymbolVal(const TypedRegion* R) { return nonloc::SymbolVal(sym); } -DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *SymbolTag, - const Expr *E, - unsigned Count) { - QualType T = E->getType(); +DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *symbolTag, + const Expr *expr, + unsigned count) { + QualType T = expr->getType(); if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); - SymbolRef sym = SymMgr.getConjuredSymbol(E, Count, SymbolTag); + SymbolRef sym = SymMgr.getConjuredSymbol(expr, count, symbolTag); if (Loc::isLocType(T)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); @@ -100,31 +100,32 @@ DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *SymbolTag, return nonloc::SymbolVal(sym); } -DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *SymbolTag, - const Expr *E, - QualType T, - unsigned Count) { +DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *symbolTag, + const Expr *expr, + QualType type, + unsigned count) { - if (!SymbolManager::canSymbolicate(T)) + if (!SymbolManager::canSymbolicate(type)) return UnknownVal(); - SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count, SymbolTag); + SymbolRef sym = SymMgr.getConjuredSymbol(expr, type, count, symbolTag); - if (Loc::isLocType(T)) + if (Loc::isLocType(type)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); return nonloc::SymbolVal(sym); } -DefinedSVal SValBuilder::getMetadataSymbolVal(const void *SymbolTag, - const MemRegion *MR, - const Expr *E, QualType T, - unsigned Count) { - assert(SymbolManager::canSymbolicate(T) && "Invalid metadata symbol type"); +DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag, + const MemRegion *region, + const Expr *expr, QualType type, + unsigned count) { + assert(SymbolManager::canSymbolicate(type) && "Invalid metadata symbol type"); - SymbolRef sym = SymMgr.getMetadataSymbol(MR, E, T, Count, SymbolTag); + SymbolRef sym = + SymMgr.getMetadataSymbol(region, expr, type, count, symbolTag); - if (Loc::isLocType(T)) + if (Loc::isLocType(type)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); return nonloc::SymbolVal(sym); @@ -132,13 +133,13 @@ DefinedSVal SValBuilder::getMetadataSymbolVal(const void *SymbolTag, DefinedOrUnknownSVal SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, - const TypedRegion *R) { - QualType T = R->getValueType(); + const TypedRegion *region) { + QualType T = region->getValueType(); if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); - SymbolRef sym = SymMgr.getDerivedSymbol(parentSymbol, R); + SymbolRef sym = SymMgr.getDerivedSymbol(parentSymbol, region); if (Loc::isLocType(T)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); @@ -146,53 +147,53 @@ SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, return nonloc::SymbolVal(sym); } -DefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl* FD) { - return loc::MemRegionVal(MemMgr.getFunctionTextRegion(FD)); +DefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl* func) { + return loc::MemRegionVal(MemMgr.getFunctionTextRegion(func)); } -DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *D, - CanQualType locTy, - const LocationContext *LC) { +DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block, + CanQualType locTy, + const LocationContext *locContext) { const BlockTextRegion *BC = - MemMgr.getBlockTextRegion(D, locTy, LC->getAnalysisContext()); - const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, LC); + MemMgr.getBlockTextRegion(block, locTy, locContext->getAnalysisContext()); + const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, locContext); return loc::MemRegionVal(BD); } //===----------------------------------------------------------------------===// -SVal SValBuilder::evalBinOp(const GRState *ST, BinaryOperator::Opcode Op, - SVal L, SVal R, QualType T) { +SVal SValBuilder::evalBinOp(const GRState *state, BinaryOperator::Opcode op, + SVal lhs, SVal rhs, QualType type) { - if (L.isUndef() || R.isUndef()) + if (lhs.isUndef() || rhs.isUndef()) return UndefinedVal(); - if (L.isUnknown() || R.isUnknown()) + if (lhs.isUnknown() || rhs.isUnknown()) return UnknownVal(); - if (isa(L)) { - if (isa(R)) - return evalBinOpLL(ST, Op, cast(L), cast(R), T); + if (isa(lhs)) { + if (isa(rhs)) + return evalBinOpLL(state, op, cast(lhs), cast(rhs), type); - return evalBinOpLN(ST, Op, cast(L), cast(R), T); + return evalBinOpLN(state, op, cast(lhs), cast(rhs), type); } - if (isa(R)) { + if (isa(rhs)) { // Support pointer arithmetic where the addend is on the left // and the pointer on the right. - assert(Op == BO_Add); + assert(op == BO_Add); // Commute the operands. - return evalBinOpLN(ST, Op, cast(R), cast(L), T); + return evalBinOpLN(state, op, cast(rhs), cast(lhs), type); } - return evalBinOpNN(ST, Op, cast(L), cast(R), T); + return evalBinOpNN(state, op, cast(lhs), cast(rhs), type); } -DefinedOrUnknownSVal SValBuilder::evalEQ(const GRState *ST, - DefinedOrUnknownSVal L, - DefinedOrUnknownSVal R) { - return cast(evalBinOp(ST, BO_EQ, L, R, +DefinedOrUnknownSVal SValBuilder::evalEQ(const GRState *state, + DefinedOrUnknownSVal lhs, + DefinedOrUnknownSVal rhs) { + return cast(evalBinOp(state, BO_EQ, lhs, rhs, Context.IntTy)); } @@ -213,11 +214,11 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) { // Check for casts from integers to integers. if (castTy->isIntegerType() && originalTy->isIntegerType()) - return evalCastNL(cast(val), castTy); + return evalCastFromNonLoc(cast(val), castTy); // Check for casts from pointers to integers. if (castTy->isIntegerType() && Loc::isLocType(originalTy)) - return evalCastL(cast(val), castTy); + return evalCastFromLoc(cast(val), castTy); // Check for casts from integers to pointers. if (Loc::isLocType(castTy) && originalTy->isIntegerType()) { @@ -256,7 +257,7 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) { // need the original decayed type. // QualType elemTy = cast(originalTy)->getElementType(); // QualType pointerTy = C.getPointerType(elemTy); - return evalCastL(cast(val), castTy); + return evalCastFromLoc(cast(val), castTy); } // Check for casts from a region to a specific type. @@ -305,6 +306,6 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) { DispatchCast: // All other cases. - return isa(val) ? evalCastL(cast(val), castTy) - : evalCastNL(cast(val), castTy); + return isa(val) ? evalCastFromLoc(cast(val), castTy) + : evalCastFromNonLoc(cast(val), castTy); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp index e0b61ab58009..1ee694ef8a13 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp @@ -15,7 +15,6 @@ #include "SimpleConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" namespace clang { diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 9a46bd6d69a0..5d802511510a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -20,8 +20,8 @@ using namespace ento; namespace { class SimpleSValBuilder : public SValBuilder { protected: - virtual SVal evalCastNL(NonLoc val, QualType castTy); - virtual SVal evalCastL(Loc val, QualType castTy); + virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy); + virtual SVal evalCastFromLoc(Loc val, QualType castTy); public: SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, @@ -57,7 +57,7 @@ SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, // Transfer function for Casts. //===----------------------------------------------------------------------===// -SVal SimpleSValBuilder::evalCastNL(NonLoc val, QualType castTy) { +SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) { bool isLocType = Loc::isLocType(castTy); @@ -106,7 +106,7 @@ SVal SimpleSValBuilder::evalCastNL(NonLoc val, QualType castTy) { return makeIntVal(i); } -SVal SimpleSValBuilder::evalCastL(Loc val, QualType castTy) { +SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) { // Casts from pointers -> pointers, just return the lval. // @@ -255,11 +255,12 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, } // Idempotent ops (like a*1) can still change the type of an expression. - // Wrap the LHS up in a NonLoc again and let evalCastNL do the dirty work. + // Wrap the LHS up in a NonLoc again and let evalCastFromNonLoc do the + // dirty work. if (isIdempotent) { if (SymbolRef LHSSym = dyn_cast(LHS)) - return evalCastNL(nonloc::SymbolVal(LHSSym), resultTy); - return evalCastNL(nonloc::SymExprVal(LHS), resultTy); + return evalCastFromNonLoc(nonloc::SymbolVal(LHSSym), resultTy); + return evalCastFromNonLoc(nonloc::SymExprVal(LHS), resultTy); } // If we reach this point, the expression cannot be simplified. @@ -289,7 +290,7 @@ SVal SimpleSValBuilder::evalBinOpNN(const GRState *state, return makeIntVal(0, resultTy); case BO_Or: case BO_And: - return evalCastNL(lhs, resultTy); + return evalCastFromNonLoc(lhs, resultTy); } while (1) { @@ -552,7 +553,7 @@ SVal SimpleSValBuilder::evalBinOpLL(const GRState *state, default: break; case BO_Sub: - return evalCastL(lhs, resultTy); + return evalCastFromLoc(lhs, resultTy); case BO_EQ: case BO_LE: case BO_LT: @@ -588,7 +589,7 @@ SVal SimpleSValBuilder::evalBinOpLL(const GRState *state, SVal ResultVal = cast(lhs).evalBinOp(BasicVals, op, *rInt); if (Loc *Result = dyn_cast(&ResultVal)) - return evalCastL(*Result, resultTy); + return evalCastFromLoc(*Result, resultTy); else return UnknownVal(); } @@ -633,7 +634,7 @@ SVal SimpleSValBuilder::evalBinOpLL(const GRState *state, default: break; case BO_Sub: - return evalCastL(lhs, resultTy); + return evalCastFromLoc(lhs, resultTy); case BO_EQ: case BO_LT: case BO_LE: @@ -698,7 +699,7 @@ SVal SimpleSValBuilder::evalBinOpLL(const GRState *state, NonLoc *LeftIndex = dyn_cast(&LeftIndexVal); if (!LeftIndex) return UnknownVal(); - LeftIndexVal = evalCastNL(*LeftIndex, resultTy); + LeftIndexVal = evalCastFromNonLoc(*LeftIndex, resultTy); LeftIndex = dyn_cast(&LeftIndexVal); if (!LeftIndex) return UnknownVal(); @@ -708,7 +709,7 @@ SVal SimpleSValBuilder::evalBinOpLL(const GRState *state, NonLoc *RightIndex = dyn_cast(&RightIndexVal); if (!RightIndex) return UnknownVal(); - RightIndexVal = evalCastNL(*RightIndex, resultTy); + RightIndexVal = evalCastFromNonLoc(*RightIndex, resultTy); RightIndex = dyn_cast(&RightIndexVal); if (!RightIndex) return UnknownVal(); @@ -872,7 +873,8 @@ SVal SimpleSValBuilder::evalBinOpLN(const GRState *state, QualType elementType; if (const ElementRegion *elemReg = dyn_cast(region)) { - index = evalBinOpNN(state, BO_Add, elemReg->getIndex(), rhs, + assert(op == BO_Add || op == BO_Sub); + index = evalBinOpNN(state, op, elemReg->getIndex(), rhs, getArrayIndexType()); superR = elemReg->getSuperRegion(); elementType = elemReg->getElementType(); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp index 722517097c73..b936738009ec 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp @@ -230,9 +230,9 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedRegion *R, } if (const Loc *L = dyn_cast(&V)) - return svalBuilder.evalCastL(*L, castTy); + return svalBuilder.evalCastFromLoc(*L, castTy); else if (const NonLoc *NL = dyn_cast(&V)) - return svalBuilder.evalCastNL(*NL, castTy); + return svalBuilder.evalCastFromNonLoc(*NL, castTy); return V; } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index e3e7ee957a6f..fe6e1fd6bbd2 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -17,8 +17,6 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ParentMap.h" -#include "clang/Analysis/Analyses/LiveVariables.h" -#include "clang/Analysis/Analyses/UninitializedValues.h" #include "clang/Analysis/CFG.h" #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" @@ -30,12 +28,6 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h" #include "clang/StaticAnalyzer/Core/PathDiagnosticClients.h" -// FIXME: Restructure checker registration. -#include "../Checkers/ClangSACheckers.h" -#include "../Checkers/ExperimentalChecks.h" -#include "../Checkers/InternalChecks.h" -#include "../Checkers/BasicObjCFoundationChecks.h" - #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/AnalyzerOptions.h" @@ -69,20 +61,6 @@ createPlistHTMLDiagnosticClient(const std::string& prefix, namespace { class AnalysisConsumer : public ASTConsumer { -public: - typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D); - typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M, - TranslationUnitDecl &TU); - -private: - typedef std::vector Actions; - typedef std::vector TUActions; - - Actions FunctionActions; - Actions ObjCMethodActions; - Actions ObjCImplementationActions; - Actions CXXMethodActions; - public: ASTContext* Ctx; const Preprocessor &PP; @@ -163,16 +141,6 @@ class AnalysisConsumer : public ASTConsumer { } } - void addCodeAction(CodeAction action) { - FunctionActions.push_back(action); - ObjCMethodActions.push_back(action); - CXXMethodActions.push_back(action); - } - - void addObjCImplementationAction(CodeAction action) { - ObjCImplementationActions.push_back(action); - } - virtual void Initialize(ASTContext &Context) { Ctx = &Context; checkerMgr.reset(registerCheckers(Opts, PP.getLangOptions(), @@ -194,7 +162,7 @@ class AnalysisConsumer : public ASTConsumer { virtual void HandleTranslationUnit(ASTContext &C); void HandleDeclContext(ASTContext &C, DeclContext *dc); - void HandleCode(Decl *D, Actions& actions); + void HandleCode(Decl *D); }; } // end anonymous namespace @@ -228,23 +196,25 @@ void AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) { FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction) break; DisplayFunction(FD); - HandleCode(FD, FunctionActions); + HandleCode(FD); } break; } case Decl::ObjCImplementation: { ObjCImplementationDecl* ID = cast(*I); - HandleCode(ID, ObjCImplementationActions); + HandleCode(ID); for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(), ME = ID->meth_end(); MI != ME; ++MI) { + checkerMgr->runCheckersOnASTDecl(*MI, *Mgr, BR); + if ((*MI)->isThisDeclarationADefinition()) { if (!Opts.AnalyzeSpecificFunction.empty() && Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString()) break; DisplayFunction(*MI); - HandleCode(*MI, ObjCMethodActions); + HandleCode(*MI); } } break; @@ -279,9 +249,12 @@ static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl &WL) { FindBlocks(DC, WL); } -void AnalysisConsumer::HandleCode(Decl *D, Actions& actions) { +static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr, + Decl *D); - // Don't run the actions if an error has occured with parsing the file. +void AnalysisConsumer::HandleCode(Decl *D) { + + // Don't run the actions if an error has occurred with parsing the file. Diagnostic &Diags = PP.getDiagnostics(); if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) return; @@ -306,27 +279,17 @@ void AnalysisConsumer::HandleCode(Decl *D, Actions& actions) { BugReporter BR(*Mgr); for (llvm::SmallVectorImpl::iterator WI=WL.begin(), WE=WL.end(); WI != WE; ++WI) - if ((*WI)->hasBody()) + if ((*WI)->hasBody()) { checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR); - - for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I) - for (llvm::SmallVectorImpl::iterator WI=WL.begin(), WE=WL.end(); - WI != WE; ++WI) - (*I)(*this, *Mgr, *WI); + if (checkerMgr->hasPathSensitiveCheckers()) + ActionObjCMemChecker(*this, *Mgr, *WI); + } } //===----------------------------------------------------------------------===// -// Analyses +// Path-sensitive checking. //===----------------------------------------------------------------------===// -static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D) { - if (CFG* c = mgr.getCFG(D)) { - CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic()); - } -} - - static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D, TransferFuncs* tf) { @@ -340,18 +303,6 @@ static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, return; ExprEngine Eng(mgr, TF.take()); - RegisterNSErrorChecks(Eng.getBugReporter(), Eng, *D); - - if (C.Opts.EnableExperimentalChecks) - RegisterExperimentalChecks(Eng); - - if (C.Opts.BufferOverflows) - RegisterArrayBoundCheckerV2(Eng); - - // Enable AnalyzerStatsChecker if it was given as an argument - if (C.Opts.AnalyzerStats) - RegisterAnalyzerStatsChecker(Eng); - // Set the graph auditor. llvm::OwningPtr Auditor; if (mgr.shouldVisualizeUbigraph()) { @@ -414,16 +365,6 @@ ASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp, const AnalyzerOptions& Opts) { llvm::OwningPtr C(new AnalysisConsumer(pp, OutDir, Opts)); - for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i) - switch (Opts.AnalysisList[i]) { -#define ANALYSIS(NAME, CMD, DESC, SCOPE)\ - case NAME:\ - C->add ## SCOPE ## Action(&Action ## NAME);\ - break; -#include "clang/Frontend/Analyses.def" - default: break; - } - // Last, disable the effects of '-Werror' when using the AnalysisConsumer. pp.getDiagnostics().setWarningsAsErrors(false); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index 677e20cd9c0e..d7edc7e599df 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp @@ -43,6 +43,8 @@ CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts, // FIXME: Load CheckerProviders from plugins. + checkerMgr->finishedCheckerRegistration(); + for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { if (checkerOpts[i].isUnclaimed()) diags.Report(diag::warn_unkwown_analyzer_checker) @@ -55,9 +57,6 @@ CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts, void ento::printCheckerHelp(llvm::raw_ostream &OS) { OS << "OVERVIEW: Clang Static Analyzer Checkers List\n"; OS << '\n'; - OS << "USAGE: -analyzer-checker \n"; - OS << '\n'; - OS << "CHECKERS:\n"; llvm::OwningPtr provider(createClangSACheckerProvider()); provider->printHelp(OS); diff --git a/contrib/llvm/tools/clang/lib/Tooling/CMakeLists.txt b/contrib/llvm/tools/clang/lib/Tooling/CMakeLists.txt new file mode 100644 index 000000000000..f52cf6c8917f --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Tooling/CMakeLists.txt @@ -0,0 +1,6 @@ +SET(LLVM_USED_LIBS clangBasic clangFrontend clangAST) + +add_clang_library(clangTooling + JsonCompileCommandLineDatabase.cpp + Tooling.cpp + ) diff --git a/contrib/llvm/tools/clang/lib/Tooling/JsonCompileCommandLineDatabase.cpp b/contrib/llvm/tools/clang/lib/Tooling/JsonCompileCommandLineDatabase.cpp new file mode 100644 index 000000000000..7f027cfbead4 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Tooling/JsonCompileCommandLineDatabase.cpp @@ -0,0 +1,214 @@ +//===--- JsonCompileCommandLineDatabase.cpp - Simple JSON database --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements reading a compile command line database, as written +// out for example by CMake. +// +//===----------------------------------------------------------------------===// + +#include "JsonCompileCommandLineDatabase.h" +#include "llvm/ADT/Twine.h" + +namespace clang { +namespace tooling { + +namespace { + +// A parser for JSON escaped strings of command line arguments with \-escaping +// for quoted arguments (see the documentation of UnescapeJsonCommandLine(...)). +class CommandLineArgumentParser { + public: + CommandLineArgumentParser(llvm::StringRef CommandLine) + : Input(CommandLine), Position(Input.begin()-1) {} + + std::vector Parse() { + bool HasMoreInput = true; + while (HasMoreInput && NextNonWhitespace()) { + std::string Argument; + HasMoreInput = ParseStringInto(Argument); + CommandLine.push_back(Argument); + } + return CommandLine; + } + + private: + // All private methods return true if there is more input available. + + bool ParseStringInto(std::string &String) { + do { + if (*Position == '"') { + if (!ParseQuotedStringInto(String)) return false; + } else { + if (!ParseFreeStringInto(String)) return false; + } + } while (*Position != ' '); + return true; + } + + bool ParseQuotedStringInto(std::string &String) { + if (!Next()) return false; + while (*Position != '"') { + if (!SkipEscapeCharacter()) return false; + String.push_back(*Position); + if (!Next()) return false; + } + return Next(); + } + + bool ParseFreeStringInto(std::string &String) { + do { + if (!SkipEscapeCharacter()) return false; + String.push_back(*Position); + if (!Next()) return false; + } while (*Position != ' ' && *Position != '"'); + return true; + } + + bool SkipEscapeCharacter() { + if (*Position == '\\') { + return Next(); + } + return true; + } + + bool NextNonWhitespace() { + do { + if (!Next()) return false; + } while (*Position == ' '); + return true; + } + + bool Next() { + ++Position; + if (Position == Input.end()) return false; + // Remove the JSON escaping first. This is done unconditionally. + if (*Position == '\\') ++Position; + return Position != Input.end(); + } + + const llvm::StringRef Input; + llvm::StringRef::iterator Position; + std::vector CommandLine; +}; + +} // end namespace + +std::vector UnescapeJsonCommandLine( + llvm::StringRef JsonEscapedCommandLine) { + CommandLineArgumentParser parser(JsonEscapedCommandLine); + return parser.Parse(); +} + +JsonCompileCommandLineParser::JsonCompileCommandLineParser( + const llvm::StringRef Input, CompileCommandHandler *CommandHandler) + : Input(Input), Position(Input.begin()-1), CommandHandler(CommandHandler) {} + +bool JsonCompileCommandLineParser::Parse() { + NextNonWhitespace(); + return ParseTranslationUnits(); +} + +std::string JsonCompileCommandLineParser::GetErrorMessage() const { + return ErrorMessage; +} + +bool JsonCompileCommandLineParser::ParseTranslationUnits() { + if (!ConsumeOrError('[', "at start of compile command file")) return false; + if (!ParseTranslationUnit(/*First=*/true)) return false; + while (Consume(',')) { + if (!ParseTranslationUnit(/*First=*/false)) return false; + } + if (!ConsumeOrError(']', "at end of array")) return false; + if (CommandHandler != NULL) { + CommandHandler->EndTranslationUnits(); + } + return true; +} + +bool JsonCompileCommandLineParser::ParseTranslationUnit(bool First) { + if (First) { + if (!Consume('{')) return true; + } else { + if (!ConsumeOrError('{', "at start of object")) return false; + } + if (!Consume('}')) { + if (!ParseObjectKeyValuePairs()) return false; + if (!ConsumeOrError('}', "at end of object")) return false; + } + if (CommandHandler != NULL) { + CommandHandler->EndTranslationUnit(); + } + return true; +} + +bool JsonCompileCommandLineParser::ParseObjectKeyValuePairs() { + do { + llvm::StringRef Key; + if (!ParseString(Key)) return false; + if (!ConsumeOrError(':', "between name and value")) return false; + llvm::StringRef Value; + if (!ParseString(Value)) return false; + if (CommandHandler != NULL) { + CommandHandler->HandleKeyValue(Key, Value); + } + } while (Consume(',')); + return true; +} + +bool JsonCompileCommandLineParser::ParseString(llvm::StringRef &String) { + if (!ConsumeOrError('"', "at start of string")) return false; + llvm::StringRef::iterator First = Position; + llvm::StringRef::iterator Last = Position; + while (!Consume('"')) { + Consume('\\'); + ++Position; + // We need to store Position, as Consume will change Last before leaving + // the loop. + Last = Position; + } + String = llvm::StringRef(First, Last - First); + return true; +} + +bool JsonCompileCommandLineParser::Consume(char C) { + if (Position == Input.end()) return false; + if (*Position != C) return false; + NextNonWhitespace(); + return true; +} + +bool JsonCompileCommandLineParser::ConsumeOrError( + char C, llvm::StringRef Message) { + if (!Consume(C)) { + SetExpectError(C, Message); + return false; + } + return true; +} + +void JsonCompileCommandLineParser::SetExpectError( + char C, llvm::StringRef Message) { + ErrorMessage = (llvm::Twine("'") + llvm::StringRef(&C, 1) + + "' expected " + Message + ".").str(); +} + +void JsonCompileCommandLineParser::NextNonWhitespace() { + do { + ++Position; + } while (IsWhitespace()); +} + +bool JsonCompileCommandLineParser::IsWhitespace() { + if (Position == Input.end()) return false; + return (*Position == ' ' || *Position == '\t' || + *Position == '\n' || *Position == '\r'); +} + +} // end namespace tooling +} // end namespace clang diff --git a/contrib/llvm/tools/clang/lib/Tooling/JsonCompileCommandLineDatabase.h b/contrib/llvm/tools/clang/lib/Tooling/JsonCompileCommandLineDatabase.h new file mode 100644 index 000000000000..9e776d60010d --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Tooling/JsonCompileCommandLineDatabase.h @@ -0,0 +1,107 @@ +//===--- JsonCompileCommandLineDatabase - Simple JSON database --*- 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 reading a compile command line database, as written +// out for example by CMake. It only supports the subset of the JSON standard +// that is needed to parse the CMake output. +// See http://www.json.org/ for the full standard. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_JSON_COMPILE_COMMAND_LINE_DATABASE_H +#define LLVM_CLANG_TOOLING_JSON_COMPILE_COMMAND_LINE_DATABASE_H + +#include "llvm/ADT/StringRef.h" +#include +#include + +namespace clang { +namespace tooling { + +/// \brief Converts a JSON escaped command line to a vector of arguments. +/// +/// \param JsonEscapedCommandLine The escaped command line as a string. This +/// is assumed to be escaped as a JSON string (e.g. " and \ are escaped). +/// In addition, any arguments containing spaces are assumed to be \-escaped +/// +/// For example, the input (|| denoting non C-escaped strings): +/// |./call a \"b \\\" c \\\\ \" d| +/// would yield: +/// [ |./call|, |a|, |b " c \ |, |d| ]. +std::vector UnescapeJsonCommandLine( + llvm::StringRef JsonEscapedCommandLine); + +/// \brief Interface for users of the JsonCompileCommandLineParser. +class CompileCommandHandler { + public: + virtual ~CompileCommandHandler() {} + + /// \brief Called after all translation units are parsed. + virtual void EndTranslationUnits() {} + + /// \brief Called at the end of a single translation unit. + virtual void EndTranslationUnit() {} + + /// \brief Called for every (Key, Value) pair in a translation unit + /// description. + virtual void HandleKeyValue(llvm::StringRef Key, llvm::StringRef Value) {} +}; + +/// \brief A JSON parser that supports the subset of JSON needed to parse +/// JSON compile command line databases as written out by CMake. +/// +/// The supported subset describes a list of compile command lines for +/// each processed translation unit. The translation units are stored in a +/// JSON array, where each translation unit is described by a JSON object +/// containing (Key, Value) pairs for the working directory the compile command +/// line was executed from, the main C/C++ input file of the translation unit +/// and the actual compile command line, for example: +/// [ +/// { +/// "file":"/file.cpp", +/// "directory":"/", +/// "command":"/cc /file.cpp" +/// } +/// ] +class JsonCompileCommandLineParser { + public: + /// \brief Create a parser on 'Input', calling 'CommandHandler' to handle the + /// parsed constructs. 'CommandHandler' may be NULL in order to just check + /// the validity of 'Input'. + JsonCompileCommandLineParser(const llvm::StringRef Input, + CompileCommandHandler *CommandHandler); + + /// \brief Parses the specified input. Returns true if no parsing errors were + /// foudn. + bool Parse(); + + /// \brief Returns an error message if Parse() returned false previously. + std::string GetErrorMessage() const; + + private: + bool ParseTranslationUnits(); + bool ParseTranslationUnit(bool First); + bool ParseObjectKeyValuePairs(); + bool ParseString(llvm::StringRef &String); + bool Consume(char C); + bool ConsumeOrError(char C, llvm::StringRef Message); + void NextNonWhitespace(); + bool IsWhitespace(); + void SetExpectError(char C, llvm::StringRef Message); + + const llvm::StringRef Input; + llvm::StringRef::iterator Position; + std::string ErrorMessage; + CompileCommandHandler * const CommandHandler; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_JSON_COMPILE_COMMAND_LINE_DATABASE_H diff --git a/contrib/llvm/tools/clang/lib/Tooling/Makefile b/contrib/llvm/tools/clang/lib/Tooling/Makefile new file mode 100644 index 000000000000..501a00c3f4f4 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Tooling/Makefile @@ -0,0 +1,15 @@ +##===- clang/lib/Tooling/Makefile ---------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +CLANG_LEVEL := ../.. +LIBRARYNAME := clangTooling + +include $(CLANG_LEVEL)/Makefile + + diff --git a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp new file mode 100644 index 000000000000..c1714a9be715 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp @@ -0,0 +1,322 @@ +//===--- Tooling.cpp - Running clang standalone tools --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements functions to run clang tools standalone instead +// of running them as a plugin. +// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Tool.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "JsonCompileCommandLineDatabase.h" +#include +#include + +namespace clang { +namespace tooling { + +namespace { + +// Checks that the input conforms to the argv[] convention as in +// main(). Namely: +// - it must contain at least a program path, +// - argv[0], ..., and argv[argc - 1] mustn't be NULL, and +// - argv[argc] must be NULL. +void ValidateArgv(int argc, char* argv[]) { + if (argc < 1) { + fprintf(stderr, "ERROR: argc is %d. It must be >= 1.\n", argc); + abort(); + } + + for (int i = 0; i < argc; ++i) { + if (argv[i] == NULL) { + fprintf(stderr, "ERROR: argv[%d] is NULL.\n", i); + abort(); + } + } + + if (argv[argc] != NULL) { + fprintf(stderr, "ERROR: argv[argc] isn't NULL.\n"); + abort(); + } +} + +} // end namespace + +// FIXME: This file contains structural duplication with other parts of the +// code that sets up a compiler to run tools on it, and we should refactor +// it to be based on the same framework. + +static clang::Diagnostic* NewTextDiagnostics() { + llvm::IntrusiveRefCntPtr DiagIDs( + new clang::DiagnosticIDs()); + clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter( + llvm::errs(), clang::DiagnosticOptions()); + return new clang::Diagnostic(DiagIDs, DiagClient); +} + +// Exists solely for the purpose of lookup of the main executable. +static int StaticSymbol; + +/// \brief Builds a clang driver initialized for running clang tools. +static clang::driver::Driver* NewDriver(clang::Diagnostic* Diagnostics, + const char* BinaryName) { + // This just needs to be some symbol in the binary. + void* const SymbolAddr = &StaticSymbol; + const llvm::sys::Path ExePath = + llvm::sys::Path::GetMainExecutable(BinaryName, SymbolAddr); + + const std::string DefaultOutputName = "a.out"; + clang::driver::Driver* CompilerDriver = new clang::driver::Driver( + ExePath.str(), llvm::sys::getHostTriple(), + DefaultOutputName, false, false, *Diagnostics); + CompilerDriver->setTitle("clang_based_tool"); + return CompilerDriver; +} + +/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs. +/// Returns NULL on error. +static const clang::driver::ArgStringList* GetCC1Arguments( + clang::Diagnostic* Diagnostics, clang::driver::Compilation* Compilation) { + // We expect to get back exactly one Command job, if we didn't something + // failed. Extract that job from the Compilation. + const clang::driver::JobList &Jobs = Compilation->getJobs(); + if (Jobs.size() != 1 || !isa(*Jobs.begin())) { + llvm::SmallString<256> error_msg; + llvm::raw_svector_ostream error_stream(error_msg); + Compilation->PrintJob(error_stream, Compilation->getJobs(), "; ", true); + Diagnostics->Report(clang::diag::err_fe_expected_compiler_job) + << error_stream.str(); + return NULL; + } + + // The one job we find should be to invoke clang again. + const clang::driver::Command *Cmd = + cast(*Jobs.begin()); + if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { + Diagnostics->Report(clang::diag::err_fe_expected_clang_command); + return NULL; + } + + return &Cmd->getArguments(); +} + +/// \brief Returns a clang build invocation initialized from the CC1 flags. +static clang::CompilerInvocation* NewInvocation( + clang::Diagnostic* Diagnostics, + const clang::driver::ArgStringList& CC1Args) { + clang::CompilerInvocation* Invocation = new clang::CompilerInvocation; + clang::CompilerInvocation::CreateFromArgs( + *Invocation, CC1Args.data(), CC1Args.data() + CC1Args.size(), + *Diagnostics); + Invocation->getFrontendOpts().DisableFree = false; + return Invocation; +} + +/// \brief Runs the specified clang tool action and returns whether it executed +/// successfully. +static bool RunInvocation(const char* BinaryName, + clang::driver::Compilation* Compilation, + clang::CompilerInvocation* Invocation, + const clang::driver::ArgStringList& CC1Args, + clang::FrontendAction* ToolAction) { + llvm::OwningPtr ScopedToolAction(ToolAction); + // Show the invocation, with -v. + if (Invocation->getHeaderSearchOpts().Verbose) { + llvm::errs() << "clang Invocation:\n"; + Compilation->PrintJob(llvm::errs(), Compilation->getJobs(), "\n", true); + llvm::errs() << "\n"; + } + + // Create a compiler instance to handle the actual work. + clang::CompilerInstance Compiler; + Compiler.setInvocation(Invocation); + + // Create the compilers actual diagnostics engine. + Compiler.createDiagnostics(CC1Args.size(), + const_cast(CC1Args.data())); + if (!Compiler.hasDiagnostics()) + return false; + + // Infer the builtin include path if unspecified. + if (Compiler.getHeaderSearchOpts().UseBuiltinIncludes && + Compiler.getHeaderSearchOpts().ResourceDir.empty()) { + // This just needs to be some symbol in the binary. + void* const SymbolAddr = &StaticSymbol; + Compiler.getHeaderSearchOpts().ResourceDir = + clang::CompilerInvocation::GetResourcesPath(BinaryName, SymbolAddr); + } + + const bool Success = Compiler.ExecuteAction(*ToolAction); + return Success; +} + +/// \brief Converts a string vector representing a Command line into a C +/// string vector representing the Argv (including the trailing NULL). +std::vector CommandLineToArgv(const std::vector* Command) { + std::vector Result(Command->size() + 1); + for (std::vector::size_type I = 0; I < Command->size(); ++I) { + Result[I] = const_cast((*Command)[I].c_str()); + } + Result[Command->size()] = NULL; + return Result; +} + +bool RunToolWithFlags( + clang::FrontendAction* ToolAction, int Args, char* Argv[]) { + ValidateArgv(Args, Argv); + const llvm::OwningPtr Diagnostics(NewTextDiagnostics()); + const llvm::OwningPtr Driver( + NewDriver(Diagnostics.get(), Argv[0])); + const llvm::OwningPtr Compilation( + Driver->BuildCompilation(llvm::ArrayRef(Argv, Args))); + const clang::driver::ArgStringList* const CC1Args = GetCC1Arguments( + Diagnostics.get(), Compilation.get()); + if (CC1Args == NULL) { + return false; + } + llvm::OwningPtr Invocation( + NewInvocation(Diagnostics.get(), *CC1Args)); + return RunInvocation(Argv[0], Compilation.get(), Invocation.take(), + *CC1Args, ToolAction); +} + +/// \brief Runs 'ToolAction' on the code specified by 'FileContents'. +/// +/// \param FileContents A mapping from file name to source code. For each +/// entry a virtual file mapping will be created when running the tool. +bool RunToolWithFlagsOnCode( + const std::vector& CommandLine, + const std::map& FileContents, + clang::FrontendAction* ToolAction) { + const std::vector Argv = CommandLineToArgv(&CommandLine); + const char* const BinaryName = Argv[0]; + + const llvm::OwningPtr Diagnostics(NewTextDiagnostics()); + const llvm::OwningPtr Driver( + NewDriver(Diagnostics.get(), BinaryName)); + + // Since the Input is only virtual, don't check whether it exists. + Driver->setCheckInputsExist(false); + + const llvm::OwningPtr Compilation( + Driver->BuildCompilation(llvm::ArrayRef(&Argv[0], + Argv.size() - 1))); + const clang::driver::ArgStringList* const CC1Args = GetCC1Arguments( + Diagnostics.get(), Compilation.get()); + if (CC1Args == NULL) { + return false; + } + llvm::OwningPtr Invocation( + NewInvocation(Diagnostics.get(), *CC1Args)); + + for (std::map::const_iterator + It = FileContents.begin(), End = FileContents.end(); + It != End; ++It) { + // Inject the code as the given file name into the preprocessor options. + const llvm::MemoryBuffer* Input = + llvm::MemoryBuffer::getMemBuffer(It->second.c_str()); + Invocation->getPreprocessorOpts().addRemappedFile(It->first.c_str(), Input); + } + + return RunInvocation(BinaryName, Compilation.get(), + Invocation.take(), *CC1Args, ToolAction); +} + +bool RunSyntaxOnlyToolOnCode( + clang::FrontendAction *ToolAction, llvm::StringRef Code) { + const char* const FileName = "input.cc"; + const char* const CommandLine[] = { + "clang-tool", "-fsyntax-only", FileName + }; + std::map FileContents; + FileContents[FileName] = Code; + return RunToolWithFlagsOnCode( + std::vector( + CommandLine, + CommandLine + sizeof(CommandLine)/sizeof(CommandLine[0])), + FileContents, ToolAction); +} + +namespace { + +// A CompileCommandHandler implementation that finds compile commands for a +// specific input file. +// +// FIXME: Implement early exit when JsonCompileCommandLineParser supports it. +class FindHandler : public clang::tooling::CompileCommandHandler { + public: + explicit FindHandler(llvm::StringRef File) + : FileToMatch(File), FoundMatchingCommand(false) {} + + virtual void EndTranslationUnits() { + if (!FoundMatchingCommand && ErrorMessage.empty()) { + ErrorMessage = "ERROR: No matching command found."; + } + } + + virtual void EndTranslationUnit() { + if (File == FileToMatch) { + FoundMatchingCommand = true; + MatchingCommand.Directory = Directory; + MatchingCommand.CommandLine = UnescapeJsonCommandLine(Command); + } + } + + virtual void HandleKeyValue(llvm::StringRef Key, llvm::StringRef Value) { + if (Key == "directory") { Directory = Value; } + else if (Key == "file") { File = Value; } + else if (Key == "command") { Command = Value; } + else { + ErrorMessage = (llvm::Twine("Unknown key: \"") + Key + "\"").str(); + } + } + + const llvm::StringRef FileToMatch; + bool FoundMatchingCommand; + CompileCommand MatchingCommand; + std::string ErrorMessage; + + llvm::StringRef Directory; + llvm::StringRef File; + llvm::StringRef Command; +}; + +} // end namespace + +CompileCommand FindCompileArgsInJsonDatabase( + llvm::StringRef FileName, llvm::StringRef JsonDatabase, + std::string &ErrorMessage) { + FindHandler find_handler(FileName); + JsonCompileCommandLineParser parser(JsonDatabase, &find_handler); + if (!parser.Parse()) { + ErrorMessage = parser.GetErrorMessage(); + return CompileCommand(); + } + return find_handler.MatchingCommand; +} + +} // end namespace tooling +} // end namespace clang + diff --git a/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp b/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp index 7fb394fa5b01..535eaa9c96f8 100644 --- a/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp +++ b/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp @@ -168,7 +168,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd, // When running with -disable-free, don't do any destruction or shutdown. if (Clang->getFrontendOpts().DisableFree) { - if (Clang->getFrontendOpts().ShowStats) + if (llvm::AreStatisticsEnabled() || Clang->getFrontendOpts().ShowStats) llvm::PrintStatistics(); Clang.take(); return !Success; diff --git a/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp index 1d544f3d3c9d..ec6ce65a9b8b 100644 --- a/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp +++ b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp @@ -71,6 +71,7 @@ struct AssemblerInvocation { std::vector IncludePaths; unsigned NoInitialTextSection : 1; + unsigned SaveTemporaryLabels : 1; /// @} /// @name Frontend Options @@ -156,6 +157,7 @@ void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, // Language Options Opts.IncludePaths = Args->getAllArgValues(OPT_I); Opts.NoInitialTextSection = Args->hasArg(OPT_n); + Opts.SaveTemporaryLabels = Args->hasArg(OPT_L); // Frontend Options if (Args->hasArg(OPT_INPUT)) { @@ -265,6 +267,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) { const TargetAsmInfo *tai = new TargetAsmInfo(*TM); MCContext Ctx(*MAI, tai); + if (Opts.SaveTemporaryLabels) + Ctx.setAllowTemporaryLabels(false); OwningPtr Str; @@ -275,7 +279,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) { // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (Opts.OutputType == AssemblerInvocation::FT_Asm) { MCInstPrinter *IP = - TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI); + TheTarget->createMCInstPrinter(*TM, Opts.OutputAsmVariant, *MAI); MCCodeEmitter *CE = 0; TargetAsmBackend *TAB = 0; if (Opts.ShowEncoding) { @@ -283,7 +287,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) { TAB = TheTarget->createAsmBackend(Opts.Triple); } Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true, - /*useLoc*/ true, IP, CE, TAB, + /*useLoc*/ true, + /*useCFI*/ true, IP, CE, TAB, Opts.ShowInst)); } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { Str.reset(createNullStreamer(Ctx)); diff --git a/contrib/llvm/tools/clang/tools/driver/driver.cpp b/contrib/llvm/tools/clang/tools/driver/driver.cpp index 0b5d2c97a4e7..db72da42ea34 100644 --- a/contrib/llvm/tools/clang/tools/driver/driver.cpp +++ b/contrib/llvm/tools/clang/tools/driver/driver.cpp @@ -18,6 +18,7 @@ #include "clang/Frontend/DiagnosticOptions.h" #include "clang/Frontend/TextDiagnosticPrinter.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/OwningPtr.h" @@ -35,6 +36,8 @@ #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/system_error.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetSelect.h" #include using namespace clang; using namespace clang::driver; @@ -252,6 +255,85 @@ static void ExpandArgv(int argc, const char **argv, } } +static void ParseProgName(llvm::SmallVectorImpl &ArgVector, + std::set &SavedStrings, + Driver &TheDriver) +{ + // Try to infer frontend type and default target from the program name. + + // suffixes[] contains the list of known driver suffixes. + // Suffixes are compared against the program name in order. + // If there is a match, the frontend type is updated as necessary (CPP/C++). + // If there is no match, a second round is done after stripping the last + // hyphen and everything following it. This allows using something like + // "clang++-2.9". + + // If there is a match in either the first or second round, + // the function tries to identify a target as prefix. E.g. + // "x86_64-linux-clang" as interpreted as suffix "clang" with + // target prefix "x86_64-linux". If such a target prefix is found, + // is gets added via -ccc-host-triple as implicit first argument. + static const struct { + const char *Suffix; + bool IsCXX; + bool IsCPP; + } suffixes [] = { + { "clang", false, false }, + { "clang++", true, false }, + { "clang-c++", true, false }, + { "clang-cc", false, false }, + { "clang-cpp", false, true }, + { "clang-g++", true, false }, + { "clang-gcc", false, false }, + { "cc", false, false }, + { "cpp", false, true }, + { "++", true, false }, + }; + std::string ProgName(llvm::sys::path::stem(ArgVector[0])); + llvm::StringRef ProgNameRef(ProgName); + llvm::StringRef Prefix; + + for (int Components = 2; Components; --Components) { + bool FoundMatch = false; + size_t i; + + for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { + if (ProgNameRef.endswith(suffixes[i].Suffix)) { + FoundMatch = true; + if (suffixes[i].IsCXX) + TheDriver.CCCIsCXX = true; + if (suffixes[i].IsCPP) + TheDriver.CCCIsCPP = true; + break; + } + } + + if (FoundMatch) { + llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-', + ProgNameRef.size() - strlen(suffixes[i].Suffix)); + if (LastComponent != llvm::StringRef::npos) + Prefix = ProgNameRef.slice(0, LastComponent); + break; + } + + llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-'); + if (LastComponent == llvm::StringRef::npos) + break; + ProgNameRef = ProgNameRef.slice(0, LastComponent); + } + + if (Prefix.empty()) + return; + + std::string IgnoredError; + if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { + ArgVector.insert(&ArgVector[1], + SaveStringInSet(SavedStrings, Prefix)); + ArgVector.insert(&ArgVector[1], + SaveStringInSet(SavedStrings, std::string("-ccc-host-triple"))); + } +} + int main(int argc_, const char **argv_) { llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc_, argv_); @@ -328,19 +410,8 @@ int main(int argc_, const char **argv_) { TheDriver.setInstalledDir(InstalledPath); } - // Check for ".*++" or ".*++-[^-]*" to determine if we are a C++ - // compiler. This matches things like "c++", "clang++", and "clang++-1.1". - // - // Note that we intentionally want to use argv[0] here, to support "clang++" - // being a symlink. - // - // We use *argv instead of argv[0] to work around a bogus g++ warning. - const char *progname = argv_[0]; - std::string ProgName(llvm::sys::path::stem(progname)); - if (llvm::StringRef(ProgName).endswith("++") || - llvm::StringRef(ProgName).rsplit('-').first.endswith("++")) { - TheDriver.CCCIsCXX = true; - } + llvm::InitializeAllTargets(); + ParseProgName(argv, SavedStrings, TheDriver); // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE. TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS"); @@ -352,6 +423,11 @@ int main(int argc_, const char **argv_) { if (TheDriver.CCPrintHeaders) TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE"); + // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE. + TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS"); + if (TheDriver.CCLogDiagnostics) + TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE"); + // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a // command line behind the scenes. if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) { @@ -378,8 +454,7 @@ int main(int argc_, const char **argv_) { argv.insert(&argv[1], ExtraArgs.begin(), ExtraArgs.end()); } - llvm::OwningPtr C(TheDriver.BuildCompilation(argv.size(), - &argv[0])); + llvm::OwningPtr C(TheDriver.BuildCompilation(argv)); int Res = 0; if (C.get()) Res = TheDriver.ExecuteCompilation(*C); diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp index a8de7452ea06..62bd1c65e4b1 100644 --- a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp +++ b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp @@ -607,7 +607,7 @@ void ARMFilter::recurse() { for (bitIndex = 0; bitIndex < NumBits; bitIndex++) BitValueArray[StartBit + bitIndex] = BIT_UNSET; - // Delegates to an inferior filter chooser for futher processing on this + // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. FilterChooserMap.insert(std::pair( (unsigned)-1, @@ -639,7 +639,7 @@ void ARMFilter::recurse() { BitValueArray[StartBit + bitIndex] = BIT_FALSE; } - // Delegates to an inferior filter chooser for futher processing on this + // Delegates to an inferior filter chooser for further processing on this // category of instructions. FilterChooserMap.insert(std::pair( mapIterator->first, @@ -1382,7 +1382,7 @@ bool ARMFilterChooser::emit(raw_ostream &o, unsigned &Indentation) { // 2. source registers are identical => VMOVQ; otherwise => VORRq // 3. LDR, LDRcp => return LDR for now. // FIXME: How can we distinguish between LDR and LDRcp? Do we need to? - // 4. tLDM, tLDM_UPD => Rn = Inst{10-8}, reglist = Inst{7-0}, + // 4. tLDMIA, tLDMIA_UPD => Rn = Inst{10-8}, reglist = Inst{7-0}, // wback = registers = 0 // NOTE: (tLDM, tLDM_UPD) resolution must come before Advanced SIMD // addressing mode resolution!!! @@ -1423,7 +1423,7 @@ bool ARMFilterChooser::emit(raw_ostream &o, unsigned &Indentation) { << "; // Returning LDR for {LDR, LDRcp}\n"; return true; } - if (name1 == "tLDM" && name2 == "tLDM_UPD") { + if (name1 == "tLDMIA" && name2 == "tLDMIA_UPD") { // Inserting the opening curly brace for this case block. --Indentation; --Indentation; o.indent(Indentation) << "{\n"; @@ -1570,9 +1570,7 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, return false; if (TN == TARGET_ARM) { - // FIXME: what about Int_MemBarrierV6 and Int_SyncBarrierV6? - if ((Name != "Int_MemBarrierV7" && Name != "Int_SyncBarrierV7") && - Form == ARM_FORMAT_PSEUDO) + if (Form == ARM_FORMAT_PSEUDO) return false; if (thumbInstruction(Form)) return false; @@ -1586,61 +1584,18 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, Name == "MOVr_TC") return false; + // Delegate ADR disassembly to the more generic ADDri/SUBri instructions. + if (Name == "ADR") + return false; + // // The following special cases are for conflict resolutions. // - // NEON NLdStFrm conflict resolutions: - // - // 1. Ignore suffix "odd" and "odd_UPD", prefer the "even" register- - // numbered ones which have the same Asm format string. - // 2. Ignore VST2d64_UPD, which conflicts with VST1q64_UPD. - // 3. Ignore VLD2d64_UPD, which conflicts with VLD1q64_UPD. - // 4. Ignore VLD1q[_UPD], which conflicts with VLD1q64[_UPD]. - // 5. Ignore VST1q[_UPD], which conflicts with VST1q64[_UPD]. - if (Name.endswith("odd") || Name.endswith("odd_UPD") || - Name == "VST2d64_UPD" || Name == "VLD2d64_UPD" || - Name == "VLD1q" || Name == "VLD1q_UPD" || - Name == "VST1q" || Name == "VST1q_UPD") - return false; - // RSCSri and RSCSrs set the 's' bit, but are not predicated. We are // better off using the generic RSCri and RSCrs instructions. if (Name == "RSCSri" || Name == "RSCSrs") return false; - // MOVCCr, MOVCCs, MOVCCi, MOVCCi16, FCYPScc, FCYPDcc, FNEGScc, and - // FNEGDcc are used in the compiler to implement conditional moves. - // We can ignore them in favor of their more generic versions of - // instructions. See also SDNode *ARMDAGToDAGISel::Select(SDValue Op). - if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" || - Name == "MOVCCi16" || Name == "FCPYScc" || Name == "FCPYDcc" || - Name == "FNEGScc" || Name == "FNEGDcc") - return false; - - // Ditto for VMOVDcc, VMOVScc, VNEGDcc, and VNEGScc. - if (Name == "VMOVDcc" || Name == "VMOVScc" || Name == "VNEGDcc" || - Name == "VNEGScc") - return false; - - // LDMIA_RET is a special case of LDM (Load Multiple) where the registers - // loaded include the PC, causing a branch to a loaded address. Ignore - // the LDMIA_RET instruction when decoding. - if (Name == "LDMIA_RET") return false; - - // Bcc is in a more generic form than B. Ignore B when decoding. - if (Name == "B") return false; - - // Ignore the non-Darwin BL instructions and the TPsoft (TLS) instruction. - if (Name == "BL" || Name == "BL_pred" || Name == "BLX" || Name == "BX" || - Name == "TPsoft") - return false; - - // Ignore VDUPf[d|q] instructions known to conflict with VDUP32[d-q] for - // decoding. The instruction duplicates an element from an ARM core - // register into every element of the destination vector. There is no - // distinction between data types. - if (Name == "VDUPfd" || Name == "VDUPfq") return false; - // A8-598: VEXT // Vector Extract extracts elements from the bottom end of the second // operand vector and the top end of the first, concatenates them and @@ -1656,34 +1611,23 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, if (Name == "VEXTd16" || Name == "VEXTd32" || Name == "VEXTdf" || Name == "VEXTq16" || Name == "VEXTq32" || Name == "VEXTqf") return false; - - // Vector Reverse is similar to Vector Extract. There is no distinction - // between data types, other than size. - // - // VREV64df is equivalent to VREV64d32. - // VREV64qf is equivalent to VREV64q32. - if (Name == "VREV64df" || Name == "VREV64qf") return false; - - // VDUPLNfd is equivalent to VDUPLN32d. - // VDUPLNfq is equivalent to VDUPLN32q. - // VLD1df is equivalent to VLD1d32. - // VLD1qf is equivalent to VLD1q32. - // VLD2d64 is equivalent to VLD1q64. - // VST1df is equivalent to VST1d32. - // VST1qf is equivalent to VST1q32. - // VST2d64 is equivalent to VST1q64. - if (Name == "VDUPLNfd" || Name == "VDUPLNfq" || - Name == "VLD1df" || Name == "VLD1qf" || Name == "VLD2d64" || - Name == "VST1df" || Name == "VST1qf" || Name == "VST2d64") - return false; } else if (TN == TARGET_THUMB) { if (!thumbInstruction(Form)) return false; + // A8.6.189 STM / STMIA / STMEA -- Encoding T1 + // There's only STMIA_UPD for Thumb1. + if (Name == "tSTMIA") + return false; + // On Darwin R9 is call-clobbered. Ignore the non-Darwin counterparts. if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr") return false; + // A8.6.25 BX. Use the generic tBX_Rm, ignore tBX_RET and tBX_RET_vararg. + if (Name == "tBX_RET" || Name == "tBX_RET_vararg") + return false; + // Ignore the TPsoft (TLS) instructions, which conflict with tBLr9. if (Name == "tTPsoft" || Name == "t2TPsoft") return false; @@ -1692,6 +1636,11 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, if (Name == "tADR") return false; + // Delegate t2ADR disassembly to the more generic t2ADDri12/t2SUBri12 + // instructions. + if (Name == "t2ADR") + return false; + // Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr. // Ignore t2SUBrSPs, prefer the t2SUB[S]r[r|s]. // Ignore t2ADDrSPs, prefer the t2ADD[S]r[r|s]. @@ -1703,6 +1652,11 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, Name == "t2ADDrSPi12" || Name == "t2SUBrSPi12") return false; + // FIXME: Use ldr.n to work around a Darwin assembler bug. + // Introduce a workaround with tLDRpciDIS opcode. + if (Name == "tLDRpci") + return false; + // Ignore t2LDRDpci, prefer the generic t2LDRDi8, t2LDRD_PRE, t2LDRD_POST. if (Name == "t2LDRDpci") return false; diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp index e3def4185238..1d14037d3ab7 100644 --- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -88,7 +88,7 @@ // 2. The operand matcher will try every possible entry with the same // mnemonic and will check if the target feature for this mnemonic also // matches. After that, if the operand to be matched has its index -// present in the mask, a successfull match occurs. Otherwise, fallback +// present in the mask, a successful match occurs. Otherwise, fallback // to the regular operand parsing. // // 3. For a match success, each operand class that has a 'ParserMethod' @@ -258,7 +258,7 @@ struct ClassInfo { return ValueName < RHS.ValueName; default: - // This class preceeds the RHS if it is a proper subset of the RHS. + // This class precedes the RHS if it is a proper subset of the RHS. if (isSubsetOf(RHS)) return true; if (RHS.isSubsetOf(*this)) @@ -1265,7 +1265,7 @@ void AsmMatcherInfo::BuildInfo() { II->BuildAliasResultOperands(); } - // Reorder classes so that classes preceed super classes. + // Reorder classes so that classes precede super classes. std::sort(Classes.begin(), Classes.end(), less_ptr()); } @@ -1483,10 +1483,10 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName, MatchableInfo &II = **it; // Check if we have a custom match function. - StringRef AsmMatchConverter = II.getResultInst()->TheDef->getValueAsString( - "AsmMatchConverter"); + std::string AsmMatchConverter = + II.getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); if (!AsmMatchConverter.empty()) { - std::string Signature = "ConvertCustom_" + AsmMatchConverter.str(); + std::string Signature = "ConvertCustom_" + AsmMatchConverter; II.ConversionFnKind = Signature; // Check if we have already generated this signature. @@ -1538,7 +1538,7 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName, // operand from the earlier one.We can only tie single MCOperand values. //assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand"); unsigned TiedOp = OpInfo.TiedOperandNum; - assert(i > TiedOp && "Tied operand preceeds its target!"); + assert(i > TiedOp && "Tied operand precedes its target!"); CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n"; Signature += "__Tie" + utostr(TiedOp); break; diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h index 729c938fcd36..c13adf3dc535 100644 --- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h @@ -16,8 +16,6 @@ #define ASMMATCHER_EMITTER_H #include "TableGenBackend.h" -#include -#include #include namespace llvm { diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp index cd31e0c3448d..2b1a4cc8a3d4 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -542,12 +542,220 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { << "}\n\n#endif\n"; } -void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { - CodeGenTarget Target(Records); - Record *AsmWriter = Target.getAsmWriter(); +namespace { - O << "\n#ifdef PRINT_ALIAS_INSTR\n"; - O << "#undef PRINT_ALIAS_INSTR\n\n"; +/// SubtargetFeatureInfo - Helper class for storing information on a subtarget +/// feature which participates in instruction matching. +struct SubtargetFeatureInfo { + /// \brief The predicate record for this feature. + const Record *TheDef; + + /// \brief An unique index assigned to represent this feature. + unsigned Index; + + SubtargetFeatureInfo(const Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} + + /// \brief The name of the enumerated constant identifying this feature. + std::string getEnumName() const { + return "Feature_" + TheDef->getName(); + } +}; + +struct AsmWriterInfo { + /// Map of Predicate records to their subtarget information. + std::map SubtargetFeatures; + + /// getSubtargetFeature - Lookup or create the subtarget feature info for the + /// given operand. + SubtargetFeatureInfo *getSubtargetFeature(const Record *Def) const { + assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); + std::map::const_iterator I = + SubtargetFeatures.find(Def); + return I == SubtargetFeatures.end() ? 0 : I->second; + } + + void addReqFeatures(const std::vector &Features) { + for (std::vector::const_iterator + I = Features.begin(), E = Features.end(); I != E; ++I) { + const Record *Pred = *I; + + // Ignore predicates that are not intended for the assembler. + if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) + continue; + + if (Pred->getName().empty()) + throw TGError(Pred->getLoc(), "Predicate has no name!"); + + // Don't add the predicate again. + if (getSubtargetFeature(Pred)) + continue; + + unsigned FeatureNo = SubtargetFeatures.size(); + SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); + assert(FeatureNo < 32 && "Too many subtarget features!"); + } + } + + const SubtargetFeatureInfo *getFeatureInfo(const Record *R) { + return SubtargetFeatures[R]; + } +}; + +// IAPrinter - Holds information about an InstAlias. Two InstAliases match if +// they both have the same conditionals. In which case, we cannot print out the +// alias for that pattern. +class IAPrinter { + AsmWriterInfo &AWI; + std::vector Conds; + std::map OpMap; + std::string Result; + std::string AsmString; + std::vector ReqFeatures; +public: + IAPrinter(AsmWriterInfo &Info, std::string R, std::string AS) + : AWI(Info), Result(R), AsmString(AS) {} + + void addCond(const std::string &C) { Conds.push_back(C); } + void addReqFeatures(const std::vector &Features) { + AWI.addReqFeatures(Features); + ReqFeatures = Features; + } + + void addOperand(StringRef Op, unsigned Idx) { OpMap[Op] = Idx; } + unsigned getOpIndex(StringRef Op) { return OpMap[Op]; } + bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); } + + bool print(raw_ostream &O) { + if (Conds.empty() && ReqFeatures.empty()) { + O.indent(6) << "return true;\n"; + return false; + } + + O << "if ("; + + for (std::vector::iterator + I = Conds.begin(), E = Conds.end(); I != E; ++I) { + if (I != Conds.begin()) { + O << " &&\n"; + O.indent(8); + } + + O << *I; + } + + if (!ReqFeatures.empty()) { + if (Conds.begin() != Conds.end()) { + O << " &&\n"; + O.indent(8); + } else { + O << "if ("; + } + + std::string Req; + raw_string_ostream ReqO(Req); + + for (std::vector::iterator + I = ReqFeatures.begin(), E = ReqFeatures.end(); I != E; ++I) { + if (I != ReqFeatures.begin()) ReqO << " | "; + ReqO << AWI.getFeatureInfo(*I)->getEnumName(); + } + + O << "(AvailableFeatures & (" << ReqO.str() << ")) == (" + << ReqO.str() << ')'; + } + + O << ") {\n"; + O.indent(6) << "// " << Result << "\n"; + O.indent(6) << "AsmString = \"" << AsmString << "\";\n"; + + for (std::map::iterator + I = OpMap.begin(), E = OpMap.end(); I != E; ++I) + O.indent(6) << "OpMap[\"" << I->first << "\"] = " + << I->second << ";\n"; + + O.indent(6) << "break;\n"; + O.indent(4) << '}'; + return !ReqFeatures.empty(); + } + + bool operator==(const IAPrinter &RHS) { + if (Conds.size() != RHS.Conds.size()) + return false; + + unsigned Idx = 0; + for (std::vector::iterator + I = Conds.begin(), E = Conds.end(); I != E; ++I) + if (*I != RHS.Conds[Idx++]) + return false; + + return true; + } + + bool operator()(const IAPrinter &RHS) { + if (Conds.size() < RHS.Conds.size()) + return true; + + unsigned Idx = 0; + for (std::vector::iterator + I = Conds.begin(), E = Conds.end(); I != E; ++I) + if (*I != RHS.Conds[Idx++]) + return *I < RHS.Conds[Idx++]; + + return false; + } +}; + +} // end anonymous namespace + +/// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag +/// definitions. +static void EmitSubtargetFeatureFlagEnumeration(AsmWriterInfo &Info, + raw_ostream &O) { + O << "namespace {\n\n"; + O << "// Flags for subtarget features that participate in " + << "alias instruction matching.\n"; + O << "enum SubtargetFeatureFlag {\n"; + + for (std::map::const_iterator + I = Info.SubtargetFeatures.begin(), + E = Info.SubtargetFeatures.end(); I != E; ++I) { + SubtargetFeatureInfo &SFI = *I->second; + O << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n"; + } + + O << " Feature_None = 0\n"; + O << "};\n\n"; + O << "} // end anonymous namespace\n\n"; +} + +/// EmitComputeAvailableFeatures - Emit the function to compute the list of +/// available features given a subtarget. +static void EmitComputeAvailableFeatures(AsmWriterInfo &Info, + Record *AsmWriter, + CodeGenTarget &Target, + raw_ostream &O) { + std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); + + O << "unsigned " << Target.getName() << ClassName << "::\n" + << "ComputeAvailableFeatures(const " << Target.getName() + << "Subtarget *Subtarget) const {\n"; + O << " unsigned Features = 0;\n"; + + for (std::map::const_iterator + I = Info.SubtargetFeatures.begin(), + E = Info.SubtargetFeatures.end(); I != E; ++I) { + SubtargetFeatureInfo &SFI = *I->second; + O << " if (" << SFI.TheDef->getValueAsString("CondString") + << ")\n"; + O << " Features |= " << SFI.getEnumName() << ";\n"; + } + + O << " return Features;\n"; + O << "}\n\n"; +} + +void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) { + CodeGenTarget Target(Records); // Enumerate the register classes. const std::vector &RegisterClasses = @@ -606,6 +814,16 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << " }\n\n"; O << " return false;\n"; O << "}\n\n"; +} + +void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { + CodeGenTarget Target(Records); + Record *AsmWriter = Target.getAsmWriter(); + + O << "\n#ifdef PRINT_ALIAS_INSTR\n"; + O << "#undef PRINT_ALIAS_INSTR\n\n"; + + EmitRegIsInRegClass(O); // Emit the method that prints the alias instruction. std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); @@ -613,10 +831,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter"); const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr"; - O << "bool " << Target.getName() << ClassName - << "::printAliasInstr(const " << MachineInstrClassName - << " *MI, raw_ostream &OS) {\n"; - std::vector AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); @@ -626,44 +840,35 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target); const Record *R = *I; + if (!R->getValueAsBit("EmitAlias")) + continue; // We were told not to emit the alias, but to emit the aliasee. const DagInit *DI = R->getValueAsDag("ResultInst"); const DefInit *Op = dynamic_cast(DI->getOperator()); AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); } - if (AliasMap.empty() || !isMC) { - // FIXME: Support MachineInstr InstAliases? - O << " return true;\n"; - O << "}\n\n"; - O << "#endif // PRINT_ALIAS_INSTR\n"; - return; - } - - O << " StringRef AsmString;\n"; - O << " std::map OpMap;\n"; - O << " switch (MI->getOpcode()) {\n"; - O << " default: return true;\n"; + // A map of which conditions need to be met for each instruction operand + // before it can be matched to the mnemonic. + std::map > IAPrinterMap; + AsmWriterInfo AWI; for (std::map >::iterator I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) { std::vector &Aliases = I->second; - std::map CondCount; - std::map BodyMap; - - std::string AsmString = ""; - for (std::vector::iterator II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) { const CodeGenInstAlias *CGA = *II; - AsmString = CGA->AsmString; - unsigned Indent = 8; + IAPrinter *IAP = new IAPrinter(AWI, CGA->Result->getAsString(), + CGA->AsmString); + + IAP->addReqFeatures(CGA->TheDef->getValueAsListOfDefs("Predicates")); + unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); std::string Cond; - raw_string_ostream CondO(Cond); - - CondO << "if (MI->getNumOperands() == " << LastOpNo; + Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo); + IAP->addCond(Cond); std::map OpMap; bool CantHandle = false; @@ -678,23 +883,26 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { StringRef ROName = RO.getName(); if (Rec->isSubClassOf("RegisterClass")) { - CondO << " &&\n"; - CondO.indent(Indent) << "MI->getOperand(" << i << ").isReg() &&\n"; - if (OpMap.find(ROName) == OpMap.end()) { - OpMap[ROName] = i; - CondO.indent(Indent) - << "regIsInRegisterClass(RC_" - << CGA->ResultOperands[i].getRecord()->getName() - << ", MI->getOperand(" << i << ").getReg())"; + Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()"; + IAP->addCond(Cond); + + if (!IAP->isOpMapped(ROName)) { + IAP->addOperand(ROName, i); + Cond = std::string("regIsInRegisterClass(RC_") + + CGA->ResultOperands[i].getRecord()->getName() + + ", MI->getOperand(" + llvm::utostr(i) + ").getReg())"; + IAP->addCond(Cond); } else { - CondO.indent(Indent) - << "MI->getOperand(" << i - << ").getReg() == MI->getOperand(" - << OpMap[ROName] << ").getReg()"; + Cond = std::string("MI->getOperand(") + + llvm::utostr(i) + ").getReg() == MI->getOperand(" + + llvm::utostr(IAP->getOpIndex(ROName)) + ").getReg()"; + IAP->addCond(Cond); } } else { assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); // FIXME: We need to handle these situations. + delete IAP; + IAP = 0; CantHandle = true; break; } @@ -702,67 +910,92 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { break; } case CodeGenInstAlias::ResultOperand::K_Imm: - CondO << " &&\n"; - CondO.indent(Indent) << "MI->getOperand(" << i << ").getImm() == "; - CondO << CGA->ResultOperands[i].getImm(); + Cond = std::string("MI->getOperand(") + + llvm::utostr(i) + ").getImm() == " + + llvm::utostr(CGA->ResultOperands[i].getImm()); + IAP->addCond(Cond); break; case CodeGenInstAlias::ResultOperand::K_Reg: - CondO << " &&\n"; - CondO.indent(Indent) << "MI->getOperand(" << i << ").getReg() == "; - CondO << Target.getName() << "::" - << CGA->ResultOperands[i].getRegister()->getName(); + Cond = std::string("MI->getOperand(") + + llvm::utostr(i) + ").getReg() == " + Target.getName() + + "::" + CGA->ResultOperands[i].getRegister()->getName(); + IAP->addCond(Cond); break; } - if (CantHandle) break; + if (!IAP) break; } if (CantHandle) continue; - - CondO << ")"; - - std::string Body; - raw_string_ostream BodyO(Body); - - BodyO << " // " << CGA->Result->getAsString() << "\n"; - BodyO << " AsmString = \"" << AsmString << "\";\n"; - - for (std::map::iterator - III = OpMap.begin(), IIE = OpMap.end(); III != IIE; ++III) - BodyO << " OpMap[\"" << III->first << "\"] = " - << III->second << ";\n"; - - ++CondCount[CondO.str()]; - BodyMap[CondO.str()] = BodyO.str(); + IAPrinterMap[I->first].push_back(IAP); } - - std::string Code; - raw_string_ostream CodeO(Code); - - bool EmitElse = false; - for (std::map::iterator - II = CondCount.begin(), IE = CondCount.end(); II != IE; ++II) { - if (II->second != 1) continue; - CodeO << " "; - if (EmitElse) CodeO << "} else "; - CodeO << II->first << " {\n"; - CodeO << BodyMap[II->first]; - EmitElse = true; - } - - if (CodeO.str().empty()) continue; - - O << " case " << I->first << ":\n"; - O << CodeO.str(); - O << " }\n"; - O << " break;\n"; } - O << " }\n\n"; + EmitSubtargetFeatureFlagEnumeration(AWI, O); + EmitComputeAvailableFeatures(AWI, AsmWriter, Target, O); + + O << "bool " << Target.getName() << ClassName + << "::printAliasInstr(const " << MachineInstrClassName + << " *MI, raw_ostream &OS) {\n"; + + std::string Cases; + raw_string_ostream CasesO(Cases); + bool NeedAvailableFeatures = false; + + for (std::map >::iterator + I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) { + std::vector &IAPs = I->second; + std::vector UniqueIAPs; + + for (std::vector::iterator + II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) { + IAPrinter *LHS = *II; + bool IsDup = false; + for (std::vector::iterator + III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) { + IAPrinter *RHS = *III; + if (LHS != RHS && *LHS == *RHS) { + IsDup = true; + break; + } + } + + if (!IsDup) UniqueIAPs.push_back(LHS); + } + + if (UniqueIAPs.empty()) continue; + + CasesO.indent(2) << "case " << I->first << ":\n"; + + for (std::vector::iterator + II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) { + IAPrinter *IAP = *II; + CasesO.indent(4); + NeedAvailableFeatures |= IAP->print(CasesO); + CasesO << '\n'; + } + + CasesO.indent(4) << "return false;\n"; + } + + if (CasesO.str().empty() || !isMC) { + O << " return false;\n"; + O << "}\n\n"; + O << "#endif // PRINT_ALIAS_INSTR\n"; + return; + } + + O.indent(2) << "StringRef AsmString;\n"; + O.indent(2) << "std::map OpMap;\n"; + if (NeedAvailableFeatures) + O.indent(2) << "unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + O.indent(2) << "switch (MI->getOpcode()) {\n"; + O.indent(2) << "default: return false;\n"; + O << CasesO.str(); + O.indent(2) << "}\n\n"; // Code that prints the alias, replacing the operands with the ones from the // MCInst. - O << " if (AsmString.empty()) return true;\n"; O << " std::pair ASM = AsmString.split(' ');\n"; O << " OS << '\\t' << ASM.first;\n"; @@ -786,7 +1019,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << " }\n"; O << " }\n\n"; - O << " return false;\n"; + O << " return true;\n"; O << "}\n\n"; O << "#endif // PRINT_ALIAS_INSTR\n"; diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h index 5e8d6f5b7fe7..84c925b66e8c 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h @@ -38,6 +38,7 @@ namespace llvm { void EmitPrintInstruction(raw_ostream &o); void EmitGetRegisterName(raw_ostream &o); void EmitGetInstructionName(raw_ostream &o); + void EmitRegIsInRegClass(raw_ostream &O); void EmitPrintAliasInstruction(raw_ostream &O); AsmWriterInst *getAsmWriterInstByID(unsigned ID) const { diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.h b/contrib/llvm/utils/TableGen/CallingConvEmitter.h index 7fc2507e8889..431c33bcc0df 100644 --- a/contrib/llvm/utils/TableGen/CallingConvEmitter.h +++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.h @@ -16,8 +16,6 @@ #define CALLINGCONV_EMITTER_H #include "TableGenBackend.h" -#include -#include #include namespace llvm { diff --git a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp index 187ab4679994..d9d5a3ccd907 100644 --- a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp @@ -155,10 +155,13 @@ void ClangDeclContextEmitter::run(raw_ostream &OS) { } } - for (RecordSet::iterator i = DeclContexts.begin(), e = DeclContexts.end(); - i != e; ++i) { - OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; - } + // To keep identical order, RecordVector may be used + // instead of RecordSet. + for (RecordVector::iterator + i = DeclContextsVector.begin(), e = DeclContextsVector.end(); + i != e; ++i) + if (DeclContexts.find(*i) != DeclContexts.end()) + OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; OS << "#undef DECL_CONTEXT\n"; OS << "#undef DECL_CONTEXT_BASE\n"; diff --git a/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp index 27e1e027d0fa..26bd8786a49c 100644 --- a/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp +++ b/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp @@ -46,6 +46,7 @@ std::string ReadPCHRecord(StringRef type) { ">(GetDecl(Record[Idx++]))") .Case("QualType", "GetType(Record[Idx++])") .Case("Expr *", "ReadSubExpr()") + .Case("IdentifierInfo *", "GetIdentifierInfo(Record, Idx)") .Default("Record[Idx++]"); } @@ -56,6 +57,8 @@ std::string WritePCHRecord(StringRef type, StringRef name) { ", Record);\n") .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n") .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") + .Case("IdentifierInfo *", + "AddIdentifierRef(" + std::string(name) + ", Record);\n") .Default("Record.push_back(" + std::string(name) + ");\n"); } @@ -415,6 +418,47 @@ namespace { OS << "Record.push_back(SA->get" << getUpperName() << "());\n"; } }; + + class VersionArgument : public Argument { + public: + VersionArgument(Record &Arg, StringRef Attr) + : Argument(Arg, Attr) + {} + + void writeAccessors(raw_ostream &OS) const { + OS << " VersionTuple get" << getUpperName() << "() const {\n"; + OS << " return " << getLowerName() << ";\n"; + OS << " }\n"; + OS << " void set" << getUpperName() + << "(ASTContext &C, VersionTuple V) {\n"; + OS << " " << getLowerName() << " = V;\n"; + OS << " }"; + } + void writeCloneArgs(raw_ostream &OS) const { + OS << "get" << getUpperName() << "()"; + } + void writeCtorBody(raw_ostream &OS) const { + } + void writeCtorInitializers(raw_ostream &OS) const { + OS << getLowerName() << "(" << getUpperName() << ")"; + } + void writeCtorParameters(raw_ostream &OS) const { + OS << "VersionTuple " << getUpperName(); + } + void writeDeclarations(raw_ostream &OS) const { + OS << "VersionTuple " << getLowerName() << ";\n"; + } + void writePCHReadDecls(raw_ostream &OS) const { + OS << " VersionTuple " << getLowerName() + << "= ReadVersionTuple(Record, Idx);\n"; + } + void writePCHReadArgs(raw_ostream &OS) const { + OS << getLowerName(); + } + void writePCHWrite(raw_ostream &OS) const { + OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n"; + } + }; } static Argument *createArgument(Record &Arg, StringRef Attr, @@ -433,6 +477,8 @@ static Argument *createArgument(Record &Arg, StringRef Attr, Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *"); else if (ArgName == "IdentifierArgument") Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *"); + else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr, + "bool"); else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int"); else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr); else if (ArgName == "TypeArgument") @@ -441,6 +487,8 @@ static Argument *createArgument(Record &Arg, StringRef Attr, Ptr = new SimpleArgument(Arg, Attr, "unsigned"); else if (ArgName == "VariadicUnsignedArgument") Ptr = new VariadicArgument(Arg, Attr, "unsigned"); + else if (ArgName == "VersionArgument") + Ptr = new VersionArgument(Arg, Attr); if (!Ptr) { std::vector Bases = Search->getSuperClasses(); @@ -589,23 +637,37 @@ void ClangAttrListEmitter::run(raw_ostream &OS) { OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; OS << "#endif\n\n"; + OS << "#ifndef INHERITABLE_PARAM_ATTR\n"; + OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n"; + OS << "#endif\n\n"; + + OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n"; + OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)" + " INHERITABLE_PARAM_ATTR(NAME)\n"; + OS << "#endif\n\n"; + Record *InhClass = Records.getClass("InheritableAttr"); + Record *InhParamClass = Records.getClass("InheritableParamAttr"); std::vector Attrs = Records.getAllDerivedDefinitions("Attr"), - NonInhAttrs, InhAttrs; + NonInhAttrs, InhAttrs, InhParamAttrs; for (std::vector::iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i) { - if ((*i)->isSubClassOf(InhClass)) + if ((*i)->isSubClassOf(InhParamClass)) + InhParamAttrs.push_back(*i); + else if ((*i)->isSubClassOf(InhClass)) InhAttrs.push_back(*i); else NonInhAttrs.push_back(*i); } + EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs); EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs); EmitAttrList(OS, "ATTR", NonInhAttrs); OS << "#undef LAST_ATTR\n"; OS << "#undef INHERITABLE_ATTR\n"; OS << "#undef LAST_INHERITABLE_ATTR\n"; + OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; OS << "#undef ATTR\n"; } diff --git a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp index 60e67c467466..0f4b606808ef 100644 --- a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -19,8 +19,9 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/VectorExtras.h" -#include #include +#include +#include using namespace llvm; //===----------------------------------------------------------------------===// @@ -121,7 +122,6 @@ namespace { } // end anonymous namespace. - //===----------------------------------------------------------------------===// // Warning Tables (.inc file) generation. //===----------------------------------------------------------------------===// @@ -179,6 +179,14 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { // Category number. OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap)); + + // Brief + OS << ", \""; + OS.write_escaped(R.getValueAsString("Brief")) << '"'; + + // Explanation + OS << ", \""; + OS.write_escaped(R.getValueAsString("Explanation")) << '"'; OS << ")\n"; } } @@ -294,3 +302,49 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { OS << "CATEGORY(\"" << *I << "\")\n"; OS << "#endif // GET_CATEGORY_TABLE\n\n"; } + +//===----------------------------------------------------------------------===// +// Diagnostic name index generation +//===----------------------------------------------------------------------===// + +namespace { +struct RecordIndexElement +{ + RecordIndexElement() {} + explicit RecordIndexElement(Record const &R): + Name(R.getName()) {} + + std::string Name; +}; + +struct RecordIndexElementSorter : + public std::binary_function { + + bool operator()(RecordIndexElement const &Lhs, + RecordIndexElement const &Rhs) const { + return Lhs.Name < Rhs.Name; + } + +}; + +} // end anonymous namespace. + +void ClangDiagsIndexNameEmitter::run(raw_ostream &OS) { + const std::vector &Diags = + Records.getAllDerivedDefinitions("Diagnostic"); + + std::vector Index; + Index.reserve(Diags.size()); + for (unsigned i = 0, e = Diags.size(); i != e; ++i) { + const Record &R = *(Diags[i]); + Index.push_back(RecordIndexElement(R)); + } + + std::sort(Index.begin(), Index.end(), RecordIndexElementSorter()); + + for (unsigned i = 0, e = Index.size(); i != e; ++i) { + const RecordIndexElement &R = Index[i]; + + OS << "DIAG_NAME_INDEX(" << R.Name << ")\n"; + } +} diff --git a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h index edd062a73835..1e4c8b70c26d 100644 --- a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h +++ b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.h @@ -33,13 +33,21 @@ class ClangDiagsDefsEmitter : public TableGenBackend { }; class ClangDiagGroupsEmitter : public TableGenBackend { - RecordKeeper &Records; + RecordKeeper &Records; public: explicit ClangDiagGroupsEmitter(RecordKeeper &R) : Records(R) {} void run(raw_ostream &OS); }; +class ClangDiagsIndexNameEmitter : public TableGenBackend { + RecordKeeper &Records; +public: + explicit ClangDiagsIndexNameEmitter(RecordKeeper &R) : Records(R) {} + + void run(raw_ostream &OS); +}; + } // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp b/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp index 8865db36b6c3..97739c6b3f4c 100644 --- a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp +++ b/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp @@ -71,7 +71,7 @@ static std::string getStringValue(const Record &R, StringRef field) { namespace { struct GroupInfo { - std::vector Checkers; + llvm::DenseSet Checkers; llvm::DenseSet SubGroups; bool Hidden; unsigned Index; @@ -80,33 +80,24 @@ struct GroupInfo { }; } +static void addPackageToCheckerGroup(const Record *package, const Record *group, + llvm::DenseMap &recordGroupMap) { + llvm::DenseSet &checkers = recordGroupMap[package]->Checkers; + for (llvm::DenseSet::iterator + I = checkers.begin(), E = checkers.end(); I != E; ++I) + recordGroupMap[group]->Checkers.insert(*I); + + llvm::DenseSet &subGroups = recordGroupMap[package]->SubGroups; + for (llvm::DenseSet::iterator + I = subGroups.begin(), E = subGroups.end(); I != E; ++I) + addPackageToCheckerGroup(*I, group, recordGroupMap); +} + void ClangSACheckersEmitter::run(raw_ostream &OS) { std::vector checkers = Records.getAllDerivedDefinitions("Checker"); llvm::DenseMap checkerRecIndexMap; for (unsigned i = 0, e = checkers.size(); i != e; ++i) checkerRecIndexMap[checkers[i]] = i; - - OS << "\n#ifdef GET_CHECKERS\n"; - for (unsigned i = 0, e = checkers.size(); i != e; ++i) { - const Record &R = *checkers[i]; - - OS << "CHECKER(" << "\""; - std::string name; - if (isCheckerNamed(&R)) - name = getCheckerFullName(&R); - OS.write_escaped(name) << "\", "; - OS << R.getName() << ", "; - OS << getStringValue(R, "DescFile") << ", "; - OS << "\""; - OS.write_escaped(getStringValue(R, "HelpText")) << "\", "; - // Hidden bit - if (isHidden(R)) - OS << "true"; - else - OS << "false"; - OS << ")\n"; - } - OS << "#endif // GET_CHECKERS\n\n"; // Invert the mapping of checkers to package/group into a one to many // mapping of packages/groups to checkers. @@ -150,9 +141,9 @@ void ClangSACheckersEmitter::run(raw_ostream &OS) { GroupInfo &info = groupInfoByName[fullName]; info.Hidden = R->getValueAsBit("Hidden"); recordGroupMap[R] = &info; - info.Checkers.push_back(R); + info.Checkers.insert(R); } else { - recordGroupMap[package]->Checkers.push_back(R); + recordGroupMap[package]->Checkers.insert(R); } Record *currR = isCheckerNamed(R) ? R : package; @@ -166,9 +157,94 @@ void ClangSACheckersEmitter::run(raw_ostream &OS) { } // Insert the checker into the set of its group. if (DefInit *DI = dynamic_cast(R->getValueInit("Group"))) - recordGroupMap[DI->getDef()]->Checkers.push_back(R); + recordGroupMap[DI->getDef()]->Checkers.insert(R); } + // If a package is in group, add all its checkers and its sub-packages + // checkers into the group. + for (unsigned i = 0, e = packages.size(); i != e; ++i) + if (DefInit *DI = dynamic_cast(packages[i]->getValueInit("Group"))) + addPackageToCheckerGroup(packages[i], DI->getDef(), recordGroupMap); + + typedef std::map SortedRecords; + typedef llvm::DenseMap RecToSortIndex; + + SortedRecords sortedGroups; + RecToSortIndex groupToSortIndex; + OS << "\n#ifdef GET_GROUPS\n"; + { + for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) + sortedGroups[checkerGroups[i]->getValueAsString("GroupName")] + = checkerGroups[i]; + + unsigned sortIndex = 0; + for (SortedRecords::iterator + I = sortedGroups.begin(), E = sortedGroups.end(); I != E; ++I) { + const Record *R = I->second; + + OS << "GROUP(" << "\""; + OS.write_escaped(R->getValueAsString("GroupName")) << "\""; + OS << ")\n"; + + groupToSortIndex[R] = sortIndex++; + } + } + OS << "#endif // GET_GROUPS\n\n"; + + OS << "\n#ifdef GET_PACKAGES\n"; + { + SortedRecords sortedPackages; + for (unsigned i = 0, e = packages.size(); i != e; ++i) + sortedPackages[getPackageFullName(packages[i])] = packages[i]; + + for (SortedRecords::iterator + I = sortedPackages.begin(), E = sortedPackages.end(); I != E; ++I) { + const Record &R = *I->second; + + OS << "PACKAGE(" << "\""; + OS.write_escaped(getPackageFullName(&R)) << "\", "; + // Group index + if (DefInit *DI = dynamic_cast(R.getValueInit("Group"))) + OS << groupToSortIndex[DI->getDef()] << ", "; + else + OS << "-1, "; + // Hidden bit + if (isHidden(R)) + OS << "true"; + else + OS << "false"; + OS << ")\n"; + } + } + OS << "#endif // GET_PACKAGES\n\n"; + + OS << "\n#ifdef GET_CHECKERS\n"; + for (unsigned i = 0, e = checkers.size(); i != e; ++i) { + const Record &R = *checkers[i]; + + OS << "CHECKER(" << "\""; + std::string name; + if (isCheckerNamed(&R)) + name = getCheckerFullName(&R); + OS.write_escaped(name) << "\", "; + OS << R.getName() << ", "; + OS << getStringValue(R, "DescFile") << ", "; + OS << "\""; + OS.write_escaped(getStringValue(R, "HelpText")) << "\", "; + // Group index + if (DefInit *DI = dynamic_cast(R.getValueInit("Group"))) + OS << groupToSortIndex[DI->getDef()] << ", "; + else + OS << "-1, "; + // Hidden bit + if (isHidden(R)) + OS << "true"; + else + OS << "false"; + OS << ")\n"; + } + OS << "#endif // GET_CHECKERS\n\n"; + unsigned index = 0; for (std::map::iterator I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) @@ -182,21 +258,34 @@ void ClangSACheckersEmitter::run(raw_ostream &OS) { for (std::map::iterator I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) { maxLen = std::max(maxLen, (unsigned)I->first.size()); - - std::vector &V = I->second.Checkers; - if (!V.empty()) { + + llvm::DenseSet &checkers = I->second.Checkers; + if (!checkers.empty()) { OS << "static const short CheckerArray" << I->second.Index << "[] = { "; - for (unsigned i = 0, e = V.size(); i != e; ++i) - OS << checkerRecIndexMap[V[i]] << ", "; + // Make the output order deterministic. + std::map sorted; + for (llvm::DenseSet::iterator + I = checkers.begin(), E = checkers.end(); I != E; ++I) + sorted[(*I)->getID()] = *I; + + for (std::map::iterator + I = sorted.begin(), E = sorted.end(); I != E; ++I) + OS << checkerRecIndexMap[I->second] << ", "; OS << "-1 };\n"; } llvm::DenseSet &subGroups = I->second.SubGroups; if (!subGroups.empty()) { OS << "static const short SubPackageArray" << I->second.Index << "[] = { "; + // Make the output order deterministic. + std::map sorted; for (llvm::DenseSet::iterator - I = subGroups.begin(), E = subGroups.end(); I != E; ++I) { - OS << recordGroupMap[*I]->Index << ", "; + I = subGroups.begin(), E = subGroups.end(); I != E; ++I) + sorted[(*I)->getID()] = *I; + + for (std::map::iterator + I = sorted.begin(), E = sorted.end(); I != E; ++I) { + OS << recordGroupMap[I->second]->Index << ", "; } OS << "-1 };\n"; } diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp index 957dd19da1c2..9d4dc5c4607a 100644 --- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -63,10 +63,14 @@ void CodeEmitterGen::reverseBits(std::vector &Insts) { // return the variable bit position. Otherwise return -1. int CodeEmitterGen::getVariableBit(const std::string &VarName, BitsInit *BI, int bit) { - if (VarBitInit *VBI = dynamic_cast(BI->getBit(bit))) + if (VarBitInit *VBI = dynamic_cast(BI->getBit(bit))) { if (VarInit *VI = dynamic_cast(VBI->getVariable())) if (VI->getName() == VarName) return VBI->getBitNum(); + } else if (VarInit *VI = dynamic_cast(BI->getBit(bit))) { + if (VI->getName() == VarName) + return 0; + } return -1; } diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index aa60f871bff5..a08cde60fb2a 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -580,34 +580,29 @@ typedef std::map DepVarMap; /// Const iterator shorthand for DepVarMap typedef DepVarMap::const_iterator DepVarMap_citer; -namespace { -void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { +static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { if (N->isLeaf()) { - if (dynamic_cast(N->getLeafValue()) != NULL) { + if (dynamic_cast(N->getLeafValue()) != NULL) DepMap[N->getName()]++; - } } else { for (size_t i = 0, e = N->getNumChildren(); i != e; ++i) FindDepVarsOf(N->getChild(i), DepMap); } } - -//! Find dependent variables within child patterns -/*! - */ -void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) { + +/// Find dependent variables within child patterns +static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) { DepVarMap depcounts; FindDepVarsOf(N, depcounts); for (DepVarMap_citer i = depcounts.begin(); i != depcounts.end(); ++i) { - if (i->second > 1) { // std::pair + if (i->second > 1) // std::pair DepVars.insert(i->first); - } } } -//! Dump the dependent variable set: #ifndef NDEBUG -void DumpDepVars(MultipleUseVarSet &DepVars) { +/// Dump the dependent variable set: +static void DumpDepVars(MultipleUseVarSet &DepVars) { if (DepVars.empty()) { DEBUG(errs() << ""); } else { @@ -621,6 +616,66 @@ void DumpDepVars(MultipleUseVarSet &DepVars) { } #endif + +//===----------------------------------------------------------------------===// +// TreePredicateFn Implementation +//===----------------------------------------------------------------------===// + +/// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. +TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) { + assert((getPredCode().empty() || getImmCode().empty()) && + ".td file corrupt: can't have a node predicate *and* an imm predicate"); +} + +std::string TreePredicateFn::getPredCode() const { + return PatFragRec->getRecord()->getValueAsCode("PredicateCode"); +} + +std::string TreePredicateFn::getImmCode() const { + return PatFragRec->getRecord()->getValueAsCode("ImmediateCode"); +} + + +/// isAlwaysTrue - Return true if this is a noop predicate. +bool TreePredicateFn::isAlwaysTrue() const { + return getPredCode().empty() && getImmCode().empty(); +} + +/// Return the name to use in the generated code to reference this, this is +/// "Predicate_foo" if from a pattern fragment "foo". +std::string TreePredicateFn::getFnName() const { + return "Predicate_" + PatFragRec->getRecord()->getName(); +} + +/// getCodeToRunOnSDNode - Return the code for the function body that +/// evaluates this predicate. The argument is expected to be in "Node", +/// not N. This handles casting and conversion to a concrete node type as +/// appropriate. +std::string TreePredicateFn::getCodeToRunOnSDNode() const { + // Handle immediate predicates first. + std::string ImmCode = getImmCode(); + if (!ImmCode.empty()) { + std::string Result = + " int64_t Imm = cast(Node)->getSExtValue();\n"; + return Result + ImmCode; + } + + // Handle arbitrary node predicates. + assert(!getPredCode().empty() && "Don't have any predicate code!"); + std::string ClassName; + if (PatFragRec->getOnlyTree()->isLeaf()) + ClassName = "SDNode"; + else { + Record *Op = PatFragRec->getOnlyTree()->getOperator(); + ClassName = PatFragRec->getDAGPatterns().getSDNodeInfo(Op).getSDClassName(); + } + std::string Result; + if (ClassName == "SDNode") + Result = " SDNode *N = Node;\n"; + else + Result = " " + ClassName + "*N = cast<" + ClassName + ">(Node);\n"; + + return Result + getPredCode(); } //===----------------------------------------------------------------------===// @@ -1015,7 +1070,7 @@ void TreePatternNode::print(raw_ostream &OS) const { } for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i) - OS << "<>"; + OS << "<>"; if (TransformFn) OS << "<getName() << ">>"; if (!getName().empty()) @@ -1150,9 +1205,9 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { TreePatternNode *FragTree = Frag->getOnlyTree()->clone(); - std::string Code = Op->getValueAsCode("Predicate"); - if (!Code.empty()) - FragTree->addPredicateFn("Predicate_"+Op->getName()); + TreePredicateFn PredFn(Frag); + if (!PredFn.isAlwaysTrue()) + FragTree->addPredicateFn(PredFn); // Resolve formal arguments to their actual value. if (Frag->getNumArgs()) { @@ -2063,9 +2118,9 @@ void CodeGenDAGPatterns::ParsePatternFragments() { // If there is a code init for this fragment, keep track of the fact that // this fragment uses it. - std::string Code = Fragments[i]->getValueAsCode("Predicate"); - if (!Code.empty()) - P->getOnlyTree()->addPredicateFn("Predicate_"+Fragments[i]->getName()); + TreePredicateFn PredFn(P); + if (!PredFn.isAlwaysTrue()) + P->getOnlyTree()->addPredicateFn(PredFn); // If there is a node transformation corresponding to this, keep track of // it. @@ -2288,13 +2343,14 @@ class InstAnalyzer { const CodeGenDAGPatterns &CDP; bool &mayStore; bool &mayLoad; + bool &IsBitcast; bool &HasSideEffects; bool &IsVariadic; public: InstAnalyzer(const CodeGenDAGPatterns &cdp, - bool &maystore, bool &mayload, bool &hse, bool &isv) - : CDP(cdp), mayStore(maystore), mayLoad(mayload), HasSideEffects(hse), - IsVariadic(isv) { + bool &maystore, bool &mayload, bool &isbc, bool &hse, bool &isv) + : CDP(cdp), mayStore(maystore), mayLoad(mayload), IsBitcast(isbc), + HasSideEffects(hse), IsVariadic(isv) { } /// Analyze - Analyze the specified instruction, returning true if the @@ -2313,6 +2369,29 @@ class InstAnalyzer { } private: + bool IsNodeBitcast(const TreePatternNode *N) const { + if (HasSideEffects || mayLoad || mayStore || IsVariadic) + return false; + + if (N->getNumChildren() != 2) + return false; + + const TreePatternNode *N0 = N->getChild(0); + if (!N0->isLeaf() || !dynamic_cast(N0->getLeafValue())) + return false; + + const TreePatternNode *N1 = N->getChild(1); + if (N1->isLeaf()) + return false; + if (N1->getNumChildren() != 1 || !N1->getChild(0)->isLeaf()) + return false; + + const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N1->getOperator()); + if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1) + return false; + return OpInfo.getEnumName() == "ISD::BITCAST"; + } + void AnalyzeNode(const TreePatternNode *N) { if (N->isLeaf()) { if (DefInit *DI = dynamic_cast(N->getLeafValue())) { @@ -2333,8 +2412,10 @@ class InstAnalyzer { AnalyzeNode(N->getChild(i)); // Ignore set nodes, which are not SDNodes. - if (N->getOperator()->getName() == "set") + if (N->getOperator()->getName() == "set") { + IsBitcast = IsNodeBitcast(N); return; + } // Get information about the SDNode for the operator. const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator()); @@ -2363,12 +2444,13 @@ class InstAnalyzer { static void InferFromPattern(const CodeGenInstruction &Inst, bool &MayStore, bool &MayLoad, + bool &IsBitcast, bool &HasSideEffects, bool &IsVariadic, const CodeGenDAGPatterns &CDP) { - MayStore = MayLoad = HasSideEffects = IsVariadic = false; + MayStore = MayLoad = IsBitcast = HasSideEffects = IsVariadic = false; bool HadPattern = - InstAnalyzer(CDP, MayStore, MayLoad, HasSideEffects, IsVariadic) + InstAnalyzer(CDP, MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic) .Analyze(Inst.TheDef); // InstAnalyzer only correctly analyzes mayStore/mayLoad so far. @@ -2714,11 +2796,12 @@ void CodeGenDAGPatterns::InferInstructionFlags() { CodeGenInstruction &InstInfo = const_cast(*Instructions[i]); // Determine properties of the instruction from its pattern. - bool MayStore, MayLoad, HasSideEffects, IsVariadic; - InferFromPattern(InstInfo, MayStore, MayLoad, HasSideEffects, IsVariadic, - *this); + bool MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic; + InferFromPattern(InstInfo, MayStore, MayLoad, IsBitcast, + HasSideEffects, IsVariadic, *this); InstInfo.mayStore = MayStore; InstInfo.mayLoad = MayLoad; + InstInfo.isBitcast = IsBitcast; InstInfo.hasSideEffects = HasSideEffects; InstInfo.Operands.isVariadic = IsVariadic; } diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h index 946dceed66c0..e4e8574bbca2 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -239,6 +239,57 @@ class SDNodeInfo { return MadeChange; } }; + +/// TreePredicateFn - This is an abstraction that represents the predicates on +/// a PatFrag node. This is a simple one-word wrapper around a pointer to +/// provide nice accessors. +class TreePredicateFn { + /// PatFragRec - This is the TreePattern for the PatFrag that we + /// originally came from. + TreePattern *PatFragRec; +public: + /// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. + TreePredicateFn(TreePattern *N); + + + TreePattern *getOrigPatFragRecord() const { return PatFragRec; } + + /// isAlwaysTrue - Return true if this is a noop predicate. + bool isAlwaysTrue() const; + + bool isImmediatePattern() const { return !getImmCode().empty(); } + + /// getImmediatePredicateCode - Return the code that evaluates this pattern if + /// this is an immediate predicate. It is an error to call this on a + /// non-immediate pattern. + std::string getImmediatePredicateCode() const { + std::string Result = getImmCode(); + assert(!Result.empty() && "Isn't an immediate pattern!"); + return Result; + } + + + bool operator==(const TreePredicateFn &RHS) const { + return PatFragRec == RHS.PatFragRec; + } + + bool operator!=(const TreePredicateFn &RHS) const { return !(*this == RHS); } + + /// Return the name to use in the generated code to reference this, this is + /// "Predicate_foo" if from a pattern fragment "foo". + std::string getFnName() const; + + /// getCodeToRunOnSDNode - Return the code for the function body that + /// evaluates this predicate. The argument is expected to be in "Node", + /// not N. This handles casting and conversion to a concrete node type as + /// appropriate. + std::string getCodeToRunOnSDNode() const; + +private: + std::string getPredCode() const; + std::string getImmCode() const; +}; + /// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped /// patterns), and as such should be ref counted. We currently just leak all @@ -263,7 +314,7 @@ class TreePatternNode { /// PredicateFns - The predicate functions to execute on this node to check /// for a match. If this list is empty, no predicate is involved. - std::vector PredicateFns; + std::vector PredicateFns; /// TransformFn - The transformation function to execute on this node before /// it can be substituted into the resulting instruction on a pattern match. @@ -323,14 +374,18 @@ class TreePatternNode { return false; } - const std::vector &getPredicateFns() const {return PredicateFns;} + bool hasAnyPredicate() const { return !PredicateFns.empty(); } + + const std::vector &getPredicateFns() const { + return PredicateFns; + } void clearPredicateFns() { PredicateFns.clear(); } - void setPredicateFns(const std::vector &Fns) { + void setPredicateFns(const std::vector &Fns) { assert(PredicateFns.empty() && "Overwriting non-empty predicate list!"); PredicateFns = Fns; } - void addPredicateFn(const std::string &Fn) { - assert(!Fn.empty() && "Empty predicate string!"); + void addPredicateFn(const TreePredicateFn &Fn) { + assert(!Fn.isAlwaysTrue() && "Empty predicate string!"); if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) == PredicateFns.end()) PredicateFns.push_back(Fn); diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp index f37d3eabcd41..5b0aedfbc836 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp @@ -288,6 +288,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { isIndirectBranch = R->getValueAsBit("isIndirectBranch"); isCompare = R->getValueAsBit("isCompare"); isMoveImm = R->getValueAsBit("isMoveImm"); + isBitcast = R->getValueAsBit("isBitcast"); isBarrier = R->getValueAsBit("isBarrier"); isCall = R->getValueAsBit("isCall"); canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h index 58913b9da26b..5f1e0bea7666 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.h +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h @@ -26,7 +26,7 @@ namespace llvm { class DagInit; class CodeGenTarget; class StringRef; - + class CGIOperandList { public: class ConstraintInfo { @@ -34,25 +34,25 @@ namespace llvm { unsigned OtherTiedOperand; public: ConstraintInfo() : Kind(None) {} - + static ConstraintInfo getEarlyClobber() { ConstraintInfo I; I.Kind = EarlyClobber; I.OtherTiedOperand = 0; return I; } - + static ConstraintInfo getTied(unsigned Op) { ConstraintInfo I; I.Kind = Tied; I.OtherTiedOperand = Op; return I; } - + bool isNone() const { return Kind == None; } bool isEarlyClobber() const { return Kind == EarlyClobber; } bool isTied() const { return Kind == Tied; } - + unsigned getTiedOperand() const { assert(isTied()); return OtherTiedOperand; @@ -65,19 +65,19 @@ namespace llvm { /// Rec - The definition this operand is declared as. /// Record *Rec; - + /// Name - If this operand was assigned a symbolic name, this is it, /// otherwise, it's empty. std::string Name; - + /// PrinterMethodName - The method used to print operands of this type in /// the asmprinter. std::string PrinterMethodName; - + /// EncoderMethodName - The method used to get the machine operand value /// for binary encoding. "getMachineOpValue" by default. std::string EncoderMethodName; - + /// MIOperandNo - Currently (this is meant to be phased out), some logical /// operands correspond to multiple MachineInstr operands. In the X86 /// target for example, one address operand is represented as 4 @@ -86,27 +86,27 @@ namespace llvm { /// does, this contains the MI operand index of this operand. unsigned MIOperandNo; unsigned MINumOperands; // The number of operands. - + /// DoNotEncode - Bools are set to true in this vector for each operand in /// the DisableEncoding list. These should not be emitted by the code /// emitter. std::vector DoNotEncode; - + /// MIOperandInfo - Default MI operand type. Note an operand may be made /// up of multiple MI operands. DagInit *MIOperandInfo; - + /// Constraint info for this operand. This operand can have pieces, so we /// track constraint info for each. std::vector Constraints; - + OperandInfo(Record *R, const std::string &N, const std::string &PMN, const std::string &EMN, unsigned MION, unsigned MINO, DagInit *MIOI) : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN), MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {} - - + + /// getTiedOperand - If this operand is tied to another one, return the /// other operand number. Otherwise, return -1. int getTiedRegister() const { @@ -117,43 +117,44 @@ namespace llvm { return -1; } }; - + CGIOperandList(Record *D); - + Record *TheDef; // The actual record containing this OperandList. /// NumDefs - Number of def operands declared, this is the number of /// elements in the instruction's (outs) list. /// unsigned NumDefs; - + /// OperandList - The list of declared operands, along with their declared /// type (which is a record). std::vector OperandList; - + // Information gleaned from the operand list. bool isPredicable; bool hasOptionalDef; bool isVariadic; - + // Provide transparent accessors to the operand list. + bool empty() const { return OperandList.empty(); } unsigned size() const { return OperandList.size(); } const OperandInfo &operator[](unsigned i) const { return OperandList[i]; } OperandInfo &operator[](unsigned i) { return OperandList[i]; } OperandInfo &back() { return OperandList.back(); } const OperandInfo &back() const { return OperandList.back(); } - - + + /// getOperandNamed - Return the index of the operand with the specified /// non-empty name. If the instruction does not have an operand with the /// specified name, throw an exception. unsigned getOperandNamed(StringRef Name) const; - + /// hasOperandNamed - Query whether the instruction has an operand of the /// given name. If so, return true and set OpIdx to the index of the /// operand. Otherwise, return false. bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const; - + /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar", /// where $foo is a whole operand and $foo.bar refers to a suboperand. /// This throws an exception if the name is invalid. If AllowWholeOp is @@ -161,13 +162,13 @@ namespace llvm { /// not. std::pair ParseOperandName(const std::string &Op, bool AllowWholeOp = true); - + /// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a /// flat machineinstr operand #. unsigned getFlattenedOperandNumber(std::pair Op) const { return OperandList[Op.first].MIOperandNo + Op.second; } - + /// getSubOperandNumber - Unflatten a operand number into an /// operand/suboperand pair. std::pair getSubOperandNumber(unsigned Op) const { @@ -177,8 +178,8 @@ namespace llvm { return std::make_pair(i, Op-OperandList[i].MIOperandNo); } } - - + + /// isFlatOperandNotEmitted - Return true if the specified flat operand # /// should not be emitted with the code emitter. bool isFlatOperandNotEmitted(unsigned FlatOpNo) const { @@ -187,10 +188,10 @@ namespace llvm { return OperandList[Op.first].DoNotEncode[Op.second]; return false; } - + void ProcessDisableEncoding(std::string Value); }; - + class CodeGenInstruction { public: @@ -215,6 +216,7 @@ namespace llvm { bool isIndirectBranch; bool isCompare; bool isMoveImm; + bool isBitcast; bool isBarrier; bool isCall; bool canFoldAsLoad; @@ -242,45 +244,45 @@ namespace llvm { /// MVT::Other. MVT::SimpleValueType HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const; - - + + /// FlattenAsmStringVariants - Flatten the specified AsmString to only /// include text from the specified variant, returning the new string. static std::string FlattenAsmStringVariants(StringRef AsmString, unsigned Variant); }; - - + + /// CodeGenInstAlias - This represents an InstAlias definition. class CodeGenInstAlias { public: Record *TheDef; // The actual record defining this InstAlias. - + /// AsmString - The format string used to emit a .s file for the /// instruction. std::string AsmString; - + /// Result - The result instruction. DagInit *Result; - + /// ResultInst - The instruction generated by the alias (decoded from /// Result). CodeGenInstruction *ResultInst; - - + + struct ResultOperand { private: StringRef Name; Record *R; - + int64_t Imm; - public: + public: enum { K_Record, K_Imm, K_Reg } Kind; - + ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {} ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {} ResultOperand(Record *r) : R(r), Kind(K_Reg) {} @@ -288,13 +290,13 @@ namespace llvm { bool isRecord() const { return Kind == K_Record; } bool isImm() const { return Kind == K_Imm; } bool isReg() const { return Kind == K_Reg; } - + StringRef getName() const { assert(isRecord()); return Name; } Record *getRecord() const { assert(isRecord()); return R; } int64_t getImm() const { assert(isImm()); return Imm; } Record *getRegister() const { assert(isReg()); return R; } }; - + /// ResultOperands - The decoded operands for the result instruction. std::vector ResultOperands; @@ -304,13 +306,13 @@ namespace llvm { /// index specifies the suboperand. If there are no suboperands or if all /// of them are matched by the operand, the second value should be -1. std::vector > ResultInstOperandIndex; - + CodeGenInstAlias(Record *R, CodeGenTarget &T); bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, Record *InstOpRec, bool hasSubOps, SMLoc Loc, CodeGenTarget &T, ResultOperand &ResOp); - }; + }; } #endif diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h index bbd0cefa5804..39b92c515ad7 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.h +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h @@ -29,7 +29,8 @@ namespace llvm { struct CodeGenRegister { Record *TheDef; const std::string &getName() const; - unsigned DeclaredSpillSize, DeclaredSpillAlignment; + unsigned EnumValue; + unsigned CostPerUse; CodeGenRegister(Record *R); }; @@ -49,23 +50,23 @@ namespace llvm { const std::string &getName() const; const std::vector &getValueTypes() const {return VTs;} unsigned getNumValueTypes() const { return VTs.size(); } - + MVT::SimpleValueType getValueTypeNum(unsigned VTNum) const { if (VTNum < VTs.size()) return VTs[VTNum]; assert(0 && "VTNum greater than number of ValueTypes in RegClass!"); abort(); } - + bool containsRegister(Record *R) const { for (unsigned i = 0, e = Elements.size(); i != e; ++i) if (Elements[i] == R) return true; return false; } - + // Returns true if RC is a strict subclass. // RC is a sub-class of this class if it is a valid replacement for any - // instruction operand where a register of this classis required. It must + // instruction operand where a register of this classis required. It must // satisfy these conditions: // // 1. All RC registers are also in this. diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp index d0f7d8b44079..57f7fdc4dc49 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp @@ -164,11 +164,13 @@ void CodeGenTarget::ReadRegisters() const { Registers.reserve(Regs.size()); Registers.assign(Regs.begin(), Regs.end()); + // Assign the enumeration values. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) + Registers[i].EnumValue = i + 1; } CodeGenRegister::CodeGenRegister(Record *R) : TheDef(R) { - DeclaredSpillSize = R->getValueAsInt("SpillSize"); - DeclaredSpillAlignment = R->getValueAsInt("SpillAlignment"); + CostPerUse = R->getValueAsInt("CostPerUse"); } const std::string &CodeGenRegister::getName() const { @@ -199,7 +201,7 @@ const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { if (Reg.TheDef->getValueAsString("AsmName") == Name) return &Reg; } - + return 0; } @@ -216,7 +218,7 @@ getRegisterVTs(Record *R) const { } } } - + // Remove duplicates. array_pod_sort(Result.begin(), Result.end()); Result.erase(std::unique(Result.begin(), Result.end()), Result.end()); @@ -229,8 +231,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { if (R->getName().size() > 9 && R->getName()[9] == '.') { static unsigned AnonCounter = 0; R->setName("AnonRegClass_"+utostr(AnonCounter++)); - } - + } + std::vector TypeList = R->getValueAsListOfDefs("RegTypes"); for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { Record *Type = TypeList[i]; @@ -240,7 +242,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { VTs.push_back(getValueType(Type)); } assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); - + std::vector RegList = R->getValueAsListOfDefs("MemberList"); for (unsigned i = 0, e = RegList.size(); i != e; ++i) { Record *Reg = RegList[i]; @@ -293,7 +295,7 @@ void CodeGenTarget::ReadLegalValueTypes() const { for (unsigned i = 0, e = RCs.size(); i != e; ++i) for (unsigned ri = 0, re = RCs[i].VTs.size(); ri != re; ++ri) LegalValueTypes.push_back(RCs[i].VTs[ri]); - + // Remove duplicates. std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); LegalValueTypes.erase(std::unique(LegalValueTypes.begin(), @@ -314,10 +316,10 @@ void CodeGenTarget::ReadInstructions() const { static const CodeGenInstruction * GetInstByName(const char *Name, - const DenseMap &Insts, + const DenseMap &Insts, RecordKeeper &Records) { const Record *Rec = Records.getDef(Name); - + DenseMap::const_iterator I = Insts.find(Rec); if (Rec == 0 || I == Insts.end()) @@ -434,7 +436,7 @@ ComplexPattern::ComplexPattern(Record *R) { std::vector llvm::LoadIntrinsics(const RecordKeeper &RC, bool TargetOnly) { std::vector I = RC.getAllDerivedDefinitions("Intrinsic"); - + std::vector Result; for (unsigned i = 0, e = I.size(); i != e; ++i) { @@ -451,8 +453,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { ModRef = ReadWriteMem; isOverloaded = false; isCommutative = false; - - if (DefName.size() <= 4 || + + if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") throw "Intrinsic '" + DefName + "' does not start with 'int_'!"; @@ -472,11 +474,11 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { Name += (EnumName[i] == '_') ? '.' : EnumName[i]; } else { // Verify it starts with "llvm.". - if (Name.size() <= 5 || + if (Name.size() <= 5 || std::string(Name.begin(), Name.begin() + 5) != "llvm.") throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"; } - + // If TargetPrefix is specified, make sure that Name starts with // "llvm..". if (!TargetPrefix.empty()) { @@ -486,7 +488,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { throw "Intrinsic '" + DefName + "' does not start with 'llvm." + TargetPrefix + ".'!"; } - + // Parse the list of return types. std::vector OverloadedVTs; ListInit *TypeList = R->getValueAsListInit("RetTypes"); @@ -517,11 +519,11 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // Reject invalid types. if (VT == MVT::isVoid) throw "Intrinsic '" + DefName + " has void in result type list!"; - + IS.RetVTs.push_back(VT); IS.RetTypeDefs.push_back(TyEl); } - + // Parse the list of parameter types. TypeList = R->getValueAsListInit("ParamTypes"); for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { @@ -542,16 +544,16 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { "Expected iAny or vAny type"); } else VT = getValueType(TyEl->getValueAsDef("VT")); - + if (EVT(VT).isOverloaded()) { OverloadedVTs.push_back(VT); isOverloaded = true; } - + // Reject invalid types. if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) throw "Intrinsic '" + DefName + " has void in result type list!"; - + IS.ParamVTs.push_back(VT); IS.ParamTypeDefs.push_back(TyEl); } @@ -562,7 +564,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { Record *Property = PropList->getElementAsRecord(i); assert(Property->isSubClassOf("IntrinsicProperty") && "Expected a property!"); - + if (Property->getName() == "IntrNoMem") ModRef = NoMem; else if (Property->getName() == "IntrReadArgMem") diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h index f1058eb63181..4e041548f5f1 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.h +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h @@ -32,8 +32,8 @@ class CodeGenTarget; // SDNPMemOperand: indicates that a node touches memory and therefore must // have an associated memory operand that describes the access. enum SDNP { - SDNPCommutative, - SDNPAssociative, + SDNPCommutative, + SDNPAssociative, SDNPHasChain, SDNPOutGlue, SDNPInGlue, @@ -57,7 +57,7 @@ std::string getEnumName(MVT::SimpleValueType T); /// getQualifiedName - Return the name of the specified record, with a /// namespace qualifier if the record contains one. std::string getQualifiedName(const Record *R); - + /// CodeGenTarget - This class corresponds to the Target class in the .td files. /// class CodeGenTarget { @@ -74,7 +74,7 @@ class CodeGenTarget { void ReadRegisterClasses() const; void ReadInstructions() const; void ReadLegalValueTypes() const; - + mutable std::vector InstrsByEnum; public: CodeGenTarget(RecordKeeper &Records); @@ -102,7 +102,7 @@ class CodeGenTarget { if (Registers.empty()) ReadRegisters(); return Registers; } - + /// getRegisterByName - If there is a register with the specific AsmName, /// return it. const CodeGenRegister *getRegisterByName(StringRef Name) const; @@ -134,7 +134,7 @@ class CodeGenTarget { assert(0 && "Didn't find the register class"); abort(); } - + /// getRegisterClassForRegister - Find the register class that contains the /// specified physical register. If the register is not in a register /// class, return null. If the register is in multiple classes, and the @@ -192,19 +192,19 @@ class CodeGenTarget { /// getRegisterVTs - Find the union of all possible SimpleValueTypes for the /// specified physical register. std::vector getRegisterVTs(Record *R) const; - + const std::vector &getLegalValueTypes() const { if (LegalValueTypes.empty()) ReadLegalValueTypes(); return LegalValueTypes; } - + /// isLegalValueType - Return true if the specified value type is natively /// supported by the target (i.e. there are registers that directly hold it). bool isLegalValueType(MVT::SimpleValueType VT) const { const std::vector &LegalVTs = getLegalValueTypes(); for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i) if (LegalVTs[i] == VT) return true; - return false; + return false; } private: @@ -213,7 +213,7 @@ class CodeGenTarget { return Instructions; } public: - + CodeGenInstruction &getInstruction(const Record *InstRec) const { if (Instructions.empty()) ReadInstructions(); DenseMap::iterator I = @@ -233,12 +233,12 @@ class CodeGenTarget { typedef std::vector::const_iterator inst_iterator; inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();} inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); } - - + + /// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]? /// bool isLittleEndianEncoding() const; - + private: void ComputeInstrsByEnum() const; }; diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp index 8a73404dad95..d66ae96cbc97 100644 --- a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp @@ -27,7 +27,7 @@ using namespace llvm; static unsigned getResultPatternCost(TreePatternNode *P, CodeGenDAGPatterns &CGP) { if (P->isLeaf()) return 0; - + unsigned Cost = 0; Record *Op = P->getOperator(); if (Op->isSubClassOf("Instruction")) { @@ -43,7 +43,7 @@ static unsigned getResultPatternCost(TreePatternNode *P, /// getResultPatternCodeSize - Compute the code size of instructions for this /// pattern. -static unsigned getResultPatternSize(TreePatternNode *P, +static unsigned getResultPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) { if (P->isLeaf()) return 0; @@ -64,21 +64,21 @@ namespace { struct PatternSortingPredicate { PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {} CodeGenDAGPatterns &CGP; - + bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) { const TreePatternNode *LHSSrc = LHS->getSrcPattern(); const TreePatternNode *RHSSrc = RHS->getSrcPattern(); - + if (LHSSrc->getNumTypes() != 0 && RHSSrc->getNumTypes() != 0 && LHSSrc->getType(0) != RHSSrc->getType(0)) { MVT::SimpleValueType V1 = LHSSrc->getType(0), V2 = RHSSrc->getType(0); if (MVT(V1).isVector() != MVT(V2).isVector()) return MVT(V2).isVector(); - + if (MVT(V1).isFloatingPoint() != MVT(V2).isFloatingPoint()) return MVT(V2).isFloatingPoint(); } - + // Otherwise, if the patterns might both match, sort based on complexity, // which means that we prefer to match patterns that cover more nodes in the // input over nodes that cover fewer. @@ -86,18 +86,18 @@ struct PatternSortingPredicate { unsigned RHSSize = RHS->getPatternComplexity(CGP); if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost if (LHSSize < RHSSize) return false; - + // If the patterns have equal complexity, compare generated instruction cost unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP); unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP); if (LHSCost < RHSCost) return true; if (LHSCost > RHSCost) return false; - + unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP); unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP); if (LHSPatSize < RHSPatSize) return true; if (LHSPatSize > RHSPatSize) return false; - + // Sort based on the UID of the pattern, giving us a deterministic ordering // if all other sorting conditions fail. assert(LHS == RHS || LHS->ID != RHS->ID); @@ -110,7 +110,7 @@ struct PatternSortingPredicate { void DAGISelEmitter::run(raw_ostream &OS) { EmitSourceFileHeader("DAG Instruction Selector for the " + CGP.getTargetInfo().getName() + " target", OS); - + OS << "// *** NOTE: This file is #included into the middle of the target\n" << "// *** instruction selector class. These functions are really " << "methods.\n\n"; @@ -132,8 +132,8 @@ void DAGISelEmitter::run(raw_ostream &OS) { // We want to process the matches in order of minimal cost. Sort the patterns // so the least cost one is at the start. std::sort(Patterns.begin(), Patterns.end(), PatternSortingPredicate(CGP)); - - + + // Convert each variant of each pattern into a Matcher. std::vector PatternMatchers; for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { @@ -144,7 +144,7 @@ void DAGISelEmitter::run(raw_ostream &OS) { break; } } - + Matcher *TheMatcher = new ScopeMatcher(&PatternMatchers[0], PatternMatchers.size()); diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.h b/contrib/llvm/utils/TableGen/DAGISelEmitter.h index 2117e65455ac..35ab55034308 100644 --- a/contrib/llvm/utils/TableGen/DAGISelEmitter.h +++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.h @@ -16,7 +16,6 @@ #include "TableGenBackend.h" #include "CodeGenDAGPatterns.h" -#include namespace llvm { diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp index 2afa2b907bc4..b12e1015c33b 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp @@ -83,6 +83,15 @@ ScopeMatcher::~ScopeMatcher() { } +CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred) + : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()) {} + +TreePredicateFn CheckPredicateMatcher::getPredicate() const { + return TreePredicateFn(Pred); +} + + + // printImpl methods. void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { @@ -129,7 +138,7 @@ printImpl(raw_ostream &OS, unsigned indent) const { } void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const { - OS.indent(indent) << "CheckPredicate " << PredName << '\n'; + OS.indent(indent) << "CheckPredicate " << getPredicate().getFnName() << '\n'; } void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { @@ -263,7 +272,7 @@ unsigned CheckPatternPredicateMatcher::getHashImpl() const { } unsigned CheckPredicateMatcher::getHashImpl() const { - return HashString(PredName); + return HashString(getPredicate().getFnName()); } unsigned CheckOpcodeMatcher::getHashImpl() const { @@ -301,7 +310,6 @@ bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const { Opcode.getEnumName(); } - bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const { const EmitNodeMatcherCommon *M = cast(m); return M->OpcodeName == OpcodeName && M->VTs == VTs && diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.h b/contrib/llvm/utils/TableGen/DAGISelMatcher.h index 8e6e44647ea1..dcb8da71086e 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcher.h +++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.h @@ -17,6 +17,7 @@ #include "llvm/Support/Casting.h" namespace llvm { + struct CodeGenRegister; class CodeGenDAGPatterns; class Matcher; class PatternToMatch; @@ -24,6 +25,8 @@ namespace llvm { class ComplexPattern; class Record; class SDNodeInfo; + class TreePredicateFn; + class TreePattern; Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant, const CodeGenDAGPatterns &CGP); @@ -418,12 +421,11 @@ class CheckPatternPredicateMatcher : public Matcher { /// CheckPredicateMatcher - This checks the target-specific predicate to /// see if the node is acceptable. class CheckPredicateMatcher : public Matcher { - StringRef PredName; + TreePattern *Pred; public: - CheckPredicateMatcher(StringRef predname) - : Matcher(CheckPredicate), PredName(predname) {} + CheckPredicateMatcher(const TreePredicateFn &pred); - StringRef getPredicateName() const { return PredName; } + TreePredicateFn getPredicate() const; static inline bool classof(const Matcher *N) { return N->getKind() == CheckPredicate; @@ -435,7 +437,7 @@ class CheckPredicateMatcher : public Matcher { private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { - return cast(M)->PredName == PredName; + return cast(M)->Pred == Pred; } virtual unsigned getHashImpl() const; }; @@ -816,13 +818,13 @@ class EmitStringIntegerMatcher : public Matcher { class EmitRegisterMatcher : public Matcher { /// Reg - The def for the register that we're emitting. If this is null, then /// this is a reference to zero_reg. - Record *Reg; + const CodeGenRegister *Reg; MVT::SimpleValueType VT; public: - EmitRegisterMatcher(Record *reg, MVT::SimpleValueType vt) + EmitRegisterMatcher(const CodeGenRegister *reg, MVT::SimpleValueType vt) : Matcher(EmitRegister), Reg(reg), VT(vt) {} - Record *getReg() const { return Reg; } + const CodeGenRegister *getReg() const { return Reg; } MVT::SimpleValueType getVT() const { return VT; } static inline bool classof(const Matcher *N) { diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp index 0b7fbf7c8518..acb0135422e8 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -33,8 +33,12 @@ OmitComments("omit-comments", cl::desc("Do not generate comments"), namespace { class MatcherTableEmitter { const CodeGenDAGPatterns &CGP; - StringMap NodePredicateMap, PatternPredicateMap; - std::vector NodePredicates, PatternPredicates; + + DenseMap NodePredicateMap; + std::vector NodePredicates; + + StringMap PatternPredicateMap; + std::vector PatternPredicates; DenseMap ComplexPatternMap; std::vector ComplexPatterns; @@ -44,26 +48,28 @@ class MatcherTableEmitter { std::vector NodeXForms; public: - MatcherTableEmitter(const CodeGenDAGPatterns &cgp) : CGP(cgp) {} + MatcherTableEmitter(const CodeGenDAGPatterns &cgp) + : CGP(cgp) {} unsigned EmitMatcherList(const Matcher *N, unsigned Indent, unsigned StartIdx, formatted_raw_ostream &OS); - + void EmitPredicateFunctions(formatted_raw_ostream &OS); - + void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS); private: unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, formatted_raw_ostream &OS); - - unsigned getNodePredicate(StringRef PredName) { - unsigned &Entry = NodePredicateMap[PredName]; + + unsigned getNodePredicate(TreePredicateFn Pred) { + unsigned &Entry = NodePredicateMap[Pred.getOrigPatFragRecord()]; if (Entry == 0) { - NodePredicates.push_back(PredName.str()); + NodePredicates.push_back(Pred); Entry = NodePredicates.size(); } return Entry-1; } + unsigned getPatternPredicate(StringRef PredName) { unsigned &Entry = PatternPredicateMap[PredName]; if (Entry == 0) { @@ -72,7 +78,6 @@ class MatcherTableEmitter { } return Entry-1; } - unsigned getComplexPat(const ComplexPattern &P) { unsigned &Entry = ComplexPatternMap[&P]; if (Entry == 0) { @@ -81,7 +86,7 @@ class MatcherTableEmitter { } return Entry-1; } - + unsigned getNodeXFormID(Record *Rec) { unsigned &Entry = NodeXFormMap[Rec]; if (Entry == 0) { @@ -90,13 +95,13 @@ class MatcherTableEmitter { } return Entry-1; } - + }; } // end anonymous namespace. static unsigned GetVBRSize(unsigned Val) { if (Val <= 127) return 1; - + unsigned NumBytes = 0; while (Val >= 128) { Val >>= 7; @@ -112,7 +117,7 @@ static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) { OS << Val << ", "; return 1; } - + uint64_t InVal = Val; unsigned NumBytes = 0; while (Val >= 128) { @@ -133,14 +138,14 @@ unsigned MatcherTableEmitter:: EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, formatted_raw_ostream &OS) { OS.PadToColumn(Indent*2); - + switch (N->getKind()) { case Matcher::Scope: { const ScopeMatcher *SM = cast(N); assert(SM->getNext() == 0 && "Shouldn't have next after scope"); - + unsigned StartIdx = CurrentIdx; - + // Emit all of the children. for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) { if (i == 0) { @@ -164,29 +169,29 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, unsigned VBRSize = 0; do { VBRSize = GetVBRSize(ChildSize); - + TmpBuf.clear(); raw_svector_ostream OS(TmpBuf); formatted_raw_ostream FOS(OS); ChildSize = EmitMatcherList(SM->getChild(i), Indent+1, CurrentIdx+VBRSize, FOS); } while (GetVBRSize(ChildSize) != VBRSize); - + assert(ChildSize != 0 && "Should not have a zero-sized child!"); - + CurrentIdx += EmitVBRValue(ChildSize, OS); if (!OmitComments) { OS << "/*->" << CurrentIdx+ChildSize << "*/"; - + if (i == 0) OS.PadToColumn(CommentIndent) << "// " << SM->getNumChildren() << " children in Scope"; } - + OS << '\n' << TmpBuf.str(); CurrentIdx += ChildSize; } - + // Emit a zero as a sentinel indicating end of 'Scope'. if (!OmitComments) OS << "/*" << CurrentIdx << "*/"; @@ -196,7 +201,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << '\n'; return CurrentIdx - StartIdx + 1; } - + case Matcher::RecordNode: OS << "OPC_RecordNode,"; if (!OmitComments) @@ -215,30 +220,30 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, << cast(N)->getWhatFor(); OS << '\n'; return 1; - + case Matcher::RecordMemRef: OS << "OPC_RecordMemRef,\n"; return 1; - + case Matcher::CaptureGlueInput: OS << "OPC_CaptureGlueInput,\n"; return 1; - + case Matcher::MoveChild: OS << "OPC_MoveChild, " << cast(N)->getChildNo() << ",\n"; return 2; - + case Matcher::MoveParent: OS << "OPC_MoveParent,\n"; return 1; - + case Matcher::CheckSame: OS << "OPC_CheckSame, " << cast(N)->getMatchNumber() << ",\n"; return 2; case Matcher::CheckPatternPredicate: { - StringRef Pred = cast(N)->getPredicate(); + StringRef Pred =cast(N)->getPredicate(); OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ','; if (!OmitComments) OS.PadToColumn(CommentIndent) << "// " << Pred; @@ -246,23 +251,23 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, return 2; } case Matcher::CheckPredicate: { - StringRef Pred = cast(N)->getPredicateName(); + TreePredicateFn Pred = cast(N)->getPredicate(); OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ','; if (!OmitComments) - OS.PadToColumn(CommentIndent) << "// " << Pred; + OS.PadToColumn(CommentIndent) << "// " << Pred.getFnName(); OS << '\n'; return 2; } case Matcher::CheckOpcode: - OS << "OPC_CheckOpcode, TARGET_OPCODE(" + OS << "OPC_CheckOpcode, TARGET_VAL(" << cast(N)->getOpcode().getEnumName() << "),\n"; return 3; - + case Matcher::SwitchOpcode: case Matcher::SwitchType: { unsigned StartIdx = CurrentIdx; - + unsigned NumCases; if (const SwitchOpcodeMatcher *SOM = dyn_cast(N)) { OS << "OPC_SwitchOpcode "; @@ -276,7 +281,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << "/*" << NumCases << " cases */"; OS << ", "; ++CurrentIdx; - + // For each case we emit the size, then the opcode, then the matcher. for (unsigned i = 0, e = NumCases; i != e; ++i) { const Matcher *Child; @@ -288,7 +293,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, Child = cast(N)->getCaseMatcher(i); IdxSize = 1; // size of type in table is 1 byte. } - + // We need to encode the opcode and the offset of the case code before // emitting the case code. Handle this by buffering the output into a // string while we get the size. Unfortunately, the offset of the @@ -299,29 +304,29 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, unsigned VBRSize = 0; do { VBRSize = GetVBRSize(ChildSize); - + TmpBuf.clear(); raw_svector_ostream OS(TmpBuf); formatted_raw_ostream FOS(OS); ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize, FOS); } while (GetVBRSize(ChildSize) != VBRSize); - + assert(ChildSize != 0 && "Should not have a zero-sized child!"); - + if (i != 0) { OS.PadToColumn(Indent*2); if (!OmitComments) OS << (isa(N) ? "/*SwitchOpcode*/ " : "/*SwitchType*/ "); } - + // Emit the VBR. CurrentIdx += EmitVBRValue(ChildSize, OS); - + OS << ' '; if (const SwitchOpcodeMatcher *SOM = dyn_cast(N)) - OS << "TARGET_OPCODE(" << SOM->getCaseOpcode(i).getEnumName() << "),"; + OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),"; else OS << getEnumName(cast(N)->getCaseType(i)) << ','; @@ -351,13 +356,13 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << "OPC_CheckType, " << getEnumName(cast(N)->getType()) << ",\n"; return 2; - + case Matcher::CheckChildType: OS << "OPC_CheckChild" << cast(N)->getChildNo() << "Type, " << getEnumName(cast(N)->getType()) << ",\n"; return 2; - + case Matcher::CheckInteger: { OS << "OPC_CheckInteger, "; unsigned Bytes=1+EmitVBRValue(cast(N)->getValue(), OS); @@ -368,7 +373,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << "OPC_CheckCondCode, ISD::" << cast(N)->getCondCodeName() << ",\n"; return 2; - + case Matcher::CheckValueType: OS << "OPC_CheckValueType, MVT::" << cast(N)->getTypeName() << ",\n"; @@ -379,20 +384,20 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, const ComplexPattern &Pattern = CCPM->getPattern(); OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/" << CCPM->getMatchNumber() << ','; - + if (!OmitComments) { OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc(); OS << ":$" << CCPM->getName(); for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i) OS << " #" << CCPM->getFirstResult()+i; - + if (Pattern.hasProperty(SDNPHasChain)) OS << " + chain result"; } OS << '\n'; return 3; } - + case Matcher::CheckAndImm: { OS << "OPC_CheckAndImm, "; unsigned Bytes=1+EmitVBRValue(cast(N)->getValue(), OS); @@ -406,11 +411,11 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << '\n'; return Bytes; } - + case Matcher::CheckFoldableChainNode: OS << "OPC_CheckFoldableChainNode,\n"; return 1; - + case Matcher::EmitInteger: { int64_t Val = cast(N)->getValue(); OS << "OPC_EmitInteger, " @@ -427,35 +432,45 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, << Val << ",\n"; return 3; } - - case Matcher::EmitRegister: - OS << "OPC_EmitRegister, " - << getEnumName(cast(N)->getVT()) << ", "; - if (Record *R = cast(N)->getReg()) - OS << getQualifiedName(R) << ",\n"; - else { - OS << "0 "; - if (!OmitComments) - OS << "/*zero_reg*/"; - OS << ",\n"; + + case Matcher::EmitRegister: { + const EmitRegisterMatcher *Matcher = cast(N); + const CodeGenRegister *Reg = Matcher->getReg(); + // If the enum value of the register is larger than one byte can handle, + // use EmitRegister2. + if (Reg && Reg->EnumValue > 255) { + OS << "OPC_EmitRegister2, " << getEnumName(Matcher->getVT()) << ", "; + OS << "TARGET_VAL(" << getQualifiedName(Reg->TheDef) << "),\n"; + return 4; + } else { + OS << "OPC_EmitRegister, " << getEnumName(Matcher->getVT()) << ", "; + if (Reg) { + OS << getQualifiedName(Reg->TheDef) << ",\n"; + } else { + OS << "0 "; + if (!OmitComments) + OS << "/*zero_reg*/"; + OS << ",\n"; + } + return 3; } - return 3; - + } + case Matcher::EmitConvertToTarget: OS << "OPC_EmitConvertToTarget, " << cast(N)->getSlot() << ",\n"; return 2; - + case Matcher::EmitMergeInputChains: { const EmitMergeInputChainsMatcher *MN = cast(N); - + // Handle the specialized forms OPC_EmitMergeInputChains1_0 and 1_1. if (MN->getNumNodes() == 1 && MN->getNode(0) < 2) { OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n"; return 1; } - + OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", "; for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i) OS << MN->getNode(i) << ", "; @@ -477,13 +492,13 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS <<'\n'; return 3; } - + case Matcher::EmitNode: case Matcher::MorphNodeTo: { const EmitNodeMatcherCommon *EN = cast(N); OS << (isa(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo"); - OS << ", TARGET_OPCODE(" << EN->getOpcodeName() << "), 0"; - + OS << ", TARGET_VAL(" << EN->getOpcodeName() << "), 0"; + if (EN->hasChain()) OS << "|OPFL_Chain"; if (EN->hasInFlag()) OS << "|OPFL_GlueInput"; if (EN->hasOutFlag()) OS << "|OPFL_GlueOutput"; @@ -491,7 +506,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, if (EN->getNumFixedArityOperands() != -1) OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands(); OS << ",\n"; - + OS.PadToColumn(Indent*2+4) << EN->getNumVTs(); if (!OmitComments) OS << "/*#VTs*/"; @@ -506,7 +521,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, unsigned NumOperandBytes = 0; for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i) NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS); - + if (!OmitComments) { // Print the result #'s for EmitNode. if (const EmitNodeMatcher *E = dyn_cast(EN)) { @@ -521,14 +536,14 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, if (const MorphNodeToMatcher *SNT = dyn_cast(N)) { OS.PadToColumn(Indent*2) << "// Src: " - << *SNT->getPattern().getSrcPattern() << " - Complexity = " + << *SNT->getPattern().getSrcPattern() << " - Complexity = " << SNT->getPattern().getPatternComplexity(CGP) << '\n'; OS.PadToColumn(Indent*2) << "// Dst: " << *SNT->getPattern().getDstPattern() << '\n'; } } else OS << '\n'; - + return 6+EN->getNumVTs()+NumOperandBytes; } case Matcher::MarkGlueResults: { @@ -549,7 +564,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << '\n'; if (!OmitComments) { OS.PadToColumn(Indent*2) << "// Src: " - << *CM->getPattern().getSrcPattern() << " - Complexity = " + << *CM->getPattern().getSrcPattern() << " - Complexity = " << CM->getPattern().getPatternComplexity(CGP) << '\n'; OS.PadToColumn(Indent*2) << "// Dst: " << *CM->getPattern().getDstPattern(); @@ -573,7 +588,7 @@ EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx, unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS); Size += MatcherSize; CurrentIdx += MatcherSize; - + // If there are other nodes in this list, iterate to them, otherwise we're // done. N = N->getNext(); @@ -592,44 +607,32 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { OS << " }\n"; OS << "}\n\n"; } - + // Emit Node predicates. // FIXME: Annoyingly, these are stored by name, which we never even emit. Yay? StringMap PFsByName; - + for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end(); I != E; ++I) PFsByName[I->first->getName()] = I->second; - + if (!NodePredicates.empty()) { OS << "bool CheckNodePredicate(SDNode *Node, unsigned PredNo) const {\n"; OS << " switch (PredNo) {\n"; OS << " default: assert(0 && \"Invalid predicate in table?\");\n"; for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) { - // FIXME: Storing this by name is horrible. - TreePattern *P =PFsByName[NodePredicates[i].substr(strlen("Predicate_"))]; - assert(P && "Unknown name?"); - // Emit the predicate code corresponding to this pattern. - std::string Code = P->getRecord()->getValueAsCode("Predicate"); - assert(!Code.empty() && "No code in this predicate"); - OS << " case " << i << ": { // " << NodePredicates[i] << '\n'; - std::string ClassName; - if (P->getOnlyTree()->isLeaf()) - ClassName = "SDNode"; - else - ClassName = - CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName(); - if (ClassName == "SDNode") - OS << " SDNode *N = Node;\n"; - else - OS << " " << ClassName << "*N = cast<" << ClassName << ">(Node);\n"; - OS << Code << "\n }\n"; + TreePredicateFn PredFn = NodePredicates[i]; + + assert(!PredFn.isAlwaysTrue() && "No code in this predicate"); + OS << " case " << i << ": { // " << NodePredicates[i].getFnName() <<'\n'; + + OS << PredFn.getCodeToRunOnSDNode() << "\n }\n"; } OS << " }\n"; OS << "}\n\n"; } - + // Emit CompletePattern matchers. // FIXME: This should be const. if (!ComplexPatterns.empty()) { @@ -645,7 +648,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { if (P.hasProperty(SDNPHasChain)) ++NumOps; // Get the chained node too. - + OS << " case " << i << ":\n"; OS << " Result.resize(NextRes+" << NumOps << ");\n"; OS << " return " << P.getSelectFunc(); @@ -655,12 +658,12 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { // first argument. if (P.hasProperty(SDNPWantRoot)) OS << "Root, "; - + // If the complex pattern wants the parent of the operand being matched, // pass it in as the next argument. if (P.hasProperty(SDNPWantParent)) OS << "Parent, "; - + OS << "N"; for (unsigned i = 0; i != NumOps; ++i) OS << ", Result[NextRes+" << i << "].first"; @@ -669,28 +672,28 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { OS << " }\n"; OS << "}\n\n"; } - - + + // Emit SDNodeXForm handlers. // FIXME: This should be const. if (!NodeXForms.empty()) { OS << "SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {\n"; OS << " switch (XFormNo) {\n"; OS << " default: assert(0 && \"Invalid xform # in table?\");\n"; - + // FIXME: The node xform could take SDValue's instead of SDNode*'s. for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) { const CodeGenDAGPatterns::NodeXForm &Entry = CGP.getSDNodeTransform(NodeXForms[i]); - + Record *SDNode = Entry.first; const std::string &Code = Entry.second; - + OS << " case " << i << ": { "; if (!OmitComments) OS << "// " << NodeXForms[i]->getName(); OS << '\n'; - + std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName(); if (ClassName == "SDNode") OS << " SDNode *N = V.getNode();\n"; @@ -710,12 +713,12 @@ static void BuildHistogram(const Matcher *M, std::vector &OpcodeFreq){ if (unsigned(M->getKind()) >= OpcodeFreq.size()) OpcodeFreq.resize(M->getKind()+1); OpcodeFreq[M->getKind()]++; - + // Handle recursive nodes. if (const ScopeMatcher *SM = dyn_cast(M)) { for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) BuildHistogram(SM->getChild(i), OpcodeFreq); - } else if (const SwitchOpcodeMatcher *SOM = + } else if (const SwitchOpcodeMatcher *SOM = dyn_cast(M)) { for (unsigned i = 0, e = SOM->getNumCases(); i != e; ++i) BuildHistogram(SOM->getCaseMatcher(i), OpcodeFreq); @@ -730,16 +733,16 @@ void MatcherTableEmitter::EmitHistogram(const Matcher *M, formatted_raw_ostream &OS) { if (OmitComments) return; - + std::vector OpcodeFreq; BuildHistogram(M, OpcodeFreq); - + OS << " // Opcode Histogram:\n"; for (unsigned i = 0, e = OpcodeFreq.size(); i != e; ++i) { OS << " // #"; switch ((Matcher::KindTy)i) { - case Matcher::Scope: OS << "OPC_Scope"; break; - case Matcher::RecordNode: OS << "OPC_RecordNode"; break; + case Matcher::Scope: OS << "OPC_Scope"; break; + case Matcher::RecordNode: OS << "OPC_RecordNode"; break; case Matcher::RecordChild: OS << "OPC_RecordChild"; break; case Matcher::RecordMemRef: OS << "OPC_RecordMemRef"; break; case Matcher::CaptureGlueInput: OS << "OPC_CaptureGlueInput"; break; @@ -772,9 +775,9 @@ void MatcherTableEmitter::EmitHistogram(const Matcher *M, case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break; case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break; case Matcher::MarkGlueResults: OS << "OPC_MarkGlueResults"; break; - case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break; + case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break; } - + OS.PadToColumn(40) << " = " << OpcodeFreq[i] << '\n'; } OS << '\n'; @@ -782,26 +785,28 @@ void MatcherTableEmitter::EmitHistogram(const Matcher *M, void llvm::EmitMatcherTable(const Matcher *TheMatcher, - const CodeGenDAGPatterns &CGP, raw_ostream &O) { + const CodeGenDAGPatterns &CGP, + raw_ostream &O) { formatted_raw_ostream OS(O); - + OS << "// The main instruction selector code.\n"; OS << "SDNode *SelectCode(SDNode *N) {\n"; MatcherTableEmitter MatcherEmitter(CGP); - OS << " // Opcodes are emitted as 2 bytes, TARGET_OPCODE handles this.\n"; - OS << " #define TARGET_OPCODE(X) X & 255, unsigned(X) >> 8\n"; + OS << " // Some target values are emitted as 2 bytes, TARGET_VAL handles\n"; + OS << " // this.\n"; + OS << " #define TARGET_VAL(X) X & 255, unsigned(X) >> 8\n"; OS << " static const unsigned char MatcherTable[] = {\n"; unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 5, 0, OS); OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n"; - + MatcherEmitter.EmitHistogram(TheMatcher, OS); - - OS << " #undef TARGET_OPCODE\n"; + + OS << " #undef TARGET_VAL\n"; OS << " return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n"; OS << '\n'; - + // Next up, emit the function for node and pattern predicates: MatcherEmitter.EmitPredicateFunctions(OS); } diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp index 7c0badec1d6d..393ac69eb169 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -9,7 +9,9 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" +#include "CodeGenRegisters.h" #include "Record.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include @@ -91,6 +93,10 @@ namespace { /// CurPredicate - As we emit matcher nodes, this points to the latest check /// which should have future checks stuck into its Next position. Matcher *CurPredicate; + + /// RegisterDefMap - A map of register record definitions to the + /// corresponding target CodeGenRegister entry. + DenseMap RegisterDefMap; public: MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp); @@ -159,6 +165,12 @@ MatcherGen::MatcherGen(const PatternToMatch &pattern, // If there are types that are manifestly known, infer them. InferPossibleTypes(); + + // Populate the map from records to CodeGenRegister entries. + const CodeGenTarget &CGT = CGP.getTargetInfo(); + const std::vector &Registers = CGT.getRegisters(); + for (unsigned i = 0, e = Registers.size(); i != e; ++i) + RegisterDefMap[Registers[i].TheDef] = &Registers[i]; } /// InferPossibleTypes - As we emit the pattern, we end up generating type @@ -578,7 +590,8 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, // If this is an explicit register reference, handle it. if (DefInit *DI = dynamic_cast(N->getLeafValue())) { if (DI->getDef()->isSubClassOf("Register")) { - AddMatcher(new EmitRegisterMatcher(DI->getDef(), N->getType(0))); + AddMatcher(new EmitRegisterMatcher(RegisterDefMap[DI->getDef()], + N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp index 3169ea1e16af..f9964223c248 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp @@ -18,7 +18,6 @@ #include "llvm/ADT/StringSet.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include using namespace llvm; /// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record' diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp index 90a2af21f3a4..d68d3b00e66d 100644 --- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp @@ -40,12 +40,12 @@ using namespace llvm::X86Disassembler; /// all cases as a 64-bit instruction with only OPSIZE set. (The XS prefix /// may have effects on its execution, but does not change the instruction /// returned.) This allows considerable space savings in other tables. -/// - Four tables (ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, and -/// THREEBYTE3A_SYM) contain the hierarchy that the decoder traverses while -/// decoding an instruction. At the lowest level of this hierarchy are -/// instruction UIDs, 16-bit integers that can be used to uniquely identify -/// the instruction and correspond exactly to its position in the list of -/// CodeGenInstructions for the target. +/// - Six tables (ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM, +/// THREEBYTEA6_SYM, and THREEBYTEA7_SYM contain the hierarchy that the +/// decoder traverses while decoding an instruction. At the lowest level of +/// this hierarchy are instruction UIDs, 16-bit integers that can be used to +/// uniquely identify the instruction and correspond exactly to its position +/// in the list of CodeGenInstructions for the target. /// - One table (INSTRUCTIONS_SYM) contains information about the operands of /// each instruction and how to decode them. /// diff --git a/contrib/llvm/utils/TableGen/EDEmitter.cpp b/contrib/llvm/utils/TableGen/EDEmitter.cpp index 020a4a312d7b..5358c0c36169 100644 --- a/contrib/llvm/utils/TableGen/EDEmitter.cpp +++ b/contrib/llvm/utils/TableGen/EDEmitter.cpp @@ -24,7 +24,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include #include #include @@ -598,6 +597,11 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("t2adrlabel"); IMM("shift_imm"); IMM("neon_vcvt_imm32"); + IMM("shr_imm8"); + IMM("shr_imm16"); + IMM("shr_imm32"); + IMM("shr_imm64"); + IMM("t2ldrlabel"); MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ? @@ -632,10 +636,12 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I + MISC("addrmode7", "kOperandTypeARMAddrMode7"); // R MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ... MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ... MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ... MISC("it_mask", "kOperandTypeThumbITMask"); // I + MISC("t2addrmode_reg", "kOperandTypeThumb2AddrModeReg"); // R MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I @@ -853,6 +859,7 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) { operandTypes.addEntry("kOperandTypeARMAddrMode5"); operandTypes.addEntry("kOperandTypeARMAddrMode6"); operandTypes.addEntry("kOperandTypeARMAddrMode6Offset"); + operandTypes.addEntry("kOperandTypeARMAddrMode7"); operandTypes.addEntry("kOperandTypeARMAddrModePC"); operandTypes.addEntry("kOperandTypeARMRegisterList"); operandTypes.addEntry("kOperandTypeARMDPRRegisterList"); @@ -864,6 +871,7 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) { operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); operandTypes.addEntry("kOperandTypeThumbAddrModePC"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeReg"); operandTypes.addEntry("kOperandTypeThumb2SoReg"); operandTypes.addEntry("kOperandTypeThumb2SoImm"); operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8"); diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp index f01de1dcfce6..9c11bf6e5e33 100644 --- a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp @@ -35,36 +35,150 @@ struct InstructionMemo { std::string SubRegNo; std::vector* PhysRegs; }; + +/// ImmPredicateSet - This uniques predicates (represented as a string) and +/// gives them unique (small) integer ID's that start at 0. +class ImmPredicateSet { + DenseMap ImmIDs; + std::vector PredsByName; +public: + + unsigned getIDFor(TreePredicateFn Pred) { + unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()]; + if (Entry == 0) { + PredsByName.push_back(Pred); + Entry = PredsByName.size(); + } + return Entry-1; + } + + const TreePredicateFn &getPredicate(unsigned i) { + assert(i < PredsByName.size()); + return PredsByName[i]; + } + + typedef std::vector::const_iterator iterator; + iterator begin() const { return PredsByName.begin(); } + iterator end() const { return PredsByName.end(); } + +}; /// OperandsSignature - This class holds a description of a list of operand /// types. It has utility methods for emitting text based on the operands. /// struct OperandsSignature { - std::vector Operands; + class OpKind { + enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 }; + char Repr; + public: + + OpKind() : Repr(OK_Invalid) {} + + bool operator<(OpKind RHS) const { return Repr < RHS.Repr; } + bool operator==(OpKind RHS) const { return Repr == RHS.Repr; } + + static OpKind getReg() { OpKind K; K.Repr = OK_Reg; return K; } + static OpKind getFP() { OpKind K; K.Repr = OK_FP; return K; } + static OpKind getImm(unsigned V) { + assert((unsigned)OK_Imm+V < 128 && + "Too many integer predicates for the 'Repr' char"); + OpKind K; K.Repr = OK_Imm+V; return K; + } + + bool isReg() const { return Repr == OK_Reg; } + bool isFP() const { return Repr == OK_FP; } + bool isImm() const { return Repr >= OK_Imm; } + + unsigned getImmCode() const { assert(isImm()); return Repr-OK_Imm; } + + void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates, + bool StripImmCodes) const { + if (isReg()) + OS << 'r'; + else if (isFP()) + OS << 'f'; + else { + OS << 'i'; + if (!StripImmCodes) + if (unsigned Code = getImmCode()) + OS << "_" << ImmPredicates.getPredicate(Code-1).getFnName(); + } + } + }; + + + SmallVector Operands; bool operator<(const OperandsSignature &O) const { return Operands < O.Operands; } + bool operator==(const OperandsSignature &O) const { + return Operands == O.Operands; + } bool empty() const { return Operands.empty(); } + bool hasAnyImmediateCodes() const { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + if (Operands[i].isImm() && Operands[i].getImmCode() != 0) + return true; + return false; + } + + /// getWithoutImmCodes - Return a copy of this with any immediate codes forced + /// to zero. + OperandsSignature getWithoutImmCodes() const { + OperandsSignature Result; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + if (!Operands[i].isImm()) + Result.Operands.push_back(Operands[i]); + else + Result.Operands.push_back(OpKind::getImm(0)); + return Result; + } + + void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) { + bool EmittedAnything = false; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (!Operands[i].isImm()) continue; + + unsigned Code = Operands[i].getImmCode(); + if (Code == 0) continue; + + if (EmittedAnything) + OS << " &&\n "; + + TreePredicateFn PredFn = ImmPredicates.getPredicate(Code-1); + + // Emit the type check. + OS << "VT == " + << getEnumName(PredFn.getOrigPatFragRecord()->getTree(0)->getType(0)) + << " && "; + + + OS << PredFn.getFnName() << "(imm" << i <<')'; + EmittedAnything = true; + } + } + /// initialize - Examine the given pattern and initialize the contents /// of the Operands array accordingly. Return true if all the operands /// are supported, false otherwise. /// - bool initialize(TreePatternNode *InstPatNode, - const CodeGenTarget &Target, - MVT::SimpleValueType VT) { - - if (!InstPatNode->isLeaf()) { - if (InstPatNode->getOperator()->getName() == "imm") { - Operands.push_back("i"); - return true; - } - if (InstPatNode->getOperator()->getName() == "fpimm") { - Operands.push_back("f"); - return true; - } + bool initialize(TreePatternNode *InstPatNode, const CodeGenTarget &Target, + MVT::SimpleValueType VT, + ImmPredicateSet &ImmediatePredicates) { + if (InstPatNode->isLeaf()) + return false; + + if (InstPatNode->getOperator()->getName() == "imm") { + Operands.push_back(OpKind::getImm(0)); + return true; + } + + if (InstPatNode->getOperator()->getName() == "fpimm") { + Operands.push_back(OpKind::getFP()); + return true; } const CodeGenRegisterClass *DstRC = 0; @@ -72,35 +186,65 @@ struct OperandsSignature { for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { TreePatternNode *Op = InstPatNode->getChild(i); + // Handle imm operands specially. + if (!Op->isLeaf() && Op->getOperator()->getName() == "imm") { + unsigned PredNo = 0; + if (!Op->getPredicateFns().empty()) { + TreePredicateFn PredFn = Op->getPredicateFns()[0]; + // If there is more than one predicate weighing in on this operand + // then we don't handle it. This doesn't typically happen for + // immediates anyway. + if (Op->getPredicateFns().size() > 1 || + !PredFn.isImmediatePattern()) + return false; + // Ignore any instruction with 'FastIselShouldIgnore', these are + // not needed and just bloat the fast instruction selector. For + // example, X86 doesn't need to generate code to match ADD16ri8 since + // ADD16ri will do just fine. + Record *Rec = PredFn.getOrigPatFragRecord()->getRecord(); + if (Rec->getValueAsBit("FastIselShouldIgnore")) + return false; + + PredNo = ImmediatePredicates.getIDFor(PredFn)+1; + } + + // Handle unmatched immediate sizes here. + //if (Op->getType(0) != VT) + // return false; + + Operands.push_back(OpKind::getImm(PredNo)); + continue; + } + + // For now, filter out any operand with a predicate. // For now, filter out any operand with multiple values. - if (!Op->getPredicateFns().empty() || - Op->getNumTypes() != 1) - return false; - - assert(Op->hasTypeSet(0) && "Type infererence not done?"); - // For now, all the operands must have the same type. - if (Op->getType(0) != VT) + if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1) return false; if (!Op->isLeaf()) { - if (Op->getOperator()->getName() == "imm") { - Operands.push_back("i"); - continue; - } - if (Op->getOperator()->getName() == "fpimm") { - Operands.push_back("f"); + if (Op->getOperator()->getName() == "fpimm") { + Operands.push_back(OpKind::getFP()); continue; } // For now, ignore other non-leaf nodes. return false; } + + assert(Op->hasTypeSet(0) && "Type infererence not done?"); + + // For now, all the operands must have the same type (if they aren't + // immediates). Note that this causes us to reject variable sized shifts + // on X86. + if (Op->getType(0) != VT) + return false; + DefInit *OpDI = dynamic_cast(Op->getLeafValue()); if (!OpDI) return false; Record *OpLeafRec = OpDI->getDef(); + // For now, the only other thing we accept is register operands. - const CodeGenRegisterClass *RC = 0; if (OpLeafRec->isSubClassOf("RegisterClass")) RC = &Target.getRegisterClass(OpLeafRec); @@ -120,18 +264,18 @@ struct OperandsSignature { return false; } else DstRC = RC; - Operands.push_back("r"); + Operands.push_back(OpKind::getReg()); } return true; } void PrintParameters(raw_ostream &OS) const { for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - if (Operands[i] == "r") { + if (Operands[i].isReg()) { OS << "unsigned Op" << i << ", bool Op" << i << "IsKill"; - } else if (Operands[i] == "i") { + } else if (Operands[i].isImm()) { OS << "uint64_t imm" << i; - } else if (Operands[i] == "f") { + } else if (Operands[i].isFP()) { OS << "ConstantFP *f" << i; } else { assert("Unknown operand kind!"); @@ -143,7 +287,7 @@ struct OperandsSignature { } void PrintArguments(raw_ostream &OS, - const std::vector& PR) const { + const std::vector &PR) const { assert(PR.size() == Operands.size()); bool PrintedArg = false; for (unsigned i = 0, e = Operands.size(); i != e; ++i) { @@ -153,13 +297,13 @@ struct OperandsSignature { if (PrintedArg) OS << ", "; - if (Operands[i] == "r") { + if (Operands[i].isReg()) { OS << "Op" << i << ", Op" << i << "IsKill"; PrintedArg = true; - } else if (Operands[i] == "i") { + } else if (Operands[i].isImm()) { OS << "imm" << i; PrintedArg = true; - } else if (Operands[i] == "f") { + } else if (Operands[i].isFP()) { OS << "f" << i; PrintedArg = true; } else { @@ -171,11 +315,11 @@ struct OperandsSignature { void PrintArguments(raw_ostream &OS) const { for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - if (Operands[i] == "r") { + if (Operands[i].isReg()) { OS << "Op" << i << ", Op" << i << "IsKill"; - } else if (Operands[i] == "i") { + } else if (Operands[i].isImm()) { OS << "imm" << i; - } else if (Operands[i] == "f") { + } else if (Operands[i].isFP()) { OS << "f" << i; } else { assert("Unknown operand kind!"); @@ -187,8 +331,9 @@ struct OperandsSignature { } - void PrintManglingSuffix(raw_ostream &OS, - const std::vector& PR) const { + void PrintManglingSuffix(raw_ostream &OS, const std::vector &PR, + ImmPredicateSet &ImmPredicates, + bool StripImmCodes = false) const { for (unsigned i = 0, e = Operands.size(); i != e; ++i) { if (PR[i] != "") // Implicit physical register operand. e.g. Instruction::Mul expect to @@ -197,14 +342,14 @@ struct OperandsSignature { // like a binary instruction except for the very inner FastEmitInst_* // call. continue; - OS << Operands[i]; + Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); } } - void PrintManglingSuffix(raw_ostream &OS) const { - for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - OS << Operands[i]; - } + void PrintManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates, + bool StripImmCodes = false) const { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); } }; @@ -218,13 +363,17 @@ class FastISelMap { OperandsOpcodeTypeRetPredMap SimplePatterns; + std::map > + SignaturesWithConstantForms; + std::string InstNS; - + ImmPredicateSet ImmediatePredicates; public: explicit FastISelMap(std::string InstNS); - void CollectPatterns(CodeGenDAGPatterns &CGP); - void PrintFunctionDefinitions(raw_ostream &OS); + void collectPatterns(CodeGenDAGPatterns &CGP); + void printImmediatePredicates(raw_ostream &OS); + void printFunctionDefinitions(raw_ostream &OS); }; } @@ -244,7 +393,34 @@ FastISelMap::FastISelMap(std::string instns) : InstNS(instns) { } -void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { +static std::string PhyRegForNode(TreePatternNode *Op, + const CodeGenTarget &Target) { + std::string PhysReg; + + if (!Op->isLeaf()) + return PhysReg; + + DefInit *OpDI = dynamic_cast(Op->getLeafValue()); + Record *OpLeafRec = OpDI->getDef(); + if (!OpLeafRec->isSubClassOf("Register")) + return PhysReg; + + PhysReg += static_cast(OpLeafRec->getValue( \ + "Namespace")->getValue())->getValue(); + PhysReg += "::"; + + std::vector Regs = Target.getRegisters(); + for (unsigned i = 0; i < Regs.size(); ++i) { + if (Regs[i].TheDef == OpLeafRec) { + PhysReg += Regs[i].getName(); + break; + } + } + + return PhysReg; +} + +void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { const CodeGenTarget &Target = CGP.getTargetInfo(); // Determine the target's namespace name. @@ -264,7 +440,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { if (!Op->isSubClassOf("Instruction")) continue; CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op); - if (II.Operands.size() == 0) + if (II.Operands.empty()) continue; // For now, ignore multi-instruction patterns. @@ -322,54 +498,45 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { VT = InstPatNode->getChild(0)->getType(0); } - // For now, filter out instructions which just set a register to - // an Operand or an immediate, like MOV32ri. - if (InstPatOp->isSubClassOf("Operand")) - continue; - // For now, filter out any instructions with predicates. if (!InstPatNode->getPredicateFns().empty()) continue; // Check all the operands. OperandsSignature Operands; - if (!Operands.initialize(InstPatNode, Target, VT)) + if (!Operands.initialize(InstPatNode, Target, VT, ImmediatePredicates)) continue; std::vector* PhysRegInputs = new std::vector(); - if (!InstPatNode->isLeaf() && - (InstPatNode->getOperator()->getName() == "imm" || - InstPatNode->getOperator()->getName() == "fpimmm")) + if (InstPatNode->getOperator()->getName() == "imm" || + InstPatNode->getOperator()->getName() == "fpimmm") PhysRegInputs->push_back(""); - else if (!InstPatNode->isLeaf()) { + else { + // Compute the PhysRegs used by the given pattern, and check that + // the mapping from the src to dst patterns is simple. + bool FoundNonSimplePattern = false; + unsigned DstIndex = 0; for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { - TreePatternNode *Op = InstPatNode->getChild(i); - if (!Op->isLeaf()) { - PhysRegInputs->push_back(""); - continue; - } - - DefInit *OpDI = dynamic_cast(Op->getLeafValue()); - Record *OpLeafRec = OpDI->getDef(); - std::string PhysReg; - if (OpLeafRec->isSubClassOf("Register")) { - PhysReg += static_cast(OpLeafRec->getValue( \ - "Namespace")->getValue())->getValue(); - PhysReg += "::"; - - std::vector Regs = Target.getRegisters(); - for (unsigned i = 0; i < Regs.size(); ++i) { - if (Regs[i].TheDef == OpLeafRec) { - PhysReg += Regs[i].getName(); - break; - } + std::string PhysReg = PhyRegForNode(InstPatNode->getChild(i), Target); + if (PhysReg.empty()) { + if (DstIndex >= Dst->getNumChildren() || + Dst->getChild(DstIndex)->getName() != + InstPatNode->getChild(i)->getName()) { + FoundNonSimplePattern = true; + break; } + ++DstIndex; } PhysRegInputs->push_back(PhysReg); } - } else - PhysRegInputs->push_back(""); + + if (Op->getName() != "EXTRACT_SUBREG" && DstIndex < Dst->getNumChildren()) + FoundNonSimplePattern = true; + + if (FoundNonSimplePattern) + continue; + } // Get the predicate that guards this pattern. std::string PredicateCheck = Pattern.getPredicateCheck(); @@ -381,15 +548,39 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { SubRegNo, PhysRegInputs }; - if (SimplePatterns[Operands][OpcodeName][VT][RetVT] - .count(PredicateCheck)) - throw TGError(Pattern.getSrcRecord()->getLoc(), "Duplicate record!"); + + if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck)) + throw TGError(Pattern.getSrcRecord()->getLoc(), + "Duplicate record in FastISel table!"); SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo; + + // If any of the operands were immediates with predicates on them, strip + // them down to a signature that doesn't have predicates so that we can + // associate them with the stripped predicate version. + if (Operands.hasAnyImmediateCodes()) { + SignaturesWithConstantForms[Operands.getWithoutImmCodes()] + .push_back(Operands); + } } } -void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { +void FastISelMap::printImmediatePredicates(raw_ostream &OS) { + if (ImmediatePredicates.begin() == ImmediatePredicates.end()) + return; + + OS << "\n// FastEmit Immediate Predicate functions.\n"; + for (ImmPredicateSet::iterator I = ImmediatePredicates.begin(), + E = ImmediatePredicates.end(); I != E; ++I) { + OS << "static bool " << I->getFnName() << "(int64_t Imm) {\n"; + OS << I->getImmediatePredicateCode() << "\n}\n"; + } + + OS << "\n\n"; +} + + +void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Now emit code for all the patterns that we collected. for (OperandsOpcodeTypeRetPredMap::const_iterator OI = SimplePatterns.begin(), OE = SimplePatterns.end(); OI != OE; ++OI) { @@ -420,7 +611,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "("; Operands.PrintParameters(OS); OS << ") {\n"; @@ -451,7 +642,8 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " return FastEmitInst_"; if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs); + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); OS << "(" << InstNS << Memo.Name << ", "; OS << InstNS << Memo.RC->getName() << "RegisterClass"; if (!Operands.empty()) @@ -460,9 +652,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << ");\n"; } else { OS << "extractsubreg(" << getName(RetVT); - OS << ", Op0, Op0IsKill, "; - OS << Memo.SubRegNo; - OS << ");\n"; + OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; } if (HasPred) @@ -480,7 +670,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << "unsigned FastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT RetVT"; if (!Operands.empty()) OS << ", "; @@ -492,7 +682,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " case " << getName(RetVT) << ": return FastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "("; Operands.PrintArguments(OS); OS << ");\n"; @@ -504,7 +694,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << "unsigned FastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT RetVT"; if (!Operands.empty()) OS << ", "; @@ -544,7 +734,8 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " return FastEmitInst_"; if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs); + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); OS << "(" << InstNS << Memo.Name << ", "; OS << InstNS << Memo.RC->getName() << "RegisterClass"; if (!Operands.empty()) @@ -572,7 +763,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { // Emit one function for the opcode that demultiplexes based on the type. OS << "unsigned FastEmit_" << getLegalCName(Opcode) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT"; if (!Operands.empty()) OS << ", "; @@ -585,7 +776,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { std::string TypeName = getName(VT); OS << " case " << TypeName << ": return FastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(RetVT"; if (!Operands.empty()) OS << ", "; @@ -604,12 +795,44 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { // Emit one function for the operand signature that demultiplexes based // on opcode and type. OS << "unsigned FastEmit_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT, unsigned Opcode"; if (!Operands.empty()) OS << ", "; Operands.PrintParameters(OS); OS << ") {\n"; + + // If there are any forms of this signature available that operand on + // constrained forms of the immediate (e.g. 32-bit sext immediate in a + // 64-bit operand), check them first. + + std::map >::iterator MI + = SignaturesWithConstantForms.find(Operands); + if (MI != SignaturesWithConstantForms.end()) { + // Unique any duplicates out of the list. + std::sort(MI->second.begin(), MI->second.end()); + MI->second.erase(std::unique(MI->second.begin(), MI->second.end()), + MI->second.end()); + + // Check each in order it was seen. It would be nice to have a good + // relative ordering between them, but we're not going for optimality + // here. + for (unsigned i = 0, e = MI->second.size(); i != e; ++i) { + OS << " if ("; + MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates); + OS << ")\n if (unsigned Reg = FastEmit_"; + MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates); + OS << "(VT, RetVT, Opcode"; + if (!MI->second[i].empty()) + OS << ", "; + MI->second[i].PrintArguments(OS); + OS << "))\n return Reg;\n\n"; + } + + // Done with this, remove it. + SignaturesWithConstantForms.erase(MI); + } + OS << " switch (Opcode) {\n"; for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end(); I != E; ++I) { @@ -617,7 +840,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " case " << Opcode << ": return FastEmit_" << getLegalCName(Opcode) << "_"; - Operands.PrintManglingSuffix(OS); + Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT"; if (!Operands.empty()) OS << ", "; @@ -629,6 +852,8 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << "}\n"; OS << "\n"; } + + // TODO: SignaturesWithConstantForms should be empty here. } void FastISelEmitter::run(raw_ostream &OS) { @@ -642,12 +867,12 @@ void FastISelEmitter::run(raw_ostream &OS) { Target.getName() + " target", OS); FastISelMap F(InstNS); - F.CollectPatterns(CGP); - F.PrintFunctionDefinitions(OS); + F.collectPatterns(CGP); + F.printImmediatePredicates(OS); + F.printFunctionDefinitions(OS); } FastISelEmitter::FastISelEmitter(RecordKeeper &R) - : Records(R), - CGP(R) { + : Records(R), CGP(R) { } diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index 2c222b39b137..9312fe8d02cd 100644 --- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -438,7 +438,7 @@ void Filter::recurse() { for (bitIndex = 0; bitIndex < NumBits; bitIndex++) BitValueArray[StartBit + bitIndex] = BIT_UNSET; - // Delegates to an inferior filter chooser for futher processing on this + // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. FilterChooserMap.insert(std::pair( (unsigned)-1, @@ -471,7 +471,7 @@ void Filter::recurse() { BitValueArray[StartBit + bitIndex] = BIT_FALSE; } - // Delegates to an inferior filter chooser for futher processing on this + // Delegates to an inferior filter chooser for further processing on this // category of instructions. FilterChooserMap.insert(std::pair( mapIterator->first, @@ -611,7 +611,8 @@ void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation) { o << '\n'; o.indent(Indentation) << - "static bool decodeInstruction(MCInst &MI, field_t insn) {\n"; + "static bool decodeInstruction(MCInst &MI, field_t insn, " + "uint64_t Address, const void *Decoder) {\n"; o.indent(Indentation) << " unsigned tmp = 0;\n"; ++Indentation; ++Indentation; @@ -795,7 +796,8 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { // If a custom instruction decoder was specified, use that. if (I->FieldBase == ~0U && I->FieldLength == ~0U) { - o.indent(Indentation) << " " << I->Decoder << "(MI, insn);\n"; + o.indent(Indentation) << " " << I->Decoder + << "(MI, insn, Address, Decoder);\n"; break; } @@ -803,7 +805,8 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, << " tmp = fieldFromInstruction(insn, " << I->FieldBase << ", " << I->FieldLength << ");\n"; if (I->Decoder != "") { - o.indent(Indentation) << " " << I->Decoder << "(MI, tmp);\n"; + o.indent(Indentation) << " " << I->Decoder + << "(MI, tmp, Address, Decoder);\n"; } else { o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n"; @@ -846,7 +849,8 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { // If a custom instruction decoder was specified, use that. if (I->FieldBase == ~0U && I->FieldLength == ~0U) { - o.indent(Indentation) << " " << I->Decoder << "(MI, insn);\n"; + o.indent(Indentation) << " " << I->Decoder + << "(MI, insn, Address, Decoder);\n"; break; } @@ -854,7 +858,8 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, << " tmp = fieldFromInstruction(insn, " << I->FieldBase << ", " << I->FieldLength << ");\n"; if (I->Decoder != "") { - o.indent(Indentation) << " " << I->Decoder << "(MI, tmp);\n"; + o.indent(Indentation) << " " << I->Decoder + << "(MI, tmp, Address, Decoder);\n"; } else { o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n"; @@ -1224,7 +1229,8 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI, if (Bits.allInComplete()) return false; // Ignore "asm parser only" instructions. - if (Def.getValueAsBit("isAsmParserOnly")) + if (Def.getValueAsBit("isAsmParserOnly") || + Def.getValueAsBit("isCodeGenOnly")) return false; std::vector InsnOperands; diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp index 2b684bede3ea..67cce0e55f28 100644 --- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -272,6 +272,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isIndirectBranch) OS << "|(1<= '2' && proto[0] <= '4'); - // If this builtin takes an immediate argument, we need to #define it rather - // than use a standard declaration, so that SemaChecking can range check - // the immediate passed by the user. - bool define = proto.find('i') != std::string::npos; + bool define = UseMacro(proto); // Check if the prototype has a scalar operand with the type of the vector // elements. If not, bitcasting the args will take care of arg checking. @@ -1008,7 +1035,7 @@ static std::string GenIntrinsic(const std::string &name, StringRef outTypeStr, StringRef inTypeStr, OpKind kind, ClassKind classKind) { assert(!proto.empty() && ""); - bool define = proto.find('i') != std::string::npos; + bool define = UseMacro(proto); std::string s; // static always inline + return type @@ -1148,17 +1175,20 @@ void NeonEmitter::run(raw_ostream &OS) { std::vector RV = Records.getAllDerivedDefinitions("Inst"); - // Emit vmovl and vabd intrinsics first so they can be used by other + // Emit vmovl, vmull and vabd intrinsics first so they can be used by other // intrinsics. (Some of the saturating multiply instructions are also // used to implement the corresponding "_lane" variants, but tablegen // sorts the records into alphabetical order so that the "_lane" variants // come after the intrinsics they use.) emitIntrinsic(OS, Records.getDef("VMOVL")); + emitIntrinsic(OS, Records.getDef("VMULL")); emitIntrinsic(OS, Records.getDef("VABD")); for (unsigned i = 0, e = RV.size(); i != e; ++i) { Record *R = RV[i]; - if (R->getName() != "VMOVL" && R->getName() != "VABD") + if (R->getName() != "VMOVL" && + R->getName() != "VMULL" && + R->getName() != "VABD") emitIntrinsic(OS, R); } diff --git a/contrib/llvm/utils/TableGen/NeonEmitter.h b/contrib/llvm/utils/TableGen/NeonEmitter.h index 1e6fcbf555df..12e4e8679908 100644 --- a/contrib/llvm/utils/TableGen/NeonEmitter.h +++ b/contrib/llvm/utils/TableGen/NeonEmitter.h @@ -30,13 +30,11 @@ enum OpKind { OpSubl, OpSubw, OpMul, - OpMull, OpMla, OpMlal, OpMls, OpMlsl, OpMulN, - OpMullN, OpMlaN, OpMlsN, OpMlalN, @@ -105,13 +103,11 @@ namespace llvm { OpMap["OP_SUBL"] = OpSubl; OpMap["OP_SUBW"] = OpSubw; OpMap["OP_MUL"] = OpMul; - OpMap["OP_MULL"] = OpMull; OpMap["OP_MLA"] = OpMla; OpMap["OP_MLAL"] = OpMlal; OpMap["OP_MLS"] = OpMls; OpMap["OP_MLSL"] = OpMlsl; OpMap["OP_MUL_N"] = OpMulN; - OpMap["OP_MULL_N"]= OpMullN; OpMap["OP_MLA_N"] = OpMlaN; OpMap["OP_MLS_N"] = OpMlsN; OpMap["OP_MLAL_N"] = OpMlalN; diff --git a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp index 6892912eee13..431026c669c3 100644 --- a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp +++ b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp @@ -35,7 +35,7 @@ static int CompareOptionRecords(const void *Av, const void *Bv) { const Record *A = *(Record**) Av; const Record *B = *(Record**) Bv; - // Sentinel options preceed all others and are only ordered by precedence. + // Sentinel options precede all others and are only ordered by precedence. bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel"); if (ASent != BSent) diff --git a/contrib/llvm/utils/TableGen/Record.h b/contrib/llvm/utils/TableGen/Record.h index f3a5df23ec5c..522b719803c3 100644 --- a/contrib/llvm/utils/TableGen/Record.h +++ b/contrib/llvm/utils/TableGen/Record.h @@ -707,7 +707,7 @@ class CodeInit : public Init { public: explicit CodeInit(const std::string &V) : Value(V) {} - const std::string getValue() const { return Value; } + const std::string &getValue() const { return Value; } virtual Init *convertInitializerTo(RecTy *Ty) { return Ty->convertValue(this); diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp index 96399a4d0525..4ddc47d5519a 100644 --- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -38,7 +38,10 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS) { OS << "enum {\n NoRegister,\n"; for (unsigned i = 0, e = Registers.size(); i != e; ++i) - OS << " " << Registers[i].getName() << ", \t// " << i+1 << "\n"; + OS << " " << Registers[i].getName() << " = " << + Registers[i].EnumValue << ",\n"; + assert(Registers.size() == Registers[Registers.size()-1].EnumValue && + "Register enum value mismatch!"); OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n"; OS << "};\n"; if (!Namespace.empty()) @@ -91,7 +94,7 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { if (!RegisterClasses.empty()) { OS << "namespace " << RegisterClasses[0].Namespace << " { // Register classes\n"; - + OS << " enum {\n"; for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { if (i) OS << ",\n"; @@ -358,7 +361,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { // Give the register class a legal C name if it's anonymous. std::string Name = RC.TheDef->getName(); - + // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " static const unsigned " << Name @@ -376,12 +379,12 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { // Emit the ValueType arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = RegisterClasses[rc]; - + // Give the register class a legal C name if it's anonymous. std::string Name = RC.TheDef->getName() + "VTs"; - + // Emit the register list now. - OS << " // " << Name + OS << " // " << Name << " Register Class Value Types...\n" << " static const EVT " << Name << "[] = {\n "; @@ -390,7 +393,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << "MVT::Other\n };\n\n"; } OS << "} // end anonymous namespace\n\n"; - + // Now that all of the structs have been emitted, emit the instances. if (!RegisterClasses.empty()) { OS << "namespace " << RegisterClasses[0].Namespace @@ -398,7 +401,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) OS << " " << RegisterClasses[i].getName() << "Class\t" << RegisterClasses[i].getName() << "RegClass;\n"; - + std::map > SuperClassMap; std::map > SuperRegClassMap; OS << "\n"; @@ -488,7 +491,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { // Give the register class a legal C name if it's anonymous. std::string Name = RC.TheDef->getName(); - OS << " // " << Name + OS << " // " << Name << " Register Class sub-classes...\n" << " static const TargetRegisterClass* const " << Name << "Subclasses[] = {\n "; @@ -500,7 +503,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { // Sub-classes are used to determine if a virtual register can be used // as an instruction operand, or if it must be copied first. if (rc == rc2 || !RC.hasSubClass(&RC2)) continue; - + if (!Empty) OS << ", "; OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass"; Empty = false; @@ -524,7 +527,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { // Give the register class a legal C name if it's anonymous. std::string Name = RC.TheDef->getName(); - OS << " // " << Name + OS << " // " << Name << " Register Class super-classes...\n" << " static const TargetRegisterClass* const " << Name << "Superclasses[] = {\n "; @@ -538,7 +541,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { const CodeGenRegisterClass &RC2 = RegisterClasses[*II]; if (!Empty) OS << ", "; OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass"; - Empty = false; + Empty = false; } } @@ -550,7 +553,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = RegisterClasses[i]; OS << RC.MethodBodies << "\n"; - OS << RC.getName() << "Class::" << RC.getName() + OS << RC.getName() << "Class::" << RC.getName() << "Class() : TargetRegisterClass(" << RC.getName() + "RegClassID" << ", " << '\"' << RC.getName() << "\", " @@ -567,7 +570,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << RC.getName() << ", " << RC.getName() << " + " << RC.Elements.size() << ") {}\n"; } - + OS << "}\n"; } @@ -584,7 +587,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { std::map, LessRecord> RegisterAliases; typedef std::map, LessRecord> DwarfRegNumsMapTy; DwarfRegNumsMapTy DwarfRegNums; - + const std::vector &Regs = Target.getRegisters(); for (unsigned i = 0, e = Regs.size(); i != e; ++i) { @@ -623,7 +626,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { RegisterAliases); } } - + // Print the SubregHashTable, a simple quadratically probed // hash table for determining if a register is a subregister // of another register. @@ -633,13 +636,13 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { RegNo[Regs[i].TheDef] = i; NumSubRegs += RegisterSubRegs[Regs[i].TheDef].size(); } - + unsigned SubregHashTableSize = 2 * NextPowerOf2(2 * NumSubRegs); unsigned* SubregHashTable = new unsigned[2 * SubregHashTableSize]; std::fill(SubregHashTable, SubregHashTable + 2 * SubregHashTableSize, ~0U); - + unsigned hashMisses = 0; - + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { Record* R = Regs[i].TheDef; for (std::set::iterator I = RegisterSubRegs[R].begin(), @@ -654,26 +657,26 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { SubregHashTable[index*2+1] != ~0U) { index = (index + ProbeAmt) & (SubregHashTableSize-1); ProbeAmt += 2; - + hashMisses++; } - + SubregHashTable[index*2] = i; SubregHashTable[index*2+1] = RegNo[RJ]; } } - + OS << "\n\n // Number of hash collisions: " << hashMisses << "\n"; - + if (SubregHashTableSize) { std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace"); - + OS << " const unsigned SubregHashTable[] = { "; for (unsigned i = 0; i < SubregHashTableSize - 1; ++i) { if (i != 0) // Insert spaces for nice formatting. OS << " "; - + if (SubregHashTable[2*i] != ~0U) { OS << getQualifiedName(Regs[SubregHashTable[2*i]].TheDef) << ", " << getQualifiedName(Regs[SubregHashTable[2*i+1]].TheDef) << ", \n"; @@ -681,7 +684,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n"; } } - + unsigned Idx = SubregHashTableSize*2-2; if (SubregHashTable[Idx] != ~0U) { OS << " " @@ -690,14 +693,14 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { } else { OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n"; } - + OS << " const unsigned SubregHashTableSize = " << SubregHashTableSize << ";\n"; } else { OS << " const unsigned SubregHashTable[] = { ~0U, ~0U };\n" << " const unsigned SubregHashTableSize = 1;\n"; } - + delete [] SubregHashTable; @@ -709,13 +712,13 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { RegNo[Regs[i].TheDef] = i; NumAliases += RegisterAliases[Regs[i].TheDef].size(); } - + unsigned AliasesHashTableSize = 2 * NextPowerOf2(2 * NumAliases); unsigned* AliasesHashTable = new unsigned[2 * AliasesHashTableSize]; std::fill(AliasesHashTable, AliasesHashTable + 2 * AliasesHashTableSize, ~0U); - + hashMisses = 0; - + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { Record* R = Regs[i].TheDef; for (std::set::iterator I = RegisterAliases[R].begin(), @@ -730,26 +733,26 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { AliasesHashTable[index*2+1] != ~0U) { index = (index + ProbeAmt) & (AliasesHashTableSize-1); ProbeAmt += 2; - + hashMisses++; } - + AliasesHashTable[index*2] = i; AliasesHashTable[index*2+1] = RegNo[RJ]; } } - + OS << "\n\n // Number of hash collisions: " << hashMisses << "\n"; - + if (AliasesHashTableSize) { std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace"); - + OS << " const unsigned AliasesHashTable[] = { "; for (unsigned i = 0; i < AliasesHashTableSize - 1; ++i) { if (i != 0) // Insert spaces for nice formatting. OS << " "; - + if (AliasesHashTable[2*i] != ~0U) { OS << getQualifiedName(Regs[AliasesHashTable[2*i]].TheDef) << ", " << getQualifiedName(Regs[AliasesHashTable[2*i+1]].TheDef) << ", \n"; @@ -757,7 +760,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n"; } } - + unsigned Idx = AliasesHashTableSize*2-2; if (AliasesHashTable[Idx] != ~0U) { OS << " " @@ -766,14 +769,14 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { } else { OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n"; } - + OS << " const unsigned AliasesHashTableSize = " << AliasesHashTableSize << ";\n"; } else { OS << " const unsigned AliasesHashTable[] = { ~0U, ~0U };\n" << " const unsigned AliasesHashTableSize = 1;\n"; } - + delete [] AliasesHashTable; if (!RegisterAliases.empty()) @@ -838,7 +841,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { } OS<<"\n const TargetRegisterDesc RegisterDescriptors[] = { // Descriptors\n"; - OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; + OS << " { \"NOREG\",\t0,\t0,\t0,\t0 },\n"; // Now that register alias and sub-registers sets have been emitted, emit the // register descriptors now. @@ -851,9 +854,10 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { else OS << "Empty_SubRegsSet,\t"; if (!RegisterSuperRegs[Reg.TheDef].empty()) - OS << Reg.getName() << "_SuperRegsSet },\n"; + OS << Reg.getName() << "_SuperRegsSet,\t"; else - OS << "Empty_SuperRegsSet },\n"; + OS << "Empty_SuperRegsSet,\t"; + OS << Reg.CostPerUse << " },\n"; } OS << " };\n"; // End of register descriptors... @@ -966,7 +970,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { } // Now we know maximal length of number list. Append -1's, where needed - for (DwarfRegNumsMapTy::iterator + for (DwarfRegNumsMapTy::iterator I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) for (unsigned i = I->second.size(), e = maxLength; i != e; ++i) I->second.push_back(-1); @@ -978,18 +982,18 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << " default:\n" << " assert(0 && \"Unknown DWARF flavour\");\n" << " return -1;\n"; - + for (unsigned i = 0, e = maxLength; i != e; ++i) { OS << " case " << i << ":\n" << " switch (RegNum) {\n" << " default:\n" << " assert(0 && \"Invalid RegNum\");\n" << " return -1;\n"; - - // Sort by name to get a stable order. - - for (DwarfRegNumsMapTy::iterator + // Sort by name to get a stable order. + + + for (DwarfRegNumsMapTy::iterator I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { int RegNo = I->second[i]; if (RegNo != -2) @@ -1002,7 +1006,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { } OS << " };\n"; } - + OS << " };\n}\n\n"; OS << "} // End llvm namespace \n"; diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp index e35bdca97887..928fa4bee900 100644 --- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -31,24 +31,30 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, // Open enumeration OS << "enum {\n"; - + // For each record - for (unsigned i = 0, N = DefList.size(); i < N;) { + unsigned N = DefList.size(); + if (N > 64) { + errs() << "Too many (> 64) subtarget features!\n"; + exit(1); + } + + for (unsigned i = 0; i < N;) { // Next record Record *Def = DefList[i]; - + // Get and emit name OS << " " << Def->getName(); - + // If bit flags then emit expression (1 << i) - if (isBits) OS << " = " << " 1 << " << i; + if (isBits) OS << " = " << " 1ULL << " << i; // Depending on 'if more in the list' emit comma if (++i < N) OS << ","; - + OS << "\n"; } - + // Close enumeration OS << "};\n"; } @@ -66,7 +72,7 @@ void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { // Begin feature table OS << "// Sorted (by key) array of values for CPU features.\n" << "static const llvm::SubtargetFeatureKV FeatureKV[] = {\n"; - + // For each feature for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) { // Next feature @@ -75,20 +81,20 @@ void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { const std::string &Name = Feature->getName(); const std::string &CommandLineName = Feature->getValueAsString("Name"); const std::string &Desc = Feature->getValueAsString("Desc"); - + if (CommandLineName.empty()) continue; - + // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in } OS << " { " << "\"" << CommandLineName << "\", " << "\"" << Desc << "\", " << Name << ", "; - const std::vector &ImpliesList = + const std::vector &ImpliesList = Feature->getValueAsListOfDefs("Implies"); - + if (ImpliesList.empty()) { - OS << "0"; + OS << "0ULL"; } else { for (unsigned j = 0, M = ImpliesList.size(); j < M;) { OS << ImpliesList[j]->getName(); @@ -97,13 +103,13 @@ void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { } OS << " }"; - + // Depending on 'if more in the list' emit comma if ((i + 1) < N) OS << ","; - + OS << "\n"; } - + // End feature table OS << "};\n"; @@ -126,39 +132,39 @@ void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { // Begin processor table OS << "// Sorted (by key) array of values for CPU subtype.\n" << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n"; - + // For each processor for (unsigned i = 0, N = ProcessorList.size(); i < N;) { // Next processor Record *Processor = ProcessorList[i]; const std::string &Name = Processor->getValueAsString("Name"); - const std::vector &FeatureList = + const std::vector &FeatureList = Processor->getValueAsListOfDefs("Features"); - + // Emit as { "cpu", "description", f1 | f2 | ... fn }, OS << " { " << "\"" << Name << "\", " << "\"Select the " << Name << " processor\", "; - + if (FeatureList.empty()) { - OS << "0"; + OS << "0ULL"; } else { for (unsigned j = 0, M = FeatureList.size(); j < M;) { OS << FeatureList[j]->getName(); if (++j < M) OS << " | "; } } - + // The "0" is for the "implies" section of this data structure. - OS << ", 0 }"; - + OS << ", 0ULL }"; + // Depending on 'if more in the list' emit comma if (++i < N) OS << ","; - + OS << "\n"; } - + // End processor table OS << "};\n"; @@ -185,7 +191,7 @@ CollectAllItinClasses(raw_ostream &OS, // Assign itinerary class a unique number ItinClassesMap[ItinClass->getName()] = i; } - + // Emit size of table OS<<"\nenum {\n"; OS<<" ItinClassesSize = " << N << "\n"; @@ -213,21 +219,21 @@ void SubtargetEmitter::FormItineraryStageString(const std::string &Name, for (unsigned i = 0; i < N;) { // Next stage const Record *Stage = StageList[i]; - + // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind } int Cycles = Stage->getValueAsInt("Cycles"); ItinString += " { " + itostr(Cycles) + ", "; - + // Get unit list const std::vector &UnitList = Stage->getValueAsListOfDefs("Units"); - + // For each unit for (unsigned j = 0, M = UnitList.size(); j < M;) { // Add name and bitwise or ItinString += Name + "FU::" + UnitList[j]->getName(); if (++j < M) ItinString += " | "; } - + int TimeInc = Stage->getValueAsInt("TimeInc"); ItinString += ", " + itostr(TimeInc); @@ -256,7 +262,7 @@ void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData, for (unsigned i = 0; i < N;) { // Next operand cycle const int OCycle = OperandCycleList[i]; - + ItinString += " " + itostr(OCycle); if (++i < N) ItinString += ", "; } @@ -292,7 +298,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // Gather processor iteraries std::vector ProcItinList = Records.getAllDerivedDefinitions("ProcessorItineraries"); - + // If just no itinerary then don't bother if (ProcItinList.size() < 2) return; @@ -332,7 +338,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // Begin stages table std::string StageTable = "\nstatic const llvm::InstrStage Stages[] = {\n"; StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; - + // Begin operand cycle table std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n"; OperandCycleTable += " 0, // No itinerary\n"; @@ -340,32 +346,31 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // Begin pipeline bypass table std::string BypassTable = "static const unsigned ForwardingPathes[] = {\n"; BypassTable += " 0, // No itinerary\n"; - + unsigned StageCount = 1, OperandCycleCount = 1; - unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1; std::map ItinStageMap, ItinOperandMap; for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { // Next record Record *Proc = ProcItinList[i]; - + // Get processor itinerary name const std::string &Name = Proc->getName(); - + // Skip default if (Name == "NoItineraries") continue; - + // Create and expand processor itinerary to cover all itinerary classes std::vector ItinList; ItinList.resize(NItinClasses); - + // Get itinerary data list std::vector ItinDataList = Proc->getValueAsListOfDefs("IID"); - + // For each itinerary data for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { // Next itinerary data Record *ItinData = ItinDataList[j]; - + // Get string and stage count std::string ItinStageString; unsigned NStages; @@ -386,15 +391,17 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, if (NStages > 0) { FindStage = ItinStageMap[ItinStageString]; if (FindStage == 0) { - // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index - StageTable += ItinStageString + ", // " + itostr(ItinStageEnum) + "\n"; + // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices + StageTable += ItinStageString + ", // " + itostr(StageCount); + if (NStages > 1) + StageTable += "-" + itostr(StageCount + NStages - 1); + StageTable += "\n"; // Record Itin class number. ItinStageMap[ItinStageString] = FindStage = StageCount; StageCount += NStages; - ItinStageEnum++; } } - + // Check to see if operand cycle already exists and create if it doesn't unsigned FindOperandCycle = 0; if (NOperandCycles > 0) { @@ -402,25 +409,25 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, FindOperandCycle = ItinOperandMap[ItinOperandString]; if (FindOperandCycle == 0) { // Emit as cycle, // index - OperandCycleTable += ItinOperandCycleString + ", // " + - itostr(ItinOperandCycleEnum) + "\n"; + OperandCycleTable += ItinOperandCycleString + ", // "; + std::string OperandIdxComment = itostr(OperandCycleCount); + if (NOperandCycles > 1) + OperandIdxComment += "-" + + itostr(OperandCycleCount + NOperandCycles - 1); + OperandCycleTable += OperandIdxComment + "\n"; // Record Itin class number. - ItinOperandMap[ItinOperandCycleString] = + ItinOperandMap[ItinOperandCycleString] = FindOperandCycle = OperandCycleCount; - // Emit as bypass, // index - BypassTable += ItinBypassString + ", // " + - itostr(ItinOperandCycleEnum) + "\n"; - + BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n"; OperandCycleCount += NOperandCycles; - ItinOperandCycleEnum++; } } - + // Locate where to inject into processor itinerary table const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); unsigned Find = ItinClassesMap[Name]; - + // Set up itinerary as location and location + stage count unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps"); InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages, @@ -430,7 +437,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // Inject - empty slots will be 0, 0 ItinList[Find] = Intinerary; } - + // Add process itinerary to list ProcList.push_back(ItinList); } @@ -450,7 +457,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, OS << StageTable; OS << OperandCycleTable; OS << BypassTable; - + // Emit size of tables OS<<"\nenum {\n"; OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n"; @@ -461,12 +468,14 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // // EmitProcessorData - Generate data for processor itineraries. // -void SubtargetEmitter::EmitProcessorData(raw_ostream &OS, - std::vector > &ProcList) { +void SubtargetEmitter:: +EmitProcessorData(raw_ostream &OS, + std::vector &ItinClassList, + std::vector > &ProcList) { // Get an iterator for processor itinerary stages std::vector >::iterator ProcListIter = ProcList.begin(); - + // For each processor itinerary std::vector Itins = Records.getAllDerivedDefinitions("ProcessorItineraries"); @@ -476,35 +485,36 @@ void SubtargetEmitter::EmitProcessorData(raw_ostream &OS, // Get processor itinerary name const std::string &Name = Itin->getName(); - + // Skip default if (Name == "NoItineraries") continue; // Begin processor itinerary table OS << "\n"; OS << "static const llvm::InstrItinerary " << Name << "[] = {\n"; - + // For each itinerary class std::vector &ItinList = *ProcListIter++; + assert(ItinList.size() == ItinClassList.size() && "bad itinerary"); for (unsigned j = 0, M = ItinList.size(); j < M; ++j) { InstrItinerary &Intinerary = ItinList[j]; - - // Emit in the form of + + // Emit in the form of // { firstStage, lastStage, firstCycle, lastCycle } // index if (Intinerary.FirstStage == 0) { OS << " { 1, 0, 0, 0, 0 }"; } else { OS << " { " << Intinerary.NumMicroOps << ", " << - Intinerary.FirstStage << ", " << - Intinerary.LastStage << ", " << - Intinerary.FirstOperandCycle << ", " << + Intinerary.FirstStage << ", " << + Intinerary.LastStage << ", " << + Intinerary.FirstOperandCycle << ", " << Intinerary.LastOperandCycle << " }"; } - - OS << ", // " << j << "\n"; + + OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n"; } - + // End processor itinerary table OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n"; OS << "};\n"; @@ -524,7 +534,7 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { OS << "\n"; OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" << "static const llvm::SubtargetInfoKV ProcItinKV[] = {\n"; - + // For each processor for (unsigned i = 0, N = ProcessorList.size(); i < N;) { // Next processor @@ -533,20 +543,20 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { const std::string &Name = Processor->getValueAsString("Name"); const std::string &ProcItin = Processor->getValueAsDef("ProcItin")->getName(); - + // Emit as { "cpu", procinit }, OS << " { " << "\"" << Name << "\", " << "(void *)&" << ProcItin; - + OS << " }"; - + // Depending on ''if more in the list'' emit comma if (++i < N) OS << ","; - + OS << "\n"; } - + // End processor table OS << "};\n"; @@ -566,20 +576,20 @@ void SubtargetEmitter::EmitData(raw_ostream &OS) { std::vector ItinClassList = Records.getAllDerivedDefinitions("InstrItinClass"); std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); - + // Enumerate all the itinerary classes unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap, ItinClassList); // Make sure the rest is worth the effort HasItineraries = NItinClasses != 1; // Ignore NoItinerary. - + if (HasItineraries) { std::vector > ProcList; // Emit the stage data EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ItinClassList, ProcList); // Emit the processor itinerary data - EmitProcessorData(OS, ProcList); + EmitProcessorData(OS, ItinClassList, ProcList); // Emit the processor lookup data EmitProcessorLookup(OS); } @@ -594,8 +604,8 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { Records.getAllDerivedDefinitions("SubtargetFeature"); std::sort(Features.begin(), Features.end(), LessRecord()); - OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" - << "// subtarget options.\n" + OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" + << "// subtarget options.\n" << "std::string llvm::"; OS << Target; OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n" @@ -604,7 +614,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n" << " SubtargetFeatures Features(FS);\n" << " Features.setCPUIfNone(CPU);\n" - << " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" + << " uint64_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" << " FeatureKV, FeatureKVSize);\n"; for (unsigned i = 0; i < Features.size(); i++) { @@ -618,7 +628,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { OS << " if ((Bits & " << Instance << ") != 0) " << Attribute << " = " << Value << ";\n"; else - OS << " if ((Bits & " << Instance << ") != 0 && " << Attribute << + OS << " if ((Bits & " << Instance << ") != 0 && " << Attribute << " < " << Value << ") " << Attribute << " = " << Value << ";\n"; } diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.h b/contrib/llvm/utils/TableGen/SubtargetEmitter.h index 3abec3b24091..93055b7fec12 100644 --- a/contrib/llvm/utils/TableGen/SubtargetEmitter.h +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.h @@ -24,11 +24,11 @@ namespace llvm { class SubtargetEmitter : public TableGenBackend { - + RecordKeeper &Records; std::string Target; bool HasItineraries; - + void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits); void FeatureKeyValues(raw_ostream &OS); void CPUKeyValues(raw_ostream &OS); @@ -48,11 +48,12 @@ class SubtargetEmitter : public TableGenBackend { std::vector &ItinClassList, std::vector > &ProcList); void EmitProcessorData(raw_ostream &OS, - std::vector > &ProcList); + std::vector &ItinClassList, + std::vector > &ProcList); void EmitProcessorLookup(raw_ostream &OS); void EmitData(raw_ostream &OS); void ParseFeaturesFunction(raw_ostream &OS); - + public: SubtargetEmitter(RecordKeeper &R) : Records(R), HasItineraries(false) {} diff --git a/contrib/llvm/utils/TableGen/TGLexer.h b/contrib/llvm/utils/TableGen/TGLexer.h index 55a6c5d9b52e..e1aa5a723212 100644 --- a/contrib/llvm/utils/TableGen/TGLexer.h +++ b/contrib/llvm/utils/TableGen/TGLexer.h @@ -15,7 +15,6 @@ #define TGLEXER_H #include "llvm/Support/DataTypes.h" -#include #include #include @@ -36,7 +35,7 @@ namespace tgtok { l_brace, r_brace, // { } l_paren, r_paren, // ( ) less, greater, // < > - colon, semi, // ; : + colon, semi, // : ; comma, period, // , . equal, question, // = ? diff --git a/contrib/llvm/utils/TableGen/TGParser.cpp b/contrib/llvm/utils/TableGen/TGParser.cpp index f6041be95e16..59097f986f79 100644 --- a/contrib/llvm/utils/TableGen/TGParser.cpp +++ b/contrib/llvm/utils/TableGen/TGParser.cpp @@ -1153,6 +1153,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { s << "Type mismatch for list, expected list type, got " << ItemType->getAsString(); TokError(s.str()); + return 0; } GivenListTy = ListType; } diff --git a/contrib/llvm/utils/TableGen/TGValueTypes.cpp b/contrib/llvm/utils/TableGen/TGValueTypes.cpp index 122d085b0d78..af0d9f44cf43 100644 --- a/contrib/llvm/utils/TableGen/TGValueTypes.cpp +++ b/contrib/llvm/utils/TableGen/TGValueTypes.cpp @@ -16,7 +16,6 @@ #include "llvm/CodeGen/ValueTypes.h" #include -#include using namespace llvm; namespace llvm { diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp index 3b7dc0193b28..aa9230252421 100644 --- a/contrib/llvm/utils/TableGen/TableGen.cpp +++ b/contrib/llvm/utils/TableGen/TableGen.cpp @@ -65,6 +65,7 @@ enum ActionType { GenClangAttrSpellingList, GenClangDiagsDefs, GenClangDiagGroups, + GenClangDiagsIndexName, GenClangDeclNodes, GenClangStmtNodes, GenClangSACheckers, @@ -133,12 +134,16 @@ namespace { "Generate clang PCH attribute reader"), clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write", "Generate clang PCH attribute writer"), - clEnumValN(GenClangAttrSpellingList, "gen-clang-attr-spelling-list", + clEnumValN(GenClangAttrSpellingList, + "gen-clang-attr-spelling-list", "Generate a clang attribute spelling list"), clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", "Generate Clang diagnostics definitions"), clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", "Generate Clang diagnostic groups"), + clEnumValN(GenClangDiagsIndexName, + "gen-clang-diags-index-name", + "Generate Clang diagnostic name index"), clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes", "Generate Clang AST declaration nodes"), clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes", @@ -295,6 +300,9 @@ int main(int argc, char **argv) { case GenClangDiagGroups: ClangDiagGroupsEmitter(Records).run(Out.os()); break; + case GenClangDiagsIndexName: + ClangDiagsIndexNameEmitter(Records).run(Out.os()); + break; case GenClangDeclNodes: ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out.os()); ClangDeclContextEmitter(Records).run(Out.os()); diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp index 94797f55f713..74310593d29d 100644 --- a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp +++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp @@ -18,6 +18,7 @@ #include "X86DisassemblerTables.h" #include "TableGenBackend.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" @@ -46,9 +47,11 @@ static inline bool inheritsFrom(InstructionContext child, case IC_OPSIZE: return(inheritsFrom(child, IC_64BIT_OPSIZE)); case IC_XD: - return(inheritsFrom(child, IC_64BIT_XD)); + return(inheritsFrom(child, IC_64BIT_XD) || + inheritsFrom(child, IC_VEX_XD)); case IC_XS: - return(inheritsFrom(child, IC_64BIT_XS)); + return(inheritsFrom(child, IC_64BIT_XS) || + inheritsFrom(child, IC_VEX_XS)); case IC_64BIT_REXW: return(inheritsFrom(child, IC_64BIT_REXW_XS) || inheritsFrom(child, IC_64BIT_REXW_XD) || @@ -65,6 +68,35 @@ static inline bool inheritsFrom(InstructionContext child, return false; case IC_64BIT_REXW_OPSIZE: return false; + case IC_VEX: + return(inheritsFrom(child, IC_VEX_XS) || + inheritsFrom(child, IC_VEX_XD) || + inheritsFrom(child, IC_VEX_L) || + inheritsFrom(child, IC_VEX_W) || + inheritsFrom(child, IC_VEX_OPSIZE)); + case IC_VEX_XS: + return(inheritsFrom(child, IC_VEX_L_XS) || + inheritsFrom(child, IC_VEX_W_XS)); + case IC_VEX_XD: + return(inheritsFrom(child, IC_VEX_L_XD) || + inheritsFrom(child, IC_VEX_W_XD)); + case IC_VEX_L: + return(inheritsFrom(child, IC_VEX_L_XS) || + inheritsFrom(child, IC_VEX_L_XD)); + case IC_VEX_L_XS: + return false; + case IC_VEX_L_XD: + return false; + case IC_VEX_W: + return(inheritsFrom(child, IC_VEX_W_XS) || + inheritsFrom(child, IC_VEX_W_XD) || + inheritsFrom(child, IC_VEX_W_OPSIZE)); + case IC_VEX_W_XS: + return false; + case IC_VEX_W_XD: + return false; + case IC_VEX_OPSIZE: + return inheritsFrom(child, IC_VEX_W_OPSIZE); default: return false; } @@ -236,7 +268,7 @@ static const char* stringForModifierType(ModifierType mt) DisassemblerTables::DisassemblerTables() { unsigned i; - for (i = 0; i < 4; i++) { + for (i = 0; i < array_lengthof(Tables); i++) { Tables[i] = new ContextDecision; memset(Tables[i], 0, sizeof(ContextDecision)); } @@ -247,7 +279,7 @@ DisassemblerTables::DisassemblerTables() { DisassemblerTables::~DisassemblerTables() { unsigned i; - for (i = 0; i < 4; i++) + for (i = 0; i < array_lengthof(Tables); i++) delete Tables[i]; } @@ -461,7 +493,29 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { for (index = 0; index < 256; ++index) { o.indent(i * 2); - if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS)) + if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE)) + o << "IC_VEX_L_OPSIZE"; + else if ((index & ATTR_VEXL) && (index & ATTR_XD)) + o << "IC_VEX_L_XD"; + else if ((index & ATTR_VEXL) && (index & ATTR_XS)) + o << "IC_VEX_L_XS"; + else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) + o << "IC_VEX_W_OPSIZE"; + else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD)) + o << "IC_VEX_W_XD"; + else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS)) + o << "IC_VEX_W_XS"; + else if (index & ATTR_VEXL) + o << "IC_VEX_L"; + else if ((index & ATTR_VEX) && (index & ATTR_REXW)) + o << "IC_VEX_W"; + else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE)) + o << "IC_VEX_OPSIZE"; + else if ((index & ATTR_VEX) && (index & ATTR_XD)) + o << "IC_VEX_XD"; + else if ((index & ATTR_VEX) && (index & ATTR_XS)) + o << "IC_VEX_XS"; + else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS)) o << "IC_64BIT_REXW_XS"; else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD)) o << "IC_64BIT_REXW_XD"; @@ -484,6 +538,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { o << "IC_XD"; else if (index & ATTR_OPSIZE) o << "IC_OPSIZE"; + else if (index & ATTR_VEX) + o << "IC_VEX"; else o << "IC"; @@ -510,6 +566,8 @@ void DisassemblerTables::emitContextDecisions(raw_ostream &o1, emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR); emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR); emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR); + emitContextDecision(o1, o2, i1, i2, *Tables[4], THREEBYTEA6_STR); + emitContextDecision(o1, o2, i1, i2, *Tables[5], THREEBYTEA7_STR); } void DisassemblerTables::emit(raw_ostream &o) const { diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.h b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h index 08eba019c09a..d16ebfca419e 100644 --- a/contrib/llvm/utils/TableGen/X86DisassemblerTables.h +++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h @@ -39,7 +39,9 @@ class DisassemblerTables { /// [1] two-byte opcodes of the form 0f __ /// [2] three-byte opcodes of the form 0f 38 __ /// [3] three-byte opcodes of the form 0f 3a __ - ContextDecision* Tables[4]; + /// [4] three-byte opcodes of the form 0f a6 __ + /// [5] three-byte opcodes of the form 0f a7 __ + ContextDecision* Tables[6]; /// The instruction information table std::vector InstructionSpecifiers; @@ -77,7 +79,7 @@ class DisassemblerTables { /// regardless of ModR/M byte, two entries - one for bytes 0x00-0xbf and one /// for bytes 0xc0-0xff -, or 256 entries, one for each possible byte. /// nnnn is the number of a table for looking up these values. The tables - /// are writen separately so that tables consisting entirely of zeros will + /// are written separately so that tables consisting entirely of zeros will /// not be duplicated. (These all have the name modRMEmptyTable.) A table /// is printed as: /// @@ -141,8 +143,9 @@ class DisassemblerTables { /// } /// } /// - /// NAME is the name of the ContextDecision (typically one of the four names - /// ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, and THREEBYTE3A_SYM from + /// NAME is the name of the ContextDecision (typically one of the four names + /// ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM, + /// THREEBYTEA6_SYM, and THREEBYTEA7_SYM from /// X86DisassemblerDecoderCommon.h). /// IC is one of the contexts in InstructionContext. There is an opcode /// decision for each possible context. diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp index b0839c33982d..f7518a988ccf 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -68,7 +68,7 @@ namespace X86Local { DC = 7, DD = 8, DE = 9, DF = 10, XD = 11, XS = 12, T8 = 13, P_TA = 14, - P_0F_AE = 16, P_0F_01 = 17 + A6 = 15, A7 = 16 }; } @@ -214,7 +214,9 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); + HasVEXPrefix = Rec->getValueAsBit("hasVEXPrefix"); HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix"); + HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix"); HasLockPrefix = Rec->getValueAsBit("hasLockPrefix"); IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly"); @@ -224,7 +226,8 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, Operands = &insn.Operands.OperandList; IsSSE = HasOpSizePrefix && (Name.find("16") == Name.npos); - HasFROperands = false; + HasFROperands = hasFROperands(); + HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L"); ShouldBeEmitted = true; } @@ -248,7 +251,32 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables, InstructionContext RecognizableInstr::insnContext() const { InstructionContext insnContext; - if (Name.find("64") != Name.npos || HasREX_WPrefix) { + if (HasVEX_4VPrefix || HasVEXPrefix) { + if (HasOpSizePrefix && HasVEX_LPrefix) + insnContext = IC_VEX_L_OPSIZE; + else if (HasOpSizePrefix && HasVEX_WPrefix) + insnContext = IC_VEX_W_OPSIZE; + else if (HasOpSizePrefix) + insnContext = IC_VEX_OPSIZE; + else if (HasVEX_LPrefix && Prefix == X86Local::XS) + insnContext = IC_VEX_L_XS; + else if (HasVEX_LPrefix && Prefix == X86Local::XD) + insnContext = IC_VEX_L_XD; + else if (HasVEX_WPrefix && Prefix == X86Local::XS) + insnContext = IC_VEX_W_XS; + else if (HasVEX_WPrefix && Prefix == X86Local::XD) + insnContext = IC_VEX_W_XD; + else if (HasVEX_WPrefix) + insnContext = IC_VEX_W; + else if (HasVEX_LPrefix) + insnContext = IC_VEX_L; + else if (Prefix == X86Local::XD) + insnContext = IC_VEX_XD; + else if (Prefix == X86Local::XS) + insnContext = IC_VEX_XS; + else + insnContext = IC_VEX; + } else if (Name.find("64") != Name.npos || HasREX_WPrefix) { if (HasREX_WPrefix && HasOpSizePrefix) insnContext = IC_64BIT_REXW_OPSIZE; else if (HasOpSizePrefix) @@ -280,6 +308,10 @@ InstructionContext RecognizableInstr::insnContext() const { } RecognizableInstr::filter_ret RecognizableInstr::filter() const { + /////////////////// + // FILTER_STRONG + // + // Filter out intrinsics if (!Rec->isSubClassOf("X86Inst")) @@ -291,26 +323,71 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { if (Form == X86Local::MRMInitReg) return FILTER_STRONG; + + + // TEMPORARY pending bug fixes - + if (Name.find("VMOVDQU") != Name.npos || + Name.find("VMOVDQA") != Name.npos || + Name.find("VROUND") != Name.npos) + return FILTER_STRONG; + + // Filter out artificial instructions + + if (Name.find("TAILJMP") != Name.npos || + Name.find("_Int") != Name.npos || + Name.find("_int") != Name.npos || + Name.find("Int_") != Name.npos || + Name.find("_NOREX") != Name.npos || + Name.find("_TC") != Name.npos || + Name.find("EH_RETURN") != Name.npos || + Name.find("V_SET") != Name.npos || + Name.find("LOCK_") != Name.npos || + Name.find("WIN") != Name.npos || + Name.find("_AVX") != Name.npos || + Name.find("2SDL") != Name.npos) + return FILTER_STRONG; + + // Filter out instructions with segment override prefixes. + // They're too messy to handle now and we'll special case them if needed. + + if (SegOvr) + return FILTER_STRONG; + + // Filter out instructions that can't be printed. + + if (AsmString.size() == 0) + return FILTER_STRONG; + + // Filter out instructions with subreg operands. + + if (AsmString.find("subreg") != AsmString.npos) + return FILTER_STRONG; + + ///////////////// + // FILTER_WEAK + // + + // Filter out instructions with a LOCK prefix; // prefer forms that do not have the prefix if (HasLockPrefix) return FILTER_WEAK; - - // Filter out artificial instructions - if (Name.find("TAILJMP") != Name.npos || - Name.find("_Int") != Name.npos || - Name.find("_int") != Name.npos || - Name.find("Int_") != Name.npos || - Name.find("_NOREX") != Name.npos || - Name.find("_TC") != Name.npos || - Name.find("EH_RETURN") != Name.npos || - Name.find("V_SET") != Name.npos || - Name.find("LOCK_") != Name.npos || - Name.find("WIN") != Name.npos) - return FILTER_STRONG; + // Filter out alternate forms of AVX instructions + if (Name.find("_alt") != Name.npos || + Name.find("XrYr") != Name.npos || + Name.find("r64r") != Name.npos || + Name.find("_64mr") != Name.npos || + Name.find("Xrr") != Name.npos || + Name.find("rr64") != Name.npos) + return FILTER_WEAK; + + if (Name == "VMASKMOVDQU64" || + Name == "VEXTRACTPSrr64" || + Name == "VMOVQd64rr" || + Name == "VMOVQs64rr") + return FILTER_WEAK; // Special cases. @@ -339,6 +416,7 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { Name == "PUSH32i16" || Name == "PUSH64i16" || Name == "MOVPQI2QImr" || + Name == "VMOVPQI2QImr" || Name == "MOVSDmr" || Name == "MOVSDrm" || Name == "MOVSSmr" || @@ -349,22 +427,6 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { Name == "CRC32r16") return FILTER_WEAK; - // Filter out instructions with segment override prefixes. - // They're too messy to handle now and we'll special case them if needed. - - if (SegOvr) - return FILTER_STRONG; - - // Filter out instructions that can't be printed. - - if (AsmString.size() == 0) - return FILTER_STRONG; - - // Filter out instructions with subreg operands. - - if (AsmString.find("subreg") != AsmString.npos) - return FILTER_STRONG; - if (HasFROperands && Name.find("MOV") != Name.npos && ((Name.find("2") != Name.npos && Name.find("32") == Name.npos) || (Name.find("to") != Name.npos))) @@ -372,6 +434,33 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { return FILTER_NORMAL; } + +bool RecognizableInstr::hasFROperands() const { + const std::vector &OperandList = *Operands; + unsigned numOperands = OperandList.size(); + + for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { + const std::string &recName = OperandList[operandIndex].Rec->getName(); + + if (recName.find("FR") != recName.npos) + return true; + } + return false; +} + +bool RecognizableInstr::has256BitOperands() const { + const std::vector &OperandList = *Operands; + unsigned numOperands = OperandList.size(); + + for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { + const std::string &recName = OperandList[operandIndex].Rec->getName(); + + if (!recName.compare("VR256") || !recName.compare("f256mem")) { + return true; + } + } + return false; +} void RecognizableInstr::handleOperand( bool optional, @@ -395,13 +484,13 @@ void RecognizableInstr::handleOperand( } const std::string &typeName = (*Operands)[operandIndex].Rec->getName(); - + Spec->operands[operandIndex].encoding = encodingFromString(typeName, HasOpSizePrefix); Spec->operands[operandIndex].type = typeFromString(typeName, - IsSSE, - HasREX_WPrefix, - HasOpSizePrefix); + IsSSE, + HasREX_WPrefix, + HasOpSizePrefix); ++operandIndex; ++physicalOperandIndex; @@ -530,31 +619,45 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { case X86Local::MRMSrcReg: // Operand 1 is a register operand in the Reg/Opcode field. // Operand 2 is a register operand in the R/M field. + // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMSrcRegFrm"); - HANDLE_OPERAND(roRegister) - HANDLE_OPERAND(rmRegister) + if (HasVEX_4VPrefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && + "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); + else + assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMSrcRegFrm"); + + HANDLE_OPERAND(roRegister) + if (HasVEX_4VPrefix) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field - HANDLE_OPTIONAL(rmRegister) - else - HANDLE_OPTIONAL(immediate) + HANDLE_OPERAND(vvvvRegister) + + HANDLE_OPERAND(rmRegister) + HANDLE_OPTIONAL(immediate) break; case X86Local::MRMSrcMem: // Operand 1 is a register operand in the Reg/Opcode field. // Operand 2 is a memory operand (possibly SIB-extended) + // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMSrcMemFrm"); + + if (HasVEX_4VPrefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && + "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); + else + assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMSrcMemFrm"); + HANDLE_OPERAND(roRegister) if (HasVEX_4VPrefix) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field - HANDLE_OPTIONAL(rmRegister) + HANDLE_OPERAND(vvvvRegister) HANDLE_OPERAND(memory) HANDLE_OPTIONAL(immediate) @@ -569,8 +672,14 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { case X86Local::MRM7r: // Operand 1 is a register operand in the R/M field. // Operand 2 (optional) is an immediate or relocation. - assert(numPhysicalOperands <= 2 && - "Unexpected number of operands for MRMnRFrm"); + if (HasVEX_4VPrefix) + assert(numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); + else + assert(numPhysicalOperands <= 2 && + "Unexpected number of operands for MRMnRFrm"); + if (HasVEX_4VPrefix) + HANDLE_OPERAND(vvvvRegister); HANDLE_OPTIONAL(rmRegister) HANDLE_OPTIONAL(relocation) break; @@ -687,6 +796,22 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { filter = new DumbFilter(); opcodeToSet = Opcode; break; + case X86Local::A6: + opcodeType = THREEBYTE_A6; + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + opcodeToSet = Opcode; + break; + case X86Local::A7: + opcodeType = THREEBYTE_A7; + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + opcodeToSet = Opcode; + break; case X86Local::D8: case X86Local::D9: case X86Local::DA: @@ -854,6 +979,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("ssmem", TYPE_M32FP) TYPE("RST", TYPE_ST) TYPE("i128mem", TYPE_M128) + TYPE("i256mem", TYPE_M256) TYPE("i64i32imm_pcrel", TYPE_REL64) TYPE("i16imm_pcrel", TYPE_REL16) TYPE("i32imm_pcrel", TYPE_REL32) @@ -878,6 +1004,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("offset16", TYPE_MOFFS16) TYPE("offset32", TYPE_MOFFS32) TYPE("offset64", TYPE_MOFFS64) + TYPE("VR256", TYPE_XMM256) errs() << "Unhandled type string " << s << "\n"; llvm_unreachable("Unhandled type string"); } @@ -900,6 +1027,10 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString ENCODING("i64i32imm", ENCODING_ID) ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) + // This is not a typo. Instructions like BLENDVPD put + // register IDs in 8-bit immediates nowadays. + ENCODING("VR256", ENCODING_IB) + ENCODING("VR128", ENCODING_IB) errs() << "Unhandled immediate encoding " << s << "\n"; llvm_unreachable("Unhandled immediate encoding"); } @@ -915,6 +1046,7 @@ OperandEncoding RecognizableInstr::rmRegisterEncodingFromString ENCODING("FR64", ENCODING_RM) ENCODING("FR32", ENCODING_RM) ENCODING("VR64", ENCODING_RM) + ENCODING("VR256", ENCODING_RM) errs() << "Unhandled R/M register encoding " << s << "\n"; llvm_unreachable("Unhandled R/M register encoding"); } @@ -933,10 +1065,22 @@ OperandEncoding RecognizableInstr::roRegisterEncodingFromString ENCODING("SEGMENT_REG", ENCODING_REG) ENCODING("DEBUG_REG", ENCODING_REG) ENCODING("CONTROL_REG", ENCODING_REG) + ENCODING("VR256", ENCODING_REG) errs() << "Unhandled reg/opcode register encoding " << s << "\n"; llvm_unreachable("Unhandled reg/opcode register encoding"); } +OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + ENCODING("FR32", ENCODING_VVVV) + ENCODING("FR64", ENCODING_VVVV) + ENCODING("VR128", ENCODING_VVVV) + ENCODING("VR256", ENCODING_VVVV) + errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; + llvm_unreachable("Unhandled VEX.vvvv register encoding"); +} + OperandEncoding RecognizableInstr::memoryEncodingFromString (const std::string &s, bool hasOpSizePrefix) { @@ -951,6 +1095,7 @@ OperandEncoding RecognizableInstr::memoryEncodingFromString ENCODING("f64mem", ENCODING_RM) ENCODING("f32mem", ENCODING_RM) ENCODING("i128mem", ENCODING_RM) + ENCODING("i256mem", ENCODING_RM) ENCODING("f80mem", ENCODING_RM) ENCODING("lea32mem", ENCODING_RM) ENCODING("lea64_32mem", ENCODING_RM) diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h index c043b909b42f..c7ec18ca6dbb 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h @@ -52,8 +52,14 @@ class RecognizableInstr { bool HasOpSizePrefix; /// The hasREX_WPrefix field from the record bool HasREX_WPrefix; + /// The hasVEXPrefix field from the record + bool HasVEXPrefix; /// The hasVEX_4VPrefix field from the record bool HasVEX_4VPrefix; + /// The hasVEX_WPrefix field from the record + bool HasVEX_WPrefix; + /// Inferred from the operands; indicates whether the L bit in the VEX prefix is set + bool HasVEX_LPrefix; /// The hasLockPrefix field from the record bool HasLockPrefix; /// The isCodeGenOnly filed from the record @@ -96,7 +102,7 @@ class RecognizableInstr { // error if it conflcits with any other FILTER_NORMAL // instruction }; - + /// filter - Determines whether the instruction should be decodable. Some /// instructions are pure intrinsics and use unencodable operands; many /// synthetic instructions are duplicates of other instructions; other @@ -106,6 +112,12 @@ class RecognizableInstr { /// /// @return - The degree of filtering to be applied (see filter_ret). filter_ret filter() const; + + /// hasFROperands - Returns true if any operand is a FR operand. + bool hasFROperands() const; + + /// has256BitOperands - Returns true if any operand is a 256-bit SSE operand. + bool has256BitOperands() const; /// typeFromString - Translates an operand type from the string provided in /// the LLVM tables to an OperandType for use in the operand specifier. @@ -155,6 +167,8 @@ class RecognizableInstr { bool hasOpSizePrefix); static OperandEncoding opcodeModifierEncodingFromString(const std::string &s, bool hasOpSizePrefix); + static OperandEncoding vvvvRegisterEncodingFromString(const std::string &s, + bool HasOpSizePrefix); /// handleOperand - Converts a single operand from the LLVM table format to /// the emitted table format, handling any duplicate operands it encounters diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index f9ef8f8b0a20..f960c5243e2d 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -84,7 +84,7 @@ .. .. clang - 2.9 + 3.0 .. .. crypto diff --git a/lib/clang/Makefile b/lib/clang/Makefile index c37e0896b4ed..212c7c8b8570 100644 --- a/lib/clang/Makefile +++ b/lib/clang/Makefile @@ -14,9 +14,9 @@ SUBDIR= libclanganalysis \ libclangrewrite \ libclangsema \ libclangserialization \ + libclangstaticanalyzercheckers \ libclangstaticanalyzercore \ libclangstaticanalyzerfrontend \ - libclangstaticanalyzercheckers \ \ libllvmanalysis \ libllvmasmparser \ @@ -24,8 +24,9 @@ SUBDIR= libclanganalysis \ libllvmbitreader \ libllvmbitwriter \ libllvmcodegen \ - libllvminstcombine \ libllvmcore \ + libllvminstcombine \ + libllvminstrumentation \ libllvmipa \ libllvmipo \ libllvmmc \ @@ -37,20 +38,20 @@ SUBDIR= libclanganalysis \ libllvmtransformutils \ \ libllvmarmasmparser \ - libllvmarminstprinter \ libllvmarmcodegen \ libllvmarmdisassembler \ libllvmarminfo \ + libllvmarminstprinter \ libllvmmipscodegen \ libllvmmipsinfo \ - libllvmpowerpcinstprinter \ libllvmpowerpccodegen \ libllvmpowerpcinfo \ + libllvmpowerpcinstprinter \ libllvmx86asmparser \ - libllvmx86instprinter \ libllvmx86codegen \ libllvmx86disassembler \ libllvmx86info \ + libllvmx86instprinter \ libllvmx86utils .endif diff --git a/lib/clang/clang.build.mk b/lib/clang/clang.build.mk index 579140ea82dc..da5345502547 100644 --- a/lib/clang/clang.build.mk +++ b/lib/clang/clang.build.mk @@ -96,24 +96,29 @@ arm_neon.inc.h: ${CLANG_SRCS}/include/clang/Basic/arm_neon.td DiagnosticGroups.inc.h: ${CLANG_SRCS}/include/clang/Basic/Diagnostic.td ${TBLGEN} -gen-clang-diag-groups -I${CLANG_SRCS}/include/clang/Basic \ - ${CLANG_SRCS}/include/clang/Basic/Diagnostic.td > ${.TARGET} + ${.ALLSRC} > ${.TARGET} + +DiagnosticIndexName.inc.h: ${CLANG_SRCS}/include/clang/Basic/Diagnostic.td + ${TBLGEN} -gen-clang-diags-index-name \ + -I${CLANG_SRCS}/include/clang/Basic ${.ALLSRC} > ${.TARGET} + .for hdr in AST Analysis Common Driver Frontend Lex Parse Sema Diagnostic${hdr}Kinds.inc.h: ${CLANG_SRCS}/include/clang/Basic/Diagnostic.td ${TBLGEN} -gen-clang-diags-defs -clang-component=${hdr} \ - -I${CLANG_SRCS}/include/clang/Basic \ - ${CLANG_SRCS}/include/clang/Basic/Diagnostic.td > ${.TARGET} + -I${CLANG_SRCS}/include/clang/Basic ${.ALLSRC} > ${.TARGET} .endfor + Options.inc.h: ${CLANG_SRCS}/include/clang/Driver/Options.td ${TBLGEN} -gen-opt-parser-defs -I${CLANG_SRCS}/include/clang/Driver \ - ${CLANG_SRCS}/include/clang/Driver/Options.td > ${.TARGET} + ${.ALLSRC} > ${.TARGET} CC1Options.inc.h: ${CLANG_SRCS}/include/clang/Driver/CC1Options.td ${TBLGEN} -gen-opt-parser-defs -I${CLANG_SRCS}/include/clang/Driver \ - ${CLANG_SRCS}/include/clang/Driver/CC1Options.td > ${.TARGET} + ${.ALLSRC} > ${.TARGET} CC1AsOptions.inc.h: ${CLANG_SRCS}/include/clang/Driver/CC1AsOptions.td ${TBLGEN} -gen-opt-parser-defs -I${CLANG_SRCS}/include/clang/Driver \ - ${CLANG_SRCS}/include/clang/Driver/CC1AsOptions.td > ${.TARGET} + ${.ALLSRC} > ${.TARGET} Checkers.inc.h: ${CLANG_SRCS}/lib/StaticAnalyzer/Checkers/Checkers.td \ ${CLANG_SRCS}/include/clang/StaticAnalyzer/Checkers/CheckerBase.td diff --git a/lib/clang/include/Makefile b/lib/clang/include/Makefile index 9f3397dc9c71..6f46e2842fa5 100644 --- a/lib/clang/include/Makefile +++ b/lib/clang/include/Makefile @@ -2,13 +2,21 @@ .PATH: ${.CURDIR}/../../../contrib/llvm/tools/clang/lib/Headers -INCSDIR=${INCLUDEDIR}/clang/2.9 +INCSDIR=${INCLUDEDIR}/clang/3.0 -INCS= emmintrin.h \ +INCS= altivec.h \ + avxintrin.h \ + emmintrin.h \ + immintrin.h \ + mm3dnow.h \ mm_malloc.h \ mmintrin.h \ + nmmintrin.h \ pmmintrin.h \ + smmintrin.h \ tmmintrin.h \ + wmmintrin.h \ + x86intrin.h \ xmmintrin.h .include diff --git a/lib/clang/include/clang/Basic/DiagnosticIndexName.inc b/lib/clang/include/clang/Basic/DiagnosticIndexName.inc new file mode 100644 index 000000000000..1baf975fcf30 --- /dev/null +++ b/lib/clang/include/clang/Basic/DiagnosticIndexName.inc @@ -0,0 +1,2 @@ +/* $FreeBSD$ */ +#include "DiagnosticIndexName.inc.h" diff --git a/lib/clang/include/clang/Basic/Version.inc b/lib/clang/include/clang/Basic/Version.inc index 1d6509c8fe84..1febce2ffff6 100644 --- a/lib/clang/include/clang/Basic/Version.inc +++ b/lib/clang/include/clang/Basic/Version.inc @@ -1,10 +1,10 @@ /* $FreeBSD$ */ -#define CLANG_VERSION 2.9 -#define CLANG_VERSION_MAJOR 2 -#define CLANG_VERSION_MINOR 9 +#define CLANG_VERSION 3.0 +#define CLANG_VERSION_MAJOR 3 +#define CLANG_VERSION_MINOR 0 #define CLANG_VENDOR "FreeBSD " -#define CLANG_VENDOR_SUFFIX " 20110226" +#define CLANG_VENDOR_SUFFIX " 20110502" -#define SVN_REVISION "126547" +#define SVN_REVISION "130700" diff --git a/lib/clang/include/llvm/Config/config.h b/lib/clang/include/llvm/Config/config.h index 6b0629cd6c18..229b705ecaba 100644 --- a/lib/clang/include/llvm/Config/config.h +++ b/lib/clang/include/llvm/Config/config.h @@ -645,13 +645,13 @@ #define PACKAGE_NAME "llvm" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "llvm 2.9svn" +#define PACKAGE_STRING "llvm 3.0svn" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "-llvm-" /* Define to the version of this package. */ -#define PACKAGE_VERSION "2.9svn" +#define PACKAGE_VERSION "3.0svn" /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void diff --git a/lib/clang/libclanganalysis/Makefile b/lib/clang/libclanganalysis/Makefile index e1224698ebfe..d0df7798838a 100644 --- a/lib/clang/libclanganalysis/Makefile +++ b/lib/clang/libclanganalysis/Makefile @@ -14,8 +14,7 @@ SRCS= AnalysisContext.cpp \ PseudoConstantAnalysis.cpp \ ReachableCode.cpp \ ScanfFormatString.cpp \ - UninitializedValues.cpp \ - UninitializedValuesV2.cpp + UninitializedValues.cpp TGHDRS= AttrList \ Attrs \ diff --git a/lib/clang/libclangast/Makefile b/lib/clang/libclangast/Makefile index d68f4775c4fb..61b44fb22828 100644 --- a/lib/clang/libclangast/Makefile +++ b/lib/clang/libclangast/Makefile @@ -24,6 +24,7 @@ SRCS= APValue.cpp \ ExprCXX.cpp \ ExprClassification.cpp \ ExprConstant.cpp \ + ExternalASTSource.cpp \ InheritViz.cpp \ ItaniumCXXABI.cpp \ ItaniumMangle.cpp \ diff --git a/lib/clang/libclangbasic/Makefile b/lib/clang/libclangbasic/Makefile index eec370cd661e..49e35339b696 100644 --- a/lib/clang/libclangbasic/Makefile +++ b/lib/clang/libclangbasic/Makefile @@ -15,6 +15,7 @@ SRCS= Builtins.cpp \ TargetInfo.cpp \ Targets.cpp \ TokenKinds.cpp \ + VersionTuple.cpp \ Version.cpp TGHDRS= DiagnosticAnalysisKinds \ @@ -23,6 +24,7 @@ TGHDRS= DiagnosticAnalysisKinds \ DiagnosticDriverKinds \ DiagnosticFrontendKinds \ DiagnosticGroups \ + DiagnosticIndexName \ DiagnosticLexKinds \ DiagnosticParseKinds \ DiagnosticSemaKinds \ diff --git a/lib/clang/libclangcodegen/Makefile b/lib/clang/libclangcodegen/Makefile index c17434384b1b..d1798ca1bb15 100644 --- a/lib/clang/libclangcodegen/Makefile +++ b/lib/clang/libclangcodegen/Makefile @@ -24,6 +24,7 @@ SRCS= BackendUtil.cpp \ CGObjC.cpp \ CGObjCGNU.cpp \ CGObjCMac.cpp \ + CGObjCRuntime.cpp \ CGRTTI.cpp \ CGRecordLayoutBuilder.cpp \ CGStmt.cpp \ diff --git a/lib/clang/libclangfrontend/Makefile b/lib/clang/libclangfrontend/Makefile index 45e064bee82c..71f76b7e80af 100644 --- a/lib/clang/libclangfrontend/Makefile +++ b/lib/clang/libclangfrontend/Makefile @@ -10,10 +10,9 @@ SRCS= ASTConsumers.cpp \ CacheTokens.cpp \ CompilerInstance.cpp \ CompilerInvocation.cpp \ - DeclXML.cpp \ + CreateInvocationFromCommandLine.cpp \ DependencyFile.cpp \ DiagChecker.cpp \ - DocumentXML.cpp \ FrontendAction.cpp \ FrontendActions.cpp \ FrontendOptions.cpp \ @@ -21,12 +20,11 @@ SRCS= ASTConsumers.cpp \ InitHeaderSearch.cpp \ InitPreprocessor.cpp \ LangStandards.cpp \ + LogDiagnosticPrinter.cpp \ MultiplexConsumer.cpp \ PrintPreprocessedOutput.cpp \ - StmtXML.cpp \ TextDiagnosticBuffer.cpp \ TextDiagnosticPrinter.cpp \ - TypeXML.cpp \ VerifyDiagnosticsClient.cpp \ Warnings.cpp @@ -40,6 +38,7 @@ TGHDRS= AttrList \ DiagnosticFrontendKinds \ DiagnosticLexKinds \ DiagnosticSemaKinds \ + Options \ StmtNodes .include "../clang.lib.mk" diff --git a/lib/clang/libclangsema/Makefile b/lib/clang/libclangsema/Makefile index 14259291465d..d2c7e34a6a7f 100644 --- a/lib/clang/libclangsema/Makefile +++ b/lib/clang/libclangsema/Makefile @@ -7,8 +7,10 @@ SRCS= AnalysisBasedWarnings.cpp \ AttributeList.cpp \ CodeCompleteConsumer.cpp \ DeclSpec.cpp \ + DelayedDiagnostic.cpp \ IdentifierResolver.cpp \ JumpDiagnostics.cpp \ + Scope.cpp \ Sema.cpp \ SemaAccess.cpp \ SemaAttr.cpp \ diff --git a/lib/clang/libclangserialization/Makefile b/lib/clang/libclangserialization/Makefile index 1dbcf5d63b9d..75a00312e701 100644 --- a/lib/clang/libclangserialization/Makefile +++ b/lib/clang/libclangserialization/Makefile @@ -10,6 +10,7 @@ SRCS= ASTCommon.cpp \ ASTWriter.cpp \ ASTWriterDecl.cpp \ ASTWriterStmt.cpp \ + ChainedIncludesSource.cpp \ GeneratePCH.cpp TGHDRS= AttrList \ diff --git a/lib/clang/libclangstaticanalyzercheckers/Makefile b/lib/clang/libclangstaticanalyzercheckers/Makefile index 496d10798953..adc78822e7fc 100644 --- a/lib/clang/libclangstaticanalyzercheckers/Makefile +++ b/lib/clang/libclangstaticanalyzercheckers/Makefile @@ -24,10 +24,9 @@ SRCS= AdjustedReturnValueChecker.cpp \ DebugCheckers.cpp \ DereferenceChecker.cpp \ DivZeroChecker.cpp \ - ExperimentalChecks.cpp \ - ExprEngine.cpp \ FixedAddressChecker.cpp \ IdempotentOperationChecker.cpp \ + IteratorsChecker.cpp \ LLVMConventionsChecker.cpp \ MacOSXAPIChecker.cpp \ MallocChecker.cpp \ diff --git a/lib/clang/libclangstaticanalyzercore/Makefile b/lib/clang/libclangstaticanalyzercore/Makefile index 59df789c0682..76863dc2961f 100644 --- a/lib/clang/libclangstaticanalyzercore/Makefile +++ b/lib/clang/libclangstaticanalyzercore/Makefile @@ -13,12 +13,13 @@ SRCS= AggExprVisitor.cpp \ BugReporterVisitors.cpp \ CFRefCount.cpp \ CXXExprEngine.cpp \ - Checker.cpp \ + CheckerContext.cpp \ CheckerHelpers.cpp \ CheckerManager.cpp \ CoreEngine.cpp \ Environment.cpp \ ExplodedGraph.cpp \ + ExprEngine.cpp \ FlatStore.cpp \ GRState.cpp \ HTMLDiagnostics.cpp \ diff --git a/lib/clang/libllvmanalysis/Makefile b/lib/clang/libllvmanalysis/Makefile index eb2043edd38a..5436631f26c7 100644 --- a/lib/clang/libllvmanalysis/Makefile +++ b/lib/clang/libllvmanalysis/Makefile @@ -27,7 +27,6 @@ SRCS= AliasAnalysis.cpp \ LazyValueInfo.cpp \ LibCallAliasAnalysis.cpp \ Lint.cpp \ - LiveValues.cpp \ Loads.cpp \ LoopDependenceAnalysis.cpp \ LoopInfo.cpp \ diff --git a/lib/clang/libllvmasmprinter/Makefile b/lib/clang/libllvmasmprinter/Makefile index 35f942cd682e..7e5182cc86d2 100644 --- a/lib/clang/libllvmasmprinter/Makefile +++ b/lib/clang/libllvmasmprinter/Makefile @@ -3,11 +3,13 @@ LIB= llvmasmprinter SRCDIR= lib/CodeGen/AsmPrinter -SRCS= AsmPrinter.cpp \ +SRCS= ARMException.cpp \ + AsmPrinter.cpp \ AsmPrinterDwarf.cpp \ AsmPrinterInlineAsm.cpp \ DIE.cpp \ DwarfCFIException.cpp \ + DwarfCompileUnit.cpp \ DwarfDebug.cpp \ DwarfException.cpp \ DwarfTableException.cpp \ diff --git a/lib/clang/libllvmcodegen/Makefile b/lib/clang/libllvmcodegen/Makefile index bd9b707bbe6c..c7c55a24563a 100644 --- a/lib/clang/libllvmcodegen/Makefile +++ b/lib/clang/libllvmcodegen/Makefile @@ -4,10 +4,12 @@ LIB= llvmcodegen SRCDIR= lib/CodeGen SRCS= AggressiveAntiDepBreaker.cpp \ + AllocationOrder.cpp \ Analysis.cpp \ BranchFolding.cpp \ CalcSpillWeights.cpp \ CallingConvLower.cpp \ + CodeGen.cpp \ CodePlacementOpt.cpp \ CriticalAntiDepBreaker.cpp \ DeadMachineInstructionElim.cpp \ @@ -17,9 +19,11 @@ SRCS= AggressiveAntiDepBreaker.cpp \ EdgeBundles.cpp \ ExpandISelPseudos.cpp \ GCMetadata.cpp \ + GCMetadataPrinter.cpp \ GCStrategy.cpp \ IfConversion.cpp \ InlineSpiller.cpp \ + InterferenceCache.cpp \ IntrinsicLowering.cpp \ LLVMTargetMachine.cpp \ LatencyPriorityQueue.cpp \ @@ -42,6 +46,7 @@ SRCS= AggressiveAntiDepBreaker.cpp \ MachineInstr.cpp \ MachineLICM.cpp \ MachineLoopInfo.cpp \ + MachineLoopRanges.cpp \ MachineModuleInfo.cpp \ MachineModuleInfoImpls.cpp \ MachinePassRegistry.cpp \ @@ -63,6 +68,7 @@ SRCS= AggressiveAntiDepBreaker.cpp \ PseudoSourceValue.cpp \ RegAllocBasic.cpp \ RegAllocFast.cpp \ + RegAllocGreedy.cpp \ RegAllocLinearScan.cpp \ RegAllocPBQP.cpp \ RegisterCoalescer.cpp \ @@ -79,6 +85,7 @@ SRCS= AggressiveAntiDepBreaker.cpp \ SjLjEHPrepare.cpp \ SlotIndexes.cpp \ Spiller.cpp \ + SpillPlacement.cpp \ SplitKit.cpp \ Splitter.cpp \ StackProtector.cpp \ diff --git a/lib/clang/libllvmcore/Makefile b/lib/clang/libllvmcore/Makefile index 961f15b03292..4e3adde503d9 100644 --- a/lib/clang/libllvmcore/Makefile +++ b/lib/clang/libllvmcore/Makefile @@ -10,6 +10,7 @@ SRCS= AsmWriter.cpp \ ConstantFold.cpp \ Constants.cpp \ Core.cpp \ + DebugInfoProbe.cpp \ DebugLoc.cpp \ Dominators.cpp \ Function.cpp \ diff --git a/lib/clang/libllvminstrumentation/Makefile b/lib/clang/libllvminstrumentation/Makefile new file mode 100644 index 000000000000..62d9f979687c --- /dev/null +++ b/lib/clang/libllvminstrumentation/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +LIB= llvminstrumentation + +SRCDIR= lib/Transforms/Instrumentation +SRCS= EdgeProfiling.cpp \ + GCOVProfiling.cpp \ + Instrumentation.cpp \ + OptimalEdgeProfiling.cpp \ + PathProfiling.cpp \ + ProfilingUtils.cpp \ + +#TGHDRS= Intrinsics + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmipo/Makefile b/lib/clang/libllvmipo/Makefile index 5653684cf7d4..f919dd145240 100644 --- a/lib/clang/libllvmipo/Makefile +++ b/lib/clang/libllvmipo/Makefile @@ -22,8 +22,7 @@ SRCS= ArgumentPromotion.cpp \ PartialInlining.cpp \ PruneEH.cpp \ StripDeadPrototypes.cpp \ - StripSymbols.cpp \ - StructRetPromotion.cpp + StripSymbols.cpp TGHDRS= Intrinsics diff --git a/lib/clang/libllvmmc/Makefile b/lib/clang/libllvmmc/Makefile index 5bbff4b803fa..a7ed25b29fbe 100644 --- a/lib/clang/libllvmmc/Makefile +++ b/lib/clang/libllvmmc/Makefile @@ -12,6 +12,7 @@ SRCS= ELFObjectWriter.cpp \ MCCodeEmitter.cpp \ MCContext.cpp \ MCDwarf.cpp \ + MCELF.cpp \ MCELFObjectTargetWriter.cpp \ MCELFStreamer.cpp \ MCExpr.cpp \ diff --git a/lib/clang/libllvmmipscodegen/Makefile b/lib/clang/libllvmmipscodegen/Makefile index ce84aa49f156..47744ede2fc3 100644 --- a/lib/clang/libllvmmipscodegen/Makefile +++ b/lib/clang/libllvmmipscodegen/Makefile @@ -5,6 +5,7 @@ LIB= llvmmipscodegen SRCDIR= lib/Target/Mips SRCS= MipsAsmPrinter.cpp \ MipsDelaySlotFiller.cpp \ + MipsExpandPseudo.cpp \ MipsFrameLowering.cpp \ MipsISelDAGToDAG.cpp \ MipsISelLowering.cpp \ diff --git a/lib/clang/libllvmscalaropts/Makefile b/lib/clang/libllvmscalaropts/Makefile index e4824b5a381a..757b8e03e697 100644 --- a/lib/clang/libllvmscalaropts/Makefile +++ b/lib/clang/libllvmscalaropts/Makefile @@ -11,7 +11,6 @@ SRCS= ADCE.cpp \ DCE.cpp \ DeadStoreElimination.cpp \ EarlyCSE.cpp \ - GEPSplitter.cpp \ GVN.cpp \ IndVarSimplify.cpp \ JumpThreading.cpp \ @@ -27,7 +26,6 @@ SRCS= ADCE.cpp \ SCCP.cpp \ ScalarReplAggregates.cpp \ SimplifyCFGPass.cpp \ - SimplifyHalfPowrLibCalls.cpp \ SimplifyLibCalls.cpp \ Sink.cpp \ TailDuplication.cpp \ diff --git a/lib/clang/libllvmx86instprinter/Makefile b/lib/clang/libllvmx86instprinter/Makefile index dda091e82037..eb30daa89b90 100644 --- a/lib/clang/libllvmx86instprinter/Makefile +++ b/lib/clang/libllvmx86instprinter/Makefile @@ -10,6 +10,7 @@ SRCS= X86ATTInstPrinter.cpp \ TGHDRS= X86GenAsmWriter \ X86GenAsmWriter1 \ - X86GenInstrNames + X86GenInstrNames \ + X86GenRegisterNames .include "../clang.lib.mk" diff --git a/usr.bin/clang/clang/Makefile b/usr.bin/clang/clang/Makefile index b5c2b1dd7579..2abafd793f7d 100644 --- a/usr.bin/clang/clang/Makefile +++ b/usr.bin/clang/clang/Makefile @@ -35,38 +35,39 @@ LIBDEPS=clangfrontendtool \ clangast \ clanglex \ clangbasic \ - llvminstcombine \ llvmipo \ + llvminstrumentation \ llvmbitwriter \ llvmbitreader \ - llvmpowerpccodegen \ - llvmpowerpcinstprinter \ - llvmpowerpcinfo \ - llvmx86asmparser \ - llvmx86disassembler \ - llvmx86codegen \ - llvmx86instprinter \ - llvmx86info \ - llvmx86utils \ - llvmmipscodegen \ - llvmmipsinfo \ + llvmasmparser \ + llvmarmdisassembler \ llvmarmasmparser \ llvmarmcodegen \ llvmarminstprinter \ - llvmasmparser \ + llvmarminfo \ + llvmmipscodegen \ + llvmmipsinfo \ + llvmpowerpccodegen \ + llvmpowerpcinstprinter \ + llvmpowerpcinfo \ + llvmx86disassembler \ + llvmx86asmparser \ + llvmx86codegen \ llvmselectiondag \ llvmasmprinter \ + llvmmcparser \ llvmcodegen \ llvmscalaropts \ + llvminstcombine \ llvmtransformutils \ - llvmmc \ - llvmmcparser \ llvmipa \ llvmanalysis \ llvmtarget \ - llvmmc \ + llvmx86instprinter \ + llvmx86utils \ llvmcore \ - llvmarminfo \ + llvmx86info \ + llvmmc \ llvmsupport .include "../clang.prog.mk"