Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#### Platform support
- Supports LLVM 15 - 19.
- Initial compiler and runtime support for ppc64 and ppc64le systems that use IEEE 754R 128-bit floating-point as the default 128-bit floating-point format. (#4833)
- Added support for building for Windows on ARM64. Use option '-march=arm64' to compile, 'ldc-build-runtime.exe --dFlags -march=arm64' to build the runtime libraries. (#4835)

#### Bug fixes
- Building multi-file D applications with control-flow protection will no longer cause LDC to throw an internal compiler error. (#4828)
Expand Down
13 changes: 12 additions & 1 deletion dmd/root/longdouble.d
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,20 @@ void ld_setll(longdouble_soft* pthis, long d)

void ld_setull(longdouble_soft* pthis, ulong d)
{
d ^= (1L << 63);
version(AsmX86)
{
// emulator accuracy not good enough when running on Windows on ARM,
// so avoid chopping off small numbers
if (!(d & (1L << 63)))
{
asm nothrow @nogc pure @trusted
{
fild qword ptr d;
}
mixin(fstp_parg!("pthis"));
return;
}
d ^= (1L << 63);
auto pTwoPow63 = &twoPow63;
mixin(fld_parg!("pTwoPow63"));
asm nothrow @nogc pure @trusted
Expand Down
9 changes: 7 additions & 2 deletions gen/abi/aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ struct AArch64TargetABI : TargetABI {
IndirectByvalRewrite indirectByvalRewrite;
ArgTypesRewrite argTypesRewrite;

bool hasAAPCS64VaList() {
return !isDarwin() &&
!global.params.targetTriple->isWindowsMSVCEnvironment();
}

bool isAAPCS64VaList(Type *t) {
if (isDarwin())
if (!hasAAPCS64VaList())
return false;

// look for a __va_list struct in a `std` C++ namespace
Expand Down Expand Up @@ -152,7 +157,7 @@ struct AArch64TargetABI : TargetABI {
}

Type *vaListType() override {
if (isDarwin())
if (!hasAAPCS64VaList())
return TargetABI::vaListType(); // char*

// We need to pass the actual va_list type for correct mangling. Simply
Expand Down
6 changes: 3 additions & 3 deletions gen/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ llvm::Type *getRealType(const llvm::Triple &triple) {

case Triple::aarch64:
case Triple::aarch64_be:
// AArch64 has 128-bit quad precision; Apple uses double
return triple.isOSDarwin() ? LLType::getDoubleTy(ctx)
: LLType::getFP128Ty(ctx);
// AArch64 has 128-bit quad precision; Apple and MSVC use double
return triple.isOSDarwin() || triple.isWindowsMSVCEnvironment()
? LLType::getDoubleTy(ctx) : LLType::getFP128Ty(ctx);

case Triple::riscv32:
case Triple::riscv64:
Expand Down
3 changes: 2 additions & 1 deletion runtime/druntime/src/__importc_builtins.di
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ version (LDC)
}
else version (ARM_Any)
{
// Darwin does not use __va_list
// Darwin and Windows do not use __va_list
version (OSX) {}
else version (iOS) {}
else version (TVOS) {}
else version (WatchOS) {}
else version (CRuntime_Microsoft) {}
else:

version (ARM)
Expand Down
3 changes: 2 additions & 1 deletion runtime/druntime/src/core/internal/vararg/aarch64.d
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ module core.internal.vararg.aarch64;

version (AArch64):

// Darwin uses a simpler varargs implementation
// Darwin and Windows use a simpler varargs implementation
version (OSX) {}
else version (iOS) {}
else version (TVOS) {}
else version (WatchOS) {}
else version (CRuntime_Microsoft) {}
else:

import core.stdc.stdarg : alignUp;
Expand Down
2 changes: 1 addition & 1 deletion runtime/druntime/src/core/stdc/math.d
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) only
else // for backward compatibility with older runtimes
{
///
pure int isnan(float x) { version (Win64) return _isnanf(x); else return _isnan(cast(double) x); }
pure int isnan(float x) { version (X86_64) return _isnanf(x); else return _isnan(cast(double) x); }
///
extern(C) pragma(mangle, "_isnan") pure int isnan(double x);
///
Expand Down
3 changes: 2 additions & 1 deletion runtime/druntime/src/core/stdc/stdarg.d
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,12 @@ version (GNU)
}
else version (ARM_Any)
{
// Darwin uses a simpler varargs implementation
// Darwin and Windows use a simpler varargs implementation
version (OSX) {}
else version (iOS) {}
else version (TVOS) {}
else version (WatchOS) {}
else version (CRuntime_Microsoft) {}
else:

version (ARM)
Expand Down
8 changes: 6 additions & 2 deletions runtime/druntime/src/core/sys/windows/dll.d
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ private bool isWindows8OrLater() nothrow @nogc
int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc
{
void** peb;
version (Win64)
version (X86_64)
{
asm pure nothrow @nogc
{
Expand All @@ -411,14 +411,18 @@ int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc
mov peb, RAX;
}
}
else version (Win32)
else version (X86)
{
asm pure nothrow @nogc
{
mov EAX,FS:[0x30];
mov peb, EAX;
}
}
else version (AArch64)
{
asm nothrow @nogc { "ldr %0, [x18,%1]" : "=r" (peb) : "r" (0x30); }
}
dll_aux.LDR_MODULE *ldrMod = dll_aux.findLdrModule( hInstance, peb );
if ( !ldrMod )
return -2; // not in module list, bail out
Expand Down
1 change: 1 addition & 0 deletions runtime/druntime/src/core/sys/windows/stacktrace.d
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ private:

version (X86) enum imageType = IMAGE_FILE_MACHINE_I386;
else version (X86_64) enum imageType = IMAGE_FILE_MACHINE_AMD64;
else version (AArch64) enum imageType = IMAGE_FILE_MACHINE_ARM64;
else static assert(0, "unimplemented");

size_t frameNum = 0;
Expand Down
5 changes: 3 additions & 2 deletions runtime/druntime/src/core/sys/windows/threadaux.d
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,9 @@ struct thread_aux
{
static void** getTEB() nothrow @nogc @naked
{
version (Win32) return __asm!(void**)("mov %fs:(0x18), $0", "=r");
else version (Win64) return __asm!(void**)("mov %gs:0($1), $0", "=r,r", 0x30);
version (X86) return __asm!(void**)("mov %fs:(0x18), $0", "=r");
else version (X86_64) return __asm!(void**)("mov %gs:0($1), $0", "=r,r", 0x30);
else version (AArch64) return __asm!(void**)("mov $0, x18", "=r");
else static assert(false);
}
}
Expand Down
48 changes: 47 additions & 1 deletion runtime/druntime/src/core/sys/windows/winnt.d
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,8 @@ enum : WORD {
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466,
IMAGE_FILE_MACHINE_EBC = 0x0EBC,
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
IMAGE_FILE_MACHINE_M32R = 0x9041
IMAGE_FILE_MACHINE_M32R = 0x9041,
IMAGE_FILE_MACHINE_ARM64 = 0xAA64,
}

// ???
Expand Down Expand Up @@ -2257,6 +2258,51 @@ enum LEGACY_SAVE_AREA_LENGTH = XMM_SAVE_AREA32.sizeof;
DWORD64 LastExceptionFromRip;
}

} else version(AArch64) {
enum CONTEXT_ARM64 = 0x400000;

enum CONTEXT_CONTROL = (CONTEXT_ARM64 | 0x1L);
enum CONTEXT_INTEGER = (CONTEXT_ARM64 | 0x2L);
enum CONTEXT_SEGMENTS = (CONTEXT_ARM64 | 0x4L);
enum CONTEXT_FLOATING_POINT = (CONTEXT_ARM64 | 0x8L);
enum CONTEXT_DEBUG_REGISTERS = (CONTEXT_ARM64 | 0x10L);

enum CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT);
enum CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS);

enum ARM64_MAX_BREAKPOINTS = 8;
enum ARM64_MAX_WATCHPOINTS = 2;

union ARM64_NT_NEON128 {
struct {
ULONGLONG Low;
LONGLONG High;
};
double[2] D;
float[4] S;
WORD[8] H;
BYTE[16] B;
}
alias PARM64_NT_NEON128 = ARM64_NT_NEON128*;

align(16) struct CONTEXT
{
DWORD ContextFlags;
DWORD Cpsr;
DWORD64[31] X;
DWORD64 Sp;
DWORD64 Pc;

ARM64_NT_NEON128[32] V;
DWORD Fpcr;

DWORD Fpsr;

DWORD[ARM64_MAX_BREAKPOINTS] Bcr;
DWORD64[ARM64_MAX_BREAKPOINTS] Bvr;
DWORD[ARM64_MAX_WATCHPOINTS] Wcr;
DWORD64[ARM64_MAX_WATCHPOINTS] Wvr;
}
} else {
static assert(false, "Unsupported CPU");
// Versions for PowerPC, Alpha, SHX, and MIPS removed.
Expand Down
97 changes: 97 additions & 0 deletions runtime/druntime/src/core/thread/fiber.d
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ private
version = AsmExternal;
version = AlignFiberStackTo16Byte;
}
else version (Windows)
{
version = AsmAArch64_Windows;
version = AlignFiberStackTo16Byte;
}
}
else version (ARM)
{
Expand Down Expand Up @@ -355,6 +360,63 @@ private
"~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15}"
);
}
else version (AsmAArch64_Windows)
{
pragma(LDC_never_inline);
asm pure nothrow @nogc
{
`// save current stack state (similar to posix version in threadasm.S)
stp x19, x20, [sp, #-16]!
stp x21, x22, [sp, #-16]!
stp x23, x24, [sp, #-16]!
stp x25, x26, [sp, #-16]!
stp x27, x28, [sp, #-16]!
stp fp, lr, [sp, #-16]!
mov x19, sp // no need to scan FP registers, so snapshot sp here

stp d8, d9, [sp, #-16]!
stp d10, d11, [sp, #-16]!
stp d12, d13, [sp, #-16]!
stp d14, d15, [sp, #-16]!

ldr x20, [x18, #8] // read stack range from TEB
ldr x21, [x18, #16]
stp x20, x21, [sp, #-16]!

ldr x20, [x18, #0x1478] // read Deallocation Stack
ldr w21, [x18, #0x1748] // read GuaranteedStackBytes
stp x20, x21, [sp, #-16]!

// store oldp
str x19, [x0]
// load newp to begin context switch
sub x1, x1, #6*16
mov sp, x1

ldp x20, x21, [sp], #16 // restore Deallocation/GuaranteedStackBytes
str x20, [x18, #0x1478]
str w21, [x18, #0x1748] // word only

ldp x20, x21, [sp], #16 // restore stack range
str x20, [x18, #8]
str x21, [x18, #16]

// load saved state from new stack
ldp d14, d15, [sp], #16
ldp d12, d13, [sp], #16
ldp d10, d11, [sp], #16
ldp d8, d9, [sp], #16

ldp fp, lr, [sp], #16
ldp x27, x28, [sp], #16
ldp x25, x26, [sp], #16
ldp x23, x24, [sp], #16
ldp x21, x22, [sp], #16
ldp x19, x20, [sp], #16

ret`;
}
}
else
static assert(false);
}
Expand Down Expand Up @@ -1616,6 +1678,41 @@ private:
push( cast(size_t) m_ctxt.bstack + m_size ); // GS:[16]
}
}
else version (AsmAArch64_Windows)
{
version (StackGrowsDown) {} else static assert( false );

push( 0x00000000_00000000 ); // another stack frame is needed
push( 0x00000000_00000000 ); // to catch exceptions in fiber_entryPoint
auto nextfp = pstack;

push( 0x00000000_00000000 ); // X20
push( 0x00000000_00000000 ); // X19
push( 0x00000000_00000000 ); // X22
push( 0x00000000_00000000 ); // X21
push( 0x00000000_00000000 ); // X24
push( 0x00000000_00000000 ); // X23
push( 0x00000000_00000000 ); // X26
push( 0x00000000_00000000 ); // X25
push( 0x00000000_00000000 ); // X28
push( 0x00000000_00000000 ); // X27
push( cast(size_t) &fiber_entryPoint ); // X30 (lr)
push( cast(size_t) nextfp ); // X29 (fp)
push( 0x00000000_00000000 ); // V9 (low)
push( 0x00000000_00000000 ); // V8 (low)
push( 0x00000000_00000000 ); // V11 (low)
push( 0x00000000_00000000 ); // V10 (low)
push( 0x00000000_00000000 ); // V13 (low)
push( 0x00000000_00000000 ); // V12 (low)
push( 0x00000000_00000000 ); // V15 (low)
push( 0x00000000_00000000 ); // V14 (low)
push( cast(size_t) m_ctxt.bstack - m_size ); // StackLimit x18[16] (X18 is TEB)
push( cast(size_t) m_ctxt.bstack ); // StackBase x18[8]
push( 0x00000000_00000000 ); // GuaranteedStackBytes
push( cast(size_t) m_ctxt.bstack - m_size ); // DeallocationStack

pstack += size_t.sizeof * 12; // exclude V8 and TEB-entries from scanning by the GC
}
else version (AsmX86_Posix)
{
push( 0x00000000 ); // Return address of fiber_entryPoint call
Expand Down
16 changes: 16 additions & 0 deletions runtime/druntime/src/core/thread/osthread.d
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,10 @@ class Thread : ThreadBase
ulong[16] m_reg; // rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax
// r8,r9,r10,r11,r12,r13,r14,r15
}
else version (AArch64)
{
ulong[33] m_reg; // x0-x31, pc
}
else
{
static assert(false, "Architecture not supported." );
Expand Down Expand Up @@ -1760,6 +1764,8 @@ version (LDC_Windows)
return __asm!(void*)("mov %fs:(4), $0", "=r");
else version (X86_64)
return __asm!(void*)("mov %gs:0($1), $0", "=r,r", 8);
else version (AArch64)
return __asm!(void*)("ldr $0, [x18,$1]", "=r,r", 8);
else
static assert(false, "Architecture not supported.");
}
Expand Down Expand Up @@ -1918,6 +1924,16 @@ private extern (D) bool suspend( Thread t ) nothrow @nogc
t.m_reg[14] = context.R14;
t.m_reg[15] = context.R15;
}
else version (AArch64)
{
for( int i = 0; i < 31; i++ )
t.m_reg[i] = context.X[i];

t.m_reg[31] = context.Sp;
t.m_reg[32] = context.Pc;
if ( !t.m_lock )
t.m_curr.tstack = cast(void*) context.Sp;
}
else
{
static assert(false, "Architecture not supported." );
Expand Down
Loading
Loading