diff options
| author | Username-Leon <leonardo.temperanza@gmail.com> | 2025-10-15 15:30:32 +0200 |
|---|---|---|
| committer | Username-Leon <leonardo.temperanza@gmail.com> | 2025-10-15 15:30:32 +0200 |
| commit | 4dd6bb2e871e9b8583a89e62ce36a98d02d48cc3 (patch) | |
| tree | 25b7599645caf76ebe9136da51e5114006ab93f4 /src/llvm_backend_const.cpp | |
| parent | e10093bd991334789031df9ed587d27823ca90dd (diff) | |
| parent | 596066aa0453752f24cc2fa5087fafe2c4686536 (diff) | |
Merge branch 'master' of https://github.com/LeonardoTemperanza/Odin
Diffstat (limited to 'src/llvm_backend_const.cpp')
| -rw-r--r-- | src/llvm_backend_const.cpp | 144 |
1 files changed, 133 insertions, 11 deletions
diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 193bffe08..4c154c85a 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -81,7 +81,7 @@ gb_internal String lb_get_const_string(lbModule *m, lbValue value) { } -gb_internal LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst, bool *failure_) { +gb_internal LLVMValueRef llvm_const_cast(lbModule *m, LLVMValueRef val, LLVMTypeRef dst, bool *failure_) { LLVMTypeRef src = LLVMTypeOf(val); if (src == dst) { return val; @@ -93,14 +93,33 @@ gb_internal LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst, bool GB_ASSERT_MSG(lb_sizeof(dst) == lb_sizeof(src), "%s vs %s", LLVMPrintTypeToString(dst), LLVMPrintTypeToString(src)); LLVMTypeKind kind = LLVMGetTypeKind(dst); switch (kind) { - case LLVMPointerTypeKind: + case LLVMPointerTypeKind: { return LLVMConstPointerCast(val, dst); - case LLVMStructTypeKind: - if (LLVMTypeOf(val) != dst) { - if (failure_) *failure_ = true; + } + case LLVMStructTypeKind: { + unsigned src_n = LLVMCountStructElementTypes(src); + unsigned dst_n = LLVMCountStructElementTypes(dst); + if (src_n != dst_n) goto failure; + + LLVMValueRef *field_vals = temporary_alloc_array<LLVMValueRef>(dst_n); + for (unsigned i = 0; i < dst_n; i++) { + LLVMValueRef field_val = llvm_const_extract_value(m, val, i); + if (field_val == nullptr) goto failure; + + LLVMTypeRef dst_elem_ty = LLVMStructGetTypeAtIndex(dst, i); + field_vals[i] = llvm_const_cast(m, field_val, dst_elem_ty, failure_); + if (failure_ && *failure_) goto failure; } - return val; + + if (!LLVMIsLiteralStruct(dst)) { + return LLVMConstNamedStruct(dst, field_vals, dst_n); + } else { + return LLVMConstStructInContext(m->ctx, field_vals, dst_n, LLVMIsPackedStruct(dst)); + } + } } + +failure: if (failure_) *failure_ = true; return val; } @@ -192,7 +211,7 @@ gb_internal LLVMValueRef llvm_const_named_struct_internal(lbModule *m, LLVMTypeR bool failure = false; for (unsigned i = 0; i < elem_count; i++) { LLVMTypeRef elem_type = LLVMStructGetTypeAtIndex(t, i); - values[i] = llvm_const_cast(values[i], elem_type, &failure); + values[i] = llvm_const_cast(m, values[i], elem_type, &failure); } if (failure) { @@ -205,7 +224,7 @@ gb_internal LLVMValueRef llvm_const_array(lbModule *m, LLVMTypeRef elem_type, LL unsigned value_count = cast(unsigned)value_count_; bool failure = false; for (unsigned i = 0; i < value_count; i++) { - values[i] = llvm_const_cast(values[i], elem_type, &failure); + values[i] = llvm_const_cast(m, values[i], elem_type, &failure); } if (failure) { return LLVMConstStructInContext(m->ctx, values, value_count, false); @@ -549,6 +568,104 @@ gb_internal bool lb_is_nested_possibly_constant(Type *ft, Selection const &sel, return lb_is_elem_const(elem, ft); } +#if LLVM_VERSION_MAJOR == 14 +LLVMValueRef llvm_const_pad_to_size(lbModule *m, LLVMValueRef val, LLVMTypeRef dst_ty) { + LLVMContextRef ctx = m->ctx; + LLVMTargetDataRef td = LLVMGetModuleDataLayout(m->mod); + LLVMTypeRef src_ty = LLVMTypeOf(val); + unsigned src_bits = (unsigned)LLVMSizeOfTypeInBits(td, src_ty); + unsigned dst_bits = (unsigned)LLVMSizeOfTypeInBits(td, dst_ty); + + LLVMValueRef as_int = nullptr; + LLVMTypeKind src_kind = LLVMGetTypeKind(src_ty); + + if (src_kind == LLVMIntegerTypeKind || + src_kind == LLVMFloatTypeKind || + src_kind == LLVMDoubleTypeKind || + src_kind == LLVMPointerTypeKind || + src_kind == LLVMVectorTypeKind) { + LLVMTypeRef src_int_ty = LLVMIntTypeInContext(ctx, src_bits); + as_int = LLVMConstBitCast(val, src_int_ty); + + } else if (src_kind == LLVMArrayTypeKind) { + unsigned elem_count = LLVMGetArrayLength(src_ty); + LLVMTypeRef elem_ty = LLVMGetElementType(src_ty); + unsigned elem_bits = (unsigned)LLVMSizeOfTypeInBits(td, elem_ty); + LLVMTypeRef src_int_ty = LLVMIntTypeInContext(ctx, src_bits); + as_int = LLVMConstInt(src_int_ty, 0, false); + + for (unsigned i = 0; i < elem_count; i++) { + LLVMValueRef elem = llvm_const_extract_value(m, val, i); + LLVMTypeRef elem_int_ty = LLVMIntTypeInContext(ctx, elem_bits); + LLVMValueRef elem_int = llvm_const_pad_to_size(m, elem, elem_int_ty); + LLVMValueRef shifted = LLVMConstShl(LLVMConstZExt(elem_int, src_int_ty), LLVMConstInt(src_int_ty, i * elem_bits, false)); + as_int = LLVMConstOr(as_int, shifted); + } + } else if (src_kind == LLVMStructTypeKind) { + unsigned field_count = LLVMCountStructElementTypes(src_ty); + LLVMTypeRef src_int_ty = LLVMIntTypeInContext(ctx, src_bits); + as_int = LLVMConstInt(src_int_ty, 0, false); + + for (unsigned i = 0; i < field_count; i++) { + LLVMTypeRef field_ty = LLVMStructGetTypeAtIndex(src_ty, i); + unsigned field_bits = (unsigned)LLVMSizeOfTypeInBits(td, field_ty); + LLVMValueRef field = llvm_const_extract_value(m, val, i); + + LLVMTypeRef field_int_ty = LLVMIntTypeInContext(ctx, field_bits); + LLVMValueRef field_int = llvm_const_pad_to_size(m, field, field_int_ty); + + uint64_t field_offset_bytes = LLVMOffsetOfElement(td, src_ty, i); + uint64_t field_offset_bits = field_offset_bytes * 8; + + LLVMValueRef shifted = LLVMConstShl(LLVMConstZExt(field_int, src_int_ty), LLVMConstInt(src_int_ty, field_offset_bits, false)); + as_int = LLVMConstOr(as_int, shifted); + } + } else { + gb_printf_err("unsupported const_pad source type: %s\n", LLVMPrintTypeToString(src_ty)); + return nullptr; + } + + if (src_bits != dst_bits) { + LLVMTypeRef dst_int_ty = LLVMIntTypeInContext(ctx, dst_bits); + if (src_bits < dst_bits) { + as_int = LLVMConstZExt(as_int, dst_int_ty); + } else { + as_int = LLVMConstTrunc(as_int, dst_int_ty); + } + } + + LLVMTypeKind dst_kind = LLVMGetTypeKind(dst_ty); + + if (dst_kind == LLVMIntegerTypeKind || + dst_kind == LLVMFloatTypeKind || + dst_kind == LLVMDoubleTypeKind || + dst_kind == LLVMPointerTypeKind || + dst_kind == LLVMVectorTypeKind) { + return LLVMConstBitCast(as_int, dst_ty); + + } else if (dst_kind == LLVMArrayTypeKind) { + unsigned elem_count = LLVMGetArrayLength(dst_ty); + LLVMTypeRef elem_ty = LLVMGetElementType(dst_ty); + unsigned elem_bits = (unsigned)LLVMSizeOfTypeInBits(td, elem_ty); + + LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(elem_count); + LLVMTypeRef as_int_ty = LLVMTypeOf(as_int); + + for (unsigned i = 0; i < elem_count; i++) { + LLVMValueRef shifted = LLVMConstLShr(as_int, LLVMConstInt(as_int_ty, i * elem_bits, false)); + LLVMTypeRef elem_int_ty = LLVMIntTypeInContext(ctx, elem_bits); + LLVMValueRef trunc = LLVMConstTrunc(shifted, elem_int_ty); + elems[i] = llvm_const_pad_to_size(m, trunc, elem_ty); + } + + return LLVMConstArray(elem_ty, elems, elem_count); + } + + gb_printf_err("unsupported const_pad destination type: %s\n", LLVMPrintTypeToString(dst_ty)); + return nullptr; +} +#endif + gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lbConstContext cc, Type *value_type) { if (cc.allow_local) { cc.is_rodata = false; @@ -637,11 +754,16 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb LLVMValueRef values[4] = {}; unsigned value_count = 0; + #if LLVM_VERSION_MAJOR == 14 + LLVMTypeRef block_type = lb_type_internal_union_block_type(m, bt); + values[value_count++] = llvm_const_pad_to_size(m, cv.value, block_type); + #else values[value_count++] = cv.value; if (type_size_of(variant_type) != block_size) { LLVMTypeRef padding_type = lb_type_padding_filler(m, block_size - type_size_of(variant_type), 1); values[value_count++] = LLVMConstNull(padding_type); } + #endif Type *tag_type = union_tag_type(bt); LLVMTypeRef llvm_tag_type = lb_type(m, tag_type); @@ -870,7 +992,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb Type *elem = type->Matrix.elem; lbValue single_elem = lb_const_value(m, elem, value, cc); - single_elem.value = llvm_const_cast(single_elem.value, lb_type(m, elem), /*failure_*/nullptr); + single_elem.value = llvm_const_cast(m, single_elem.value, lb_type(m, elem), /*failure_*/nullptr); i64 total_elem_count = matrix_type_total_internal_elems(type); LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)total_elem_count); @@ -892,7 +1014,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb Type *elem = type->SimdVector.elem; lbValue single_elem = lb_const_value(m, elem, value, cc); - single_elem.value = llvm_const_cast(single_elem.value, lb_type(m, elem), /*failure_*/nullptr); + single_elem.value = llvm_const_cast(m, single_elem.value, lb_type(m, elem), /*failure_*/nullptr); LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, count); for (i64 i = 0; i < count; i++) { @@ -1472,7 +1594,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb values[i] = LLVMConstNull(et); } for (isize i = 0; i < total_elem_count; i++) { - values[i] = llvm_const_cast(values[i], et, /*failure_*/nullptr); + values[i] = llvm_const_cast(m, values[i], et, /*failure_*/nullptr); } res.value = LLVMConstVector(values, cast(unsigned)total_elem_count); |