mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Merge branch 'master' of https://github.com/odin-lang/Odin
This commit is contained in:
@@ -9,6 +9,7 @@ package poly1305
|
|||||||
import "core:crypto"
|
import "core:crypto"
|
||||||
import field "core:crypto/_fiat/field_poly1305"
|
import field "core:crypto/_fiat/field_poly1305"
|
||||||
import "core:encoding/endian"
|
import "core:encoding/endian"
|
||||||
|
import "core:math/bits"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
|
|
||||||
// KEY_SIZE is the Poly1305 key size in bytes.
|
// KEY_SIZE is the Poly1305 key size in bytes.
|
||||||
@@ -50,7 +51,7 @@ verify :: proc(tag, msg, key: []byte) -> bool {
|
|||||||
Context :: struct {
|
Context :: struct {
|
||||||
_r: field.Tight_Field_Element,
|
_r: field.Tight_Field_Element,
|
||||||
_a: field.Tight_Field_Element,
|
_a: field.Tight_Field_Element,
|
||||||
_s: field.Tight_Field_Element,
|
_s: [2]u64,
|
||||||
_buffer: [_BLOCK_SIZE]byte,
|
_buffer: [_BLOCK_SIZE]byte,
|
||||||
_leftover: int,
|
_leftover: int,
|
||||||
_is_initialized: bool,
|
_is_initialized: bool,
|
||||||
@@ -66,11 +67,12 @@ init :: proc(ctx: ^Context, key: []byte) {
|
|||||||
// r = le_bytes_to_num(key[0..15])
|
// r = le_bytes_to_num(key[0..15])
|
||||||
// r = clamp(r) (r &= 0xffffffc0ffffffc0ffffffc0fffffff)
|
// r = clamp(r) (r &= 0xffffffc0ffffffc0ffffffc0fffffff)
|
||||||
tmp_lo := endian.unchecked_get_u64le(key[0:]) & 0x0ffffffc0fffffff
|
tmp_lo := endian.unchecked_get_u64le(key[0:]) & 0x0ffffffc0fffffff
|
||||||
tmp_hi := endian.unchecked_get_u64le(key[8:]) & 0xffffffc0ffffffc
|
tmp_hi := endian.unchecked_get_u64le(key[8:]) & 0x0ffffffc0ffffffc
|
||||||
field.fe_from_u64s(&ctx._r, tmp_lo, tmp_hi)
|
field.fe_from_u64s(&ctx._r, tmp_lo, tmp_hi)
|
||||||
|
|
||||||
// s = le_bytes_to_num(key[16..31])
|
// s = le_bytes_to_num(key[16..31])
|
||||||
field.fe_from_bytes(&ctx._s, key[16:32], 0)
|
ctx._s[0] = endian.unchecked_get_u64le(key[16:])
|
||||||
|
ctx._s[1] = endian.unchecked_get_u64le(key[24:])
|
||||||
|
|
||||||
// a = 0
|
// a = 0
|
||||||
field.fe_zero(&ctx._a)
|
field.fe_zero(&ctx._a)
|
||||||
@@ -138,14 +140,20 @@ final :: proc(ctx: ^Context, dst: []byte) {
|
|||||||
_blocks(ctx, ctx._buffer[:], true)
|
_blocks(ctx, ctx._buffer[:], true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// a += s
|
// a += s (NOT mod p)
|
||||||
field.fe_add(field.fe_relax_cast(&ctx._a), &ctx._a, &ctx._s) // _a unreduced
|
|
||||||
field.fe_carry(&ctx._a, field.fe_relax_cast(&ctx._a)) // _a reduced
|
|
||||||
|
|
||||||
// return num_to_16_le_bytes(a)
|
|
||||||
tmp: [32]byte = ---
|
tmp: [32]byte = ---
|
||||||
field.fe_to_bytes(&tmp, &ctx._a)
|
field.fe_to_bytes(&tmp, &ctx._a)
|
||||||
copy_slice(dst, tmp[0:16])
|
|
||||||
|
c: u64
|
||||||
|
lo := endian.unchecked_get_u64le(tmp[0:])
|
||||||
|
hi := endian.unchecked_get_u64le(tmp[8:])
|
||||||
|
|
||||||
|
lo, c = bits.add_u64(lo, ctx._s[0], 0)
|
||||||
|
hi, _ = bits.add_u64(hi, ctx._s[1], c)
|
||||||
|
|
||||||
|
// return num_to_16_le_bytes(a)
|
||||||
|
endian.unchecked_put_u64le(dst[0:], lo)
|
||||||
|
endian.unchecked_put_u64le(dst[8:], hi)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset sanitizes the Context. The Context must be re-initialized to
|
// reset sanitizes the Context. The Context must be re-initialized to
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ init_from_f64 :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), val: f64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init_from_parts :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), integer, fraction: Backing) {
|
init_from_parts :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), integer, fraction: Backing) {
|
||||||
i, f := math.modf(val)
|
|
||||||
x.i = fraction
|
x.i = fraction
|
||||||
x.i &= 1<<Fraction_Width - 1
|
x.i &= 1<<Fraction_Width - 1
|
||||||
x.i |= integer
|
x.i |= integer
|
||||||
|
|||||||
@@ -324,6 +324,7 @@ foreign kernel32 {
|
|||||||
lpName: LPCWSTR,
|
lpName: LPCWSTR,
|
||||||
) -> HANDLE ---
|
) -> HANDLE ---
|
||||||
ResetEvent :: proc(hEvent: HANDLE) -> BOOL ---
|
ResetEvent :: proc(hEvent: HANDLE) -> BOOL ---
|
||||||
|
SetEvent :: proc(hEvent: HANDLE) -> BOOL ---
|
||||||
WaitForMultipleObjects :: proc(
|
WaitForMultipleObjects :: proc(
|
||||||
nCount: DWORD,
|
nCount: DWORD,
|
||||||
lpHandles: ^HANDLE,
|
lpHandles: ^HANDLE,
|
||||||
@@ -545,6 +546,10 @@ FILE_MAP_RESERVE :: DWORD(0x80000000)
|
|||||||
FILE_MAP_TARGETS_INVALID :: DWORD(0x40000000)
|
FILE_MAP_TARGETS_INVALID :: DWORD(0x40000000)
|
||||||
FILE_MAP_LARGE_PAGES :: DWORD(0x20000000)
|
FILE_MAP_LARGE_PAGES :: DWORD(0x20000000)
|
||||||
|
|
||||||
|
// Flags for `SetFileCompletionNotificationModes`.
|
||||||
|
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS :: 0x1
|
||||||
|
FILE_SKIP_SET_EVENT_ON_HANDLE :: 0x2
|
||||||
|
|
||||||
PAGE_NOACCESS :: 0x01
|
PAGE_NOACCESS :: 0x01
|
||||||
PAGE_READONLY :: 0x02
|
PAGE_READONLY :: 0x02
|
||||||
PAGE_READWRITE :: 0x04
|
PAGE_READWRITE :: 0x04
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
package sys_windows
|
package sys_windows
|
||||||
|
|
||||||
// Define flags to be used with the WSAAsyncSelect() call.
|
// Define flags to be used with the WSAAsyncSelect() call.
|
||||||
FD_READ :: 0x01
|
FD_READ :: 0x01
|
||||||
FD_WRITE :: 0x02
|
FD_WRITE :: 0x02
|
||||||
FD_OOB :: 0x04
|
FD_OOB :: 0x04
|
||||||
FD_ACCEPT :: 0x08
|
FD_ACCEPT :: 0x08
|
||||||
FD_CONNECT :: 0x10
|
FD_CONNECT :: 0x10
|
||||||
FD_CLOSE :: 0x20
|
FD_CLOSE :: 0x20
|
||||||
FD_MAX_EVENTS :: 10
|
FD_MAX_EVENTS :: 10
|
||||||
|
|
||||||
INADDR_LOOPBACK :: 0x7f000001
|
INADDR_LOOPBACK :: 0x7f000001
|
||||||
@@ -24,10 +24,10 @@ POLLERR :: 0x0001
|
|||||||
POLLHUP :: 0x0002
|
POLLHUP :: 0x0002
|
||||||
POLLNVAL :: 0x0004
|
POLLNVAL :: 0x0004
|
||||||
|
|
||||||
WSA_POLLFD::struct{
|
WSA_POLLFD :: struct{
|
||||||
fd:SOCKET,
|
fd: SOCKET,
|
||||||
events:c_short,
|
events: c_short,
|
||||||
revents:c_short,
|
revents: c_short,
|
||||||
}
|
}
|
||||||
|
|
||||||
WSANETWORKEVENTS :: struct {
|
WSANETWORKEVENTS :: struct {
|
||||||
@@ -37,16 +37,43 @@ WSANETWORKEVENTS :: struct {
|
|||||||
|
|
||||||
WSAEVENT :: HANDLE
|
WSAEVENT :: HANDLE
|
||||||
|
|
||||||
WSAID_ACCEPTEX :: GUID{0xb5367df1, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
|
WSAID_ACCEPTEX :: GUID{0xb5367df1, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
|
||||||
WSAID_GETACCEPTEXSOCKADDRS :: GUID{0xb5367df2, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
|
WSAID_GETACCEPTEXSOCKADDRS :: GUID{0xb5367df2, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
|
||||||
|
WSAID_CONNECTX :: GUID{0x25a207b9, 0xddf3, 0x4660, {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}}
|
||||||
|
|
||||||
SIO_GET_EXTENSION_FUNCTION_POINTER :: IOC_INOUT | IOC_WS2 | 6
|
SIO_GET_EXTENSION_FUNCTION_POINTER :: IOC_INOUT | IOC_WS2 | 6
|
||||||
IOC_OUT :: 0x40000000
|
|
||||||
IOC_IN :: 0x80000000
|
IOC_OUT :: 0x40000000
|
||||||
|
IOC_IN :: 0x80000000
|
||||||
IOC_INOUT :: (IOC_IN | IOC_OUT)
|
IOC_INOUT :: (IOC_IN | IOC_OUT)
|
||||||
IOC_WS2 :: 0x08000000
|
IOC_WS2 :: 0x08000000
|
||||||
|
|
||||||
|
SO_UPDATE_ACCEPT_CONTEXT :: 28683
|
||||||
|
|
||||||
|
LPFN_CONNECTEX :: #type proc "system" (
|
||||||
|
s: SOCKET,
|
||||||
|
sockaddr: ^SOCKADDR_STORAGE_LH,
|
||||||
|
namelen: c_int,
|
||||||
|
lpSendBuffer: PVOID,
|
||||||
|
dwSendDataLength: DWORD,
|
||||||
|
lpdwBytesSent: LPDWORD,
|
||||||
|
lpOverlapped: LPOVERLAPPED,
|
||||||
|
) -> BOOL
|
||||||
|
|
||||||
|
LPFN_ACCEPTEX :: #type proc "system" (
|
||||||
|
sListenSocket: SOCKET,
|
||||||
|
sAcceptSocket: SOCKET,
|
||||||
|
lpOutputBuffer: PVOID,
|
||||||
|
dwReceiveDataLength: DWORD,
|
||||||
|
dwLocalAddressLength: DWORD,
|
||||||
|
dwRemoteAddressLength: DWORD,
|
||||||
|
lpdwBytesReceived: LPDWORD,
|
||||||
|
lpOverlapped: LPOVERLAPPED,
|
||||||
|
) -> BOOL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Example Load:
|
Example Load:
|
||||||
load_accept_ex :: proc(listener: SOCKET, fn_acceptex: rawptr) {
|
load_accept_ex :: proc(listener: SOCKET, fn_acceptex: ^LPFN_ACCEPTEX) {
|
||||||
bytes: u32
|
bytes: u32
|
||||||
guid_accept_ex := WSAID_ACCEPTEX
|
guid_accept_ex := WSAID_ACCEPTEX
|
||||||
rc := WSAIoctl(listener, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid_accept_ex, size_of(guid_accept_ex),
|
rc := WSAIoctl(listener, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid_accept_ex, size_of(guid_accept_ex),
|
||||||
|
|||||||
@@ -521,7 +521,7 @@ gb_global TargetMetrics target_darwin_amd64 = {
|
|||||||
gb_global TargetMetrics target_darwin_arm64 = {
|
gb_global TargetMetrics target_darwin_arm64 = {
|
||||||
TargetOs_darwin,
|
TargetOs_darwin,
|
||||||
TargetArch_arm64,
|
TargetArch_arm64,
|
||||||
8, 8, 8, 16,
|
8, 8, 16, 16,
|
||||||
str_lit("arm64-apple-macosx"), // NOTE: Changes during initialization based on build flags.
|
str_lit("arm64-apple-macosx"), // NOTE: Changes during initialization based on build flags.
|
||||||
str_lit("e-m:o-i64:64-i128:128-n32:64-S128"),
|
str_lit("e-m:o-i64:64-i128:128-n32:64-S128"),
|
||||||
};
|
};
|
||||||
|
|||||||
+3
-3
@@ -2075,13 +2075,13 @@ gb_internal void check_expr_stmt(CheckerContext *ctx, Ast *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ast *expr = strip_or_return_expr(operand.expr);
|
Ast *expr = strip_or_return_expr(operand.expr);
|
||||||
if (expr->kind == Ast_CallExpr) {
|
if (expr && expr->kind == Ast_CallExpr) {
|
||||||
BuiltinProcId builtin_id = BuiltinProc_Invalid;
|
BuiltinProcId builtin_id = BuiltinProc_Invalid;
|
||||||
bool do_require = false;
|
bool do_require = false;
|
||||||
|
|
||||||
AstCallExpr *ce = &expr->CallExpr;
|
AstCallExpr *ce = &expr->CallExpr;
|
||||||
Type *t = base_type(type_of_expr(ce->proc));
|
Type *t = base_type(type_of_expr(ce->proc));
|
||||||
if (t->kind == Type_Proc) {
|
if (t && t->kind == Type_Proc) {
|
||||||
do_require = t->Proc.require_results;
|
do_require = t->Proc.require_results;
|
||||||
} else if (check_stmt_internal_builtin_proc_id(ce->proc, &builtin_id)) {
|
} else if (check_stmt_internal_builtin_proc_id(ce->proc, &builtin_id)) {
|
||||||
auto const &bp = builtin_procs[builtin_id];
|
auto const &bp = builtin_procs[builtin_id];
|
||||||
@@ -2093,7 +2093,7 @@ gb_internal void check_expr_stmt(CheckerContext *ctx, Ast *node) {
|
|||||||
gb_string_free(expr_str);
|
gb_string_free(expr_str);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (expr->kind == Ast_SelectorCallExpr) {
|
} else if (expr && expr->kind == Ast_SelectorCallExpr) {
|
||||||
BuiltinProcId builtin_id = BuiltinProc_Invalid;
|
BuiltinProcId builtin_id = BuiltinProc_Invalid;
|
||||||
bool do_require = false;
|
bool do_require = false;
|
||||||
|
|
||||||
|
|||||||
+17
-34
@@ -192,7 +192,7 @@ gb_internal void lb_add_function_type_attributes(LLVMValueRef fn, lbFunctionType
|
|||||||
// }
|
// }
|
||||||
LLVMSetFunctionCallConv(fn, cc_kind);
|
LLVMSetFunctionCallConv(fn, cc_kind);
|
||||||
if (calling_convention == ProcCC_Odin) {
|
if (calling_convention == ProcCC_Odin) {
|
||||||
unsigned context_index = offset+arg_count;
|
unsigned context_index = arg_index;
|
||||||
LLVMAddAttributeAtIndex(fn, context_index, noalias_attr);
|
LLVMAddAttributeAtIndex(fn, context_index, noalias_attr);
|
||||||
LLVMAddAttributeAtIndex(fn, context_index, nonnull_attr);
|
LLVMAddAttributeAtIndex(fn, context_index, nonnull_attr);
|
||||||
LLVMAddAttributeAtIndex(fn, context_index, nocapture_attr);
|
LLVMAddAttributeAtIndex(fn, context_index, nocapture_attr);
|
||||||
@@ -275,7 +275,7 @@ gb_internal i64 lb_alignof(LLVMTypeRef type) {
|
|||||||
case LLVMIntegerTypeKind:
|
case LLVMIntegerTypeKind:
|
||||||
{
|
{
|
||||||
unsigned w = LLVMGetIntTypeWidth(type);
|
unsigned w = LLVMGetIntTypeWidth(type);
|
||||||
return gb_clamp((w + 7)/8, 1, build_context.ptr_size);
|
return gb_clamp((w + 7)/8, 1, build_context.max_align);
|
||||||
}
|
}
|
||||||
case LLVMHalfTypeKind:
|
case LLVMHalfTypeKind:
|
||||||
return 2;
|
return 2;
|
||||||
@@ -558,7 +558,6 @@ namespace lbAbiAmd64SysV {
|
|||||||
Amd64TypeAttribute_StructRect,
|
Amd64TypeAttribute_StructRect,
|
||||||
};
|
};
|
||||||
|
|
||||||
gb_internal LB_ABI_COMPUTE_RETURN_TYPE(compute_return_type);
|
|
||||||
gb_internal void classify_with(LLVMTypeRef t, Array<RegClass> *cls, i64 ix, i64 off);
|
gb_internal void classify_with(LLVMTypeRef t, Array<RegClass> *cls, i64 ix, i64 off);
|
||||||
gb_internal void fixup(LLVMTypeRef t, Array<RegClass> *cls);
|
gb_internal void fixup(LLVMTypeRef t, Array<RegClass> *cls);
|
||||||
gb_internal lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention);
|
gb_internal lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention);
|
||||||
@@ -796,10 +795,10 @@ namespace lbAbiAmd64SysV {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i64 sz = lb_sizeof(type);
|
||||||
if (all_ints) {
|
if (all_ints) {
|
||||||
i64 sz = lb_sizeof(type);
|
|
||||||
for_array(i, reg_classes) {
|
for_array(i, reg_classes) {
|
||||||
GB_ASSERT(sz != 0);
|
GB_ASSERT(sz > 0);
|
||||||
// TODO(bill): is this even correct? BECAUSE LLVM DOES NOT DOCUMENT ANY OF THIS!!!
|
// TODO(bill): is this even correct? BECAUSE LLVM DOES NOT DOCUMENT ANY OF THIS!!!
|
||||||
if (sz >= 8) {
|
if (sz >= 8) {
|
||||||
array_add(&types, LLVMIntTypeInContext(c, 64));
|
array_add(&types, LLVMIntTypeInContext(c, 64));
|
||||||
@@ -811,12 +810,16 @@ namespace lbAbiAmd64SysV {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (isize i = 0; i < reg_classes.count; /**/) {
|
for (isize i = 0; i < reg_classes.count; /**/) {
|
||||||
|
GB_ASSERT(sz > 0);
|
||||||
RegClass reg_class = reg_classes[i];
|
RegClass reg_class = reg_classes[i];
|
||||||
switch (reg_class) {
|
switch (reg_class) {
|
||||||
case RegClass_Int:
|
case RegClass_Int:
|
||||||
// TODO(bill): is this even correct? BECAUSE LLVM DOES NOT DOCUMENT ANY OF THIS!!!
|
{
|
||||||
array_add(&types, LLVMIntTypeInContext(c, 64));
|
i64 rs = gb_min(sz, 8);
|
||||||
break;
|
array_add(&types, LLVMIntTypeInContext(c, cast(unsigned)(rs*8)));
|
||||||
|
sz -= rs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case RegClass_SSEFv:
|
case RegClass_SSEFv:
|
||||||
case RegClass_SSEDv:
|
case RegClass_SSEDv:
|
||||||
case RegClass_SSEInt8:
|
case RegClass_SSEInt8:
|
||||||
@@ -856,15 +859,18 @@ namespace lbAbiAmd64SysV {
|
|||||||
unsigned vec_len = llvec_len(reg_classes, i+1);
|
unsigned vec_len = llvec_len(reg_classes, i+1);
|
||||||
LLVMTypeRef vec_type = LLVMVectorType(elem_type, vec_len * elems_per_word);
|
LLVMTypeRef vec_type = LLVMVectorType(elem_type, vec_len * elems_per_word);
|
||||||
array_add(&types, vec_type);
|
array_add(&types, vec_type);
|
||||||
|
sz -= lb_sizeof(vec_type);
|
||||||
i += vec_len;
|
i += vec_len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RegClass_SSEFs:
|
case RegClass_SSEFs:
|
||||||
array_add(&types, LLVMFloatTypeInContext(c));
|
array_add(&types, LLVMFloatTypeInContext(c));
|
||||||
|
sz -= 4;
|
||||||
break;
|
break;
|
||||||
case RegClass_SSEDs:
|
case RegClass_SSEDs:
|
||||||
array_add(&types, LLVMDoubleTypeInContext(c));
|
array_add(&types, LLVMDoubleTypeInContext(c));
|
||||||
|
sz -= 8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GB_PANIC("Unhandled RegClass");
|
GB_PANIC("Unhandled RegClass");
|
||||||
@@ -876,8 +882,8 @@ namespace lbAbiAmd64SysV {
|
|||||||
if (types.count == 1) {
|
if (types.count == 1) {
|
||||||
return types[0];
|
return types[0];
|
||||||
}
|
}
|
||||||
// TODO(bill): this should be packed but it causes code generation issues
|
|
||||||
return LLVMStructTypeInContext(c, types.data, cast(unsigned)types.count, false);
|
return LLVMStructTypeInContext(c, types.data, cast(unsigned)types.count, sz == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal void classify_with(LLVMTypeRef t, Array<RegClass> *cls, i64 ix, i64 off) {
|
gb_internal void classify_with(LLVMTypeRef t, Array<RegClass> *cls, i64 ix, i64 off) {
|
||||||
@@ -980,28 +986,6 @@ namespace lbAbiAmd64SysV {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal LB_ABI_COMPUTE_RETURN_TYPE(compute_return_type) {
|
|
||||||
if (!return_is_defined) {
|
|
||||||
return lb_arg_type_direct(LLVMVoidTypeInContext(c));
|
|
||||||
} else if (lb_is_type_kind(return_type, LLVMStructTypeKind)) {
|
|
||||||
i64 sz = lb_sizeof(return_type);
|
|
||||||
switch (sz) {
|
|
||||||
case 1: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 8), nullptr, nullptr);
|
|
||||||
case 2: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 16), nullptr, nullptr);
|
|
||||||
case 4: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr);
|
|
||||||
case 8: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 64), nullptr, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
LB_ABI_MODIFY_RETURN_IF_TUPLE_MACRO();
|
|
||||||
|
|
||||||
LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", return_type);
|
|
||||||
return lb_arg_type_indirect(return_type, attr);
|
|
||||||
} else if (build_context.metrics.os == TargetOs_windows && lb_is_type_kind(return_type, LLVMIntegerTypeKind) && lb_sizeof(return_type) == 16) {
|
|
||||||
return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 128), nullptr, nullptr);
|
|
||||||
}
|
|
||||||
return non_struct(c, return_type);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1166,8 +1150,7 @@ namespace lbAbiArm64 {
|
|||||||
size_copy -= 8;
|
size_copy -= 8;
|
||||||
}
|
}
|
||||||
GB_ASSERT(size_copy <= 0);
|
GB_ASSERT(size_copy <= 0);
|
||||||
// TODO(bill): this should be packed but it causes code generation issues
|
cast_type = LLVMStructTypeInContext(c, types, count, true);
|
||||||
cast_type = LLVMStructTypeInContext(c, types, count, false);
|
|
||||||
}
|
}
|
||||||
return lb_arg_type_direct(return_type, cast_type, nullptr, nullptr);
|
return lb_arg_type_direct(return_type, cast_type, nullptr, nullptr);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -578,7 +578,10 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) {
|
|||||||
defer (param_index += 1);
|
defer (param_index += 1);
|
||||||
|
|
||||||
if (arg_type->kind == lbArg_Ignore) {
|
if (arg_type->kind == lbArg_Ignore) {
|
||||||
continue;
|
// Even though it is an ignored argument, it might still be referenced in the
|
||||||
|
// body.
|
||||||
|
lbValue dummy = lb_add_local_generated(p, e->type, false).addr;
|
||||||
|
lb_add_entity(p->module, e, dummy);
|
||||||
} else if (arg_type->kind == lbArg_Direct) {
|
} else if (arg_type->kind == lbArg_Direct) {
|
||||||
if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) {
|
if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) {
|
||||||
LLVMTypeRef param_type = lb_type(p->module, e->type);
|
LLVMTypeRef param_type = lb_type(p->module, e->type);
|
||||||
@@ -1051,6 +1054,7 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> c
|
|||||||
Type *original_type = e->type;
|
Type *original_type = e->type;
|
||||||
lbArgType *arg = &ft->args[param_index];
|
lbArgType *arg = &ft->args[param_index];
|
||||||
if (arg->kind == lbArg_Ignore) {
|
if (arg->kind == lbArg_Ignore) {
|
||||||
|
param_index += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ODIN=../../odin
|
ODIN=../../odin
|
||||||
|
|
||||||
all: rtti_test map_test pow_test
|
all: rtti_test map_test pow_test 128_test asan_test
|
||||||
|
|
||||||
rtti_test:
|
rtti_test:
|
||||||
$(ODIN) run test_rtti.odin -file -vet -strict-style -o:minimal
|
$(ODIN) run test_rtti.odin -file -vet -strict-style -o:minimal
|
||||||
@@ -10,3 +10,9 @@ map_test:
|
|||||||
|
|
||||||
pow_test:
|
pow_test:
|
||||||
$(ODIN) run test_pow.odin -file -vet -strict-style -o:minimal
|
$(ODIN) run test_pow.odin -file -vet -strict-style -o:minimal
|
||||||
|
|
||||||
|
128_test:
|
||||||
|
$(ODIN) run test_128.odin -file -vet -strict-style -o:minimal
|
||||||
|
|
||||||
|
asan_test:
|
||||||
|
$(ODIN) run test_asan.odin -file -sanitize:address -debug
|
||||||
|
|||||||
@@ -4,3 +4,5 @@ rem %PATH_TO_ODIN% run test_rtti.odin -file -vet -strict-style -o:minimal || exi
|
|||||||
%PATH_TO_ODIN% run test_map.odin -file -vet -strict-style -o:minimal || exit /b
|
%PATH_TO_ODIN% run test_map.odin -file -vet -strict-style -o:minimal || exit /b
|
||||||
rem -define:SEED=42
|
rem -define:SEED=42
|
||||||
%PATH_TO_ODIN% run test_pow.odin -file -vet -strict-style -o:minimal || exit /b
|
%PATH_TO_ODIN% run test_pow.odin -file -vet -strict-style -o:minimal || exit /b
|
||||||
|
|
||||||
|
%PATH_TO_ODIN% run test_128.odin -file -vet -strict-style -o:minimal || exit /b
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package test_128
|
||||||
|
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:os"
|
||||||
|
import "core:testing"
|
||||||
|
|
||||||
|
TEST_count := 0
|
||||||
|
TEST_fail := 0
|
||||||
|
|
||||||
|
when ODIN_TEST {
|
||||||
|
expect :: testing.expect
|
||||||
|
log :: testing.log
|
||||||
|
} else {
|
||||||
|
expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
|
||||||
|
TEST_count += 1
|
||||||
|
if !condition {
|
||||||
|
TEST_fail += 1
|
||||||
|
fmt.printf("[%v] %v\n", loc, message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
|
||||||
|
fmt.printf("[%v] ", loc)
|
||||||
|
fmt.printf("log: %v\n", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main :: proc() {
|
||||||
|
t := testing.T{}
|
||||||
|
|
||||||
|
test_128_align(&t)
|
||||||
|
|
||||||
|
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
|
||||||
|
if TEST_fail > 0 {
|
||||||
|
os.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@test
|
||||||
|
test_128_align :: proc(t: ^testing.T) {
|
||||||
|
Danger_Struct :: struct {
|
||||||
|
x: u128,
|
||||||
|
y: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
list := [?]Danger_Struct{{0, 0}, {1, 0}, {2, 0}, {3, 0}}
|
||||||
|
|
||||||
|
expect(t, list[0].x == 0, fmt.tprintf("[0].x (%v) != 0", list[0].x))
|
||||||
|
expect(t, list[0].y == 0, fmt.tprintf("[0].y (%v) != 0", list[0].y))
|
||||||
|
|
||||||
|
expect(t, list[1].x == 1, fmt.tprintf("[1].x (%v) != 1", list[1].x))
|
||||||
|
expect(t, list[1].y == 0, fmt.tprintf("[1].y (%v) != 0", list[1].y))
|
||||||
|
|
||||||
|
expect(t, list[2].x == 2, fmt.tprintf("[2].x (%v) != 2", list[2].x))
|
||||||
|
expect(t, list[2].y == 0, fmt.tprintf("[2].y (%v) != 0", list[2].y))
|
||||||
|
|
||||||
|
expect(t, list[3].x == 3, fmt.tprintf("[3].x (%v) != 3", list[3].x))
|
||||||
|
expect(t, list[3].y == 0, fmt.tprintf("[3].y (%v) != 0", list[3].y))
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
// Intended to contain code that would trigger asan easily if the abi was set up badly.
|
||||||
|
package test_asan
|
||||||
|
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:testing"
|
||||||
|
import "core:os"
|
||||||
|
|
||||||
|
TEST_count := 0
|
||||||
|
TEST_fail := 0
|
||||||
|
|
||||||
|
when ODIN_TEST {
|
||||||
|
expect :: testing.expect
|
||||||
|
log :: testing.log
|
||||||
|
} else {
|
||||||
|
expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
|
||||||
|
TEST_count += 1
|
||||||
|
if !condition {
|
||||||
|
TEST_fail += 1
|
||||||
|
fmt.printf("[%v] %v\n", loc, message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
|
||||||
|
fmt.printf("[%v] ", loc)
|
||||||
|
fmt.printf("log: %v\n", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main :: proc() {
|
||||||
|
t := testing.T{}
|
||||||
|
|
||||||
|
test_12_bytes(&t)
|
||||||
|
test_12_bytes_two(&t)
|
||||||
|
|
||||||
|
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
|
||||||
|
if TEST_fail > 0 {
|
||||||
|
os.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
test_12_bytes :: proc(t: ^testing.T) {
|
||||||
|
internal :: proc() -> (a, b: f32, ok: bool) {
|
||||||
|
return max(f32), 0, true
|
||||||
|
}
|
||||||
|
|
||||||
|
a, b, ok := internal()
|
||||||
|
expect(t, a == max(f32), fmt.tprintf("a (%v) != max(f32)", a))
|
||||||
|
expect(t, b == 0, fmt.tprintf("b (%v) != 0", b))
|
||||||
|
expect(t, ok, fmt.tprintf("ok (%v) != true", ok))
|
||||||
|
}
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
test_12_bytes_two :: proc(t: ^testing.T) {
|
||||||
|
internal :: proc() -> (a: f32, b: int) {
|
||||||
|
return 100., max(int)
|
||||||
|
}
|
||||||
|
|
||||||
|
a, b := internal()
|
||||||
|
expect(t, a == 100., fmt.tprintf("a (%v) != 100.", a))
|
||||||
|
expect(t, b == max(int), fmt.tprintf("b (%v) != max(int)", b))
|
||||||
|
}
|
||||||
Vendored
+1
@@ -34,6 +34,7 @@ foreign lib {
|
|||||||
SemWait :: proc(s: ^sem) -> c.int ---
|
SemWait :: proc(s: ^sem) -> c.int ---
|
||||||
SemTryWait :: proc(s: ^sem) -> c.int ---
|
SemTryWait :: proc(s: ^sem) -> c.int ---
|
||||||
SemWaitTimeout :: proc(s: ^sem, ms: u32) -> c.int ---
|
SemWaitTimeout :: proc(s: ^sem, ms: u32) -> c.int ---
|
||||||
|
SemPost :: proc(s: ^sem) -> c.int ---
|
||||||
SemValue :: proc(s: ^sem) -> u32 ---
|
SemValue :: proc(s: ^sem) -> u32 ---
|
||||||
|
|
||||||
CreateCond :: proc() -> ^cond ---
|
CreateCond :: proc() -> ^cond ---
|
||||||
|
|||||||
Reference in New Issue
Block a user