version (GNU)
{
- __builtin_unwind_init();
- sp = &sp;
+ // The generic solution below using a call to __builtin_unwind_init ()
+ // followed by an assignment to sp has two issues:
+ // 1) On some archs it stores a huge amount of FP and Vector state which
+ // is not the subject of the scan - and, indeed might produce false
+ // hits.
+ // 2) Even on archs like X86, where there are no callee-saved FPRs/VRs there
+ // tend to be 'holes' in the frame allocations (to deal with alignment) which
+ // also will contain random data which could produce false positives.
+ // This solution stores only the integer callee-saved registers.
+ version (X86)
+ {
+ void*[3] regs = void;
+ asm pure nothrow @nogc
+ {
+ "movl %%ebx, %0" : "=m" (regs[0]);
+ "movl %%esi, %0" : "=m" (regs[1]);
+ "movl %%edi, %0" : "=m" (regs[2]);
+ }
+ sp = cast(void*)®s[0];
+ }
+ else version (X86_64)
+ {
+ void*[5] regs = void;
+ asm pure nothrow @nogc
+ {
+ "movq %%rbx, %0" : "=m" (regs[0]);
+ "movq %%r12, %0" : "=m" (regs[1]);
+ "movq %%r13, %0" : "=m" (regs[2]);
+ "movq %%r14, %0" : "=m" (regs[3]);
+ "movq %%r15, %0" : "=m" (regs[4]);
+ }
+ sp = cast(void*)®s[0];
+ }
+ else version (PPC)
+ {
+ void*[19] regs = void;
+ version (Darwin)
+ enum regname = "r";
+ else
+ enum regname = "";
+ static foreach (i; 0 .. regs.length)
+ {{
+ enum int j = 13 + i; // source register
+ asm pure nothrow @nogc
+ {
+ "stw "~regname~j.stringof~", %0" : "=m" (regs[i]);
+ }
+ }}
+ sp = cast(void*)®s[0];
+ }
+ else version (PPC64)
+ {
+ void*[19] regs = void;
+ version (Darwin)
+ enum regname = "r";
+ else
+ enum regname = "";
+ static foreach (i; 0 .. regs.length)
+ {{
+ enum int j = 13 + i; // source register
+ asm pure nothrow @nogc
+ {
+ "std "~regname~j.stringof~", %0" : "=m" (regs[i]);
+ }
+ }}
+ sp = cast(void*)®s[0];
+ }
+ else version (AArch64)
+ {
+ // Callee-save registers, x19-x28 according to AAPCS64, section
+ // 5.1.1. Include x29 fp because it optionally can be a callee
+ // saved reg
+ size_t[11] regs = void;
+ // store the registers in pairs
+ asm pure nothrow @nogc
+ {
+ "stp x19, x20, %0" : "=m" (regs[ 0]), "=m" (regs[1]);
+ "stp x21, x22, %0" : "=m" (regs[ 2]), "=m" (regs[3]);
+ "stp x23, x24, %0" : "=m" (regs[ 4]), "=m" (regs[5]);
+ "stp x25, x26, %0" : "=m" (regs[ 6]), "=m" (regs[7]);
+ "stp x27, x28, %0" : "=m" (regs[ 8]), "=m" (regs[9]);
+ "str x29, %0" : "=m" (regs[10]);
+ "mov %0, sp" : "=r" (sp);
+ }
+ }
+ else version (ARM)
+ {
+ // Callee-save registers, according to AAPCS, section 5.1.1.
+ // arm and thumb2 instructions
+ size_t[8] regs = void;
+ asm pure nothrow @nogc
+ {
+ "stm %0, {r4-r11}" : : "r" (regs.ptr) : "memory";
+ "mov %0, sp" : "=r" (sp);
+ }
+ }
+ else
+ {
+ __builtin_unwind_init();
+ sp = &sp;
+ }
}
else version (AsmX86_Posix)
{