xref: /freebsd/contrib/llvm-project/clang/include/clang/Serialization/SourceLocationEncoding.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===--- SourceLocationEncoding.h - Small serialized locations --*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // We wish to encode the SourceLocation from other module file not dependent
10 // on the other module file. So that the source location changes from other
11 // module file may not affect the contents of the current module file. Then the
12 // users don't need to recompile the whole project due to a new line in a module
13 // unit in the root of the dependency graph.
14 //
15 // To achieve this, we need to encode the index of the module file into the
16 // encoding of the source location. The encoding of the source location may be:
17 //
18 //      |-----------------------|-----------------------|
19 //      |          A            |         B         | C |
20 //
21 //  * A: 32 bit. The index of the module file in the module manager + 1. The +1
22 //  here is necessary since we wish 0 stands for the current module file.
23 //  * B: 31 bit. The offset of the source location to the module file containing
24 //  it.
25 //  * C: The macro bit. We rotate it to the lowest bit so that we can save some
26 //  space in case the index of the module file is 0.
27 //
28 //
29 //===----------------------------------------------------------------------===//
30 
31 #ifndef LLVM_CLANG_SERIALIZATION_SOURCELOCATIONENCODING_H
32 #define LLVM_CLANG_SERIALIZATION_SOURCELOCATIONENCODING_H
33 
34 #include "clang/Basic/SourceLocation.h"
35 #include "llvm/Support/MathExtras.h"
36 #include <climits>
37 
38 namespace clang {
39 
40 /// Serialized encoding of SourceLocations without context.
41 /// Optimized to have small unsigned values (=> small after VBR encoding).
42 ///
43 // Macro locations have the top bit set, we rotate by one so it is the low bit.
44 class SourceLocationEncoding {
45   using UIntTy = SourceLocation::UIntTy;
46   constexpr static unsigned UIntBits = CHAR_BIT * sizeof(UIntTy);
47 
encodeRaw(UIntTy Raw)48   static UIntTy encodeRaw(UIntTy Raw) {
49     return (Raw << 1) | (Raw >> (UIntBits - 1));
50   }
decodeRaw(UIntTy Raw)51   static UIntTy decodeRaw(UIntTy Raw) {
52     return (Raw >> 1) | (Raw << (UIntBits - 1));
53   }
54 
55 public:
56   using RawLocEncoding = uint64_t;
57 
58   static RawLocEncoding encode(SourceLocation Loc, UIntTy BaseOffset,
59                                unsigned BaseModuleFileIndex);
60   static std::pair<SourceLocation, unsigned> decode(RawLocEncoding);
61 };
62 
63 inline SourceLocationEncoding::RawLocEncoding
encode(SourceLocation Loc,UIntTy BaseOffset,unsigned BaseModuleFileIndex)64 SourceLocationEncoding::encode(SourceLocation Loc, UIntTy BaseOffset,
65                                unsigned BaseModuleFileIndex) {
66   // If the source location is a local source location, we can try to optimize
67   // the similar sequences to only record the differences.
68   if (!BaseOffset)
69     return encodeRaw(Loc.getRawEncoding());
70   if (Loc.isInvalid())
71     return 0;
72 
73   // Otherwise, the higher bits are used to store the module file index,
74   // so it is meaningless to optimize the source locations into small
75   // integers. Let's try to always use the raw encodings.
76   assert(Loc.getOffset() >= BaseOffset);
77   Loc = Loc.getLocWithOffset(-BaseOffset);
78   RawLocEncoding Encoded = encodeRaw(Loc.getRawEncoding());
79 
80   // 16 bits should be sufficient to store the module file index.
81   assert(BaseModuleFileIndex < (1 << 16));
82   Encoded |= (RawLocEncoding)BaseModuleFileIndex << 32;
83   return Encoded;
84 }
85 inline std::pair<SourceLocation, unsigned>
decode(RawLocEncoding Encoded)86 SourceLocationEncoding::decode(RawLocEncoding Encoded) {
87   unsigned ModuleFileIndex = Encoded >> 32;
88 
89   if (!ModuleFileIndex)
90     return {SourceLocation::getFromRawEncoding(decodeRaw(Encoded)),
91             ModuleFileIndex};
92 
93   Encoded &= llvm::maskTrailingOnes<RawLocEncoding>(32);
94   SourceLocation Loc = SourceLocation::getFromRawEncoding(decodeRaw(Encoded));
95 
96   return {Loc, ModuleFileIndex};
97 }
98 
99 } // namespace clang
100 #endif
101