Support for SysV for CVaList

This commit is contained in:
Christoffer Lerno
2025-09-09 13:41:26 +02:00
parent 8e6535f13c
commit 3ba0beee96
2 changed files with 47 additions and 2 deletions

View File

@@ -2,6 +2,8 @@
// Use of this source code is governed by the MIT license
// a copy of which can be found in the LICENSE_STDLIB file.
module std::core::cinterop;
import std::core::env;
const C_INT_SIZE = $$C_INT_SIZE;
const C_LONG_SIZE = $$C_LONG_SIZE;
@@ -60,7 +62,8 @@ macro typeid unsigned_int_from_bitsize(usz $bitsize) @private
$endswitch
}
module std::core::cinterop @if(env::DARWIN && env::AARCH64);
const USE_STACK_VALIST = env::ARCH_32_BIT || env::WIN32 || (env::DARWIN && env::AARCH64);
module std::core::cinterop @if(USE_STACK_VALIST);
typedef CVaList = void*;
macro CVaList.next(&self, $Type)
@@ -70,3 +73,45 @@ macro CVaList.next(&self, $Type)
return *($Type*)ptr;
}
module std::core::cinterop @if(env::X86_64 && !env::WIN32);
struct CVaListData
{
uint gp_offset;
uint fp_offset;
void *overflow_arg_area;
void *reg_save_area;
}
typedef CVaList = CVaListData*;
macro CVaList.next(self, $Type)
{
CVaListData* data = (CVaListData*)self;
$switch:
$case $Type.kindof == FLOAT ||| ($Type.kindof == VECTOR && $Type.sizeof <= 16):
var $LoadType = $Type.sizeof < 8 ? double : $Type;
if (data.fp_offset < 6 * 8 + 8 * 16 )
{
defer data.fp_offset += (uint)mem::aligned_offset($Type.sizeof, 16);
return ($Type)*($LoadType*)(data.reg_save_area + data.fp_offset);
}
void* ptr = mem::aligned_pointer(data.overflow_arg_area, max(8, $Type.alignof));
defer data.overflow_arg_area = ptr + $Type.sizeof;
return ($Type)*($LoadType*)ptr;
$case $Type.kindof == SIGNED_INT || $Type.kindof == UNSIGNED_INT:
var $LoadType = $Type.sizeof < 4 ? int : $Type;
if (data.gp_offset < 6 * 8 && $Type.sizeof <= 8)
{
defer data.gp_offset += (uint)mem::aligned_offset($Type.sizeof, 8);
return ($Type)*($LoadType*)(data.reg_save_area + data.gp_offset);
}
void* ptr = mem::aligned_pointer(data.overflow_arg_area, max(8, $Type.alignof));
defer data.overflow_arg_area = ptr + $Type.sizeof;
return ($Type)*($LoadType*)ptr;
$default:
void* ptr = mem::aligned_pointer(data.overflow_arg_area, max(8, $Type.alignof));
defer data.overflow_arg_area = ptr + $Type.sizeof;
return *($Type*)ptr;
$endswitch
}