Skip to content

Commit 16101ef

Browse files
authored
Merge pull request #5855 from rainers/mangle_backrefs
fix Issue 15831 - Mangle back references to avoid huge symbol names merged-on-behalf-of: unknown
2 parents 832186a + 84f3b3a commit 16101ef

15 files changed

Lines changed: 498 additions & 255 deletions

File tree

src/ddmd/dmangle.d

Lines changed: 284 additions & 58 deletions
Large diffs are not rendered by default.

src/ddmd/dtemplate.d

Lines changed: 2 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -8223,123 +8223,10 @@ extern (C++) class TemplateInstance : ScopeDsymbol
82238223
*/
82248224
final Identifier genIdent(Objects* args)
82258225
{
8226-
TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
8227-
assert(tempdecl);
8228-
82298226
//printf("TemplateInstance.genIdent('%s')\n", tempdecl.ident.toChars());
8227+
assert(args is tiargs);
82308228
OutBuffer buf;
8231-
8232-
const id = tempdecl.ident.toString();
8233-
// Use "__U" for the symbols declared inside template constraint.
8234-
const char T = members ? 'T' : 'U';
8235-
buf.printf("__%c%u%.*s", T, cast(int)id.length, cast(int)id.length, id.ptr);
8236-
8237-
size_t nparams = tempdecl.parameters.dim - (tempdecl.isVariadic() ? 1 : 0);
8238-
for (size_t i = 0; i < args.dim; i++)
8239-
{
8240-
RootObject o = (*args)[i];
8241-
Type ta = isType(o);
8242-
Expression ea = isExpression(o);
8243-
Dsymbol sa = isDsymbol(o);
8244-
Tuple va = isTuple(o);
8245-
//printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
8246-
if (i < nparams && (*tempdecl.parameters)[i].specialization())
8247-
buf.writeByte('H'); // https://issues.dlang.org/show_bug.cgi?id=6574
8248-
if (ta)
8249-
{
8250-
buf.writeByte('T');
8251-
if (ta.deco)
8252-
buf.writestring(ta.deco);
8253-
else
8254-
{
8255-
debug
8256-
{
8257-
if (!global.errors)
8258-
printf("ta = %d, %s\n", ta.ty, ta.toChars());
8259-
}
8260-
assert(global.errors);
8261-
}
8262-
}
8263-
else if (ea)
8264-
{
8265-
// Don't interpret it yet, it might actually be an alias template parameter.
8266-
// Only constfold manifest constants, not const/immutable lvalues, see https://issues.dlang.org/show_bug.cgi?id=17339.
8267-
enum keepLvalue = true;
8268-
ea = ea.optimize(WANTvalue, keepLvalue);
8269-
if (ea.op == TOKvar)
8270-
{
8271-
sa = (cast(VarExp)ea).var;
8272-
ea = null;
8273-
goto Lsa;
8274-
}
8275-
if (ea.op == TOKthis)
8276-
{
8277-
sa = (cast(ThisExp)ea).var;
8278-
ea = null;
8279-
goto Lsa;
8280-
}
8281-
if (ea.op == TOKfunction)
8282-
{
8283-
if ((cast(FuncExp)ea).td)
8284-
sa = (cast(FuncExp)ea).td;
8285-
else
8286-
sa = (cast(FuncExp)ea).fd;
8287-
ea = null;
8288-
goto Lsa;
8289-
}
8290-
buf.writeByte('V');
8291-
if (ea.op == TOKtuple)
8292-
{
8293-
ea.error("tuple is not a valid template value argument");
8294-
continue;
8295-
}
8296-
// Now that we know it is not an alias, we MUST obtain a value
8297-
uint olderr = global.errors;
8298-
ea = ea.ctfeInterpret();
8299-
if (ea.op == TOKerror || olderr != global.errors)
8300-
continue;
8301-
8302-
/* Use deco that matches what it would be for a function parameter
8303-
*/
8304-
buf.writestring(ea.type.deco);
8305-
mangleToBuffer(ea, &buf);
8306-
}
8307-
else if (sa)
8308-
{
8309-
Lsa:
8310-
buf.writeByte('S');
8311-
sa = sa.toAlias();
8312-
Declaration d = sa.isDeclaration();
8313-
if (d && (!d.type || !d.type.deco))
8314-
{
8315-
error("forward reference of %s %s", d.kind(), d.toChars());
8316-
continue;
8317-
}
8318-
8319-
OutBuffer bufsa;
8320-
mangleToBuffer(sa, &bufsa);
8321-
auto s = bufsa.peekSlice();
8322-
8323-
/* https://issues.dlang.org/show_bug.cgi?id=3043
8324-
* If the first character of p is a digit this
8325-
* causes ambiguity issues because the digits of the two numbers are adjacent.
8326-
* Current demanglers resolve this by trying various places to separate the
8327-
* numbers until one gets a successful demangle.
8328-
* Unfortunately, fixing this ambiguity will break existing binary
8329-
* compatibility and the demanglers, so we'll leave it as is.
8330-
*/
8331-
buf.printf("%u%.*s", cast(uint)s.length, cast(int)s.length, s.ptr);
8332-
}
8333-
else if (va)
8334-
{
8335-
assert(i + 1 == args.dim); // must be last one
8336-
args = &va.objects;
8337-
i = -cast(size_t)1;
8338-
}
8339-
else
8340-
assert(0);
8341-
}
8342-
buf.writeByte('Z');
8229+
mangleToBuffer(this, &buf);
83438230
//printf("\tgenIdent = %s\n", buf.peekString());
83448231
return Identifier.idPool(buf.peekSlice());
83458232
}

src/ddmd/toir.d

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -415,15 +415,15 @@ int intrinsic_op(FuncDeclaration fd)
415415
"4math6yl2xp1FNaNbNiNfeeZe",
416416

417417
"4simd10__prefetchFNaNbNiNfxPvhZv",
418-
"4simd10__simd_stoFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v",
419-
"4simd10__simd_stoFNaNbNiNfE4core4simd3XMMdNhG16vZNhG16v",
420-
"4simd10__simd_stoFNaNbNiNfE4core4simd3XMMfNhG16vZNhG16v",
421-
"4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v",
422-
"4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vhZNhG16v",
423-
"4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vZNhG16v",
424-
"4simd6__simdFNaNbNiNfE4core4simd3XMMdZNhG16v",
425-
"4simd6__simdFNaNbNiNfE4core4simd3XMMfZNhG16v",
426-
"4simd9__simd_ibFNaNbNiNfE4core4simd3XMMNhG16vhZNhG16v",
418+
"4simd10__simd_stoFNaNbNiNfEQBgQBe3XMMNhG16vQgZQj",
419+
"4simd10__simd_stoFNaNbNiNfEQBgQBe3XMMdNhG16vZQh",
420+
"4simd10__simd_stoFNaNbNiNfEQBgQBe3XMMfNhG16vZQh",
421+
"4simd6__simdFNaNbNiNfEQBbQz3XMMNhG16vQgZQj",
422+
"4simd6__simdFNaNbNiNfEQBbQz3XMMNhG16vQghZQk",
423+
"4simd6__simdFNaNbNiNfEQBbQz3XMMNhG16vZQh",
424+
"4simd6__simdFNaNbNiNfEQBbQz3XMMdZNhG16v",
425+
"4simd6__simdFNaNbNiNfEQBbQz3XMMfZNhG16v",
426+
"4simd9__simd_ibFNaNbNiNfEQBeQBc3XMMNhG16vhZQi",
427427

428428
"5bitop12volatileLoadFNbNiNfPhZh",
429429
"5bitop12volatileLoadFNbNiNfPkZk",
@@ -469,15 +469,15 @@ int intrinsic_op(FuncDeclaration fd)
469469
"4math6yl2xp1FNaNbNiNfeeZe",
470470

471471
"4simd10__prefetchFNaNbNiNfxPvhZv",
472-
"4simd10__simd_stoFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v",
473-
"4simd10__simd_stoFNaNbNiNfE4core4simd3XMMdNhG16vZNhG16v",
474-
"4simd10__simd_stoFNaNbNiNfE4core4simd3XMMfNhG16vZNhG16v",
475-
"4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v",
476-
"4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vhZNhG16v",
477-
"4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vZNhG16v",
478-
"4simd6__simdFNaNbNiNfE4core4simd3XMMdZNhG16v",
479-
"4simd6__simdFNaNbNiNfE4core4simd3XMMfZNhG16v",
480-
"4simd9__simd_ibFNaNbNiNfE4core4simd3XMMNhG16vhZNhG16v",
472+
"4simd10__simd_stoFNaNbNiNfEQBgQBe3XMMNhG16vQgZQj",
473+
"4simd10__simd_stoFNaNbNiNfEQBgQBe3XMMdNhG16vZQh",
474+
"4simd10__simd_stoFNaNbNiNfEQBgQBe3XMMfNhG16vZQh",
475+
"4simd6__simdFNaNbNiNfEQBbQz3XMMNhG16vQgZQj",
476+
"4simd6__simdFNaNbNiNfEQBbQz3XMMNhG16vQghZQk",
477+
"4simd6__simdFNaNbNiNfEQBbQz3XMMNhG16vZQh",
478+
"4simd6__simdFNaNbNiNfEQBbQz3XMMdZNhG16v",
479+
"4simd6__simdFNaNbNiNfEQBbQz3XMMfZNhG16v",
480+
"4simd9__simd_ibFNaNbNiNfEQBeQBc3XMMNhG16vhZQi",
481481

482482
"5bitop12volatileLoadFNbNiNfPhZh",
483483
"5bitop12volatileLoadFNbNiNfPkZk",
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
#!/usr/bin/env bash
22

33
grep -v "\"file\" : " ${RESULTS_DIR}/compilable/json.out | grep -v "\"offset\" : " > ${RESULTS_DIR}/compilable/json.out.2
4-
diff --strip-trailing-cr compilable/extra-files/json.out ${RESULTS_DIR}/compilable/json.out.2
4+
grep -v "\"deco\" : " ${RESULTS_DIR}/compilable/json.out.2 > ${RESULTS_DIR}/compilable/json.out.3
5+
grep -v "\"deco\" : " compilable/extra-files/json.out > ${RESULTS_DIR}/compilable/json.out.4
6+
7+
diff --strip-trailing-cr ${RESULTS_DIR}/compilable/json.out.4 ${RESULTS_DIR}/compilable/json.out.3
58
if [ $? -ne 0 ]; then
69
exit 1;
710
fi
811

9-
rm ${RESULTS_DIR}/compilable/json.out{,.2}
12+
rm ${RESULTS_DIR}/compilable/json.out{,.2,.3,.4}
1013

test/compilable/test10993.d

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module test10993;
22

3+
import core.demangle : demangleType;
4+
35
auto foo(T)(T a)
46
{
57
static immutable typeof(a) q;
@@ -29,5 +31,7 @@ void main()
2931
auto y = cast()x;
3032
enum mangle_y = typeof(y).mangleof;
3133
// pragma(msg, "y : " ~ mangle_y);
32-
static assert (mangle_y == mangle_x[1..$]);
34+
enum demangle_x = demangleType(mangle_x);
35+
enum demangle_y = demangleType(mangle_y);
36+
static assert ("immutable(" ~ demangle_y ~ ")" == demangle_x);
3337
}

test/compilable/testInference.d

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,13 @@ void test8234()
261261
/***************************************************/
262262
// 8504
263263

264+
import core.demangle : demangle;
265+
264266
void foo8504()()
265267
{
266268
static assert(typeof(foo8504!()).stringof == "void()");
267269
static assert(typeof(foo8504!()).mangleof == "FZv");
268-
static assert(foo8504!().mangleof == "_D13testInference12__T7foo8504Z7foo8504FZv");
270+
static assert(demangle(foo8504!().mangleof) == "void testInference.foo8504!().foo8504()");
269271
}
270272

271273
auto toDelegate8504a(F)(auto ref F fp) { return fp; }
@@ -277,7 +279,7 @@ void test8504()
277279
{
278280
static assert(typeof(foo8504!()).stringof == "pure nothrow @nogc @safe void()");
279281
static assert(typeof(foo8504!()).mangleof == "FNaNbNiNfZv");
280-
static assert(foo8504!().mangleof == "_D13testInference12__T7foo8504Z7foo8504FNaNbNiNfZv");
282+
static assert(demangle(foo8504!().mangleof) == "pure nothrow @nogc @safe void testInference.foo8504!().foo8504()");
281283

282284
auto fp1 = toDelegate8504a(&testC8504);
283285
auto fp2 = toDelegate8504b(&testC8504);

test/runnable/extra-files/test10386.d

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ module test10386;
33
// import lib.foo.bar; // ok
44
import lib10386.foo; // linker failure
55

6+
import imports.testmangle;
7+
68
void main()
79
{
8-
static assert(foo.mangleof == "_D8lib103863foo3bar3fooFiZv");
10+
static assert(equalDemangle(foo.mangleof, "_D8lib103863foo3bar3fooFiZv"));
911
foo(1);
1012
}
1113

test/runnable/imports/testmangle.d

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// helper for mangling tests with back references
2+
3+
module imports.testmangle;
4+
5+
public import core.demangle : demangle, demangleType;
6+
7+
// detect mangle version
8+
private
9+
{
10+
struct Detect;
11+
Detect* detectMangle(Detect*);
12+
void DetectTmpl(T)() {}
13+
}
14+
15+
pragma(msg,detectMangle.mangleof);
16+
static if(detectMangle.mangleof == "_D7imports10testmangle12detectMangleFPSQL3H6DetectZQ1e")
17+
enum { BackRefs = true, BackRefSymbols = true }
18+
else static if(detectMangle.mangleof == "_D7imports10testmangle12detectMangleFPSQBlQBg6DetectZQq")
19+
enum { BackRefs = true, BackRefSymbols = false }
20+
else static if(detectMangle.mangleof == "_D7imports10testmangle12detectMangleFPS7imports10testmangle6DetectZPS7imports10testmangle6Detect")
21+
enum { BackRefs = false, BackRefSymbols = false }
22+
else
23+
static assert(false, "unknown mangling");
24+
25+
private enum tmplMangle = (DetectTmpl!int).mangleof;
26+
pragma(msg,tmplMangle);
27+
static if(tmplMangle[0..40] == "_D7imports10testmangle__T10DetectTmplTiZ")
28+
enum HasTemplateLength = false;
29+
else static if(tmplMangle[0..42] == "_D7imports10testmangle18__T10DetectTmplTiZ")
30+
enum HasTemplateLength = true;
31+
else
32+
static assert(false, "unknown mangling");
33+
34+
pragma(msg,BackRefs);
35+
pragma(msg,BackRefSymbols);
36+
37+
static if (BackRefs)
38+
{
39+
string tl(string s)() { return null; }
40+
string id(string s, string r, string r2 = null)() { return BackRefSymbols && r2 !is null ? r2 : r; }
41+
}
42+
else
43+
{
44+
string tl(string s)() { return HasTemplateLength ? s : null; }
45+
string id(string s, string r, string r2 = null)() { return s; }
46+
}
47+
48+
bool equalDemangle(string m1, string m2)
49+
{
50+
auto dm1 = demangle(m1);
51+
auto dm2 = demangle(m2);
52+
return dm1 == dm2;
53+
}
54+
55+
string unsignedToString(ulong x)
56+
{
57+
string s;
58+
s ~= cast(char)('0' + (x % 10));
59+
x /= 10;
60+
while (x > 0)
61+
{
62+
s = cast(char)('0' + (x % 10)) ~ s;
63+
x /= 10;
64+
}
65+
return s;
66+
}

test/runnable/link6574.d

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
// PERMUTE_ARGS:
22
module link6574;
33

4+
import imports.testmangle;
5+
46
enum Method { A, B, }
57

68
int foo(Method method = Method.A)()
79
{
8-
static assert(foo.mangleof == "_D8link657428__T3fooVE8link65746Methodi0Z3fooFZi");
10+
static assert(foo.mangleof == "_D8link6574"~tl!"28"~"__T3fooVE"~id!("8link6574","Qs")~"6Methodi0Z"~id!("3foo","Qs")~"FZi");
911
return 10 * foo!method();
1012
}
1113
int foo(Method method : Method.A)()
1214
{
13-
static assert(foo.mangleof == "_D8link657429__T3fooHVE8link65746Methodi0Z3fooFZi");
15+
static assert(foo.mangleof == "_D8link6574"~tl!"29"~"__T3fooHVE"~id!("8link6574","Qt")~"6Methodi0Z"~id!("3foo","Qt")~"FZi");
1416
return 2;
1517
}
1618
int foo(Method method : Method.B)()
@@ -21,7 +23,7 @@ int foo(Method method : Method.B)()
2123

2224
int bar(Method method = Method.B)()
2325
{
24-
static assert(bar.mangleof == "_D8link657428__T3barVE8link65746Methodi1Z3barFZi");
26+
static assert(bar.mangleof == "_D8link6574"~tl!"28"~"__T3barVE"~id!("8link6574","Qs")~"6Methodi1Z"~id!("3bar","Qs")~"FZi");
2527
return 10 * bar!method();
2628
}
2729
int bar(Method method : Method.A)()
@@ -31,7 +33,7 @@ int bar(Method method : Method.A)()
3133
}
3234
int bar(Method method : Method.B)()
3335
{
34-
static assert(bar.mangleof == "_D8link657429__T3barHVE8link65746Methodi1Z3barFZi");
36+
static assert(bar.mangleof == "_D8link6574"~tl!"29"~"__T3barHVE"~id!("8link6574","Qt")~"6Methodi1Z"~id!("3bar","Qt")~"FZi");
3537
return 3;
3638
}
3739

0 commit comments

Comments
 (0)