mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-31 20:00:09 +00:00
Begin to support constant array of unions
This commit is contained in:
+8
-20
@@ -3505,24 +3505,6 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal bool is_type_union_constantable(Type *type) {
|
|
||||||
Type *bt = base_type(type);
|
|
||||||
GB_ASSERT(bt->kind == Type_Union);
|
|
||||||
|
|
||||||
if (bt->Union.variants.count == 0) {
|
|
||||||
return true;
|
|
||||||
} else if (bt->Union.variants.count == 1) {
|
|
||||||
return is_type_constant_type(bt->Union.variants[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Type *v : bt->Union.variants) {
|
|
||||||
if (!is_type_constant_type(v)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
gb_internal bool check_cast_internal(CheckerContext *c, Operand *x, Type *type) {
|
gb_internal bool check_cast_internal(CheckerContext *c, Operand *x, Type *type) {
|
||||||
bool is_const_expr = x->mode == Addressing_Constant;
|
bool is_const_expr = x->mode == Addressing_Constant;
|
||||||
|
|
||||||
@@ -4880,7 +4862,10 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
operand->type = new_type;
|
operand->type = new_type;
|
||||||
operand->mode = Addressing_Value;
|
if (operand->mode != Addressing_Constant ||
|
||||||
|
!elem_type_can_be_constant(operand->type)) {
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
} else if (valid_count > 1) {
|
} else if (valid_count > 1) {
|
||||||
ERROR_BLOCK();
|
ERROR_BLOCK();
|
||||||
@@ -9895,7 +9880,10 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
|
|||||||
Operand o = {};
|
Operand o = {};
|
||||||
check_expr_or_type(c, &o, elem, field->type);
|
check_expr_or_type(c, &o, elem, field->type);
|
||||||
|
|
||||||
if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) {
|
if (is_type_any(field->type) ||
|
||||||
|
is_type_raw_union(field->type) ||
|
||||||
|
(is_type_union(field->type) && !is_type_union_constantable(field->type)) ||
|
||||||
|
is_type_typeid(field->type)) {
|
||||||
is_constant = false;
|
is_constant = false;
|
||||||
}
|
}
|
||||||
if (is_constant) {
|
if (is_constant) {
|
||||||
|
|||||||
@@ -96,10 +96,6 @@ gb_internal LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst) {
|
|||||||
case LLVMPointerTypeKind:
|
case LLVMPointerTypeKind:
|
||||||
return LLVMConstPointerCast(val, dst);
|
return LLVMConstPointerCast(val, dst);
|
||||||
case LLVMStructTypeKind:
|
case LLVMStructTypeKind:
|
||||||
// GB_PANIC("%s -> %s", LLVMPrintValueToString(val), LLVMPrintTypeToString(dst));
|
|
||||||
// NOTE(bill): It's not possible to do a bit cast on a struct, why was this code even here in the first place?
|
|
||||||
// It seems mostly to exist to get around the "anonymous -> named" struct assignments
|
|
||||||
// return LLVMConstBitCast(val, dst);
|
|
||||||
return val;
|
return val;
|
||||||
default:
|
default:
|
||||||
GB_PANIC("Unhandled const cast %s to %s", LLVMPrintTypeToString(src), LLVMPrintTypeToString(dst));
|
GB_PANIC("Unhandled const cast %s to %s", LLVMPrintTypeToString(src), LLVMPrintTypeToString(dst));
|
||||||
@@ -199,11 +195,17 @@ gb_internal LLVMValueRef llvm_const_named_struct_internal(LLVMTypeRef t, LLVMVal
|
|||||||
return LLVMConstNamedStruct(t, values, value_count);
|
return LLVMConstNamedStruct(t, values, value_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal LLVMValueRef llvm_const_array(LLVMTypeRef elem_type, LLVMValueRef *values, isize value_count_) {
|
gb_internal LLVMValueRef llvm_const_array(lbModule *m, LLVMTypeRef elem_type, LLVMValueRef *values, isize value_count_) {
|
||||||
unsigned value_count = cast(unsigned)value_count_;
|
unsigned value_count = cast(unsigned)value_count_;
|
||||||
for (unsigned i = 0; i < value_count; i++) {
|
for (unsigned i = 0; i < value_count; i++) {
|
||||||
values[i] = llvm_const_cast(values[i], elem_type);
|
values[i] = llvm_const_cast(values[i], elem_type);
|
||||||
}
|
}
|
||||||
|
for (unsigned i = 0; i < value_count; i++) {
|
||||||
|
if (elem_type != LLVMTypeOf(values[i])) {
|
||||||
|
return LLVMConstStructInContext(m->ctx, values, value_count, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return LLVMConstArray(elem_type, values, value_count);
|
return LLVMConstArray(elem_type, values, value_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,7 +463,7 @@ gb_internal LLVMValueRef lb_build_constant_array_values(lbModule *m, Type *type,
|
|||||||
return lb_addr_load(p, v).value;
|
return lb_addr_load(p, v).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return llvm_const_array(lb_type(m, elem_type), values, cast(unsigned int)count);
|
return llvm_const_array(m, lb_type(m, elem_type), values, cast(unsigned int)count);
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, BigInt const *a) {
|
gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, BigInt const *a) {
|
||||||
@@ -1016,7 +1018,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
|
|||||||
}
|
}
|
||||||
GB_ASSERT(offset == s.len);
|
GB_ASSERT(offset == s.len);
|
||||||
|
|
||||||
res.value = llvm_const_array(et, elems, cast(unsigned)count);
|
res.value = llvm_const_array(m, et, elems, cast(unsigned)count);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
// NOTE(bill, 2021-10-07): Allow for array programming value constants
|
// NOTE(bill, 2021-10-07): Allow for array programming value constants
|
||||||
@@ -1046,7 +1048,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
|
|||||||
elems[i] = single_elem.value;
|
elems[i] = single_elem.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.value = llvm_const_array(lb_type(m, elem), elems, cast(unsigned)count);
|
res.value = llvm_const_array(m, lb_type(m, elem), elems, cast(unsigned)count);
|
||||||
return res;
|
return res;
|
||||||
} else if (is_type_matrix(type) &&
|
} else if (is_type_matrix(type) &&
|
||||||
value.kind != ExactValue_Invalid &&
|
value.kind != ExactValue_Invalid &&
|
||||||
|
|||||||
@@ -3253,11 +3253,18 @@ gb_internal lbAddr lb_add_global_generated_with_name(lbModule *m, Type *type, lb
|
|||||||
GB_ASSERT(type != nullptr);
|
GB_ASSERT(type != nullptr);
|
||||||
type = default_type(type);
|
type = default_type(type);
|
||||||
|
|
||||||
|
LLVMTypeRef actual_type = lb_type(m, type);
|
||||||
|
if (value.value != nullptr) {
|
||||||
|
LLVMTypeRef value_type = LLVMTypeOf(value.value);
|
||||||
|
GB_ASSERT(lb_sizeof(actual_type) == lb_sizeof(value_type));
|
||||||
|
actual_type = value_type;
|
||||||
|
}
|
||||||
|
|
||||||
Scope *scope = nullptr;
|
Scope *scope = nullptr;
|
||||||
Entity *e = alloc_entity_variable(scope, make_token_ident(name), type);
|
Entity *e = alloc_entity_variable(scope, make_token_ident(name), type);
|
||||||
lbValue g = {};
|
lbValue g = {};
|
||||||
g.type = alloc_type_pointer(type);
|
g.type = alloc_type_pointer(type);
|
||||||
g.value = LLVMAddGlobal(m->mod, lb_type(m, type), alloc_cstring(temporary_allocator(), name));
|
g.value = LLVMAddGlobal(m->mod, actual_type, alloc_cstring(temporary_allocator(), name));
|
||||||
if (value.value != nullptr) {
|
if (value.value != nullptr) {
|
||||||
GB_ASSERT_MSG(LLVMIsConstant(value.value), LLVMPrintValueToString(value.value));
|
GB_ASSERT_MSG(LLVMIsConstant(value.value), LLVMPrintValueToString(value.value));
|
||||||
LLVMSetInitializer(g.value, value.value);
|
LLVMSetInitializer(g.value, value.value);
|
||||||
@@ -3265,6 +3272,8 @@ gb_internal lbAddr lb_add_global_generated_with_name(lbModule *m, Type *type, lb
|
|||||||
LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, type)));
|
LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g.value = LLVMConstPointerCast(g.value, lb_type(m, g.type));
|
||||||
|
|
||||||
lb_add_entity(m, e, g);
|
lb_add_entity(m, e, g);
|
||||||
lb_add_member(m, name, g);
|
lb_add_member(m, name, g);
|
||||||
|
|
||||||
|
|||||||
@@ -2237,7 +2237,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
|||||||
elements[i] = element;
|
elements[i] = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMValueRef backing_array = llvm_const_array(lb_type(m, t_load_directory_file), elements, count);
|
LLVMValueRef backing_array = llvm_const_array(m, lb_type(m, t_load_directory_file), elements, count);
|
||||||
|
|
||||||
Type *array_type = alloc_type_array(t_load_directory_file, count);
|
Type *array_type = alloc_type_array(t_load_directory_file, count);
|
||||||
lbAddr backing_array_addr = lb_add_global_generated_from_procedure(p, array_type, {backing_array, array_type});
|
lbAddr backing_array_addr = lb_add_global_generated_from_procedure(p, array_type, {backing_array, array_type});
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ
|
|||||||
(name##_values)[i] = LLVMConstNull(elem); \
|
(name##_values)[i] = LLVMConstNull(elem); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
LLVMSetInitializer(name.addr.value, llvm_const_array(elem, name##_values, at->Array.count)); \
|
LLVMSetInitializer(name.addr.value, llvm_const_array(m, elem, name##_values, at->Array.count)); \
|
||||||
})
|
})
|
||||||
|
|
||||||
type_info_allocate_values(lb_global_type_info_member_types);
|
type_info_allocate_values(lb_global_type_info_member_types);
|
||||||
@@ -752,8 +752,8 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ
|
|||||||
value_values[i] = lb_const_value(m, t_i64, fields[i]->Constant.value).value;
|
value_values[i] = lb_const_value(m, t_i64, fields[i]->Constant.value).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMValueRef name_init = llvm_const_array(lb_type(m, t_string), name_values, cast(unsigned)fields.count);
|
LLVMValueRef name_init = llvm_const_array(m, lb_type(m, t_string), name_values, cast(unsigned)fields.count);
|
||||||
LLVMValueRef value_init = llvm_const_array(lb_type(m, t_type_info_enum_value), value_values, cast(unsigned)fields.count);
|
LLVMValueRef value_init = llvm_const_array(m, lb_type(m, t_type_info_enum_value), value_values, cast(unsigned)fields.count);
|
||||||
LLVMSetInitializer(name_array.value, name_init);
|
LLVMSetInitializer(name_array.value, name_init);
|
||||||
LLVMSetInitializer(value_array.value, value_init);
|
LLVMSetInitializer(value_array.value, value_init);
|
||||||
LLVMSetGlobalConstant(name_array.value, true);
|
LLVMSetGlobalConstant(name_array.value, true);
|
||||||
|
|||||||
@@ -27,6 +27,24 @@ enum AddressingMode : u8 {
|
|||||||
Addressing_SwizzleVariable = 14, // Swizzle indexed variable
|
Addressing_SwizzleVariable = 14, // Swizzle indexed variable
|
||||||
};
|
};
|
||||||
|
|
||||||
|
gb_global String const addressing_mode_strings[] = {
|
||||||
|
str_lit("Invalid"),
|
||||||
|
str_lit("NoValue"),
|
||||||
|
str_lit("Value"),
|
||||||
|
str_lit("Context"),
|
||||||
|
str_lit("Variable"),
|
||||||
|
str_lit("Constant"),
|
||||||
|
str_lit("Type"),
|
||||||
|
str_lit("Builtin"),
|
||||||
|
str_lit("ProcGroup"),
|
||||||
|
str_lit("MapIndex"),
|
||||||
|
str_lit("OptionalOk"),
|
||||||
|
str_lit("OptionalOkPtr"),
|
||||||
|
str_lit("SoaVariable"),
|
||||||
|
str_lit("SwizzleValue"),
|
||||||
|
str_lit("SwizzleVariable"),
|
||||||
|
};
|
||||||
|
|
||||||
struct TypeAndValue {
|
struct TypeAndValue {
|
||||||
Type * type;
|
Type * type;
|
||||||
AddressingMode mode;
|
AddressingMode mode;
|
||||||
|
|||||||
+21
-1
@@ -2507,15 +2507,35 @@ gb_internal bool type_has_nil(Type *t) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gb_internal bool is_type_union_constantable(Type *type) {
|
||||||
|
Type *bt = base_type(type);
|
||||||
|
GB_ASSERT(bt->kind == Type_Union);
|
||||||
|
|
||||||
|
if (bt->Union.variants.count == 0) {
|
||||||
|
return true;
|
||||||
|
} else if (bt->Union.variants.count == 1) {
|
||||||
|
return is_type_constant_type(bt->Union.variants[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Type *v : bt->Union.variants) {
|
||||||
|
if (!is_type_constant_type(v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
gb_internal bool elem_type_can_be_constant(Type *t) {
|
gb_internal bool elem_type_can_be_constant(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
if (t == t_invalid) {
|
if (t == t_invalid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (is_type_any(t) || is_type_union(t) || is_type_raw_union(t)) {
|
if (is_type_any(t) || is_type_raw_union(t)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (is_type_union(t)) {
|
||||||
|
return is_type_union_constantable(t);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user