diff --git a/changelog/dmd.hexstring-cast.dd b/changelog/dmd.hexstring-cast.dd index 1eb8a4a1e7..a48c6a66e9 100644 --- a/changelog/dmd.hexstring-cast.dd +++ b/changelog/dmd.hexstring-cast.dd @@ -11,13 +11,17 @@ immutable uint[] data = cast(immutable uint[]) x"AABBCCDD"; static assert(data[0] == 0xAABBCCDD); --- -Character postfixes can now also be used for integers of size 2 or 4: +Character postfixes can now also be used for integers of size 2 or 4, while an `L` postfix can be used for size 8: --- immutable ushort[] f = x"80 3F"w; static assert(f[0] == 0x803F); -immutable int[] f = x"80 35 FF FD"d; -static assert(f[0] == 0x803FFF); +immutable int[] g = x"80 35 FF FD"d; +static assert(g[0] == 0x803FFFFD); + +auto h = x"0011 2233 4455 6677"L; +static assert(h[0] == 0x0011_2233_4455_6677); +static assert(is(typeof(h) == immutable ulong[])); --- Formerly, they would pad each byte with 1 or 3 zeros, which did not serve a purpose (See [Issue 24363](https://issues.dlang.org/show_bug.cgi?id=24363)). diff --git a/compiler/src/dmd/backend/dout.d b/compiler/src/dmd/backend/dout.d index c57c1629fc..1a2b1024bf 100644 --- a/compiler/src/dmd/backend/dout.d +++ b/compiler/src/dmd/backend/dout.d @@ -525,6 +525,9 @@ Symbol *out_string_literal(const(char)* str, uint len, uint sz) ty = TYchar16; else if (sz == 4) ty = TYdchar; + else if (sz == 8) + ty = TYulong; + Symbol *s = symbol_generate(SC.static_,type_static_array(len, tstypes[ty])); switch (config.objfmt) { @@ -573,6 +576,18 @@ Symbol *out_string_literal(const(char)* str, uint len, uint sz) } break; + case 8: + foreach (i; 0.. len) + { + auto p = cast(const(ulong)*)str; + if (p[i] == 0) + { + s.Sseg = CDATA; + break; + } + } + break; + default: assert(0); } diff --git a/compiler/src/dmd/backend/elfobj.d b/compiler/src/dmd/backend/elfobj.d index 8fed420d61..00287744ba 100644 --- a/compiler/src/dmd/backend/elfobj.d +++ b/compiler/src/dmd/backend/elfobj.d @@ -607,8 +607,10 @@ int ElfObj_string_literal_segment(uint sz) * .rodata.cstN - N fixed size readonly constants N bytes in size, * aligned to the same size */ - static immutable char[4][3] name = [ "1.1", "2.2", "4.4" ]; - const int i = (sz == 4) ? 2 : sz - 1; + import core.bitop : bsr, bsf; + assert(sz != 0 && bsr(sz) == bsf(sz)); // sz must be power of 2 + static immutable char[4][4] name = [ "1.1", "2.2", "4.4", "8.8" ]; + const int i = bsr(sz); // FIXME: can't use SHF_MERGE | SHF_STRINGS because of https://issues.dlang.org/show_bug.cgi?id=22483 const IDXSEC seg = ElfObj_getsegment(".rodata.str".ptr, name[i].ptr, SHT_PROGBITS, SHF_ALLOC, sz); return seg; diff --git a/compiler/src/dmd/dcast.d b/compiler/src/dmd/dcast.d index a49bd575f4..d2498fe6e2 100644 --- a/compiler/src/dmd/dcast.d +++ b/compiler/src/dmd/dcast.d @@ -629,7 +629,7 @@ MATCH implicitConvTo(Expression e, Type t) TY tyn = e.type.nextOf().ty; - if (!tyn.isSomeChar) + if (!tyn.isSomeChar && !e.hexString) return visit(e); switch (t.ty) diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index db40ae01de..bc6f1461ea 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -4248,6 +4248,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor const data = cast(const ubyte[]) e.peekString(); switch (e.postfix) { + case 'L': + e.sz = 8; + e.type = Type.tuns64.immutableOf().arrayOf(); + break; case 'd': e.sz = 4; e.type = Type.tdstring; diff --git a/compiler/src/dmd/lexer.d b/compiler/src/dmd/lexer.d index 937597cdf8..9c30fa97c8 100644 --- a/compiler/src/dmd/lexer.d +++ b/compiler/src/dmd/lexer.d @@ -1568,8 +1568,13 @@ class Lexer stringbuffer.writeByte(v); } t.setString(stringbuffer); - t.postfix = 'h'; stringPostfix(t); + if (*p == 'L') + { + t.postfix = 'L'; + p++; + } + return TOK.hexadecimalString; default: if (c >= '0' && c <= '9') diff --git a/compiler/src/dmd/todt.d b/compiler/src/dmd/todt.d index a614fcdfd0..5037fdd23c 100644 --- a/compiler/src/dmd/todt.d +++ b/compiler/src/dmd/todt.d @@ -427,8 +427,9 @@ void Expression_toDt(Expression e, ref DtBuilder dtb) } else { - ubyte pow2 = e.sz == 4 ? 2 : 1; - dtb.abytes(0, n * e.sz, p, cast(uint)e.sz, pow2); + import core.bitop : bsr; + const pow2 = cast(ubyte) bsr(e.sz); + dtb.abytes(0, n * e.sz, p, cast(uint) e.sz, pow2); } break; diff --git a/compiler/test/runnable/literal.d b/compiler/test/runnable/literal.d index 27b5543b6f..0c259c1eb1 100644 --- a/compiler/test/runnable/literal.d +++ b/compiler/test/runnable/literal.d @@ -243,23 +243,28 @@ void test12950() void testHexstring() { - static immutable uint[] x = cast(immutable uint[]) x"FFAADDEE"; + static immutable uint[] x = cast(immutable uint[]) x"FFAADDEE"d; static assert(x[0] == 0xFFAADDEE); assert(x[0] == 0xFFAADDEE); - static immutable ulong[] y = cast(immutable ulong[]) x"1122334455667788AABBCCDDEEFF0099"; + static assert(is(typeof(x""L) == immutable(ulong)[])); + static immutable ulong[] y = x"1122334455667788AABBCCDDEEFF0099"L; static assert(y[0] == 0x1122334455667788); static assert(y[1] == 0xAABBCCDDEEFF0099); assert(y[0] == 0x1122334455667788); assert(y[1] == 0xAABBCCDDEEFF0099); + immutable long[] c = x"1122334455667788AABBCCDDEEFF0099"L; + assert(c[0] == 0x1122334455667788); + assert(c[1] == 0xAABBCCDDEEFF0099); + // Test that mangling of StringExp with size 8 is the same as array literal mangling: void f(immutable ulong[] a)() {} static assert(f!y.mangleof == f!([0x1122334455667788, 0xAABBCCDDEEFF0099]).mangleof); // Test printing StringExp with size 8 enum toStr(immutable ulong[] v) = v.stringof; - static assert(toStr!y == `x"88776655443322119900FFEEDDCCBBAA"`); + static assert(toStr!y == `x"88776655443322119900FFEEDDCCBBAA"L`); // Hex string postfixes // https://issues.dlang.org/show_bug.cgi?id=24363