mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-02 04:38:16 +00:00
More const union improvements
This commit is contained in:
+55
-16
@@ -542,6 +542,12 @@ gb_internal LLVMValueRef lb_construct_const_union(lbModule *m, LLVMValueRef vari
|
|||||||
GB_ASSERT(bt->kind == Type_Union);
|
GB_ASSERT(bt->kind == Type_Union);
|
||||||
GB_ASSERT(lb_type(m, variant_type) == LLVMTypeOf(variant_value));
|
GB_ASSERT(lb_type(m, variant_type) == LLVMTypeOf(variant_value));
|
||||||
|
|
||||||
|
LLVMTypeRef llvm_type = lb_type(m, union_type);
|
||||||
|
|
||||||
|
if (LLVMIsNull(variant_value)) {
|
||||||
|
return LLVMConstNull(llvm_type);
|
||||||
|
}
|
||||||
|
|
||||||
if (bt->Union.variants.count == 0) {
|
if (bt->Union.variants.count == 0) {
|
||||||
GB_ASSERT(LLVMIsNull(variant_value));
|
GB_ASSERT(LLVMIsNull(variant_value));
|
||||||
return variant_value;
|
return variant_value;
|
||||||
@@ -550,7 +556,6 @@ gb_internal LLVMValueRef lb_construct_const_union(lbModule *m, LLVMValueRef vari
|
|||||||
i64 block_size = bt->Union.variant_block_size;
|
i64 block_size = bt->Union.variant_block_size;
|
||||||
i64 variant_size = type_size_of(variant_type);
|
i64 variant_size = type_size_of(variant_type);
|
||||||
|
|
||||||
LLVMTypeRef llvm_type = lb_type(m, union_type);
|
|
||||||
LLVMTypeRef llvm_variant_type = lb_type(m, variant_type);
|
LLVMTypeRef llvm_variant_type = lb_type(m, variant_type);
|
||||||
|
|
||||||
if (is_type_union_maybe_pointer(bt)) {
|
if (is_type_union_maybe_pointer(bt)) {
|
||||||
@@ -580,13 +585,6 @@ gb_internal LLVMValueRef lb_construct_const_union(lbModule *m, LLVMValueRef vari
|
|||||||
|
|
||||||
LLVMTypeRef block_type = LLVMStructGetTypeAtIndex(llvm_type, 0);
|
LLVMTypeRef block_type = LLVMStructGetTypeAtIndex(llvm_type, 0);
|
||||||
|
|
||||||
LLVMTypeRef block_padding = nullptr;
|
|
||||||
i64 block_padding_size = block_size - variant_size;
|
|
||||||
if (block_padding_size > 0) {
|
|
||||||
block_padding = lb_type_padding_filler(m, block_padding_size, type_align_of(variant_type));
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMTypeRef tag_type = lb_type(m, union_tag_type(bt));
|
LLVMTypeRef tag_type = lb_type(m, union_tag_type(bt));
|
||||||
|
|
||||||
i64 used_size = block_size + lb_sizeof(tag_type);
|
i64 used_size = block_size + lb_sizeof(tag_type);
|
||||||
@@ -601,12 +599,55 @@ gb_internal LLVMValueRef lb_construct_const_union(lbModule *m, LLVMValueRef vari
|
|||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
LLVMValueRef values[3] = {};
|
LLVMValueRef values[3] = {};
|
||||||
|
|
||||||
LLVMValueRef variant_value_wrapped = variant_value;
|
LLVMValueRef block_value = variant_value;
|
||||||
|
|
||||||
if (lb_sizeof(llvm_variant_type) == 0) {
|
if (lb_sizeof(llvm_variant_type) == 0) {
|
||||||
variant_value_wrapped = LLVMConstNull(block_type);
|
block_value = LLVMConstNull(block_type);
|
||||||
} else if (block_type != llvm_variant_type) {
|
} else if (block_type != llvm_variant_type) {
|
||||||
if (block_size != variant_size) {
|
if (block_size != variant_size) {
|
||||||
|
|
||||||
|
if (LLVMGetTypeKind(block_type) == LLVMArrayTypeKind &&
|
||||||
|
LLVMGetTypeKind(llvm_variant_type) == LLVMIntegerTypeKind) {
|
||||||
|
LLVMTypeRef elem = LLVMGetElementType(block_type);
|
||||||
|
unsigned count = LLVMGetArrayLength(block_type);
|
||||||
|
if (elem == llvm_variant_type) {
|
||||||
|
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(count);
|
||||||
|
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);
|
||||||
|
elems[0] = LLVMConstInt(elem, val, false);
|
||||||
|
for (unsigned j = 1; j < count; j++) {
|
||||||
|
elems[j] = LLVMConstNull(elem);
|
||||||
|
}
|
||||||
|
block_value = LLVMConstArray(elem, elems, count);
|
||||||
|
|
||||||
|
goto assign_value_wrapped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (LLVMGetTypeKind(block_type) == LLVMIntegerTypeKind &&
|
||||||
|
LLVMGetTypeKind(llvm_variant_type) == LLVMIntegerTypeKind) {
|
||||||
|
if (!is_type_different_to_arch_endianness(variant_type)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (LLVMGetTypeKind(block_type) == LLVMIntegerTypeKind) {
|
if (LLVMGetTypeKind(block_type) == LLVMIntegerTypeKind) {
|
||||||
@@ -614,10 +655,10 @@ gb_internal LLVMValueRef lb_construct_const_union(lbModule *m, LLVMValueRef vari
|
|||||||
case LLVMHalfTypeKind:
|
case LLVMHalfTypeKind:
|
||||||
case LLVMFloatTypeKind:
|
case LLVMFloatTypeKind:
|
||||||
case LLVMDoubleTypeKind:
|
case LLVMDoubleTypeKind:
|
||||||
variant_value_wrapped = LLVMConstBitCast(variant_value_wrapped, block_type);
|
block_value = LLVMConstBitCast(block_value, block_type);
|
||||||
goto assign_value_wrapped;
|
goto assign_value_wrapped;
|
||||||
case LLVMPointerTypeKind:
|
case LLVMPointerTypeKind:
|
||||||
variant_value_wrapped = LLVMConstPtrToInt(variant_value_wrapped, block_type);
|
block_value = LLVMConstPtrToInt(block_value, block_type);
|
||||||
goto assign_value_wrapped;
|
goto assign_value_wrapped;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -626,11 +667,8 @@ gb_internal LLVMValueRef lb_construct_const_union(lbModule *m, LLVMValueRef vari
|
|||||||
}
|
}
|
||||||
|
|
||||||
assign_value_wrapped:;
|
assign_value_wrapped:;
|
||||||
values[i++] = variant_value_wrapped;
|
values[i++] = block_value;
|
||||||
|
|
||||||
if (block_padding_size > 0) {
|
|
||||||
values[i++] = LLVMConstNull(block_padding);
|
|
||||||
}
|
|
||||||
unsigned long long the_tag = cast(unsigned long long)union_variant_index(union_type, variant_type);
|
unsigned long long the_tag = cast(unsigned long long)union_variant_index(union_type, variant_type);
|
||||||
values[i++] = LLVMConstInt(tag_type, the_tag, false);
|
values[i++] = LLVMConstInt(tag_type, the_tag, false);
|
||||||
if (padding > 0) {
|
if (padding > 0) {
|
||||||
@@ -646,6 +684,7 @@ gb_internal bool lb_try_construct_const_union(lbModule *m, lbValue *value, Type
|
|||||||
*value = {res, union_type};
|
*value = {res, union_type};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// gb_printf_err("%s -> %s\n", LLVMPrintValueToString(value->value), LLVMPrintTypeToString(lb_type(m, union_type)));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1733,10 +1733,11 @@ gb_internal LLVMTypeRef lb_type_internal_union_block_type(lbModule *m, Type *typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
i64 align = type_align_of(type);
|
i64 align = type_align_of(type);
|
||||||
i64 size = type_size_of(type);
|
|
||||||
gb_unused(size);
|
|
||||||
|
|
||||||
unsigned block_size = cast(unsigned)type->Union.variant_block_size;
|
unsigned block_size = cast(unsigned)type->Union.variant_block_size;
|
||||||
|
if (block_size == 0) {
|
||||||
|
return lb_type_padding_filler(m, block_size, align);
|
||||||
|
}
|
||||||
|
|
||||||
bool all_pointers = align == build_context.ptr_size;
|
bool all_pointers = align == build_context.ptr_size;
|
||||||
for (isize i = 0; all_pointers && i < type->Union.variants.count; i++) {
|
for (isize i = 0; all_pointers && i < type->Union.variants.count; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user