Skip to content

Commit 4ce08b4

Browse files
committed
Rework dlang#8542 wrt. deterministic IDs via generateIdWithLoc()
1 parent 4b2c885 commit 4ce08b4

3 files changed

Lines changed: 31 additions & 160 deletions

File tree

src/dmd/identifier.d

Lines changed: 31 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -125,18 +125,6 @@ nothrow:
125125

126126
extern (C++) __gshared StringTable stringtable;
127127

128-
/**
129-
A secondary string table is used to guarantee that we generate unique
130-
identifiers per module. See generateIdWithLoc and issues
131-
https://issues.dlang.org/show_bug.cgi?id=16995
132-
https://issues.dlang.org/show_bug.cgi?id=18097
133-
https://issues.dlang.org/show_bug.cgi?id=18111
134-
https://issues.dlang.org/show_bug.cgi?id=18880
135-
https://issues.dlang.org/show_bug.cgi?id=18868
136-
https://issues.dlang.org/show_bug.cgi?id=19058.
137-
*/
138-
private extern (C++) __gshared StringTable fullPathStringTable;
139-
140128
static Identifier generateId(const(char)* prefix)
141129
{
142130
__gshared size_t i;
@@ -166,75 +154,38 @@ nothrow:
166154
*/
167155
extern (D) static Identifier generateIdWithLoc(string prefix, const ref Loc loc)
168156
{
169-
import dmd.root.filename: absPathThen;
170-
171-
// see below for why we use absPathThen
172-
return loc.filename.absPathThen!((absPath)
157+
// generate `<prefix>_L<line>_C<col>`
158+
OutBuffer idBuf;
159+
idBuf.writestring(prefix);
160+
idBuf.writestring("_L");
161+
idBuf.print(loc.linnum);
162+
idBuf.writestring("_C");
163+
idBuf.print(loc.charnum);
164+
165+
/**
166+
* Make sure the identifiers are unique per module. See issues
167+
* https://issues.dlang.org/show_bug.cgi?id=16995
168+
* https://issues.dlang.org/show_bug.cgi?id=18097
169+
* https://issues.dlang.org/show_bug.cgi?id=18111
170+
* https://issues.dlang.org/show_bug.cgi?id=18880
171+
* https://issues.dlang.org/show_bug.cgi?id=18868
172+
* https://issues.dlang.org/show_bug.cgi?id=19058.
173+
*/
174+
static struct Key { Loc loc; string prefix; }
175+
__gshared uint[Key] counters;
176+
177+
const key = Key(loc, prefix);
178+
if (auto pCounter = key in counters)
173179
{
180+
idBuf.writestring("_");
181+
idBuf.print((*pCounter)++);
182+
}
183+
else
184+
{
185+
counters[key] = 1;
186+
}
174187

175-
// this block generates the "regular" identifier, i.e. if there are no collisions
176-
OutBuffer idBuf;
177-
idBuf.writestring(prefix);
178-
idBuf.writestring("_L");
179-
idBuf.print(loc.linnum);
180-
idBuf.writestring("_C");
181-
idBuf.print(loc.charnum);
182-
183-
// This block generates an identifier that is prefixed by the absolute path of the file
184-
// being compiled. The reason this is necessary is that we want unique identifiers per
185-
// module, but the identifiers are generated before the module information is available.
186-
// To guarantee that each generated identifier is unique without modules, we make them
187-
// unique to each absolute file path. This also makes it consistent even if the files
188-
// are compiled separately. See issues:
189-
// https://issues.dlang.org/show_bug.cgi?id=16995
190-
// https://issues.dlang.org/show_bug.cgi?id=18097
191-
// https://issues.dlang.org/show_bug.cgi?id=18111
192-
// https://issues.dlang.org/show_bug.cgi?id=18880
193-
// https://issues.dlang.org/show_bug.cgi?id=18868
194-
// https://issues.dlang.org/show_bug.cgi?id=19058.
195-
OutBuffer fullPathIdBuf;
196-
197-
if (absPath)
198-
{
199-
// replace characters that demangle can't handle
200-
for (auto ptr = absPath; *ptr != '\0'; ++ptr)
201-
{
202-
// see dmd.dmangle.isValidMangling
203-
// Unfortunately importing it leads to either build failures or cyclic dependencies
204-
// between modules.
205-
if (*ptr == '/' || *ptr == '\\' || *ptr == '.' || *ptr == '?' || *ptr == ':')
206-
*ptr = '_';
207-
}
208-
209-
fullPathIdBuf.writestring(absPath);
210-
fullPathIdBuf.writestring("_");
211-
}
212-
213-
fullPathIdBuf.writestring(idBuf.peekSlice());
214-
const fullPathIdLength = fullPathIdBuf.peekSlice().length;
215-
uint counter = 1;
216-
217-
// loop until we can't find the absolute path ~ identifier, adding a counter suffix each time
218-
while (fullPathStringTable.lookup(fullPathIdBuf.peekSlice()) !is null)
219-
{
220-
// Strip the counter suffix if any
221-
fullPathIdBuf.setsize(fullPathIdLength);
222-
// Add new counter suffix
223-
fullPathIdBuf.writestring("_");
224-
fullPathIdBuf.print(counter++);
225-
}
226-
227-
// `idStartIndex` is the start of the "true" identifier. We don't actually use the absolute
228-
// file path in the generated identifier since the module system makes sure that the fully
229-
// qualified name is unique.
230-
const idStartIndex = fullPathIdLength - idBuf.peekSlice().length;
231-
232-
// Remember the full path identifier to avoid possible future collisions
233-
fullPathStringTable.insert(fullPathIdBuf.peekSlice(),
234-
null);
235-
236-
return idPool(fullPathIdBuf.peekSlice()[idStartIndex .. $]);
237-
});
188+
return idPool(idBuf.peekSlice());
238189
}
239190

240191
/********************************************
@@ -305,8 +256,6 @@ nothrow:
305256

306257
static void initTable()
307258
{
308-
enum size = 28_000;
309-
stringtable._init(size);
310-
fullPathStringTable._init(size);
259+
stringtable._init(28_000);
311260
}
312261
}

src/dmd/identifier.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ class Identifier : public RootObject
3737
int dyncast() const;
3838

3939
static StringTable stringtable;
40-
static StringTable fullPathStringTable;
4140
static Identifier *generateId(const char *prefix);
4241
static Identifier *generateId(const char *prefix, size_t i);
4342
static Identifier *idPool(const char *s, unsigned len);

src/dmd/root/filename.d

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -926,80 +926,3 @@ version(Windows)
926926
}
927927

928928
}
929-
930-
version(Posix)
931-
{
932-
933-
/**
934-
Takes a callable F and applies it to the result of converting
935-
`fileName` to an absolute file path (char*)
936-
937-
Params:
938-
fileName = The file name to be converted to an absolute path
939-
Returns: Whatever `F` returns.
940-
*/
941-
auto absPathThen(alias F)(const(char)* fileName)
942-
{
943-
import core.sys.posix.stdlib: realpath, free;
944-
auto absPath = realpath(fileName, null /* realpath allocates */);
945-
scope(exit) free(absPath);
946-
return F(absPath);
947-
}
948-
}
949-
else
950-
{
951-
/**
952-
Takes a callable F and applies it to the result of converting
953-
`fileName` to an absolute file path (char*)
954-
955-
Params:
956-
fileName = The file name to be converted to an absolute path
957-
Returns: Whatever `F` returns.
958-
*/
959-
auto absPathThen(alias F)(const(char)* fileName)
960-
{
961-
import core.sys.windows.winnls: WideCharToMultiByte;
962-
import core.stdc.stdlib: malloc, free;
963-
964-
return fileName.extendedPathThen!((wpath) {
965-
// first find out how long the buffer must be to store the result
966-
const length = WideCharToMultiByte(0, // code page
967-
0, // flags
968-
wpath,
969-
-1, // wpath len, -1 is null terminated
970-
null, // multibyte output ptr
971-
0, // multibyte output length
972-
null, // default char
973-
null, // if used default char
974-
);
975-
976-
if(!length) return F((char*).init);
977-
978-
char[1024] buf = void;
979-
980-
scope multibyteBuf = length > buf.length
981-
? (cast(char*)malloc(length * char.sizeof))
982-
: &buf[0];
983-
scope (exit)
984-
{
985-
if (multibyteBuf != &buf[0])
986-
free(multibyteBuf);
987-
}
988-
989-
// now store the result
990-
const length2 = WideCharToMultiByte(0, // code page
991-
0, // flags
992-
wpath,
993-
-1, // wpath len, -1 is null terminated
994-
multibyteBuf,
995-
length,
996-
null, // default char
997-
null, // if used default char
998-
);
999-
1000-
assert(length == length2);
1001-
1002-
return F(multibyteBuf);
1003-
});
1004-
}
1005-
}

0 commit comments

Comments
 (0)