mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-24 07:15:21 +00:00
Begin work for bit_set[...; [N]T] (not working)
This commit is contained in:
@@ -440,6 +440,8 @@ struct BuildContext {
|
||||
bool cached;
|
||||
BuildCacheData build_cache_data;
|
||||
|
||||
bool internal_no_inline;
|
||||
|
||||
bool no_threaded_checker;
|
||||
|
||||
bool show_debug_messages;
|
||||
|
||||
@@ -9947,10 +9947,14 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
|
||||
}
|
||||
Type *et = base_type(t->BitSet.elem);
|
||||
isize field_count = 0;
|
||||
if (et->kind == Type_Enum) {
|
||||
if (et != nullptr && et->kind == Type_Enum) {
|
||||
field_count = et->Enum.fields.count;
|
||||
}
|
||||
|
||||
if (is_type_array(bit_set_to_int(t))) {
|
||||
is_constant = false;
|
||||
}
|
||||
|
||||
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||
error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed");
|
||||
is_constant = false;
|
||||
|
||||
@@ -939,22 +939,6 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam
|
||||
enum_type->Enum.max_value_index = max_value_index;
|
||||
}
|
||||
|
||||
gb_internal bool is_valid_bit_field_backing_type(Type *type) {
|
||||
if (type == nullptr) {
|
||||
return false;
|
||||
}
|
||||
type = base_type(type);
|
||||
if (is_type_untyped(type)) {
|
||||
return false;
|
||||
}
|
||||
if (is_type_integer(type)) {
|
||||
return true;
|
||||
}
|
||||
if (type->kind == Type_Array) {
|
||||
return is_type_integer(type->Array.elem);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, Type *named_type, Ast *node) {
|
||||
ast_node(bf, BitFieldType, node);
|
||||
@@ -1268,11 +1252,14 @@ gb_internal void check_bit_set_type(CheckerContext *c, Type *type, Type *named_t
|
||||
Type *t = default_type(lhs.type);
|
||||
if (bs->underlying != nullptr) {
|
||||
Type *u = check_type(c, bs->underlying);
|
||||
// if (!is_valid_bit_field_backing_type(u)) {
|
||||
if (!is_type_integer(u)) {
|
||||
gbString ts = type_to_string(u);
|
||||
error(bs->underlying, "Expected an underlying integer for the bit set, got %s", ts);
|
||||
gb_string_free(ts);
|
||||
return;
|
||||
if (!is_valid_bit_field_backing_type(u)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
type->BitSet.underlying = u;
|
||||
}
|
||||
|
||||
@@ -434,6 +434,8 @@ gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, Bi
|
||||
}
|
||||
}
|
||||
|
||||
GB_ASSERT(!is_type_array(original_type));
|
||||
|
||||
LLVMValueRef value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), cast(unsigned)((sz+7)/8), cast(u64 *)rop);
|
||||
if (big_int_is_neg(a)) {
|
||||
value = LLVMConstNeg(value);
|
||||
|
||||
@@ -296,12 +296,6 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu
|
||||
GB_ASSERT(vector_type0 == vector_type1);
|
||||
LLVMTypeRef vector_type = vector_type0;
|
||||
|
||||
LLVMValueRef lhs_vp = LLVMBuildPointerCast(p->builder, lhs_ptr.value, LLVMPointerType(vector_type, 0), "");
|
||||
LLVMValueRef rhs_vp = LLVMBuildPointerCast(p->builder, rhs_ptr.value, LLVMPointerType(vector_type, 0), "");
|
||||
LLVMValueRef x = LLVMBuildLoad2(p->builder, vector_type, lhs_vp, "");
|
||||
LLVMValueRef y = LLVMBuildLoad2(p->builder, vector_type, rhs_vp, "");
|
||||
LLVMValueRef z = nullptr;
|
||||
|
||||
Type *integral_type = base_type(elem_type);
|
||||
if (is_type_simd_vector(integral_type)) {
|
||||
integral_type = core_array_type(integral_type);
|
||||
@@ -311,8 +305,18 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu
|
||||
case Token_Add: op = Token_Or; break;
|
||||
case Token_Sub: op = Token_AndNot; break;
|
||||
}
|
||||
Type *u = bit_set_to_int(type);
|
||||
if (is_type_array(u)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LLVMValueRef lhs_vp = LLVMBuildPointerCast(p->builder, lhs_ptr.value, LLVMPointerType(vector_type, 0), "");
|
||||
LLVMValueRef rhs_vp = LLVMBuildPointerCast(p->builder, rhs_ptr.value, LLVMPointerType(vector_type, 0), "");
|
||||
LLVMValueRef x = LLVMBuildLoad2(p->builder, vector_type, lhs_vp, "");
|
||||
LLVMValueRef y = LLVMBuildLoad2(p->builder, vector_type, rhs_vp, "");
|
||||
LLVMValueRef z = nullptr;
|
||||
|
||||
if (is_type_float(integral_type)) {
|
||||
switch (op) {
|
||||
case Token_Add:
|
||||
@@ -1286,6 +1290,14 @@ handle_op:;
|
||||
case Token_Add: op = Token_Or; break;
|
||||
case Token_Sub: op = Token_AndNot; break;
|
||||
}
|
||||
Type *u = bit_set_to_int(type);
|
||||
if (is_type_array(u)) {
|
||||
lhs.type = u;
|
||||
rhs.type = u;
|
||||
res = lb_emit_arith(p, op, lhs, rhs, u);
|
||||
res.type = type;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
Type *integral_type = type;
|
||||
@@ -1441,6 +1453,7 @@ gb_internal lbValue lb_build_binary_in(lbProcedure *p, lbValue left, lbValue rig
|
||||
GB_ASSERT(are_types_identical(left.type, key_type));
|
||||
|
||||
Type *it = bit_set_to_int(rt);
|
||||
|
||||
left = lb_emit_conv(p, left, it);
|
||||
if (is_type_different_to_arch_endianness(it)) {
|
||||
left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it));
|
||||
@@ -2054,6 +2067,26 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
|
||||
}
|
||||
}
|
||||
|
||||
// bit_set <-> backing type
|
||||
if (is_type_bit_set(src)) {
|
||||
Type *backing = bit_set_to_int(src);
|
||||
if (are_types_identical(backing, dst)) {
|
||||
lbValue res = {};
|
||||
res.type = t;
|
||||
res.value = value.value;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
if (is_type_bit_set(dst)) {
|
||||
Type *backing = bit_set_to_int(dst);
|
||||
if (are_types_identical(src, backing)) {
|
||||
lbValue res = {};
|
||||
res.type = t;
|
||||
res.value = value.value;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pointer <-> uintptr
|
||||
if (is_type_pointer(src) && is_type_uintptr(dst)) {
|
||||
@@ -2951,13 +2984,32 @@ gb_internal lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind,
|
||||
case Type_Pointer:
|
||||
case Type_MultiPointer:
|
||||
case Type_Proc:
|
||||
case Type_BitSet:
|
||||
if (op_kind == Token_CmpEq) {
|
||||
res.value = LLVMBuildIsNull(p->builder, x.value, "");
|
||||
} else if (op_kind == Token_NotEq) {
|
||||
res.value = LLVMBuildIsNotNull(p->builder, x.value, "");
|
||||
}
|
||||
return res;
|
||||
case Type_BitSet:
|
||||
{
|
||||
Type *u = bit_set_to_int(bt);
|
||||
if (is_type_array(u)) {
|
||||
auto args = array_make<lbValue>(permanent_allocator(), 2);
|
||||
lbValue lhs = lb_address_from_load_or_generate_local(p, x);
|
||||
args[0] = lb_emit_conv(p, lhs, t_rawptr);
|
||||
args[1] = lb_const_int(p->module, t_int, type_size_of(t));
|
||||
lbValue val = lb_emit_runtime_call(p, "memory_compare_zero", args);
|
||||
lbValue res = lb_emit_comp(p, op_kind, val, lb_const_int(p->module, t_int, 0));
|
||||
return res;
|
||||
} else {
|
||||
if (op_kind == Token_CmpEq) {
|
||||
res.value = LLVMBuildIsNull(p->builder, x.value, "");
|
||||
} else if (op_kind == Token_NotEq) {
|
||||
res.value = LLVMBuildIsNotNull(p->builder, x.value, "");
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
case Type_Slice:
|
||||
{
|
||||
@@ -4878,29 +4930,47 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
|
||||
case Type_BitSet: {
|
||||
i64 sz = type_size_of(type);
|
||||
if (cl->elems.count > 0 && sz > 0) {
|
||||
lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
|
||||
|
||||
lbValue lower = lb_const_value(p->module, t_int, exact_value_i64(bt->BitSet.lower));
|
||||
for (Ast *elem : cl->elems) {
|
||||
GB_ASSERT(elem->kind != Ast_FieldValue);
|
||||
|
||||
if (lb_is_elem_const(elem, et)) {
|
||||
continue;
|
||||
Type *backing = bit_set_to_int(type);
|
||||
if (is_type_array(backing)) {
|
||||
GB_PANIC("TODO: bit_set [N]T");
|
||||
Type *base_it = core_array_type(backing);
|
||||
i64 bits_per_elem = 8*type_size_of(base_it);
|
||||
gb_unused(bits_per_elem);
|
||||
lbValue one = lb_const_value(p->module, t_i64, exact_value_i64(1));
|
||||
for (Ast *elem : cl->elems) {
|
||||
GB_ASSERT(elem->kind != Ast_FieldValue);
|
||||
lbValue expr = lb_build_expr(p, elem);
|
||||
GB_ASSERT(expr.type->kind != Type_Tuple);
|
||||
|
||||
lbValue e = lb_emit_conv(p, expr, t_i64);
|
||||
e = lb_emit_arith(p, Token_Sub, e, lower, t_i64);
|
||||
// lbValue idx = lb_emit_arith(p, Token_Div, e, bits_per_elem, t_i64);
|
||||
// lbValue val = lb_emit_arith(p, Token_Div, e, bits_per_elem, t_i64);
|
||||
}
|
||||
|
||||
lbValue expr = lb_build_expr(p, elem);
|
||||
GB_ASSERT(expr.type->kind != Type_Tuple);
|
||||
|
||||
} else {
|
||||
Type *it = bit_set_to_int(bt);
|
||||
lbValue one = lb_const_value(p->module, it, exact_value_i64(1));
|
||||
lbValue e = lb_emit_conv(p, expr, it);
|
||||
e = lb_emit_arith(p, Token_Sub, e, lower, it);
|
||||
e = lb_emit_arith(p, Token_Shl, one, e, it);
|
||||
for (Ast *elem : cl->elems) {
|
||||
GB_ASSERT(elem->kind != Ast_FieldValue);
|
||||
|
||||
lbValue old_value = lb_emit_transmute(p, lb_addr_load(p, v), it);
|
||||
lbValue new_value = lb_emit_arith(p, Token_Or, old_value, e, it);
|
||||
new_value = lb_emit_transmute(p, new_value, type);
|
||||
lb_addr_store(p, v, new_value);
|
||||
if (lb_is_elem_const(elem, et)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lbValue expr = lb_build_expr(p, elem);
|
||||
GB_ASSERT(expr.type->kind != Type_Tuple);
|
||||
|
||||
lbValue e = lb_emit_conv(p, expr, it);
|
||||
e = lb_emit_arith(p, Token_Sub, e, lower, it);
|
||||
e = lb_emit_arith(p, Token_Shl, one, e, it);
|
||||
|
||||
lbValue old_value = lb_emit_transmute(p, lb_addr_load(p, v), it);
|
||||
lbValue new_value = lb_emit_arith(p, Token_Or, old_value, e, it);
|
||||
new_value = lb_emit_transmute(p, new_value, type);
|
||||
lb_addr_store(p, v, new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1023,6 +1023,8 @@ gb_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
|
||||
LLVMTypeRef rawptr_type = lb_type(p->module, t_rawptr);
|
||||
LLVMTypeRef rawptr_ptr_type = LLVMPointerType(rawptr_type, 0);
|
||||
LLVMBuildStore(p->builder, LLVMConstNull(rawptr_type), LLVMBuildBitCast(p->builder, ptr.value, rawptr_ptr_type, ""));
|
||||
} else if (is_type_bit_set(a)) {
|
||||
lb_mem_zero_ptr(p, ptr.value, a, 1);
|
||||
} else if (lb_sizeof(src_t) <= lb_max_zero_init_size()) {
|
||||
LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value);
|
||||
} else {
|
||||
|
||||
@@ -159,6 +159,11 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i
|
||||
case ProcInlining_no_inline:
|
||||
lb_add_attribute_to_proc(m, p->value, "noinline");
|
||||
break;
|
||||
default:
|
||||
if (build_context.internal_no_inline) {
|
||||
lb_add_attribute_to_proc(m, p->value, "noinline");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (entity->Procedure.optimization_mode) {
|
||||
|
||||
@@ -394,6 +394,7 @@ enum BuildFlagKind {
|
||||
BuildFlag_InternalIgnorePanic,
|
||||
BuildFlag_InternalModulePerFile,
|
||||
BuildFlag_InternalCached,
|
||||
BuildFlag_InternalNoInline,
|
||||
|
||||
BuildFlag_Tilde,
|
||||
|
||||
@@ -598,6 +599,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all);
|
||||
add_flag(&build_flags, BuildFlag_InternalModulePerFile, str_lit("internal-module-per-file"), BuildFlagParam_None, Command_all);
|
||||
add_flag(&build_flags, BuildFlag_InternalCached, str_lit("internal-cached"), BuildFlagParam_None, Command_all);
|
||||
add_flag(&build_flags, BuildFlag_InternalNoInline, str_lit("internal-no-inline"), BuildFlagParam_None, Command_all);
|
||||
|
||||
#if ALLOW_TILDE
|
||||
add_flag(&build_flags, BuildFlag_Tilde, str_lit("tilde"), BuildFlagParam_None, Command__does_build);
|
||||
@@ -1422,6 +1424,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
build_context.cached = true;
|
||||
build_context.use_separate_modules = true;
|
||||
break;
|
||||
case BuildFlag_InternalNoInline:
|
||||
build_context.internal_no_inline = true;
|
||||
break;
|
||||
|
||||
case BuildFlag_Tilde:
|
||||
build_context.tilde_backend = true;
|
||||
|
||||
@@ -2011,6 +2011,24 @@ gb_internal bool is_type_valid_bit_set_elem(Type *t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
gb_internal bool is_valid_bit_field_backing_type(Type *type) {
|
||||
if (type == nullptr) {
|
||||
return false;
|
||||
}
|
||||
type = base_type(type);
|
||||
if (is_type_untyped(type)) {
|
||||
return false;
|
||||
}
|
||||
if (is_type_integer(type)) {
|
||||
return true;
|
||||
}
|
||||
if (type->kind == Type_Array) {
|
||||
return is_type_integer(type->Array.elem);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
gb_internal Type *bit_set_to_int(Type *t) {
|
||||
GB_ASSERT(is_type_bit_set(t));
|
||||
Type *bt = base_type(t);
|
||||
@@ -2018,6 +2036,9 @@ gb_internal Type *bit_set_to_int(Type *t) {
|
||||
if (underlying != nullptr && is_type_integer(underlying)) {
|
||||
return underlying;
|
||||
}
|
||||
if (underlying != nullptr && is_valid_bit_field_backing_type(underlying)) {
|
||||
return underlying;
|
||||
}
|
||||
|
||||
i64 sz = type_size_of(t);
|
||||
switch (sz) {
|
||||
|
||||
Reference in New Issue
Block a user