Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by Chris Lattner and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file defines the SourceLocation class. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_CLANG_SOURCELOCATION_H |
| 15 | #define LLVM_CLANG_SOURCELOCATION_H |
| 16 | |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 17 | #include <cassert> |
| 18 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 19 | namespace clang { |
| 20 | |
| 21 | /// SourceLocation - This is a carefully crafted 32-bit identifier that encodes |
| 22 | /// a full include stack, line and column number information for a position in |
| 23 | /// an input translation unit. |
| 24 | class SourceLocation { |
| 25 | unsigned ID; |
| 26 | public: |
| 27 | enum { |
| 28 | FileIDBits = 14, |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 29 | FilePosBits = 32-1-FileIDBits, |
| 30 | |
Chris Lattner | d1623a8 | 2007-07-21 06:41:57 +0000 | [diff] [blame] | 31 | MacroIDBits = 20, |
Chris Lattner | 31bb8be | 2007-07-20 18:00:12 +0000 | [diff] [blame] | 32 | MacroPhysOffsBits = 9, |
Chris Lattner | 2c64b7b | 2007-10-16 21:07:07 +0000 | [diff] [blame^] | 33 | MacroLogOffBits = 2, |
| 34 | |
| 35 | ChunkSize = (1 << FilePosBits) |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 36 | }; |
| 37 | |
| 38 | SourceLocation() : ID(0) {} // 0 is an invalid FileID. |
| 39 | |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 40 | bool isFileID() const { return (ID >> 31) == 0; } |
| 41 | bool isMacroID() const { return (ID >> 31) != 0; } |
| 42 | |
| 43 | static SourceLocation getFileLoc(unsigned FileID, unsigned FilePos) { |
| 44 | SourceLocation L; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 45 | // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes |
| 46 | // enough consequtive FileIDs that we have one for each chunk. |
Chris Lattner | 2c64b7b | 2007-10-16 21:07:07 +0000 | [diff] [blame^] | 47 | if (FilePos >= ChunkSize) { |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 48 | FileID += FilePos >> FilePosBits; |
Chris Lattner | 2c64b7b | 2007-10-16 21:07:07 +0000 | [diff] [blame^] | 49 | FilePos &= ChunkSize-1; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | // FIXME: Find a way to handle out of FileID bits! Maybe MaxFileID is an |
| 53 | // escape of some sort? |
Chris Lattner | 4cabcfe | 2007-08-02 04:14:33 +0000 | [diff] [blame] | 54 | assert(FileID < (1 << FileIDBits) && "Out of fileid's"); |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 55 | |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 56 | L.ID = (FileID << FilePosBits) | FilePos; |
| 57 | return L; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 58 | } |
| 59 | |
Chris Lattner | d1623a8 | 2007-07-21 06:41:57 +0000 | [diff] [blame] | 60 | static bool isValidMacroPhysOffs(int Val) { |
| 61 | if (Val >= 0) |
| 62 | return Val < (1 << (MacroPhysOffsBits-1)); |
| 63 | return -Val < (1 << (MacroPhysOffsBits-1)); |
| 64 | } |
| 65 | |
| 66 | static SourceLocation getMacroLoc(unsigned MacroID, int PhysOffs, |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 67 | unsigned LogOffs) { |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 68 | assert(MacroID < (1 << MacroIDBits) && "Too many macros!"); |
Chris Lattner | d1623a8 | 2007-07-21 06:41:57 +0000 | [diff] [blame] | 69 | assert(isValidMacroPhysOffs(PhysOffs) && "Physoffs too large!"); |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 70 | assert(LogOffs < (1 << MacroLogOffBits) && "Logical offs too large!"); |
| 71 | |
Chris Lattner | d1623a8 | 2007-07-21 06:41:57 +0000 | [diff] [blame] | 72 | PhysOffs &= (1 << MacroPhysOffsBits)-1; |
| 73 | |
| 74 | SourceLocation L; |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 75 | L.ID = (1 << 31) | (MacroID << (MacroPhysOffsBits+MacroLogOffBits)) | |
Chris Lattner | d1623a8 | 2007-07-21 06:41:57 +0000 | [diff] [blame] | 76 | (PhysOffs << MacroLogOffBits) | |
| 77 | LogOffs; |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 78 | return L; |
| 79 | } |
| 80 | |
| 81 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 82 | /// isValid - Return true if this is a valid SourceLocation object. Invalid |
| 83 | /// SourceLocations are often used when events have no corresponding location |
| 84 | /// in the source (e.g. a diagnostic is required for a command line option). |
| 85 | /// |
| 86 | bool isValid() const { return ID != 0; } |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 87 | bool isInvalid() const { return ID == 0; } |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 88 | |
| 89 | /// getFileID - Return the file identifier for this SourceLocation. This |
| 90 | /// FileID can be used with the SourceManager object to obtain an entire |
| 91 | /// include stack for a file position reference. |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 92 | unsigned getFileID() const { |
| 93 | assert(isFileID() && "can't get the file id of a non-file sloc!"); |
| 94 | return ID >> FilePosBits; |
| 95 | } |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 96 | |
| 97 | /// getRawFilePos - Return the byte offset from the start of the file-chunk |
| 98 | /// referred to by FileID. This method should not be used to get the offset |
| 99 | /// from the start of the file, instead you should use |
| 100 | /// SourceManager::getFilePos. This method will be incorrect for large files. |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 101 | unsigned getRawFilePos() const { |
| 102 | assert(isFileID() && "can't get the file id of a non-file sloc!"); |
Chris Lattner | 2c64b7b | 2007-10-16 21:07:07 +0000 | [diff] [blame^] | 103 | return ID & (ChunkSize-1); |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | unsigned getMacroID() const { |
| 107 | assert(isMacroID() && "Is not a macro id!"); |
| 108 | return (ID >> (MacroPhysOffsBits+MacroLogOffBits)) & ((1 << MacroIDBits)-1); |
| 109 | } |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 110 | |
Chris Lattner | d1623a8 | 2007-07-21 06:41:57 +0000 | [diff] [blame] | 111 | int getMacroPhysOffs() const { |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 112 | assert(isMacroID() && "Is not a macro id!"); |
Chris Lattner | d1623a8 | 2007-07-21 06:41:57 +0000 | [diff] [blame] | 113 | int Val = (ID >> MacroLogOffBits) & ((1 << MacroPhysOffsBits)-1); |
| 114 | // Sign extend it properly. |
| 115 | unsigned ShAmt = sizeof(int)*8 - MacroPhysOffsBits; |
| 116 | return (Val << ShAmt) >> ShAmt; |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 117 | } |
| 118 | |
| 119 | unsigned getMacroLogOffs() const { |
| 120 | assert(isMacroID() && "Is not a macro id!"); |
Chris Lattner | 31bb8be | 2007-07-20 18:00:12 +0000 | [diff] [blame] | 121 | return ID & ((1 << MacroLogOffBits)-1); |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 122 | } |
| 123 | |
| 124 | /// getFileLocWithOffset - Return a source location with the specified offset |
| 125 | /// from this file SourceLocation. |
Chris Lattner | d1623a8 | 2007-07-21 06:41:57 +0000 | [diff] [blame] | 126 | SourceLocation getFileLocWithOffset(int Offset) const { |
Chris Lattner | 2c64b7b | 2007-10-16 21:07:07 +0000 | [diff] [blame^] | 127 | unsigned FileID = getFileID(); |
| 128 | Offset += getRawFilePos(); |
| 129 | // Handle negative offsets correctly. |
| 130 | while (Offset < 0) { |
| 131 | --FileID; |
| 132 | Offset += ChunkSize; |
| 133 | } |
| 134 | return getFileLoc(FileID, Offset); |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 135 | } |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 136 | |
| 137 | /// getRawEncoding - When a SourceLocation itself cannot be used, this returns |
| 138 | /// an (opaque) 32-bit integer encoding for it. This should only be passed |
| 139 | /// to SourceLocation::getFromRawEncoding, it should not be inspected |
| 140 | /// directly. |
| 141 | unsigned getRawEncoding() const { return ID; } |
| 142 | |
| 143 | /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into |
| 144 | /// a real SourceLocation. |
| 145 | static SourceLocation getFromRawEncoding(unsigned Encoding) { |
| 146 | SourceLocation X; |
| 147 | X.ID = Encoding; |
| 148 | return X; |
| 149 | } |
| 150 | }; |
| 151 | |
| 152 | inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { |
| 153 | return LHS.getRawEncoding() == RHS.getRawEncoding(); |
| 154 | } |
| 155 | |
| 156 | inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) { |
| 157 | return !(LHS == RHS); |
| 158 | } |
| 159 | |
| 160 | /// SourceRange - a trival tuple used to represent a source range. |
| 161 | class SourceRange { |
| 162 | SourceLocation B; |
| 163 | SourceLocation E; |
| 164 | public: |
| 165 | SourceRange(): B(SourceLocation()), E(SourceLocation()) {} |
| 166 | SourceRange(SourceLocation loc) : B(loc), E(loc) {} |
| 167 | SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} |
| 168 | |
| 169 | SourceLocation Begin() const { return B; } |
| 170 | SourceLocation End() const { return E; } |
| 171 | |
Chris Lattner | e80a59c | 2007-07-25 00:24:17 +0000 | [diff] [blame] | 172 | void setBegin(SourceLocation b) { B = b; } |
| 173 | void setEnd(SourceLocation e) { E = e; } |
| 174 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 175 | bool isValid() const { return B.isValid() && E.isValid(); } |
| 176 | }; |
| 177 | |
| 178 | } // end namespace clang |
| 179 | |
| 180 | #endif |