From 12c56c935c6bd0130fcb545264293cc0e500799f Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Sat, 24 Dec 2016 16:22:37 +0100 Subject: [PATCH 1/4] partly fix Issue 9378 - SHA1 asm not PIC compatible - access SHA1 constants through extra register in x64 code - tried same for x86 but there is no register left and loading constants via stack was way too slow --- std/digest/sha.d | 22 +++++++----- std/internal/digest/sha_SSSE3.d | 64 +++++++++++++++++++++------------ 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/std/digest/sha.d b/std/digest/sha.d index f0db235b2c7..b548edf4c27 100644 --- a/std/digest/sha.d +++ b/std/digest/sha.d @@ -101,17 +101,14 @@ unittest hash1 = sha1.finish(); } -version(D_PIC) -{ - // Do not use (Bug9378). -} -else version(Win64) +version(Win64) { // wrong calling convention } else version(D_InlineAsm_X86) { - private version = USE_SSSE3; + version (D_PIC) {} // Bugzilla 9378 + else private version = USE_SSSE3; } else version(D_InlineAsm_X86_64) { @@ -216,11 +213,20 @@ struct SHA(uint hashBlockSize, uint digestSize) version(USE_SSSE3) { import core.cpuid : ssse3; - import std.internal.digest.sha_SSSE3 : transformSSSE3; + import std.internal.digest.sha_SSSE3 : sse3_constants=constants, transformSSSE3; static void transform(uint[5]* state, const(ubyte[64])* block) pure nothrow @nogc { - return ssse3 ? transformSSSE3(state, block) : transformX86(state, block); + if (ssse3) + { + version (D_InlineAsm_X86_64) + // constants as extra argument for PIC, see Bugzilla 9378 + transformSSSE3(state, block, &sse3_constants); + else + transformSSSE3(state, block); + } + else + transformX86(state, block); } } else diff --git a/std/internal/digest/sha_SSSE3.d b/std/internal/digest/sha_SSSE3.d index 168061084a3..f20a5987b0c 100644 --- a/std/internal/digest/sha_SSSE3.d +++ b/std/internal/digest/sha_SSSE3.d @@ -15,14 +15,14 @@ */ module std.internal.digest.sha_SSSE3; -version(D_PIC) +version(D_InlineAsm_X86) { - // Do not use (Bug9378). -} -else version(D_InlineAsm_X86) -{ - private version = USE_SSSE3; - private version = _32Bit; + version (D_PIC) {} // Bugzilla 9378 + else + { + private version = USE_SSSE3; + private version = _32Bit; + } } else version(D_InlineAsm_X86_64) { @@ -108,6 +108,7 @@ version(USE_SSSE3) private immutable string SP = "RSP"; private immutable string BUFFER_PTR = "R9"; private immutable string STATE_PTR = "R8"; + private immutable string CONSTANTS_PTR = "R10"; // Registers for temporary results (XMM10 and XMM11 are also used temporary) private immutable string W_TMP = "XMM8"; @@ -120,15 +121,11 @@ version(USE_SSSE3) private immutable string X_CONSTANT = "XMM13"; } - /* The control words for the byte shuffle instruction. */ - align(16) private immutable uint[4] bswap_shufb_ctl = - [ - 0x0001_0203, 0x0405_0607, 0x0809_0a0b, 0x0c0d_0e0f - ]; - - /* The round constants. */ - align(16) private immutable uint[16] constants = + /* The control words for the byte shuffle instruction and the round constants. */ + align(16) public immutable uint[20] constants = [ + // The control words for the byte shuffle instruction. + 0x0001_0203, 0x0405_0607, 0x0809_0a0b, 0x0c0d_0e0f, // Constants for round 0-19 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, // Constants for round 20-39 @@ -152,10 +149,22 @@ version(USE_SSSE3) return s.idup; } + /** Returns the reference to the byte shuffle control word. */ + private nothrow pure string bswap_shufb_ctl() + { + version (_64Bit) + return "["~CONSTANTS_PTR~"]"; + else + return "[constants]"; + } + /** Returns the reference to constant used in round i. */ private nothrow pure string constant(uint i) { - return "[constants + 16*"~to_string(i/20)~"]"; + version (_64Bit) + return "16 + 16*"~to_string(i/20)~"["~CONSTANTS_PTR~"]"; + else + return "[constants + 16 + 16*"~to_string(i/20)~"]"; } /** Returns the XMM register number used in round i */ @@ -304,9 +313,9 @@ version(USE_SSSE3) { if (i == 0) { - return swt3264(["movdqa "~X_SHUFFLECTL~",[bswap_shufb_ctl]", + return swt3264(["movdqa "~X_SHUFFLECTL~","~bswap_shufb_ctl(), "movdqa "~X_CONSTANT~","~constant(i)], - ["movdqa "~X_SHUFFLECTL~",[bswap_shufb_ctl]", + ["movdqa "~X_SHUFFLECTL~","~bswap_shufb_ctl(), "movdqa "~X_CONSTANT~","~constant(i)]); } version(_64Bit) @@ -589,8 +598,9 @@ version(USE_SSSE3) { /* * Parameters: - * RSI contains pointer to state - * RDI contains pointer to input buffer + * RDX contains pointer to state + * RSI contains pointer to input buffer + * RDI contains pointer to constants * * Stack layout as follows: * +----------------+ @@ -610,8 +620,9 @@ version(USE_SSSE3) "push RBP", "push RBX", // Save parameters - "mov "~STATE_PTR~", RSI", //pointer to state - "mov "~BUFFER_PTR~", RDI", //pointer to buffer + "mov "~STATE_PTR~", RDX", //pointer to state + "mov "~BUFFER_PTR~", RSI", //pointer to buffer + "mov "~CONSTANTS_PTR~", RDI", //pointer to constants to avoid absolute addressing // Align stack "sub RSP, 4*16+8", ]; @@ -643,10 +654,17 @@ version(USE_SSSE3) } } + // constants as extra argument for PIC, see Bugzilla 9378 + import std.meta : AliasSeq; + version (_64Bit) + alias ExtraArgs = AliasSeq!(typeof(&constants)); + else + alias ExtraArgs = AliasSeq!(); + /** * */ - public void transformSSSE3(uint[5]* state, const(ubyte[64])* buffer) pure nothrow @nogc + public void transformSSSE3(uint[5]* state, const(ubyte[64])* buffer, ExtraArgs) pure nothrow @nogc { mixin(wrap(["naked;"] ~ prologue())); // Precalc first 4*16=64 bytes From 40606feecef6d3e8de528fcef1135ac5a873f82a Mon Sep 17 00:00:00 2001 From: WalterWaldron Date: Fri, 30 Dec 2016 03:04:50 -0500 Subject: [PATCH 2/4] Fix unstable sort documentation. Noticed this here: https://dlang.org/library/std/algorithm/sorting/sort.html --- std/algorithm/sorting.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/algorithm/sorting.d b/std/algorithm/sorting.d index d33a0d92052..342fab61dd2 100644 --- a/std/algorithm/sorting.d +++ b/std/algorithm/sorting.d @@ -1676,7 +1676,7 @@ Params: Returns: The initial range wrapped as a $(D SortedRange) with the predicate $(D binaryFun!less). -Algorithms: $(HTTP en.wikipedia.org/wiki/Introsort) is used for unstable sorting and +Algorithms: $(HTTP en.wikipedia.org/wiki/Introsort, Introsort) is used for unstable sorting and $(HTTP en.wikipedia.org/wiki/Timsort, Timsort) is used for stable sorting. Each algorithm has benefits beyond stability. Introsort is generally faster but Timsort may achieve greater speeds on data with low entropy or if predicate calls From 8ada2b7a50f06f6d9fbfd9be302acc81374c4a5d Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 12 Jan 2017 12:27:22 +0000 Subject: [PATCH 3/4] Tweak std.traits function-related docs Also fix order of constraint tests. --- std/traits.d | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/std/traits.d b/std/traits.d index 134e787b0ad..809a7ea0269 100644 --- a/std/traits.d +++ b/std/traits.d @@ -1308,7 +1308,7 @@ alias ParameterDefaultValueTuple = ParameterDefaults; /** -Returns the attributes attached to a function $(D func). +Returns the FunctionAttribute mask for function $(D func). See_Also: $(LREF hasFunctionAttributes) @@ -1503,8 +1503,8 @@ private FunctionAttribute extractAttribFlags(Attribs...)() Checks whether a function has the given attributes attached. Params: - func = function to check - attributes = variadic number of function attributes as strings + args = Function to check, followed by a + variadic number of function attributes as strings Returns: `true`, if the function has the list of attributes attached and `false` otherwise. @@ -1513,7 +1513,7 @@ See_Also: $(LREF functionAttributes) */ template hasFunctionAttributes(args...) - if (isCallable!(args[0]) && args.length > 0 + if (args.length > 0 && isCallable!(args[0]) && allSatisfy!(isSomeString, typeof(args[1 .. $]))) { enum bool hasFunctionAttributes = { @@ -1536,7 +1536,7 @@ unittest static assert(hasFunctionAttributes!(func, "@safe", "pure")); static assert(!hasFunctionAttributes!(func, "@trusted")); - // for templates types are automatically inferred + // for templates attributes are automatically inferred bool myFunc(T)(T b) { return !b; @@ -7442,7 +7442,7 @@ template isType(X...) if (X.length == 1) * `true` if `X` is a function, `false` otherwise * * See_Also: - * Use $(REF isFunctionPointer) or $(REF isDelegate) for detecting those types + * Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types * respectively. */ template isFunction(X...) if (X.length == 1) From e3df7f2e102aad8a4f4de702d7907c6da152d24f Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Fri, 13 Jan 2017 21:40:20 +0100 Subject: [PATCH 4/4] fix typo in changelog slug --- .../{std-meta-statisissorted.dd => std-meta-staticissorted.dd} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog/{std-meta-statisissorted.dd => std-meta-staticissorted.dd} (100%) diff --git a/changelog/std-meta-statisissorted.dd b/changelog/std-meta-staticissorted.dd similarity index 100% rename from changelog/std-meta-statisissorted.dd rename to changelog/std-meta-staticissorted.dd