mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-31 20:00:09 +00:00
Again, better const union stuff
This commit is contained in:
+17
-17
@@ -522,6 +522,23 @@ namespace lbAbiAmd64Win64 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
gb_internal bool is_llvm_type_slice_like(LLVMTypeRef type) {
|
||||||
|
if (!lb_is_type_kind(type, LLVMStructTypeKind)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (LLVMCountStructElementTypes(type) != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LLVMTypeRef fields[2] = {};
|
||||||
|
LLVMGetStructElementTypes(type, fields);
|
||||||
|
if (!lb_is_type_kind(fields[0], LLVMPointerTypeKind)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return lb_is_type_kind(fields[1], LLVMIntegerTypeKind) && lb_sizeof(fields[1]) == 8;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE(bill): I hate `namespace` in C++ but this is just because I don't want to prefix everything
|
// NOTE(bill): I hate `namespace` in C++ but this is just because I don't want to prefix everything
|
||||||
namespace lbAbiAmd64SysV {
|
namespace lbAbiAmd64SysV {
|
||||||
enum RegClass {
|
enum RegClass {
|
||||||
@@ -652,23 +669,6 @@ namespace lbAbiAmd64SysV {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal bool is_llvm_type_slice_like(LLVMTypeRef type) {
|
|
||||||
if (!lb_is_type_kind(type, LLVMStructTypeKind)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (LLVMCountStructElementTypes(type) != 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LLVMTypeRef fields[2] = {};
|
|
||||||
LLVMGetStructElementTypes(type, fields);
|
|
||||||
if (!lb_is_type_kind(fields[0], LLVMPointerTypeKind)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return lb_is_type_kind(fields[1], LLVMIntegerTypeKind) && lb_sizeof(fields[1]) == 8;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gb_internal bool is_aggregate(LLVMTypeRef type) {
|
gb_internal bool is_aggregate(LLVMTypeRef type) {
|
||||||
LLVMTypeKind kind = LLVMGetTypeKind(type);
|
LLVMTypeKind kind = LLVMGetTypeKind(type);
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
|||||||
+55
-137
@@ -540,22 +540,38 @@ gb_internal bool lb_is_nested_possibly_constant(Type *ft, Selection const &sel,
|
|||||||
gb_internal Slice<LLVMValueRef> lb_construct_const_union_flatten_values(lbModule *m, LLVMValueRef variant_value, Type *variant_type, LLVMTypeRef elem) {
|
gb_internal Slice<LLVMValueRef> lb_construct_const_union_flatten_values(lbModule *m, LLVMValueRef variant_value, Type *variant_type, LLVMTypeRef elem) {
|
||||||
LLVMTypeRef llvm_variant_type = lb_type(m, variant_type);
|
LLVMTypeRef llvm_variant_type = lb_type(m, variant_type);
|
||||||
LLVMTypeKind variant_kind = LLVMGetTypeKind(llvm_variant_type);
|
LLVMTypeKind variant_kind = LLVMGetTypeKind(llvm_variant_type);
|
||||||
|
LLVMTypeKind elem_kind = LLVMGetTypeKind(elem);
|
||||||
if (are_types_identical(base_type(variant_type), t_string)) {
|
|
||||||
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(2);
|
|
||||||
elems[0] = llvm_const_extract_value(m, variant_value, 0);
|
|
||||||
elems[0] = LLVMConstPtrToInt(elems[0], elem);
|
|
||||||
|
|
||||||
elems[1] = llvm_const_extract_value(m, variant_value, 1);
|
|
||||||
|
|
||||||
return {elems, 2};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_type_struct(variant_type)) {
|
if (is_type_struct(variant_type)) {
|
||||||
// Type *st = base_type(variant_type);
|
Type *st = base_type(variant_type);
|
||||||
// if (st->Struct.fields.count == 1) {
|
GB_ASSERT(st->kind == Type_Struct);
|
||||||
// return lb_construct_const_union_flatten_values(m, llvm_const_extract_value(m, variant_value, 0), st->Struct.fields[0]->type, elem);
|
if (st->Struct.fields.count == 1) {
|
||||||
// }
|
LLVMValueRef f = llvm_const_extract_value(m, variant_value, 0);
|
||||||
|
return lb_construct_const_union_flatten_values(m, f, st->Struct.fields[0]->type, elem);
|
||||||
|
}
|
||||||
|
} else if (is_llvm_type_slice_like(llvm_variant_type)) {
|
||||||
|
if (lb_sizeof(elem) == build_context.ptr_size) {
|
||||||
|
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(2);
|
||||||
|
elems[0] = llvm_const_extract_value(m, variant_value, 0);
|
||||||
|
elems[0] = LLVMConstPtrToInt(elems[0], elem);
|
||||||
|
|
||||||
|
elems[1] = llvm_const_extract_value(m, variant_value, 1);
|
||||||
|
|
||||||
|
return {elems, 2};
|
||||||
|
}
|
||||||
|
} else if (is_type_array_like(variant_type)) {
|
||||||
|
Type *array_elem = base_array_type(variant_type);
|
||||||
|
isize array_count = get_array_type_count(variant_type);
|
||||||
|
Slice<LLVMValueRef> array = temporary_slice_make<LLVMValueRef>(array_count);
|
||||||
|
for (isize i = 0; i < array_count; i++) {
|
||||||
|
LLVMValueRef v = llvm_const_extract_value(m, variant_value, 0);
|
||||||
|
auto res = lb_construct_const_union_flatten_values(m, v, array_elem, elem);
|
||||||
|
if (res.count != 1) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
array[i] = res[0];
|
||||||
|
}
|
||||||
|
return array;
|
||||||
} else if (variant_kind == LLVMIntegerTypeKind) {
|
} else if (variant_kind == LLVMIntegerTypeKind) {
|
||||||
if (elem == llvm_variant_type) {
|
if (elem == llvm_variant_type) {
|
||||||
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(1);
|
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(1);
|
||||||
@@ -572,7 +588,8 @@ gb_internal Slice<LLVMValueRef> lb_construct_const_union_flatten_values(lbModule
|
|||||||
return {elems, 1};
|
return {elems, 1};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!is_type_different_to_arch_endianness(variant_type)) {
|
} else if (!is_type_different_to_arch_endianness(variant_type) &&
|
||||||
|
elem_kind == LLVMIntegerTypeKind) {
|
||||||
switch (variant_kind) {
|
switch (variant_kind) {
|
||||||
case LLVMHalfTypeKind:
|
case LLVMHalfTypeKind:
|
||||||
{
|
{
|
||||||
@@ -687,138 +704,39 @@ gb_internal LLVMValueRef lb_construct_const_union(lbModule *m, LLVMValueRef vari
|
|||||||
LLVMTypeKind block_kind = LLVMGetTypeKind(block_type);
|
LLVMTypeKind block_kind = LLVMGetTypeKind(block_type);
|
||||||
LLVMTypeKind variant_kind = LLVMGetTypeKind(llvm_variant_type);
|
LLVMTypeKind variant_kind = LLVMGetTypeKind(llvm_variant_type);
|
||||||
|
|
||||||
if (block_size != variant_size) {
|
|
||||||
if (block_kind == LLVMArrayTypeKind) {
|
|
||||||
LLVMTypeRef elem = LLVMGetElementType(block_type);
|
|
||||||
unsigned count = LLVMGetArrayLength(block_type);
|
|
||||||
|
|
||||||
if (variant_kind == LLVMIntegerTypeKind) {
|
if (block_kind == LLVMArrayTypeKind) {
|
||||||
if (elem == llvm_variant_type) {
|
LLVMTypeRef elem = LLVMGetElementType(block_type);
|
||||||
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(count);
|
unsigned count = LLVMGetArrayLength(block_type);
|
||||||
elems[0] = variant_value;
|
|
||||||
for (unsigned j = 1; j < count; j++) {
|
|
||||||
elems[j] = LLVMConstNull(elem);
|
|
||||||
}
|
|
||||||
block_value = LLVMConstArray(elem, elems, count);
|
|
||||||
goto assign_value_wrapped;
|
|
||||||
} else if (!is_type_different_to_arch_endianness(variant_type)) {
|
|
||||||
i64 elem_size = lb_sizeof(elem);
|
|
||||||
i64 variant_size = lb_sizeof(llvm_variant_type);
|
|
||||||
if (elem_size > variant_size) {
|
|
||||||
u64 val = LLVMConstIntGetZExtValue(variant_value);
|
|
||||||
|
|
||||||
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(count);
|
Slice<LLVMValueRef> partial_elems = lb_construct_const_union_flatten_values(m, variant_value, variant_type, elem);
|
||||||
elems[0] = LLVMConstInt(elem, val, false);
|
if (partial_elems.count == count) {
|
||||||
for (unsigned j = 1; j < count; j++) {
|
block_value = LLVMConstArray(elem, partial_elems.data, count);
|
||||||
elems[j] = LLVMConstNull(elem);
|
goto assign_value_wrapped;
|
||||||
}
|
}
|
||||||
block_value = LLVMConstArray(elem, elems, count);
|
|
||||||
goto assign_value_wrapped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!is_type_different_to_arch_endianness(variant_type)) {
|
|
||||||
switch (variant_kind) {
|
|
||||||
case LLVMHalfTypeKind:
|
|
||||||
{
|
|
||||||
LLVMBool loses = false;
|
|
||||||
f64 res = LLVMConstRealGetDouble(variant_value, &loses);
|
|
||||||
u16 val = f32_to_f16(cast(f32)res);
|
|
||||||
|
|
||||||
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(count);
|
Slice<LLVMValueRef> full_elems = temporary_slice_make<LLVMValueRef>(count);
|
||||||
elems[0] = LLVMConstInt(elem, val, false);
|
slice_copy(&full_elems, partial_elems);
|
||||||
for (unsigned j = 1; j < count; j++) {
|
for (isize j = partial_elems.count; j < count; j++) {
|
||||||
elems[j] = LLVMConstNull(elem);
|
full_elems[j] = LLVMConstNull(elem);
|
||||||
}
|
}
|
||||||
block_value = LLVMConstArray(elem, elems, count);
|
block_value = LLVMConstArray(elem, full_elems.data, count);
|
||||||
goto assign_value_wrapped;
|
goto assign_value_wrapped;
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LLVMFloatTypeKind:
|
|
||||||
{
|
|
||||||
LLVMBool loses = false;
|
|
||||||
f64 res = LLVMConstRealGetDouble(variant_value, &loses);
|
|
||||||
union { f32 f; u32 i; } val = {};
|
|
||||||
val.f = cast(f32)res;
|
|
||||||
|
|
||||||
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(count);
|
} else if (block_size != variant_size) {
|
||||||
elems[0] = LLVMConstInt(elem, val.i, false);
|
if (block_kind == LLVMIntegerTypeKind && !is_type_different_to_arch_endianness(variant_type)) {
|
||||||
for (unsigned j = 1; j < count; j++) {
|
Slice<LLVMValueRef> partial_elems = lb_construct_const_union_flatten_values(m, variant_value, variant_type, block_type);
|
||||||
elems[j] = LLVMConstNull(elem);
|
if (partial_elems.count == 1) {
|
||||||
}
|
block_value = partial_elems[0];
|
||||||
block_value = LLVMConstArray(elem, elems, count);
|
goto assign_value_wrapped;
|
||||||
goto assign_value_wrapped;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LLVMDoubleTypeKind:
|
|
||||||
{
|
|
||||||
LLVMBool loses = false;
|
|
||||||
f64 res = LLVMConstRealGetDouble(variant_value, &loses);
|
|
||||||
union { f64 f; u64 i; } val = {};
|
|
||||||
val.f = res;
|
|
||||||
|
|
||||||
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(count);
|
|
||||||
elems[0] = LLVMConstInt(elem, val.i, false);
|
|
||||||
for (unsigned j = 1; j < count; j++) {
|
|
||||||
elems[j] = LLVMConstNull(elem);
|
|
||||||
}
|
|
||||||
block_value = LLVMConstArray(elem, elems, count);
|
|
||||||
goto assign_value_wrapped;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else if (block_kind == LLVMIntegerTypeKind && !is_type_different_to_arch_endianness(variant_type)) {
|
|
||||||
if (variant_kind == LLVMIntegerTypeKind) {
|
|
||||||
i64 variant_size = lb_sizeof(llvm_variant_type);
|
|
||||||
if (block_size > variant_size) {
|
|
||||||
u64 val = LLVMConstIntGetZExtValue(variant_value);
|
|
||||||
block_value = LLVMConstInt(block_type, val, false);
|
|
||||||
|
|
||||||
goto assign_value_wrapped;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (variant_kind) {
|
|
||||||
case LLVMHalfTypeKind:
|
|
||||||
{
|
|
||||||
LLVMBool loses = false;
|
|
||||||
f64 res = LLVMConstRealGetDouble(variant_value, &loses);
|
|
||||||
u16 val = f32_to_f16(cast(f32)res);
|
|
||||||
|
|
||||||
block_value = LLVMConstInt(block_type, val, false);
|
|
||||||
goto assign_value_wrapped;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LLVMFloatTypeKind:
|
|
||||||
{
|
|
||||||
LLVMBool loses = false;
|
|
||||||
f64 res = LLVMConstRealGetDouble(variant_value, &loses);
|
|
||||||
union { f32 f; u32 i; } val = {};
|
|
||||||
val.f = cast(f32)res;
|
|
||||||
|
|
||||||
block_value = LLVMConstInt(block_type, val.i, false);
|
|
||||||
goto assign_value_wrapped;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LLVMDoubleTypeKind:
|
|
||||||
{
|
|
||||||
LLVMBool loses = false;
|
|
||||||
f64 res = LLVMConstRealGetDouble(variant_value, &loses);
|
|
||||||
union { f64 f; u64 i; } val = {};
|
|
||||||
val.f = res;
|
|
||||||
|
|
||||||
block_value = LLVMConstInt(block_type, val.i, false);
|
|
||||||
goto assign_value_wrapped;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (block_kind == LLVMIntegerTypeKind) {
|
if (block_kind == LLVMIntegerTypeKind) {
|
||||||
|
GB_ASSERT(block_size == variant_size);
|
||||||
|
|
||||||
switch (variant_kind) {
|
switch (variant_kind) {
|
||||||
case LLVMHalfTypeKind:
|
case LLVMHalfTypeKind:
|
||||||
case LLVMFloatTypeKind:
|
case LLVMFloatTypeKind:
|
||||||
|
|||||||
Reference in New Issue
Block a user