mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
Removed allocation of AbiType. Separate string arena.
This commit is contained in:
@@ -17,10 +17,11 @@ TomlArray *get_array(TomlTable *table, const char *key)
|
||||
return value->value.array;
|
||||
}
|
||||
|
||||
|
||||
static inline const char *copy_toml_string(TomlString *string)
|
||||
{
|
||||
size_t len = string->len;
|
||||
char *new_str = malloc_arena(len + 1);
|
||||
char *new_str = malloc_string(len + 1);
|
||||
memcpy(new_str, string->str, len);
|
||||
new_str[len] = '\0';
|
||||
return new_str;
|
||||
|
||||
@@ -54,7 +54,7 @@ char *i128_to_string(Int128 op, uint64_t base, bool is_signed)
|
||||
*(loc++) = digits[rem.low];
|
||||
op = i128_udiv(op, base_div);
|
||||
} while (!i128_is_zero(op));
|
||||
char *res = malloc_arena((size_t)(loc - buffer + 2));
|
||||
char *res = malloc_string((size_t)(loc - buffer + 2));
|
||||
char *c = res;
|
||||
if (add_minus) *(c++) = '-';
|
||||
while (loc > buffer)
|
||||
|
||||
@@ -11,28 +11,31 @@ typedef enum
|
||||
BY_VAL_SKIP
|
||||
} ByVal;
|
||||
|
||||
static inline ABIArgInfo *abi_arg_by_reg_attr(ABIArgInfo *info);
|
||||
|
||||
bool abi_arg_is_indirect(ABIArgInfo *info);
|
||||
ABIArgInfo *abi_arg_ignore(void);
|
||||
ABIArgInfo *abi_arg_new_direct_pair(AbiType *low_type, AbiType *high_type);
|
||||
ABIArgInfo *abi_arg_new_direct_pair(AbiType low_type, AbiType high_type);
|
||||
ABIArgInfo *abi_arg_new_direct(void);
|
||||
ABIArgInfo *abi_arg_new_direct_by_reg(bool by_reg);
|
||||
ABIArgInfo *abi_arg_new_expand(void);
|
||||
ABIArgInfo *abi_arg_new_direct_int_ext(Type *type_to_extend);
|
||||
ABIArgInfo *abi_arg_new_direct_coerce(AbiType *target_type);
|
||||
ABIArgInfo *abi_arg_new_expand_coerce(AbiType *target_type, unsigned offset);
|
||||
ABIArgInfo *abi_arg_new_expand_coerce_pair(AbiType *first_element, unsigned initial_offset, AbiType *second_element, unsigned padding, bool is_packed);
|
||||
ABIArgInfo *abi_arg_new_direct_int_ext_by_reg(Type *int_to_extend, bool by_reg);
|
||||
ABIArgInfo *abi_arg_new_direct_coerce_bits(BitSize bits);
|
||||
ABIArgInfo *abi_arg_new_direct_coerce_type(Type *type);
|
||||
ABIArgInfo *abi_arg_new_direct_coerce(AbiType type);
|
||||
ABIArgInfo *abi_arg_new_expand_coerce(AbiType target_type, unsigned offset);
|
||||
ABIArgInfo *abi_arg_new_expand_coerce_pair(AbiType first_element, unsigned initial_offset, AbiType second_element, unsigned padding, bool is_packed);
|
||||
ABIArgInfo *abi_arg_new_expand_padded(Type *padding);
|
||||
ABIArgInfo *abi_arg_new_indirect_realigned(AlignSize alignment, Type *by_val_type);
|
||||
ABIArgInfo *abi_arg_new_indirect_by_val(Type *by_val_type);
|
||||
ABIArgInfo *abi_arg_new_indirect_not_by_val(Type *type);
|
||||
|
||||
AlignSize abi_type_abi_alignment(AbiType *type);
|
||||
bool abi_type_is_integer(AbiType *type);
|
||||
bool abi_type_is_float(AbiType *type);
|
||||
AbiType *abi_type_new_plain(Type *type);
|
||||
AbiType *abi_type_new_int_bits(ByteSize bits);
|
||||
TypeSize abi_type_size(AbiType *type);
|
||||
AlignSize abi_type_abi_alignment(AbiType type);
|
||||
bool abi_type_is_integer(AbiType type);
|
||||
bool abi_type_is_float(AbiType type);
|
||||
static inline void abi_type_set_type(AbiType *abi_type, Type *type);
|
||||
static inline AbiType abi_type_get(Type *type);
|
||||
static inline void abi_type_set_int_bits(AbiType *abi_type, ByteSize bits);
|
||||
TypeSize abi_type_size(AbiType type);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -52,10 +55,24 @@ void c_abi_func_create_riscv(FunctionSignature *signature);
|
||||
void c_abi_func_create_wasm(FunctionSignature *signature);
|
||||
|
||||
|
||||
// Implementation
|
||||
static inline ABIArgInfo *abi_arg_by_reg_attr(ABIArgInfo *info)
|
||||
static inline AbiType abi_type_get(Type *type)
|
||||
{
|
||||
info->attributes.by_reg = true;
|
||||
return info;
|
||||
return (AbiType) { .type = type };
|
||||
}
|
||||
|
||||
static inline AbiType abi_type_get_int_bits(BitSize bits)
|
||||
{
|
||||
return (AbiType) { .int_bits_plus_1 = bits + 1 };
|
||||
}
|
||||
|
||||
static inline void abi_type_set_type(AbiType *abi_type, Type *type)
|
||||
{
|
||||
abi_type->type = type;
|
||||
}
|
||||
|
||||
static inline void abi_type_set_int_bits(AbiType *abi_type, ByteSize bits)
|
||||
{
|
||||
assert(bits < UINT32_MAX);
|
||||
abi_type->int_bits_plus_1 = (uintptr_t)bits + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements);
|
||||
static inline Type *type_reduced_from_expr(Expr *expr);
|
||||
static inline bool abi_type_is_type(AbiType type);
|
||||
|
||||
static inline bool abi_type_is_valid(AbiType type);
|
||||
|
||||
static inline Type *type_lowering(Type *type)
|
||||
{
|
||||
@@ -19,4 +22,14 @@ static inline Type *type_reduced_from_expr(Expr *expr)
|
||||
return type_lowering(expr->type);
|
||||
}
|
||||
|
||||
static inline bool abi_type_is_type(AbiType type)
|
||||
{
|
||||
return !(type.int_bits_plus_1 & 0x01);
|
||||
}
|
||||
|
||||
static inline bool abi_type_is_valid(AbiType type)
|
||||
{
|
||||
return type.int_bits_plus_1 != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -520,19 +520,15 @@ static const char **target_expand_source_names(const char** dirs, const char *su
|
||||
{
|
||||
if (name_len == 1 || name[name_len - 2] == '/')
|
||||
{
|
||||
char *path = strdup(name);
|
||||
path[name_len - 1] = '\0';
|
||||
char *path = copy_string(name, name_len - 1);
|
||||
file_add_wildcard_files(&files, path, false, suffix1, suffix2);
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
if (name[name_len - 2] != '*') goto INVALID_NAME;
|
||||
if (name_len == 2 || name[name_len - 3] == '/')
|
||||
{
|
||||
char *path = strdup(name);
|
||||
path[name_len - 2] = '\0';
|
||||
char *path = copy_string(name, name_len - 2);
|
||||
file_add_wildcard_files(&files, path, true, suffix1, suffix2);
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
goto INVALID_NAME;
|
||||
@@ -640,7 +636,7 @@ void compiler_register_public_symbol(Decl *decl)
|
||||
STable *sub_module_space = stable_get(&global_context.qualified_symbols, decl->module->name->module);
|
||||
if (!sub_module_space)
|
||||
{
|
||||
sub_module_space = malloc_arena(sizeof(*sub_module_space));
|
||||
sub_module_space = MALLOC(sizeof(*sub_module_space));
|
||||
stable_init(sub_module_space, 0x100);
|
||||
stable_set(&global_context.qualified_symbols, decl->module->name->module, sub_module_space);
|
||||
}
|
||||
|
||||
@@ -1450,6 +1450,7 @@ typedef struct
|
||||
typedef enum
|
||||
{
|
||||
ABI_ARG_IGNORE,
|
||||
ABI_ARG_DIRECT,
|
||||
ABI_ARG_DIRECT_PAIR,
|
||||
ABI_ARG_DIRECT_COERCE,
|
||||
ABI_ARG_EXPAND_COERCE,
|
||||
@@ -1457,22 +1458,17 @@ typedef enum
|
||||
ABI_ARG_EXPAND,
|
||||
} ABIKind;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ABI_TYPE_PLAIN,
|
||||
ABI_TYPE_INT_BITS
|
||||
} AbiTypeKind;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AbiTypeKind kind : 2;
|
||||
union
|
||||
{
|
||||
Type *type;
|
||||
uint32_t int_bits;
|
||||
uintptr_t int_bits_plus_1;
|
||||
};
|
||||
} AbiType;
|
||||
|
||||
#define ABI_TYPE_EMPTY ((AbiType) { .type = NULL })
|
||||
|
||||
typedef struct ABIArgInfo_
|
||||
{
|
||||
MemberIndex param_index_start : 16;
|
||||
@@ -1495,8 +1491,8 @@ typedef struct ABIArgInfo_
|
||||
} expand;
|
||||
struct
|
||||
{
|
||||
AbiType *lo;
|
||||
AbiType *hi;
|
||||
AbiType lo;
|
||||
AbiType hi;
|
||||
} direct_pair;
|
||||
struct
|
||||
{
|
||||
@@ -1506,16 +1502,16 @@ typedef struct ABIArgInfo_
|
||||
uint8_t hi_index;
|
||||
uint8_t offset_hi;
|
||||
bool packed : 1;
|
||||
AbiType *lo;
|
||||
AbiType *hi;
|
||||
AbiType lo;
|
||||
AbiType hi;
|
||||
} coerce_expand;
|
||||
struct
|
||||
{
|
||||
AbiType *partial_type;
|
||||
AbiType partial_type;
|
||||
};
|
||||
struct
|
||||
{
|
||||
AbiType *type;
|
||||
AbiType type;
|
||||
uint8_t elements : 7;
|
||||
bool prevent_flatten : 1;
|
||||
} direct_coerce;
|
||||
@@ -1614,6 +1610,7 @@ extern const char *kw_mainstub;
|
||||
#define AST_NEW_TOKEN(_kind, _token) new_ast(_kind, source_span_from_token_id((_token).id))
|
||||
|
||||
typedef unsigned char TokenTypeChar;
|
||||
ARENA_DEF(chars, char)
|
||||
ARENA_DEF(ast, Ast)
|
||||
ARENA_DEF(expr, Expr)
|
||||
ARENA_DEF(sourceloc, SourceLocation)
|
||||
@@ -2218,8 +2215,7 @@ static inline TypeInfo *type_info_new_base(Type *type, SourceSpan span)
|
||||
|
||||
static inline Type *type_new(TypeKind kind, const char *name)
|
||||
{
|
||||
Type *type = malloc_arena(sizeof(Type));
|
||||
memset(type, 0, sizeof(Type));
|
||||
Type *type = CALLOCS(Type);
|
||||
type->type_kind = kind;
|
||||
assert(name);
|
||||
type->name = name;
|
||||
|
||||
@@ -1089,7 +1089,7 @@ static inline bool scan_multiline_string(Lexer *lexer)
|
||||
size_t len = scan_multiline_indent(lexer->current, &end, &min_indent);
|
||||
|
||||
// Allocate result
|
||||
char *destination = malloc_arena(len + 1);
|
||||
char *destination = malloc_string(len + 1);
|
||||
|
||||
int line = 0;
|
||||
char c;
|
||||
@@ -1185,7 +1185,7 @@ static inline bool scan_string(Lexer *lexer)
|
||||
}
|
||||
}
|
||||
const char *end = current - 1;
|
||||
char *destination = malloc_arena((size_t)(end - lexer->current + 1));
|
||||
char *destination = malloc_string((size_t)(end - lexer->current + 1));
|
||||
size_t len = 0;
|
||||
while (lexer->current < end)
|
||||
{
|
||||
@@ -1251,7 +1251,7 @@ static inline bool scan_raw_string(Lexer *lexer)
|
||||
const char *current = lexer->lexing_start + 1;
|
||||
const char *end = lexer->current - 1;
|
||||
size_t len = (size_t)(end - current);
|
||||
char *destination = malloc_arena(len + 1);
|
||||
char *destination = malloc_string(len + 1);
|
||||
len = 0;
|
||||
while (current < end)
|
||||
{
|
||||
|
||||
@@ -280,7 +280,7 @@ const char *concat_string_parts(const char **args)
|
||||
{
|
||||
size_needed += strlen(args[i]) + 1;
|
||||
}
|
||||
char *output = malloc_arena(size_needed);
|
||||
char *output = malloc_string(size_needed);
|
||||
char *ptr = output;
|
||||
VECEACH(args, i)
|
||||
{
|
||||
|
||||
@@ -18,55 +18,28 @@ ABIArgInfo *abi_arg_ignore(void)
|
||||
return &info;
|
||||
}
|
||||
|
||||
AbiType *abi_type_new_plain(Type *type)
|
||||
|
||||
|
||||
bool abi_type_is_integer(AbiType type)
|
||||
{
|
||||
AbiType *abi_type = CALLOCS(AbiType);
|
||||
abi_type->kind = ABI_TYPE_PLAIN;
|
||||
abi_type->type = type;
|
||||
return abi_type;
|
||||
return !abi_type_is_type(type) || type_is_integer(type.type);
|
||||
}
|
||||
|
||||
AbiType *abi_type_new_int_bits(ByteSize bits)
|
||||
bool abi_type_is_float(AbiType type)
|
||||
{
|
||||
assert(bits < UINT32_MAX);
|
||||
AbiType *abi_type = CALLOCS(AbiType);
|
||||
abi_type->kind = ABI_TYPE_INT_BITS;
|
||||
abi_type->int_bits = (uint32_t)bits;
|
||||
return abi_type;
|
||||
return abi_type_is_type(type) && type_is_float(type.type);
|
||||
}
|
||||
|
||||
bool abi_type_is_integer(AbiType *type)
|
||||
TypeSize abi_type_size(AbiType type)
|
||||
{
|
||||
return type->kind == ABI_TYPE_INT_BITS || type_is_integer(type->type);
|
||||
if (abi_type_is_type(type)) return type_size(type.type);
|
||||
return (type.int_bits_plus_1 - 1) / 8;
|
||||
}
|
||||
|
||||
bool abi_type_is_float(AbiType *type)
|
||||
AlignSize abi_type_abi_alignment(AbiType type)
|
||||
{
|
||||
return type->kind != ABI_TYPE_INT_BITS && type_is_float(type->type);
|
||||
}
|
||||
|
||||
TypeSize abi_type_size(AbiType *type)
|
||||
{
|
||||
switch (type->kind)
|
||||
{
|
||||
case ABI_TYPE_INT_BITS:
|
||||
return type->int_bits / 8;
|
||||
case ABI_TYPE_PLAIN:
|
||||
return type_size(type->type);
|
||||
}
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
AlignSize abi_type_abi_alignment(AbiType *type)
|
||||
{
|
||||
switch (type->kind)
|
||||
{
|
||||
case ABI_TYPE_INT_BITS:
|
||||
return type_abi_alignment(type_int_unsigned_by_bitsize(next_highest_power_of_2(type->int_bits)));
|
||||
case ABI_TYPE_PLAIN:
|
||||
return type_abi_alignment(type->type);
|
||||
}
|
||||
UNREACHABLE;
|
||||
if (abi_type_is_type(type)) return type_abi_alignment(type.type);
|
||||
return type_abi_alignment(type_int_unsigned_by_bitsize(next_highest_power_of_2(type.int_bits_plus_1 - 1)));
|
||||
}
|
||||
|
||||
bool abi_arg_is_indirect(ABIArgInfo *info)
|
||||
@@ -74,6 +47,7 @@ bool abi_arg_is_indirect(ABIArgInfo *info)
|
||||
switch (info->kind)
|
||||
{
|
||||
case ABI_ARG_IGNORE:
|
||||
case ABI_ARG_DIRECT:
|
||||
case ABI_ARG_DIRECT_COERCE:
|
||||
case ABI_ARG_EXPAND:
|
||||
case ABI_ARG_DIRECT_PAIR:
|
||||
@@ -117,22 +91,27 @@ ABIArgInfo *abi_arg_new_indirect_not_by_val(Type *type)
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
ABIArgInfo *abi_arg_new_direct_int_ext(Type *int_to_extend)
|
||||
{
|
||||
ABIArgInfo *arg_info = abi_arg_new(ABI_ARG_DIRECT_COERCE);
|
||||
return abi_arg_new_direct_int_ext_by_reg(int_to_extend, false);
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_direct_int_ext_by_reg(Type *int_to_extend, bool by_reg)
|
||||
{
|
||||
ABIArgInfo *info = abi_arg_new(ABI_ARG_DIRECT);
|
||||
if (type_is_signed(int_to_extend))
|
||||
{
|
||||
arg_info->attributes.signext = true;
|
||||
info->attributes.signext = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg_info->attributes.zeroext = true;
|
||||
info->attributes.zeroext = true;
|
||||
}
|
||||
return arg_info;
|
||||
info->attributes.by_reg = by_reg;
|
||||
return info;
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_direct_pair(AbiType *low_type, AbiType *high_type)
|
||||
ABIArgInfo *abi_arg_new_direct_pair(AbiType low_type, AbiType high_type)
|
||||
{
|
||||
ABIArgInfo *arg_info = abi_arg_new(ABI_ARG_DIRECT_PAIR);
|
||||
arg_info->direct_pair.hi = high_type;
|
||||
@@ -140,17 +119,25 @@ ABIArgInfo *abi_arg_new_direct_pair(AbiType *low_type, AbiType *high_type)
|
||||
return arg_info;
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_direct_by_reg(bool by_reg)
|
||||
{
|
||||
ABIArgInfo *info = abi_arg_new(ABI_ARG_DIRECT);
|
||||
info->attributes.by_reg = by_reg;
|
||||
return info;
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_direct(void)
|
||||
{
|
||||
return abi_arg_new(ABI_ARG_DIRECT_COERCE);
|
||||
return abi_arg_new_direct_by_reg(false);
|
||||
}
|
||||
|
||||
|
||||
ABIArgInfo *abi_arg_new_expand(void)
|
||||
{
|
||||
return abi_arg_new(ABI_ARG_EXPAND);
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_expand_coerce(AbiType *target_type, unsigned offset)
|
||||
ABIArgInfo *abi_arg_new_expand_coerce(AbiType target_type, unsigned offset)
|
||||
{
|
||||
ABIArgInfo *arg = abi_arg_new(ABI_ARG_EXPAND_COERCE);
|
||||
arg->coerce_expand.packed = offset > 0;
|
||||
@@ -161,7 +148,7 @@ ABIArgInfo *abi_arg_new_expand_coerce(AbiType *target_type, unsigned offset)
|
||||
return arg;
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_expand_coerce_pair(AbiType *first_element, unsigned initial_offset, AbiType *second_element, unsigned padding, bool is_packed)
|
||||
ABIArgInfo *abi_arg_new_expand_coerce_pair(AbiType first_element, unsigned initial_offset, AbiType second_element, unsigned padding, bool is_packed)
|
||||
{
|
||||
ABIArgInfo *arg = abi_arg_new(ABI_ARG_EXPAND_COERCE);
|
||||
arg->coerce_expand.packed = is_packed;
|
||||
@@ -176,11 +163,27 @@ ABIArgInfo *abi_arg_new_expand_coerce_pair(AbiType *first_element, unsigned init
|
||||
return arg;
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_direct_coerce(AbiType *target_type)
|
||||
ABIArgInfo *abi_arg_new_direct_coerce_bits(BitSize bits)
|
||||
{
|
||||
assert(target_type);
|
||||
ABIArgInfo *info = abi_arg_new(ABI_ARG_DIRECT_COERCE);
|
||||
info->direct_coerce.type = target_type;
|
||||
abi_type_set_int_bits(&info->direct_coerce.type, bits);
|
||||
info->direct_coerce.elements = 0;
|
||||
return info;
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_direct_coerce(AbiType type)
|
||||
{
|
||||
assert(abi_type_is_valid(type));
|
||||
ABIArgInfo *info = abi_arg_new(ABI_ARG_DIRECT_COERCE);
|
||||
info->direct_coerce.type = type;
|
||||
info->direct_coerce.elements = 0;
|
||||
return info;
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_direct_coerce_type(Type *type)
|
||||
{
|
||||
ABIArgInfo *info = abi_arg_new(ABI_ARG_DIRECT_COERCE);
|
||||
abi_type_set_type(&info->direct_coerce.type, type);
|
||||
info->direct_coerce.elements = 0;
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ ABIArgInfo *aarch64_classify_argument_type(Type *type)
|
||||
unsigned members = 0;
|
||||
if (type_is_homogenous_aggregate(type, &base, &members))
|
||||
{
|
||||
ABIArgInfo *info = abi_arg_new_direct_coerce(abi_type_new_plain(base));
|
||||
ABIArgInfo *info = abi_arg_new_direct_coerce_type(base);
|
||||
assert(members < 128);
|
||||
info->direct_coerce.elements = (uint8_t)members;
|
||||
return info;
|
||||
@@ -72,7 +72,7 @@ ABIArgInfo *aarch64_classify_argument_type(Type *type)
|
||||
size = aligned_offset(size, alignment);
|
||||
// We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
|
||||
// For aggregates with 16-byte alignment, we use i128.
|
||||
ABIArgInfo *info = abi_arg_new_direct_coerce(abi_type_new_int_bits(alignment * 8));
|
||||
ABIArgInfo *info = abi_arg_new_direct_coerce_bits(alignment * 8);
|
||||
assert(size / alignment < 128);
|
||||
info->direct_coerce.elements = (uint8_t)(size / alignment);
|
||||
return info;
|
||||
@@ -97,7 +97,7 @@ ABIArgInfo *aarch64_classify_return_type(Type *type, bool variadic)
|
||||
// Large vectors by mem.
|
||||
if (type->type_kind == TYPE_VECTOR && size > 16)
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_plain(type));
|
||||
return abi_arg_new_direct_coerce_type(type);
|
||||
}
|
||||
|
||||
if (!type_is_abi_aggregate(type))
|
||||
@@ -131,9 +131,9 @@ ABIArgInfo *aarch64_classify_return_type(Type *type, bool variadic)
|
||||
unsigned aligned_size = aligned_offset(size, 8);
|
||||
if (alignment < 16 && size == 16)
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_plain(type_get_array(type_ulong, size / 8)));
|
||||
return abi_arg_new_direct_coerce_type(type_get_array(type_ulong, size / 8));
|
||||
}
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(aligned_size * 8));
|
||||
return abi_arg_new_direct_coerce_bits(aligned_size * 8);
|
||||
}
|
||||
|
||||
return abi_arg_new_indirect_by_val(type);
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#include "c_abi_internal.h"
|
||||
|
||||
|
||||
static ABIArgInfo *riscv_coerce_and_expand_fpcc_struct(AbiType *field1, unsigned field1_offset, AbiType *field2, unsigned field2_offset)
|
||||
static ABIArgInfo *riscv_coerce_and_expand_fpcc_struct(AbiType field1, unsigned field1_offset, AbiType field2, unsigned field2_offset)
|
||||
{
|
||||
if (!field2)
|
||||
if (!abi_type_is_valid(field2))
|
||||
{
|
||||
return abi_arg_new_expand_coerce(field1, field1_offset);
|
||||
}
|
||||
@@ -32,7 +32,7 @@ static ABIArgInfo *riscv_coerce_and_expand_fpcc_struct(AbiType *field1, unsigned
|
||||
return abi_arg_new_expand_coerce_pair(field1, field1_offset, field2, padding, is_packed);
|
||||
}
|
||||
|
||||
static bool riscv_detect_fpcc_struct_internal(Type *type, unsigned current_offset, AbiType **field1, unsigned *field1_offset, AbiType **field2, unsigned *field2_offset)
|
||||
static bool riscv_detect_fpcc_struct_internal(Type *type, unsigned current_offset, AbiType *field1_ref, unsigned *field1_offset, AbiType *field2_ref, unsigned *field2_offset)
|
||||
{
|
||||
bool is_int = type_is_integer(type);
|
||||
bool is_float = type_is_float(type);
|
||||
@@ -47,16 +47,16 @@ static bool riscv_detect_fpcc_struct_internal(Type *type, unsigned current_offse
|
||||
if (is_float && (size > flen || size < 4)) return false;
|
||||
// Can't be eligible if an integer type was already found (int+int pairs
|
||||
// are not eligible).
|
||||
if (is_int && *field1 && abi_type_is_integer(*field1)) return false;
|
||||
if (!*field1)
|
||||
if (is_int && abi_type_is_valid(*field1_ref) && abi_type_is_integer(*field1_ref)) return false;
|
||||
if (!abi_type_is_valid(*field1_ref))
|
||||
{
|
||||
*field1 = abi_type_new_plain(type);
|
||||
abi_type_set_type(field1_ref, type);
|
||||
*field1_offset = current_offset;
|
||||
return true;
|
||||
}
|
||||
if (!*field2)
|
||||
if (!abi_type_is_valid(*field2_ref))
|
||||
{
|
||||
*field2 = abi_type_new_plain(type);
|
||||
abi_type_set_type(field2_ref, type);
|
||||
*field2_offset = current_offset;
|
||||
return true;
|
||||
}
|
||||
@@ -72,9 +72,9 @@ static bool riscv_detect_fpcc_struct_internal(Type *type, unsigned current_offse
|
||||
{
|
||||
if (!riscv_detect_fpcc_struct_internal(element_type,
|
||||
current_offset,
|
||||
field1,
|
||||
field1_ref,
|
||||
field1_offset,
|
||||
field2,
|
||||
field2_ref,
|
||||
field2_offset)) return false;
|
||||
current_offset += (unsigned)element_size;
|
||||
}
|
||||
@@ -90,33 +90,33 @@ static bool riscv_detect_fpcc_struct_internal(Type *type, unsigned current_offse
|
||||
{
|
||||
Decl *member = members[i];
|
||||
if (!riscv_detect_fpcc_struct_internal(member->type,
|
||||
(unsigned)(current_offset + member->offset),
|
||||
field1,
|
||||
(unsigned)(current_offset + member->offset),
|
||||
field1_ref,
|
||||
field1_offset,
|
||||
field2,
|
||||
field2_ref,
|
||||
field2_offset)) return false;
|
||||
|
||||
}
|
||||
return *field1 != NULL;
|
||||
return abi_type_is_valid(*field1_ref);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool riscv_detect_fpcc_struct(Type *type, AbiType **field1, unsigned *field1_offset, AbiType **field2, unsigned *field2_offset, unsigned *gprs, unsigned *fprs)
|
||||
static bool riscv_detect_fpcc_struct(Type *type, AbiType *field1_ref, unsigned *field1_offset, AbiType *field2_ref, unsigned *field2_offset, unsigned *gprs, unsigned *fprs)
|
||||
{
|
||||
*field1 = NULL;
|
||||
*field2 = NULL;
|
||||
*field1_ref = ABI_TYPE_EMPTY;
|
||||
*field2_ref = ABI_TYPE_EMPTY;
|
||||
*gprs = 0;
|
||||
*fprs = 0;
|
||||
|
||||
bool is_candidate = riscv_detect_fpcc_struct_internal(type, 0, field1, field1_offset, field2, field2_offset);
|
||||
bool is_candidate = riscv_detect_fpcc_struct_internal(type, 0, field1_ref, field1_offset, field2_ref, field2_offset);
|
||||
|
||||
// Not really a candidate if we have a single int but no float.
|
||||
if (*field1 && !*field2 && !abi_type_is_float(*field1)) return false;
|
||||
if (abi_type_is_valid(*field1_ref) && !abi_type_is_valid(*field2_ref) && !abi_type_is_float(*field1_ref)) return false;
|
||||
if (!is_candidate) return false;
|
||||
if (*field1)
|
||||
if (abi_type_is_valid(*field1_ref))
|
||||
{
|
||||
if (abi_type_is_float(*field1))
|
||||
if (abi_type_is_float(*field1_ref))
|
||||
{
|
||||
(*fprs)++;
|
||||
}
|
||||
@@ -125,9 +125,9 @@ static bool riscv_detect_fpcc_struct(Type *type, AbiType **field1, unsigned *fie
|
||||
(*gprs)++;
|
||||
}
|
||||
}
|
||||
if (*field2)
|
||||
if (abi_type_is_valid(*field2_ref))
|
||||
{
|
||||
if (abi_type_is_float(*field2))
|
||||
if (abi_type_is_float(*field2_ref))
|
||||
{
|
||||
(*fprs)++;
|
||||
}
|
||||
@@ -158,8 +158,7 @@ static ABIArgInfo *riscv_classify_argument_type(Type *type, bool is_fixed, unsig
|
||||
|
||||
if (is_fixed && platform_target.riscv.flen && type->type_kind == TYPE_STRUCT)
|
||||
{
|
||||
AbiType *field1 = NULL;
|
||||
AbiType *field2 = NULL;
|
||||
AbiType field1, field2;
|
||||
unsigned offset1 = 0;
|
||||
unsigned offset2 = 0;
|
||||
unsigned needed_gprs;
|
||||
@@ -224,13 +223,13 @@ static ABIArgInfo *riscv_classify_argument_type(Type *type, bool is_fixed, unsig
|
||||
// required, and a 2-field XLen array if only XLen alignment is required.
|
||||
if (size <= xlen)
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(xlen * 8));
|
||||
return abi_arg_new_direct_coerce_bits(xlen * 8);
|
||||
}
|
||||
if (alignment == 2 * platform_target.riscv.xlen)
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(xlen * 16));
|
||||
return abi_arg_new_direct_coerce_bits(xlen * 16);
|
||||
}
|
||||
ABIArgInfo *info = abi_arg_new_direct_coerce(abi_type_new_int_bits(xlen));
|
||||
ABIArgInfo *info = abi_arg_new_direct_coerce_bits(xlen);
|
||||
info->direct_coerce.elements = 2;
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ static ABIArgInfo *wasm_classify_argument_type(Type *type)
|
||||
// could do reasonable-size multiple-field structs too, using getExpand(),
|
||||
// though watch out for things like bitfields.
|
||||
Type *single_type = type_abi_find_single_struct_element(type);
|
||||
if (single_type) return abi_arg_new_direct_coerce(abi_type_new_plain(single_type));
|
||||
if (single_type) return abi_arg_new_direct_coerce_type(single_type);
|
||||
|
||||
// For the experimental multivalue ABI, fully expand all other aggregates
|
||||
/*if (Kind == ABIKind::ExperimentalMV) {
|
||||
@@ -40,7 +40,7 @@ static ABIArgInfo *wasm_classify_return(Type *type)
|
||||
if (type_is_abi_aggregate(type))
|
||||
{
|
||||
Type *single_type = type_abi_find_single_struct_element(type);
|
||||
if (single_type) return abi_arg_new_direct_coerce(abi_type_new_plain(single_type));
|
||||
if (single_type) return abi_arg_new_direct_coerce_type(single_type);
|
||||
/*
|
||||
* // For the experimental multivalue ABI, return all other aggregates
|
||||
if (Kind == ABIKind::ExperimentalMV)
|
||||
|
||||
@@ -63,7 +63,7 @@ ABIArgInfo *win64_classify(Regs *regs, Type *type, bool is_return, bool is_vecto
|
||||
return abi_arg_new_indirect_not_by_val(type);
|
||||
}
|
||||
// Coerce to integer.
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(size * 8));
|
||||
return abi_arg_new_direct_coerce_bits(size * 8);
|
||||
}
|
||||
if (type_is_builtin(type->type_kind))
|
||||
{
|
||||
@@ -76,7 +76,7 @@ ABIArgInfo *win64_classify(Regs *regs, Type *type, bool is_return, bool is_vecto
|
||||
// Pass by val since greater than 8 bytes.
|
||||
if (!is_return) return abi_arg_new_indirect_not_by_val(type);
|
||||
// Make i128 return in XMM0
|
||||
return abi_arg_new_direct_coerce(abi_type_new_plain(type_get_vector(type_long, 2)));
|
||||
return abi_arg_new_direct_coerce_type(type_get_vector(type_long, 2));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -99,8 +99,7 @@ ABIArgInfo *win64_reclassify_hva_arg(Regs *regs, Type *type, ABIArgInfo *info)
|
||||
if (regs->float_regs >= elements)
|
||||
{
|
||||
regs->float_regs -= elements;
|
||||
ABIArgInfo *new_info = abi_arg_new_direct();
|
||||
new_info->attributes.by_reg = true;
|
||||
ABIArgInfo *new_info = abi_arg_new_direct_by_reg(true);
|
||||
return new_info;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ ABIArgInfo *x64_indirect_result(Type *type, unsigned free_int_regs)
|
||||
ByteSize size = type_size(type);
|
||||
if (align <= 8 && size <= 8)
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(size * 8));
|
||||
return abi_arg_new_direct_coerce_bits(size * 8);
|
||||
}
|
||||
}
|
||||
if (align < 8)
|
||||
@@ -512,12 +512,12 @@ bool x64_contains_float_at_offset(Type *type, unsigned offset)
|
||||
return false;
|
||||
}
|
||||
|
||||
AbiType *x64_get_sse_type_at_offset(Type *type, unsigned ir_offset, Type *source_type, unsigned source_offset)
|
||||
static AbiType x64_get_sse_type_at_offset(Type *type, unsigned ir_offset, Type *source_type, unsigned source_offset)
|
||||
{
|
||||
// The only three choices we have are either double, <2 x float>, or float. We
|
||||
// pass as float if the last 4 bytes is just padding. This happens for
|
||||
// structs that contain 3 floats.
|
||||
if (x64_bits_contain_no_user_data(source_type, source_offset + 4, source_offset + 8)) return abi_type_new_plain(type_float);
|
||||
if (x64_bits_contain_no_user_data(source_type, source_offset + 4, source_offset + 8)) return abi_type_get(type_float);
|
||||
|
||||
// We want to pass as <2 x float> if the LLVM IR type contains a float at
|
||||
// offset+0 and offset+4. Walk the LLVM IR type to find out if this is the
|
||||
@@ -525,15 +525,15 @@ AbiType *x64_get_sse_type_at_offset(Type *type, unsigned ir_offset, Type *source
|
||||
if (x64_contains_float_at_offset(type, ir_offset) &&
|
||||
x64_contains_float_at_offset(type, ir_offset + 4))
|
||||
{
|
||||
return abi_type_new_plain(type_get_vector(type_float, 2));
|
||||
return abi_type_get(type_get_vector(type_float, 2));
|
||||
}
|
||||
return abi_type_new_plain(type_double);
|
||||
return abi_type_get(type_double);
|
||||
}
|
||||
|
||||
/**
|
||||
* Based off X86_64ABIInfo::GetINTEGERTypeAtOffset in Clang
|
||||
*/
|
||||
AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_type, unsigned source_offset)
|
||||
AbiType x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_type, unsigned source_offset)
|
||||
{
|
||||
type = type_lowering(type);
|
||||
switch (type->type_kind)
|
||||
@@ -541,7 +541,7 @@ AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_ty
|
||||
case TYPE_U64:
|
||||
case TYPE_I64:
|
||||
case TYPE_POINTER:
|
||||
if (!offset) return abi_type_new_plain(type);
|
||||
if (!offset) return abi_type_get(type);
|
||||
break;
|
||||
case TYPE_BOOL:
|
||||
case TYPE_U8:
|
||||
@@ -555,7 +555,7 @@ AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_ty
|
||||
source_offset + type_size(type),
|
||||
source_offset + 8))
|
||||
{
|
||||
return abi_type_new_plain(type);
|
||||
return abi_type_get(type);
|
||||
}
|
||||
break;
|
||||
case TYPE_STRUCT:
|
||||
@@ -568,12 +568,12 @@ AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_ty
|
||||
break;
|
||||
}
|
||||
case TYPE_ANY:
|
||||
if (offset < 8) return abi_type_new_plain(type_ulong);
|
||||
if (offset < 16) return abi_type_new_plain(type_voidptr);
|
||||
if (offset < 8) return abi_type_get(type_ulong);
|
||||
if (offset < 16) return abi_type_get(type_voidptr);
|
||||
break;
|
||||
case TYPE_SUBARRAY:
|
||||
if (offset < 8) return abi_type_new_plain(type_voidptr);
|
||||
if (offset < 16) return abi_type_new_plain(type_ulong);
|
||||
if (offset < 8) return abi_type_get(type_voidptr);
|
||||
if (offset < 16) return abi_type_get(type_ulong);
|
||||
break;
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
@@ -609,15 +609,15 @@ AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_ty
|
||||
}
|
||||
ByteSize size = type_size(source_type);
|
||||
assert(size != source_offset);
|
||||
if (size - source_offset > 8) return abi_type_new_plain(type_ulong);
|
||||
return abi_type_new_int_bits((size - source_offset) * 8);
|
||||
if (size - source_offset > 8) return abi_type_get(type_ulong);
|
||||
return abi_type_get_int_bits((size - source_offset) * 8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is only called on SSE.
|
||||
*/
|
||||
static AbiType *x64_get_byte_vector_type(Type *type)
|
||||
static AbiType x64_get_byte_vector_type(Type *type)
|
||||
{
|
||||
// Wrapper structs/arrays that only contain vectors are passed just like
|
||||
// vectors; strip them off if present.
|
||||
@@ -632,22 +632,22 @@ static AbiType *x64_get_byte_vector_type(Type *type)
|
||||
if (platform_target.x64.pass_int128_vector_in_mem && type_is_int128(element))
|
||||
{
|
||||
// Convert to u64
|
||||
return abi_type_new_plain(type_get_vector(type_ulong, type_size(type) / 8));
|
||||
return abi_type_get(type_get_vector(type_ulong, type_size(type) / 8));
|
||||
}
|
||||
return abi_type_new_plain(type);
|
||||
return abi_type_get(type);
|
||||
}
|
||||
|
||||
if (type->type_kind == TYPE_F128) return abi_type_new_plain(type);
|
||||
if (type->type_kind == TYPE_F128) return abi_type_get(type);
|
||||
|
||||
unsigned size = type_size(type);
|
||||
|
||||
assert(size == 16 || size == 32 || size == 64);
|
||||
|
||||
// Return a vector type based on the size.
|
||||
return abi_type_new_plain(type_get_vector(type_double, size / 8));
|
||||
return abi_type_get(type_get_vector(type_double, size / 8));
|
||||
}
|
||||
|
||||
static ABIArgInfo *x64_get_argument_pair_return(AbiType *low_type, AbiType *high_type)
|
||||
static ABIArgInfo *x64_get_argument_pair_return(AbiType low_type, AbiType high_type)
|
||||
{
|
||||
TypeSize low_size = abi_type_size(low_type);
|
||||
unsigned hi_start = aligned_offset(low_size, abi_type_abi_alignment(high_type));
|
||||
@@ -668,7 +668,7 @@ ABIArgInfo *x64_classify_return(Type *return_type)
|
||||
assert(hi_class != CLASS_MEMORY || lo_class == CLASS_MEMORY);
|
||||
assert(hi_class != CLASS_SSEUP || lo_class == CLASS_SSE);
|
||||
|
||||
AbiType *result_type = NULL;
|
||||
AbiType result_type = ABI_TYPE_EMPTY;
|
||||
switch (lo_class)
|
||||
{
|
||||
case CLASS_NO_CLASS:
|
||||
@@ -702,7 +702,7 @@ ABIArgInfo *x64_classify_return(Type *return_type)
|
||||
break;
|
||||
}
|
||||
|
||||
AbiType *high_part = NULL;
|
||||
AbiType high_part = ABI_TYPE_EMPTY;
|
||||
switch (hi_class)
|
||||
{
|
||||
case CLASS_MEMORY:
|
||||
@@ -731,10 +731,10 @@ ABIArgInfo *x64_classify_return(Type *return_type)
|
||||
// If a high part was specified, merge it together with the low part. It is
|
||||
// known to pass in the high eightbyte of the result. We do this by forming a
|
||||
// first class struct aggregate with the high and low part: {low, high}
|
||||
if (high_part) return x64_get_argument_pair_return(result_type, high_part);
|
||||
if (abi_type_is_valid(high_part)) return x64_get_argument_pair_return(result_type, high_part);
|
||||
|
||||
if (result_type->kind == ABI_TYPE_PLAIN &&
|
||||
return_type->canonical == result_type->type->canonical)
|
||||
if (abi_type_is_type(result_type) &&
|
||||
return_type->canonical == result_type.type->canonical)
|
||||
{
|
||||
return abi_arg_new_direct();
|
||||
}
|
||||
@@ -762,7 +762,7 @@ static ABIArgInfo *x64_classify_argument_type(Type *type, unsigned free_int_regs
|
||||
assert(hi_class != CLASS_MEMORY || lo_class == CLASS_MEMORY);
|
||||
assert(hi_class != CLASS_SSEUP || lo_class == CLASS_SSE);
|
||||
|
||||
AbiType *result_type = NULL;
|
||||
AbiType result_type = ABI_TYPE_EMPTY;
|
||||
*needed_registers = (Registers) { 0, 0 };
|
||||
|
||||
// Start by checking the lower class.
|
||||
@@ -795,7 +795,7 @@ static ABIArgInfo *x64_classify_argument_type(Type *type, unsigned free_int_regs
|
||||
}
|
||||
|
||||
// At this point we know it's not MEMORY, since that's always handled.
|
||||
AbiType *high_part = NULL;
|
||||
AbiType high_part = ABI_TYPE_EMPTY;
|
||||
switch (hi_class)
|
||||
{
|
||||
case CLASS_MEMORY:
|
||||
@@ -822,11 +822,11 @@ static ABIArgInfo *x64_classify_argument_type(Type *type, unsigned free_int_regs
|
||||
// If a high part was specified, merge it together with the low part. It is
|
||||
// known to pass in the high eightbyte of the result. We do this by forming a
|
||||
// first class struct aggregate with the high and low part: {low, high}
|
||||
if (high_part) return x64_get_argument_pair_return(result_type, high_part);
|
||||
if (abi_type_is_valid(high_part)) return x64_get_argument_pair_return(result_type, high_part);
|
||||
|
||||
if (result_type->kind == ABI_TYPE_PLAIN)
|
||||
if (abi_type_is_type(result_type))
|
||||
{
|
||||
Type *result = result_type->type->canonical;
|
||||
Type *result = result_type.type->canonical;
|
||||
type = type->canonical;
|
||||
if (type == result) return abi_arg_new_direct();
|
||||
if (type_is_integer(type) && type_is_integer(result) && type->builtin.bytesize == result->builtin.bytesize)
|
||||
|
||||
@@ -87,7 +87,8 @@ static ABIArgInfo *create_indirect_return_x86(Type *type, Regs *regs)
|
||||
regs->int_regs--;
|
||||
if (platform_target.x86.is_mcu_api) return info;
|
||||
|
||||
return abi_arg_by_reg_attr(info);
|
||||
info->attributes.by_reg = true;
|
||||
return info;
|
||||
}
|
||||
|
||||
static bool x86_should_return_type_in_reg(Type *type)
|
||||
@@ -182,13 +183,13 @@ ABIArgInfo *x86_classify_return(CallABI call, Regs *regs, Type *type)
|
||||
if (size == 16)
|
||||
{
|
||||
// Special case, convert 128 bit vector to two 64 bit elements.
|
||||
return abi_arg_new_direct_coerce(abi_type_new_plain(type_get_vector(type_long, 2)));
|
||||
return abi_arg_new_direct_coerce_type(type_get_vector(type_long, 2));
|
||||
}
|
||||
// Always return in register if it fits in a general purpose
|
||||
// register, or if it is 64 bits and has a single field.
|
||||
if (size == 1 || size == 2 || size == 4 || (size == 8 && type->vector.len == 1))
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(size * 8));
|
||||
return abi_arg_new_direct_coerce_bits(size * 8);
|
||||
}
|
||||
return create_indirect_return_x86(type, regs);
|
||||
}
|
||||
@@ -221,7 +222,7 @@ ABIArgInfo *x86_classify_return(CallABI call, Regs *regs, Type *type)
|
||||
}
|
||||
}
|
||||
// This is not a single field struct, so we wrap it in an int.
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(size * 8));
|
||||
return abi_arg_new_direct_coerce_bits(size * 8);
|
||||
}
|
||||
return create_indirect_return_x86(type, regs);
|
||||
}
|
||||
@@ -408,9 +409,7 @@ static inline ABIArgInfo *x86_classify_homogenous_aggregate(Regs *regs, Type *ty
|
||||
// don't flatten.
|
||||
if (is_vec_call)
|
||||
{
|
||||
ABIArgInfo *info = abi_arg_new_direct();
|
||||
info->attributes.by_reg = true;
|
||||
return info;
|
||||
return abi_arg_new_direct_by_reg(true);
|
||||
}
|
||||
|
||||
// If it is a builtin, then expansion is not needed.
|
||||
@@ -435,7 +434,7 @@ static inline ABIArgInfo *x86_classify_vector(Regs *regs, Type *type)
|
||||
if (size < 64 && regs->float_regs)
|
||||
{
|
||||
regs->float_regs--;
|
||||
return abi_arg_by_reg_attr(abi_arg_new_direct());
|
||||
return abi_arg_new_direct_by_reg(true);
|
||||
}
|
||||
return x86_create_indirect_result(regs, type, BY_VAL_SKIP);
|
||||
}
|
||||
@@ -445,13 +444,13 @@ static inline ABIArgInfo *x86_classify_vector(Regs *regs, Type *type)
|
||||
{
|
||||
if ((size == 1 || size == 2 || size == 4) || (size == 8 && type->vector.len == 1))
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(size * 8));
|
||||
return abi_arg_new_direct_coerce_bits(size * 8);
|
||||
}
|
||||
}
|
||||
// MMX passed as i64
|
||||
if (x86_is_mmxtype(type))
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(64));
|
||||
return abi_arg_new_direct_coerce_bits(64);
|
||||
}
|
||||
|
||||
// Send as a normal parameter
|
||||
@@ -491,7 +490,7 @@ static inline ABIArgInfo *x86_classify_aggregate(CallABI call, Regs *regs, Type
|
||||
// Here we coerce the aggregate into a struct { i32, i32, ... }
|
||||
// but we do not generate this struct immediately here.
|
||||
unsigned size_in_regs = (size + 3) / 4;
|
||||
ABIArgInfo *info = abi_arg_new_direct_coerce(abi_type_new_int_bits(32));
|
||||
ABIArgInfo *info = abi_arg_new_direct_coerce_bits(32);
|
||||
assert(size_in_regs < 8);
|
||||
info->direct_coerce.elements = (uint8_t)size_in_regs;
|
||||
// Not in reg on MCU
|
||||
@@ -538,15 +537,10 @@ static ABIArgInfo *x86_classify_primitives(CallABI call, Regs *regs, Type *type)
|
||||
|
||||
if (type_is_promotable_integer(type))
|
||||
{
|
||||
ABIArgInfo *info = abi_arg_new_direct_int_ext(type);
|
||||
info->attributes.by_reg = in_reg;
|
||||
return info;
|
||||
return abi_arg_new_direct_int_ext_by_reg(type, in_reg);
|
||||
}
|
||||
|
||||
ABIArgInfo *info = abi_arg_new_direct();
|
||||
info->attributes.by_reg = in_reg;
|
||||
return info;
|
||||
|
||||
return abi_arg_new_direct_by_reg(in_reg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4066,6 +4066,9 @@ void llvm_emit_parameter(GenContext *c, LLVMValueRef **args, ABIArgInfo *info, B
|
||||
vec_add(*args, indirect);
|
||||
return;
|
||||
}
|
||||
case ABI_ARG_DIRECT:
|
||||
vec_add(*args, llvm_value_rvalue_store(c, be_value));
|
||||
return;
|
||||
case ABI_ARG_DIRECT_COERCE:
|
||||
{
|
||||
LLVMTypeRef coerce_type = llvm_get_coerce_type(c, info);
|
||||
@@ -4125,7 +4128,7 @@ void llvm_emit_parameter(GenContext *c, LLVMValueRef **args, ABIArgInfo *info, B
|
||||
AlignSize align;
|
||||
LLVMValueRef gep_first = llvm_emit_struct_gep_raw(c, temp, coerce_type, info->coerce_expand.lo_index, alignment, &align);
|
||||
vec_add(*args, llvm_emit_load_aligned(c, llvm_abi_type(c, info->coerce_expand.lo), gep_first, align, ""));
|
||||
if (info->coerce_expand.hi)
|
||||
if (abi_type_is_valid(info->coerce_expand.hi))
|
||||
{
|
||||
LLVMValueRef gep_second = llvm_emit_struct_gep_raw(c, temp, coerce_type, info->coerce_expand.hi_index, alignment, &align);
|
||||
vec_add(*args, llvm_emit_load_aligned(c, llvm_abi_type(c, info->coerce_expand.hi), gep_second, align, ""));
|
||||
@@ -4351,6 +4354,7 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
case ABI_ARG_DIRECT_PAIR:
|
||||
case ABI_ARG_IGNORE:
|
||||
case ABI_ARG_DIRECT_COERCE:
|
||||
case ABI_ARG_DIRECT:
|
||||
case ABI_ARG_EXPAND_COERCE:
|
||||
break;
|
||||
}
|
||||
@@ -4551,7 +4555,7 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
|
||||
// 15e. If there is only a single field, we simply store the value,
|
||||
// so { lo } set into { pad, lo, pad } -> original type.
|
||||
if (!ret_info->coerce_expand.hi)
|
||||
if (!abi_type_is_valid(ret_info->coerce_expand.hi))
|
||||
{
|
||||
// Here we do a store to call -> lo (leaving the rest undefined)
|
||||
llvm_store_aligned(c, lo, call_value, alignment);
|
||||
@@ -4574,6 +4578,9 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
|
||||
break;
|
||||
}
|
||||
case ABI_ARG_DIRECT:
|
||||
llvm_value_set(result_value, call_value, return_type);
|
||||
break;
|
||||
case ABI_ARG_DIRECT_COERCE:
|
||||
{
|
||||
// 16. A direct coerce, this is basically "call result" bitcast return type.
|
||||
|
||||
@@ -146,7 +146,7 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsig
|
||||
AlignSize element_align;
|
||||
LLVMValueRef gep_first = llvm_emit_struct_gep_raw(c, temp, coerce_type, info->coerce_expand.lo_index, alignment, &element_align);
|
||||
llvm_store_aligned(c, gep_first, llvm_get_next_param(c, index), element_align);
|
||||
if (info->coerce_expand.hi)
|
||||
if (abi_type_is_valid(info->coerce_expand.hi))
|
||||
{
|
||||
LLVMValueRef gep_second = llvm_emit_struct_gep_raw(c, temp, coerce_type, info->coerce_expand.hi_index, alignment, &element_align);
|
||||
llvm_store_aligned(c, gep_second, llvm_get_next_param(c, index), element_align);
|
||||
@@ -174,6 +174,9 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, unsig
|
||||
llvm_store_aligned(c, hi_ptr, llvm_get_next_param(c, index), element_align);
|
||||
return;
|
||||
}
|
||||
case ABI_ARG_DIRECT:
|
||||
llvm_store_aligned_decl(c, decl, llvm_get_next_param(c, index));
|
||||
return;
|
||||
case ABI_ARG_DIRECT_COERCE:
|
||||
{
|
||||
LLVMTypeRef coerce_type = llvm_get_coerce_type(c, info);
|
||||
@@ -310,7 +313,7 @@ void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *failabl
|
||||
lo_val = llvm_emit_load_aligned(c, lo_type, lo, alignment, "");
|
||||
|
||||
// We're done if there's a single field.
|
||||
if (!info->coerce_expand.hi)
|
||||
if (!abi_type_is_valid(info->coerce_expand.hi))
|
||||
{
|
||||
llvm_emit_return_value(c, lo_val);
|
||||
return;
|
||||
@@ -332,6 +335,10 @@ void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *failabl
|
||||
llvm_emit_return_value(c, composite);
|
||||
break;
|
||||
}
|
||||
case ABI_ARG_DIRECT:
|
||||
// The normal return
|
||||
llvm_emit_return_value(c, llvm_value_rvalue_store(c, return_value));
|
||||
return;
|
||||
case ABI_ARG_DIRECT_PAIR:
|
||||
case ABI_ARG_DIRECT_COERCE:
|
||||
{
|
||||
@@ -481,7 +488,7 @@ void llvm_emit_function_body(GenContext *context, Decl *decl)
|
||||
static void llvm_emit_param_attributes(GenContext *c, LLVMValueRef function, ABIArgInfo *info, bool is_return, int index, int last_index)
|
||||
{
|
||||
assert(last_index == index || info->kind == ABI_ARG_DIRECT_PAIR || info->kind == ABI_ARG_IGNORE
|
||||
|| info->kind == ABI_ARG_EXPAND || info->kind == ABI_ARG_DIRECT_COERCE);
|
||||
|| info->kind == ABI_ARG_EXPAND || info->kind == ABI_ARG_DIRECT || info->kind == ABI_ARG_DIRECT_COERCE);
|
||||
|
||||
if (info->attributes.zeroext)
|
||||
{
|
||||
@@ -505,6 +512,7 @@ static void llvm_emit_param_attributes(GenContext *c, LLVMValueRef function, ABI
|
||||
case ABI_ARG_IGNORE:
|
||||
case ABI_ARG_DIRECT_COERCE:
|
||||
case ABI_ARG_DIRECT_PAIR:
|
||||
case ABI_ARG_DIRECT:
|
||||
case ABI_ARG_EXPAND_COERCE:
|
||||
break;
|
||||
case ABI_ARG_INDIRECT:
|
||||
|
||||
@@ -218,7 +218,7 @@ void llvm_value_struct_gep(GenContext *c, BEValue *element, BEValue *struct_poin
|
||||
|
||||
LLVMValueRef llvm_value_rvalue_store(GenContext *c, BEValue *value);
|
||||
|
||||
LLVMTypeRef llvm_abi_type(GenContext *c, AbiType *type);
|
||||
LLVMTypeRef llvm_abi_type(GenContext *c, AbiType type);
|
||||
TypeSize llvm_abi_size(GenContext *c, LLVMTypeRef type);
|
||||
BitSize llvm_bitsize(GenContext *c, LLVMTypeRef type);
|
||||
AlignSize llvm_abi_alignment(GenContext *c, LLVMTypeRef type);
|
||||
|
||||
@@ -183,7 +183,7 @@ static inline void add_func_type_param(GenContext *context, Type *param_type, AB
|
||||
break;
|
||||
case ABI_ARG_EXPAND_COERCE:
|
||||
vec_add(*params, llvm_abi_type(context, arg_info->coerce_expand.lo));
|
||||
if (arg_info->coerce_expand.hi)
|
||||
if (abi_type_is_valid(arg_info->coerce_expand.hi))
|
||||
{
|
||||
vec_add(*params, llvm_abi_type(context, arg_info->coerce_expand.hi));
|
||||
}
|
||||
@@ -197,10 +197,13 @@ static inline void add_func_type_param(GenContext *context, Type *param_type, AB
|
||||
vec_add(*params, llvm_get_type(context, arg_info->expand.padding_type));
|
||||
}
|
||||
break;
|
||||
case ABI_ARG_DIRECT:
|
||||
vec_add(*params, llvm_get_type(context, param_type));
|
||||
break;
|
||||
case ABI_ARG_DIRECT_COERCE:
|
||||
{
|
||||
// Normal direct.
|
||||
if (!arg_info->direct_coerce.type)
|
||||
if (!abi_type_is_valid(arg_info->direct_coerce.type))
|
||||
{
|
||||
vec_add(*params, llvm_get_type(context, param_type));
|
||||
break;
|
||||
@@ -253,7 +256,7 @@ LLVMTypeRef llvm_func_type(GenContext *context, Type *type)
|
||||
case ABI_ARG_EXPAND_COERCE:
|
||||
{
|
||||
LLVMTypeRef lo = llvm_abi_type(context, ret_arg_info->direct_pair.lo);
|
||||
if (!ret_arg_info->direct_pair.hi)
|
||||
if (!abi_type_is_valid(ret_arg_info->direct_pair.hi))
|
||||
{
|
||||
return_type = lo;
|
||||
break;
|
||||
@@ -272,6 +275,9 @@ LLVMTypeRef llvm_func_type(GenContext *context, Type *type)
|
||||
return_type = llvm_get_twostruct(context, lo, hi);
|
||||
break;
|
||||
}
|
||||
case ABI_ARG_DIRECT:
|
||||
return_type = llvm_get_type(context, real_return_type);
|
||||
break;
|
||||
case ABI_ARG_DIRECT_COERCE:
|
||||
assert(!abi_info_should_flatten(ret_arg_info));
|
||||
return_type = llvm_get_coerce_type(context, ret_arg_info);
|
||||
@@ -395,7 +401,7 @@ LLVMTypeRef llvm_get_coerce_type(GenContext *c, ABIArgInfo *arg_info)
|
||||
{
|
||||
elements[element_index++] = LLVMArrayType(llvm_get_type(c, type_char), arg_info->coerce_expand.padding_hi);
|
||||
}
|
||||
if (arg_info->coerce_expand.hi)
|
||||
if (abi_type_is_valid(arg_info->coerce_expand.hi))
|
||||
{
|
||||
elements[element_index++] = llvm_abi_type(c, arg_info->coerce_expand.hi);
|
||||
}
|
||||
@@ -404,7 +410,8 @@ LLVMTypeRef llvm_get_coerce_type(GenContext *c, ABIArgInfo *arg_info)
|
||||
|
||||
if (arg_info->kind == ABI_ARG_DIRECT_COERCE)
|
||||
{
|
||||
if (!arg_info->direct_coerce.type) return NULL;
|
||||
assert(abi_type_is_valid(arg_info->direct_coerce.type));
|
||||
if (!abi_type_is_valid(arg_info->direct_coerce.type)) return NULL;
|
||||
LLVMTypeRef coerce_type = llvm_abi_type(c, arg_info->direct_coerce.type);
|
||||
if (arg_info->direct_coerce.elements < 2U) return coerce_type;
|
||||
LLVMTypeRef *refs = MALLOC(sizeof(LLVMValueRef) * arg_info->direct_coerce.elements);
|
||||
@@ -420,6 +427,8 @@ LLVMTypeRef llvm_get_coerce_type(GenContext *c, ABIArgInfo *arg_info)
|
||||
LLVMTypeRef hi = llvm_abi_type(c, arg_info->direct_pair.hi);
|
||||
return llvm_get_twostruct(c, lo, hi);
|
||||
}
|
||||
|
||||
assert(arg_info->kind != ABI_ARG_DIRECT);
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
@@ -429,14 +438,8 @@ LLVMTypeRef llvm_get_twostruct(GenContext *context, LLVMTypeRef lo, LLVMTypeRef
|
||||
return LLVMStructTypeInContext(context->context, types, 2, false);
|
||||
}
|
||||
|
||||
LLVMTypeRef llvm_abi_type(GenContext *c, AbiType *type)
|
||||
LLVMTypeRef llvm_abi_type(GenContext *c, AbiType type)
|
||||
{
|
||||
switch (type->kind)
|
||||
{
|
||||
case ABI_TYPE_PLAIN:
|
||||
return llvm_get_type(c, type->type);
|
||||
case ABI_TYPE_INT_BITS:
|
||||
return LLVMIntTypeInContext(c->context, type->int_bits);
|
||||
}
|
||||
UNREACHABLE
|
||||
if (abi_type_is_type(type)) return llvm_get_type(c, type.type);
|
||||
return LLVMIntTypeInContext(c->context, type.int_bits_plus_1 - 1);
|
||||
}
|
||||
|
||||
@@ -640,6 +640,8 @@ static Expr *parse_call_expr(Context *context, Expr *left)
|
||||
Decl **body_args = NULL;
|
||||
if (!TOKEN_IS(TOKEN_RPAREN))
|
||||
{
|
||||
// Pick a modest guess.
|
||||
params = VECNEW(Expr*, 4);
|
||||
if (!parse_arg_list(context, ¶ms, TOKEN_RPAREN, &unsplat)) return poisoned_expr;
|
||||
}
|
||||
if (try_consume(context, TOKEN_EOS) && parse_next_is_type(context))
|
||||
@@ -1245,7 +1247,7 @@ static Expr *parse_bytes_expr(Context *context, Expr *left)
|
||||
len += TOKDATA(tok)->len;
|
||||
tok.index++;
|
||||
}
|
||||
char *data = len > 0 ? malloc_arena(len) : NULL;
|
||||
char *data = len > 0 ? MALLOC(len) : NULL;
|
||||
char *data_current = data;
|
||||
|
||||
Expr *expr_bytes = EXPR_NEW_TOKEN(EXPR_CONST, context->lex.tok);
|
||||
@@ -1443,7 +1445,7 @@ static Expr *parse_string_literal(Context *context, Expr *left)
|
||||
while (TOKEN_IS(TOKEN_STRING))
|
||||
{
|
||||
data = TOKDATA(context->lex.tok);
|
||||
char *buffer = malloc_arena(len + data->strlen + 1);
|
||||
char *buffer = malloc_string(len + data->strlen + 1);
|
||||
memcpy(buffer, str, len);
|
||||
memcpy(buffer + len, data->string, data->strlen);
|
||||
len += data->strlen;
|
||||
|
||||
@@ -248,9 +248,7 @@ const char *symtab_add(const char *symbol, uint32_t len, uint32_t fnv1hash, Toke
|
||||
{
|
||||
FATAL_ERROR("Symtab exceeded capacity, please increase --symtab.");
|
||||
}
|
||||
char *copy = MALLOC(len + 1);
|
||||
memcpy(copy, symbol, len);
|
||||
copy[len] = '\0';
|
||||
char *copy = copy_string(symbol, len);
|
||||
entry->value = copy;
|
||||
entry->key_len = len;
|
||||
entry->hash = fnv1hash;
|
||||
@@ -300,7 +298,7 @@ static inline void stable_resize(STable *table)
|
||||
{
|
||||
ASSERT(table->capacity < MAX_HASH_SIZE, "Table size too large, exceeded max hash size");
|
||||
|
||||
uint32_t new_capacity = table->capacity ? (table->capacity << 1u) : 16u;
|
||||
uint32_t new_capacity = table->capacity ? (table->capacity << 2u) : 16u;
|
||||
SEntry *new_data = CALLOC(new_capacity * sizeof(SEntry));
|
||||
table->count = 0;
|
||||
uint32_t len = table->capacity;
|
||||
|
||||
@@ -1232,7 +1232,7 @@ void target_setup(BuildTarget *target)
|
||||
|
||||
LLVMTargetMachineRef machine = llvm_target_machine_create();
|
||||
char *target_triple = LLVMGetTargetMachineTriple(machine);
|
||||
platform_target.target_triple = strdup(target_triple);
|
||||
platform_target.target_triple = copy_string(target_triple, strlen(target_triple));
|
||||
LLVMDisposeMessage(target_triple);
|
||||
LLVMDisposeTargetMachine(machine);
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "errors.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define NO_ARENA 0
|
||||
#define MAX_VECTOR_WIDTH 65536
|
||||
#define MAX_ARRAY_SIZE INT64_MAX
|
||||
#define MAX_IDENTIFIER_LENGTH 31
|
||||
|
||||
@@ -107,18 +107,17 @@ bool filenamesplit(const char *path, char** filename_ptr, char** directory_ptr)
|
||||
if (file_len == 1 && path[0] == '.') return false;
|
||||
if (file_len == 2 && path[0] == '.' && path[1] == '.') return false;
|
||||
if (!file_len) return false;
|
||||
*filename_ptr = strcopy(&path[len - file_len], file_len);
|
||||
*filename_ptr = copy_string(&path[len - file_len], file_len);
|
||||
if (!directory_ptr) return true;
|
||||
if (file_len < len)
|
||||
{
|
||||
size_t dir_len = len - file_len;
|
||||
*directory_ptr = strcopy(path, dir_len - 1);
|
||||
*directory_ptr = copy_string(path, dir_len - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*directory_ptr = malloc_arena(2);
|
||||
*directory_ptr = calloc_string(2);
|
||||
(*directory_ptr)[0] = '.';
|
||||
(*directory_ptr)[1] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -153,7 +152,7 @@ char *read_file(const char *path, size_t *return_size)
|
||||
*return_size = file_size;
|
||||
rewind(file);
|
||||
|
||||
char *buffer = (char *)malloc_arena(file_size + 1);
|
||||
char *buffer = (char *)MALLOC(file_size + 1);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
error_exit("Not enough memory to read \"%s\".\n", path);
|
||||
|
||||
@@ -39,6 +39,9 @@ void *ccalloc(size_t size, size_t elements);
|
||||
void memory_init(void);
|
||||
void memory_release();
|
||||
void *calloc_arena(size_t mem);
|
||||
char *calloc_string(size_t len);
|
||||
char *copy_string(const char *start, size_t str_len);
|
||||
#define malloc_string calloc_string
|
||||
#define malloc_arena calloc_arena
|
||||
void free_arena(void);
|
||||
void print_arena_status(void);
|
||||
@@ -48,10 +51,22 @@ void taskqueue_add(TaskQueueRef queue, Task *task);
|
||||
void taskqueue_destroy(TaskQueueRef queue);
|
||||
void taskqueue_wait_for_completion(TaskQueueRef queue);
|
||||
|
||||
#if MEM_PRINT
|
||||
#define MALLOC(mem) (printf("Alloc at %s %zu\n", __FUNCTION__, (size_t)(mem)), malloc_arena(mem))
|
||||
#define MALLOCS(type) (printf("calloc at %s %zu\n", __FUNCTION__, sizeof(type)), malloc_arena(sizeof(type)))
|
||||
#define CALLOC(mem) (printf("calloc at %s %zu\n", __FUNCTION__, (size_t)(mem)), calloc_arena(mem))
|
||||
#define CALLOCS(type) (printf("calloc at %s %zu\n", __FUNCTION__, sizeof(type)), calloc_arena(sizeof(type)))
|
||||
#elif NO_ARENA
|
||||
#define MALLOC(mem) malloc(mem)
|
||||
#define MALLOCS(type) malloc(sizeof(type))
|
||||
#define CALLOC(mem) calloc(16 * (((mem) + 15) / 16), 16)
|
||||
#define CALLOCS(type) calloc(1, sizeof(type))
|
||||
#else
|
||||
#define MALLOC(mem) malloc_arena(mem)
|
||||
#define MALLOCS(type) malloc_arena(sizeof(type))
|
||||
#define CALLOC(mem) calloc_arena(mem)
|
||||
#define CALLOCS(type) calloc_arena(sizeof(type))
|
||||
#endif
|
||||
|
||||
#define NUMBER_CHAR_CASE '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
|
||||
|
||||
@@ -482,7 +497,7 @@ typedef struct StringSlice_
|
||||
|
||||
char *strcat_arena(const char *a, const char *b);
|
||||
char *strformat(const char *var, ...) __printflike(1, 2);
|
||||
char *strcopy(const char *start, size_t len);
|
||||
char *stringcopy(const char *start, size_t len);
|
||||
StringSlice strnexttok(StringSlice *slice, char separator);
|
||||
static inline bool slicestrcmp(StringSlice slice, const char *other)
|
||||
{
|
||||
@@ -519,7 +534,6 @@ void slicetrim(StringSlice *slice);
|
||||
|
||||
int asprintf(char **strp, const char *fmt, ...);
|
||||
int vasprintf(char **strp, const char *fmt, va_list ap);
|
||||
char *strndup(const char *s, size_t len);
|
||||
|
||||
char *realpath(const char *path, char *resolved_path);
|
||||
|
||||
|
||||
@@ -11,16 +11,35 @@
|
||||
|
||||
static int allocations_done;
|
||||
static Vmem arena;
|
||||
static Vmem char_arena;
|
||||
|
||||
void memory_init(void)
|
||||
{
|
||||
vmem_init(&arena, 4 * 1024);
|
||||
vmem_init(&char_arena, 4 * 1024);
|
||||
allocations_done = 0;
|
||||
}
|
||||
|
||||
void memory_release()
|
||||
{
|
||||
vmem_free(&arena);
|
||||
vmem_free(&char_arena);
|
||||
}
|
||||
|
||||
|
||||
void *calloc_string(size_t len)
|
||||
{
|
||||
assert(len > 0);
|
||||
allocations_done++;
|
||||
return vmem_alloc(&char_arena, len);
|
||||
}
|
||||
|
||||
char *copy_string(const char *start, size_t str_len)
|
||||
{
|
||||
char *dst = calloc_string(str_len + 1);
|
||||
memcpy(dst, start, str_len);
|
||||
// No need to set the end
|
||||
return dst;
|
||||
}
|
||||
|
||||
// Simple bump allocator with buckets.
|
||||
@@ -38,6 +57,7 @@ void print_arena_status(void)
|
||||
printf("-- ARENA INFO -- \n");
|
||||
printf(" * Memory used: %zu Kb\n", arena.allocated / 1024);
|
||||
printf(" * Allocations: %d\n", allocations_done);
|
||||
printf(" * String memory used: %zu Kb\n", char_arena.allocated / 1024);
|
||||
}
|
||||
|
||||
void free_arena(void)
|
||||
|
||||
@@ -16,7 +16,7 @@ char *strformat(const char *var, ...)
|
||||
va_end(list);
|
||||
if (len < 1) return "";
|
||||
va_start(list, var);
|
||||
char *buffer = malloc_arena((uint32_t)len + 1);
|
||||
char *buffer = malloc_string((uint32_t)len + 1);
|
||||
int new_len = vsnprintf(buffer, len + 1, var, list);
|
||||
va_end(list);
|
||||
assert(len == new_len);
|
||||
@@ -59,19 +59,12 @@ void slicetrim(StringSlice *slice)
|
||||
}
|
||||
|
||||
|
||||
char *strcopy(const char *start, size_t len)
|
||||
{
|
||||
char *buffer = malloc_arena(len + 1);
|
||||
memcpy(buffer, start, len);
|
||||
buffer[len] = '\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char *strcat_arena(const char *a, const char *b)
|
||||
{
|
||||
unsigned a_len = (unsigned)strlen(a);
|
||||
unsigned b_len = (unsigned)strlen(b);
|
||||
char *buffer = malloc_arena(a_len + b_len + 1);
|
||||
char *buffer = malloc_string(a_len + b_len + 1);
|
||||
memcpy(buffer, a, a_len);
|
||||
memcpy(buffer + a_len, b, b_len);
|
||||
buffer[a_len + b_len] = '\0';
|
||||
@@ -119,16 +112,5 @@ int vasprintf(char** ret, const char* fmt, va_list args) {
|
||||
return length;
|
||||
}
|
||||
|
||||
char *strndup(const char *s, size_t n)
|
||||
{
|
||||
n = strnlen(s, n);
|
||||
char *t = ccalloc(n + 1, 1);
|
||||
if (NULL != t)
|
||||
{
|
||||
memcpy(t, s, n);
|
||||
t[n] = '\0';
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -52,7 +52,7 @@ TaskQueueRef taskqueue_create(int threads)
|
||||
{
|
||||
assert(threads > 0);
|
||||
TaskQueue *queue = CALLOCS(TaskQueue);
|
||||
queue->threads = malloc_arena(sizeof(pthread_t) * (unsigned)threads);
|
||||
queue->threads = MALLOC(sizeof(pthread_t) * (unsigned)threads);
|
||||
queue->thread_count = threads;
|
||||
if (pthread_mutex_init(&queue->lock, NULL)) error_exit("Failed to set up mutex");
|
||||
if (pthread_cond_init(&queue->notify, NULL)) error_exit("Failed to set up cond");
|
||||
|
||||
Reference in New Issue
Block a user