2
0
Эх сурвалжийг харах

Merge pull request #5768 from A1029384756/llvm-14-fixes

LLVM 14 Const Union Fixes
gingerBill 5 өдөр өмнө
parent
commit
c7b38f855a

+ 110 - 17
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);
 	LLVMTypeRef src = LLVMTypeOf(val);
 	if (src == dst) {
 	if (src == dst) {
 		return val;
 		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));
 	GB_ASSERT_MSG(lb_sizeof(dst) == lb_sizeof(src), "%s vs %s", LLVMPrintTypeToString(dst), LLVMPrintTypeToString(src));
 	LLVMTypeKind kind = LLVMGetTypeKind(dst);
 	LLVMTypeKind kind = LLVMGetTypeKind(dst);
 	switch (kind) {
 	switch (kind) {
-	case LLVMPointerTypeKind:
+	case LLVMPointerTypeKind: {
 		return LLVMConstPointerCast(val, dst);
 		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;
 	if (failure_) *failure_ = true;
 	return val;
 	return val;
 }
 }
@@ -192,7 +211,7 @@ gb_internal LLVMValueRef llvm_const_named_struct_internal(lbModule *m, LLVMTypeR
 	bool failure = false;
 	bool failure = false;
 	for (unsigned i = 0; i < elem_count; i++) {
 	for (unsigned i = 0; i < elem_count; i++) {
 		LLVMTypeRef elem_type = LLVMStructGetTypeAtIndex(t, 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) {
 	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_;
 	unsigned value_count = cast(unsigned)value_count_;
 	bool failure = false;
 	bool failure = false;
 	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, &failure);
+		values[i] = llvm_const_cast(m, values[i], elem_type, &failure);
 	}
 	}
 	if (failure) {
 	if (failure) {
 		return LLVMConstStructInContext(m->ctx, values, value_count, false);
 		return LLVMConstStructInContext(m->ctx, values, value_count, false);
@@ -549,6 +568,83 @@ gb_internal bool lb_is_nested_possibly_constant(Type *ft, Selection const &sel,
 	return lb_is_elem_const(elem, ft);
 	return lb_is_elem_const(elem, ft);
 }
 }
 
 
+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 = llvm_const_shl(m, llvm_const_zext(m, elem_int, src_int_ty), LLVMConstInt(src_int_ty, i * elem_bits, false));
+			as_int = llvm_const_or(m, 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 = llvm_const_zext(m, 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 = llvm_const_lshr(m, 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;
+}
+
 gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lbConstContext cc, Type *value_type) {
 gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lbConstContext cc, Type *value_type) {
 	if (cc.allow_local) {
 	if (cc.allow_local) {
 		cc.is_rodata = false;
 		cc.is_rodata = false;
@@ -634,14 +730,11 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
 			lbValue cv = lb_const_value(m, value_type, value, cc, value_type);
 			lbValue cv = lb_const_value(m, value_type, value, cc, value_type);
 			Type *variant_type = cv.type;
 			Type *variant_type = cv.type;
 
 
-			LLVMValueRef values[4] = {};
+			LLVMValueRef values[3] = {};
 			unsigned value_count = 0;
 			unsigned value_count = 0;
 
 
-			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);
-			}
+			LLVMTypeRef block_type = lb_type_internal_union_block_type(m, bt);
+			values[value_count++] = llvm_const_pad_to_size(m, cv.value, block_type);
 
 
 			Type *tag_type = union_tag_type(bt);
 			Type *tag_type = union_tag_type(bt);
 			LLVMTypeRef llvm_tag_type = lb_type(m, tag_type);
 			LLVMTypeRef llvm_tag_type = lb_type(m, tag_type);
@@ -870,7 +963,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
 		Type *elem = type->Matrix.elem;
 		Type *elem = type->Matrix.elem;
 		
 		
 		lbValue single_elem = lb_const_value(m, elem, value, cc);
 		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);
 		i64 total_elem_count = matrix_type_total_internal_elems(type);
 		LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)total_elem_count);		
 		LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)total_elem_count);		
@@ -892,7 +985,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
 		Type *elem = type->SimdVector.elem;
 		Type *elem = type->SimdVector.elem;
 
 
 		lbValue single_elem = lb_const_value(m, elem, value, cc);
 		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);
 		LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, count);
 		for (i64 i = 0; i < count; i++) {
 		for (i64 i = 0; i < count; i++) {
@@ -1472,7 +1565,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
 					values[i] = LLVMConstNull(et);
 					values[i] = LLVMConstNull(et);
 				}
 				}
 				for (isize i = 0; i < total_elem_count; i++) {
 				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);
 				res.value = LLVMConstVector(values, cast(unsigned)total_elem_count);

+ 25 - 0
src/llvm_backend_general.cpp

@@ -449,6 +449,31 @@ gb_internal LLVMValueRef llvm_const_insert_value(lbModule *m, LLVMValueRef agg,
 }
 }
 
 
 
 
+gb_internal LLVMValueRef llvm_const_shl(lbModule *m, LLVMValueRef a, LLVMValueRef b) {
+	LLVMValueRef res = LLVMBuildShl(m->const_dummy_builder, a, b, "");
+	GB_ASSERT(LLVMIsConstant(res));
+	return res;
+}
+
+gb_internal LLVMValueRef llvm_const_lshr(lbModule *m, LLVMValueRef a, LLVMValueRef b) {
+	LLVMValueRef res = LLVMBuildLShr(m->const_dummy_builder, a, b, "");
+	GB_ASSERT(LLVMIsConstant(res));
+	return res;
+}
+
+gb_internal LLVMValueRef llvm_const_or(lbModule *m, LLVMValueRef a, LLVMValueRef b) {
+	LLVMValueRef res = LLVMBuildOr(m->const_dummy_builder, a, b, "");
+	GB_ASSERT(LLVMIsConstant(res));
+	return res;
+}
+
+gb_internal LLVMValueRef llvm_const_zext(lbModule *m, LLVMValueRef a, LLVMTypeRef b) {
+	LLVMValueRef res = LLVMBuildZExt(m->const_dummy_builder, a, b, "");
+	GB_ASSERT(LLVMIsConstant(res));
+	return res;
+}
+
+
 
 
 
 
 gb_internal LLVMValueRef llvm_cstring(lbModule *m, String const &str) {
 gb_internal LLVMValueRef llvm_cstring(lbModule *m, String const &str) {