浏览代码

Global const unions with `@(rodata)`

gingerBill 2 周之前
父节点
当前提交
17204bd1c2
共有 3 个文件被更改,包括 70 次插入54 次删除
  1. 42 33
      src/llvm_backend.cpp
  2. 1 1
      src/llvm_backend.hpp
  3. 27 20
      src/llvm_backend_const.cpp

+ 42 - 33
src/llvm_backend.cpp

@@ -3262,36 +3262,13 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
 		lbModule *m = &gen->default_module;
 		lbModule *m = &gen->default_module;
 		String name = lb_get_entity_name(m, e);
 		String name = lb_get_entity_name(m, e);
 
 
+		lbGlobalVariable var = {};
+		var.decl = decl;
+
 		lbValue g = {};
 		lbValue g = {};
-		g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
 		g.type = alloc_type_pointer(e->type);
 		g.type = alloc_type_pointer(e->type);
+		g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
 
 
-		lb_apply_thread_local_model(g.value, e->Variable.thread_local_model);
-
-		if (is_foreign) {
-			LLVMSetLinkage(g.value, LLVMExternalLinkage);
-			LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass);
-			LLVMSetExternallyInitialized(g.value, true);
-			lb_add_foreign_library_path(m, e->Variable.foreign_library);
-		} else {
-			LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type)));
-		}
-		if (is_export) {
-			LLVMSetLinkage(g.value, LLVMDLLExportLinkage);
-			LLVMSetDLLStorageClass(g.value, LLVMDLLExportStorageClass);
-		} else if (!is_foreign) {
-			LLVMSetLinkage(g.value, USE_SEPARATE_MODULES ? LLVMWeakAnyLinkage : LLVMInternalLinkage);
-		}
-		lb_set_linkage_from_entity_flags(m, g.value, e->flags);
-		LLVMSetAlignment(g.value, cast(u32)type_align_of(e->type));
-		
-		if (e->Variable.link_section.len > 0) {
-			LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section));
-		}
-
-		lbGlobalVariable var = {};
-		var.var = g;
-		var.decl = decl;
 
 
 		if (decl->init_expr != nullptr) {
 		if (decl->init_expr != nullptr) {
 			TypeAndValue tav = type_and_value_of_expr(decl->init_expr);
 			TypeAndValue tav = type_and_value_of_expr(decl->init_expr);
@@ -3305,6 +3282,11 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
 
 
 						ExactValue v = tav.value;
 						ExactValue v = tav.value;
 						lbValue init = lb_const_value(m, tav.type, v, cc);
 						lbValue init = lb_const_value(m, tav.type, v, cc);
+
+						LLVMDeleteGlobal(g.value);
+						g.value = nullptr;
+						g.value = LLVMAddGlobal(m->mod, LLVMTypeOf(init.value), alloc_cstring(permanent_allocator(), name));
+
 						LLVMSetInitializer(g.value, init.value);
 						LLVMSetInitializer(g.value, init.value);
 						var.is_initialized = true;
 						var.is_initialized = true;
 						if (cc.is_rodata) {
 						if (cc.is_rodata) {
@@ -3323,15 +3305,32 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
 			LLVMSetGlobalConstant(g.value, true);
 			LLVMSetGlobalConstant(g.value, true);
 		}
 		}
 
 
-		if (e->flags & EntityFlag_Require) {
-			lb_append_to_compiler_used(m, g.value);
-		}
 
 
-		array_add(&global_variables, var);
+		lb_apply_thread_local_model(g.value, e->Variable.thread_local_model);
 
 
-		lb_add_entity(m, e, g);
-		lb_add_member(m, name, g);
+		if (is_foreign) {
+			LLVMSetLinkage(g.value, LLVMExternalLinkage);
+			LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass);
+			LLVMSetExternallyInitialized(g.value, true);
+			lb_add_foreign_library_path(m, e->Variable.foreign_library);
+		} else if (!var.is_initialized) {
+			LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type)));
+		}
+		if (is_export) {
+			LLVMSetLinkage(g.value, LLVMDLLExportLinkage);
+			LLVMSetDLLStorageClass(g.value, LLVMDLLExportStorageClass);
+		} else if (!is_foreign) {
+			LLVMSetLinkage(g.value, USE_SEPARATE_MODULES ? LLVMWeakAnyLinkage : LLVMInternalLinkage);
+		}
+		lb_set_linkage_from_entity_flags(m, g.value, e->flags);
+		LLVMSetAlignment(g.value, cast(u32)type_align_of(e->type));
 
 
+		if (e->Variable.link_section.len > 0) {
+			LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section));
+		}
+		if (e->flags & EntityFlag_Require) {
+			lb_append_to_compiler_used(m, g.value);
+		}
 
 
 		if (m->debug_builder) {
 		if (m->debug_builder) {
 			String global_name = e->token.string;
 			String global_name = e->token.string;
@@ -3361,6 +3360,16 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
 				LLVMGlobalSetMetadata(g.value, 0, global_variable_metadata);
 				LLVMGlobalSetMetadata(g.value, 0, global_variable_metadata);
 			}
 			}
 		}
 		}
+
+		g.value = LLVMConstPointerCast(g.value, lb_type(m, alloc_type_pointer(e->type)));
+
+		var.var = g;
+		array_add(&global_variables, var);
+
+		lb_add_entity(m, e, g);
+		lb_add_member(m, name, g);
+
+
 	}
 	}
 
 
 	if (build_context.ODIN_DEBUG) {
 	if (build_context.ODIN_DEBUG) {

+ 1 - 1
src/llvm_backend.hpp

@@ -604,7 +604,7 @@ gb_internal lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, As
 gb_internal lbValue lb_build_cond(lbProcedure *p, Ast *cond, lbBlock *true_block, lbBlock *false_block);
 gb_internal lbValue lb_build_cond(lbProcedure *p, Ast *cond, lbBlock *true_block, lbBlock *false_block);
 
 
 gb_internal LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValueRef *values, isize value_count_);
 gb_internal LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValueRef *values, isize value_count_);
-gb_internal LLVMValueRef llvm_const_named_struct_internal(LLVMTypeRef t, LLVMValueRef *values, isize value_count_);
+gb_internal LLVMValueRef llvm_const_named_struct_internal(lbModule *m, LLVMTypeRef t, LLVMValueRef *values, isize value_count_);
 gb_internal void lb_set_entity_from_other_modules_linkage_correctly(lbModule *other_module, Entity *e, String const &name);
 gb_internal void lb_set_entity_from_other_modules_linkage_correctly(lbModule *other_module, Entity *e, String const &name);
 
 
 gb_internal lbValue lb_expr_untyped_const_to_typed(lbModule *m, Ast *expr, Type *t);
 gb_internal lbValue lb_expr_untyped_const_to_typed(lbModule *m, Ast *expr, Type *t);

+ 27 - 20
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) {
+gb_internal LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst, bool *failure_) {
 	LLVMTypeRef src = LLVMTypeOf(val);
 	LLVMTypeRef src = LLVMTypeOf(val);
 	if (src == dst) {
 	if (src == dst) {
 		return val;
 		return val;
@@ -97,10 +97,8 @@ gb_internal LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst) {
 		return LLVMConstPointerCast(val, dst);
 		return LLVMConstPointerCast(val, dst);
 	case LLVMStructTypeKind:
 	case LLVMStructTypeKind:
 		return val;
 		return val;
-	default:
-		GB_PANIC("Unhandled const cast %s to %s", LLVMPrintTypeToString(src), LLVMPrintTypeToString(dst));
 	}
 	}
-
+	if (failure_) *failure_ = true;
 	return val;
 	return val;
 }
 }
 
 
@@ -125,13 +123,13 @@ gb_internal LLVMValueRef llvm_const_string_internal(lbModule *m, Type *t, LLVMVa
 			LLVMConstNull(lb_type(m, t_i32)),
 			LLVMConstNull(lb_type(m, t_i32)),
 			len,
 			len,
 		};
 		};
-		return llvm_const_named_struct_internal(lb_type(m, t), values, 3);
+		return llvm_const_named_struct_internal(m, lb_type(m, t), values, 3);
 	} else {
 	} else {
 		LLVMValueRef values[2] = {
 		LLVMValueRef values[2] = {
 			data,
 			data,
 			len,
 			len,
 		};
 		};
-		return llvm_const_named_struct_internal(lb_type(m, t), values, 2);
+		return llvm_const_named_struct_internal(m, lb_type(m, t), values, 2);
 	}
 	}
 }
 }
 
 
@@ -143,13 +141,13 @@ gb_internal LLVMValueRef llvm_const_string16_internal(lbModule *m, Type *t, LLVM
 			LLVMConstNull(lb_type(m, t_i32)),
 			LLVMConstNull(lb_type(m, t_i32)),
 			len,
 			len,
 		};
 		};
-		return llvm_const_named_struct_internal(lb_type(m, t), values, 3);
+		return llvm_const_named_struct_internal(m, lb_type(m, t), values, 3);
 	} else {
 	} else {
 		LLVMValueRef values[2] = {
 		LLVMValueRef values[2] = {
 			data,
 			data,
 			len,
 			len,
 		};
 		};
-		return llvm_const_named_struct_internal(lb_type(m, t), values, 2);
+		return llvm_const_named_struct_internal(m, lb_type(m, t), values, 2);
 	}
 	}
 }
 }
 
 
@@ -161,7 +159,7 @@ gb_internal LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValue
 	unsigned value_count = cast(unsigned)value_count_;
 	unsigned value_count = cast(unsigned)value_count_;
 	unsigned elem_count = LLVMCountStructElementTypes(struct_type);
 	unsigned elem_count = LLVMCountStructElementTypes(struct_type);
 	if (elem_count == value_count) {
 	if (elem_count == value_count) {
-		return llvm_const_named_struct_internal(struct_type, values, value_count_);
+		return llvm_const_named_struct_internal(m, struct_type, values, value_count_);
 	}
 	}
 	Type *bt = base_type(t);
 	Type *bt = base_type(t);
 	GB_ASSERT(bt->kind == Type_Struct || bt->kind == Type_Union);
 	GB_ASSERT(bt->kind == Type_Struct || bt->kind == Type_Union);
@@ -181,24 +179,33 @@ gb_internal LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValue
 		}
 		}
 	}
 	}
 	
 	
-	return llvm_const_named_struct_internal(struct_type, values_with_padding, values_with_padding_count);
+	return llvm_const_named_struct_internal(m, struct_type, values_with_padding, values_with_padding_count);
 }
 }
 
 
-gb_internal LLVMValueRef llvm_const_named_struct_internal(LLVMTypeRef t, LLVMValueRef *values, isize value_count_) {
+gb_internal LLVMValueRef llvm_const_named_struct_internal(lbModule *m, LLVMTypeRef t, LLVMValueRef *values, isize value_count_) {
 	unsigned value_count = cast(unsigned)value_count_;
 	unsigned value_count = cast(unsigned)value_count_;
 	unsigned elem_count = LLVMCountStructElementTypes(t);
 	unsigned elem_count = LLVMCountStructElementTypes(t);
 	GB_ASSERT_MSG(value_count == elem_count, "%s %u %u", LLVMPrintTypeToString(t), value_count, elem_count);
 	GB_ASSERT_MSG(value_count == elem_count, "%s %u %u", LLVMPrintTypeToString(t), value_count, elem_count);
+	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);
+		values[i] = llvm_const_cast(values[i], elem_type, &failure);
+	}
+
+	if (failure) {
+		return LLVMConstStructInContext(m->ctx, values, value_count, true);
 	}
 	}
 	return LLVMConstNamedStruct(t, values, value_count);
 	return LLVMConstNamedStruct(t, values, value_count);
 }
 }
 
 
 gb_internal LLVMValueRef llvm_const_array(lbModule *m, 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_;
+	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);
+		values[i] = llvm_const_cast(values[i], elem_type, &failure);
+	}
+	if (failure) {
+		return LLVMConstStructInContext(m->ctx, values, value_count, false);
 	}
 	}
 	for (unsigned i = 0; i < value_count; i++) {
 	for (unsigned i = 0; i < value_count; i++) {
 		if (elem_type != LLVMTypeOf(values[i])) {
 		if (elem_type != LLVMTypeOf(values[i])) {
@@ -851,7 +858,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
 
 
 			if (is_type_union_maybe_pointer(type)) {
 			if (is_type_union_maybe_pointer(type)) {
 				LLVMValueRef values[1] = {cv.value};
 				LLVMValueRef values[1] = {cv.value};
-				res.value = llvm_const_named_struct_internal(llvm_type, values, 1);
+				res.value = llvm_const_named_struct_internal(m, llvm_type, values, 1);
 				res.type = original_type;
 				res.type = original_type;
 				return res;
 				return res;
 			} else {
 			} else {
@@ -869,7 +876,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
 					value_count = 3;
 					value_count = 3;
 					padding = LLVMConstNull(LLVMStructGetTypeAtIndex(llvm_type, 2));
 					padding = LLVMConstNull(LLVMStructGetTypeAtIndex(llvm_type, 2));
 				}
 				}
-				res.value = llvm_const_named_struct_internal(llvm_type, values, value_count);
+				res.value = llvm_const_named_struct_internal(m, llvm_type, values, value_count);
 				res.type = original_type;
 				res.type = original_type;
 				return res;
 				return res;
 			}
 			}
@@ -1060,7 +1067,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));
+		single_elem.value = llvm_const_cast(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);		
@@ -1082,7 +1089,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));
+		single_elem.value = llvm_const_cast(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++) {
@@ -1662,7 +1669,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);
+					values[i] = llvm_const_cast(values[i], et, /*failure_*/nullptr);
 				}
 				}
 
 
 				res.value = LLVMConstVector(values, cast(unsigned)total_elem_count);
 				res.value = LLVMConstVector(values, cast(unsigned)total_elem_count);
@@ -1829,7 +1836,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
 			}
 			}
 
 
 			if (is_constant) {
 			if (is_constant) {
-				res.value = llvm_const_named_struct_internal(struct_type, values, cast(unsigned)value_count);
+				res.value = llvm_const_named_struct_internal(m, struct_type, values, cast(unsigned)value_count);
 				return res;
 				return res;
 			} else {
 			} else {
 				// TODO(bill): THIS IS HACK BUT IT WORKS FOR WHAT I NEED
 				// TODO(bill): THIS IS HACK BUT IT WORKS FOR WHAT I NEED
@@ -1843,7 +1850,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
 						new_values[i] = LLVMConstNull(LLVMTypeOf(old_value));
 						new_values[i] = LLVMConstNull(LLVMTypeOf(old_value));
 					}
 					}
 				}
 				}
-				LLVMValueRef constant_value = llvm_const_named_struct_internal(struct_type, new_values, cast(unsigned)value_count);
+				LLVMValueRef constant_value = llvm_const_named_struct_internal(m, struct_type, new_values, cast(unsigned)value_count);
 
 
 				GB_ASSERT(is_local);
 				GB_ASSERT(is_local);
 				lbProcedure *p = m->curr_procedure;
 				lbProcedure *p = m->curr_procedure;