Removed allocation of AbiType. Separate string arena.

This commit is contained in:
Christoffer Lerno
2022-01-03 12:19:46 +01:00
parent fd1353f0f1
commit 8f2ae41ea5
28 changed files with 290 additions and 238 deletions

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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);
}
/**

View File

@@ -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.

View File

@@ -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:

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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, &params, 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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

@@ -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");