Skip to content
2 changes: 1 addition & 1 deletion std/algorithm/sorting.d
Original file line number Diff line number Diff line change
Expand Up @@ -1812,7 +1812,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
Expand Down
22 changes: 14 additions & 8 deletions std/digest/sha.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down
64 changes: 41 additions & 23 deletions std/internal/digest/sha_SSSE3.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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";
Expand All @@ -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
Expand All @@ -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 */
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
* +----------------+
Expand All @@ -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",
];
Expand Down Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions std/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand All @@ -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 = {
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down