Browse Source

Improve USE_NEW_LLVM_ABI_SYSTEM's System V ABI

gingerBill 4 years ago
parent
commit
a64ea342df
3 changed files with 198 additions and 79 deletions
  1. 73 43
      src/llvm_abi.cpp
  2. 125 35
      src/llvm_backend.cpp
  3. 0 1
      src/types.cpp

+ 73 - 43
src/llvm_abi.cpp

@@ -66,7 +66,7 @@ LLVMTypeRef lb_function_type_to_llvm_ptr(lbFunctionType *ft, bool is_var_arg) {
 	LLVMTypeRef *args = gb_alloc_array(heap_allocator(), LLVMTypeRef, maximum_arg_count);
 	if (offset == 1) {
 		GB_ASSERT(ft->ret.kind == lbArg_Indirect);
-		args[0] = ft->ret.type;
+		args[0] = LLVMPointerType(ft->ret.type, 0);
 	}
 
 	unsigned arg_index = offset;
@@ -172,8 +172,8 @@ i64 lb_sizeof(LLVMTypeRef type) {
 					offset = llvm_align_formula(offset, align);
 					offset += lb_sizeof(field);
 				}
+				offset = llvm_align_formula(offset, lb_alignof(type));
 			}
-			offset = llvm_align_formula(offset, lb_alignof(type));
 			return offset;
 		}
 		break;
@@ -240,14 +240,7 @@ i64 lb_alignof(LLVMTypeRef type) {
 		}
 		break;
 	case LLVMArrayTypeKind:
-		{
-			LLVMTypeRef elem = LLVMGetElementType(type);
-			i64 elem_size = lb_sizeof(elem);
-			i64 count = LLVMGetArrayLength(type);
-			i64 size = count * elem_size;
-			return size;
-		}
-		break;
+		return lb_alignof(LLVMGetElementType(type));
 
 	case LLVMX86_MMXTypeKind:
 		return 8;
@@ -269,7 +262,37 @@ i64 lb_alignof(LLVMTypeRef type) {
 	return 1;
 }
 
-Type *lb_abi_to_odin_type(LLVMTypeRef type) {
+Type *alloc_type_struct_from_field_types(Type **field_types, isize field_count, bool is_packed) {
+	Type *t = alloc_type_struct();
+	t->Struct.fields = array_make<Entity *>(heap_allocator(), field_count);
+
+	Scope *scope = nullptr;
+	for_array(i, t->Struct.fields) {
+		t->Struct.fields[i] = alloc_entity_field(scope, blank_token, field_types[i], false, cast(i32)i, EntityState_Resolved);
+	}
+	t->Struct.is_packed = is_packed;
+
+	return t;
+}
+
+Type *alloc_type_tuple_from_field_types(Type **field_types, isize field_count, bool is_packed) {
+	if (field_count == 1) {
+		return field_types[0];
+	}
+
+	Type *t = alloc_type_tuple();
+	t->Tuple.variables = array_make<Entity *>(heap_allocator(), field_count);
+
+	Scope *scope = nullptr;
+	for_array(i, t->Tuple.variables) {
+		t->Tuple.variables[i] = alloc_entity_param(scope, blank_token, field_types[i], false, false);
+	}
+	t->Tuple.is_packed = is_packed;
+
+	return t;
+}
+
+Type *lb_abi_to_odin_type(LLVMTypeRef type, bool is_return, u32 level = 0) {
 	LLVMTypeKind kind = LLVMGetTypeKind(type);
 	switch (kind) {
 	case LLVMVoidTypeKind:
@@ -282,10 +305,10 @@ Type *lb_abi_to_odin_type(LLVMTypeRef type) {
 			}
 			unsigned bytes = (w + 7)/8;
 			switch (bytes) {
-			case 1: return t_u8;
-			case 2: return t_u16;
-			case 4: return t_u32;
-			case 8: return t_u64;
+			case 1:  return t_u8;
+			case 2:  return t_u16;
+			case 4:  return t_u32;
+			case 8:  return t_u64;
 			case 16: return t_u128;
 			}
 			GB_PANIC("Unhandled integer type");
@@ -298,14 +321,23 @@ Type *lb_abi_to_odin_type(LLVMTypeRef type) {
 		return t_rawptr;
 	case LLVMStructTypeKind:
 		{
-			GB_PANIC("HERE");
+			unsigned field_count = LLVMCountStructElementTypes(type);
+			Type **fields = gb_alloc_array(heap_allocator(), Type *, field_count);
+			for (unsigned i = 0; i < field_count; i++) {
+				fields[i] = lb_abi_to_odin_type(LLVMStructGetTypeAtIndex(type, i), false, level+1);
+			}
+			if (is_return) {
+				return alloc_type_tuple_from_field_types(fields, field_count, !!LLVMIsPackedStruct(type));
+			} else {
+				return alloc_type_struct_from_field_types(fields, field_count, !!LLVMIsPackedStruct(type));
+			}
 		}
 		break;
 	case LLVMArrayTypeKind:
 		{
 
 			i64 count = LLVMGetArrayLength(type);
-			Type *elem = lb_abi_to_odin_type(LLVMGetElementType(type));
+			Type *elem = lb_abi_to_odin_type(LLVMGetElementType(type), false, level+1);
 			return alloc_type_array(elem, count);
 		}
 		break;
@@ -315,7 +347,7 @@ Type *lb_abi_to_odin_type(LLVMTypeRef type) {
 	case LLVMVectorTypeKind:
 		{
 			i64 count = LLVMGetVectorSize(type);
-			Type *elem = lb_abi_to_odin_type(LLVMGetElementType(type));
+			Type *elem = lb_abi_to_odin_type(LLVMGetElementType(type), false, level+1);
 			return alloc_type_simd_vector(count, elem);
 		}
 
@@ -400,7 +432,7 @@ namespace lbAbi386 {
 			case 4: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr);
 			case 8: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 64), nullptr, nullptr);
 			}
-			return lb_arg_type_indirect(LLVMPointerType(return_type, 0), lb_create_enum_attribute(c, "sret", true));
+			return lb_arg_type_indirect(return_type, lb_create_enum_attribute(c, "sret", true));
 		}
 		return non_struct(c, return_type);
 	}
@@ -588,18 +620,6 @@ namespace lbAbiAmd64SysV {
 		return reg_classes;
 	}
 
-	void classify_struct(LLVMTypeRef *fields, unsigned field_count, Array<RegClass> *cls, i64 i, i64 off, LLVMBool packed) {
-		i64 field_off = off;
-		for (unsigned i = 0; i < field_count; i++) {
-			LLVMTypeRef t = fields[i];
-			if (!packed) {
-				field_off = llvm_align_formula(field_off, lb_alignof(t));
-			}
-			classify_with(t, cls, i, field_off);
-			field_off += lb_sizeof(t);
-		}
-	}
-
 	void unify(Array<RegClass> *cls, i64 i, RegClass newv) {
 		RegClass &oldv = (*cls)[i];
 		if (oldv == newv) {
@@ -665,10 +685,10 @@ namespace lbAbiAmd64SysV {
 		}
 	}
 
-	unsigned llvec_len(Array<RegClass> const &reg_classes) {
+	unsigned llvec_len(Array<RegClass> const &reg_classes, isize offset) {
 		unsigned len = 1;
-		for_array(i, reg_classes) {
-			if (reg_classes[i] != RegClass_SSEUp) {
+		for (isize i = offset+1; i < reg_classes.count; i++) {
+			if (reg_classes[offset] != RegClass_SSEFv && reg_classes[i] != RegClass_SSEUp) {
 				break;
 			}
 			len++;
@@ -680,7 +700,8 @@ namespace lbAbiAmd64SysV {
 	LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const &reg_classes) {
 		auto types = array_make<LLVMTypeRef>(heap_allocator(), 0, reg_classes.count);
 		for_array(i, reg_classes) {
-			switch (reg_classes[i]) {
+			RegClass reg_class = reg_classes[i];
+			switch (reg_class) {
 			case RegClass_Int:
 				array_add(&types, LLVMIntTypeInContext(c, 64));
 				break;
@@ -693,7 +714,7 @@ namespace lbAbiAmd64SysV {
 				{
 					unsigned elems_per_word = 0;
 					LLVMTypeRef elem_type = nullptr;
-					switch (reg_classes[i]) {
+					switch (reg_class) {
 					case RegClass_SSEFv:
 						elems_per_word = 2;
 						elem_type = LLVMFloatTypeInContext(c);
@@ -720,7 +741,7 @@ namespace lbAbiAmd64SysV {
 						break;
 					}
 
-					unsigned vec_len = llvec_len(array_slice(reg_classes, i+1, reg_classes.count));
+					unsigned vec_len = llvec_len(reg_classes, i);
 					LLVMTypeRef vec_type = LLVMVectorType(elem_type, vec_len * elems_per_word);
 					array_add(&types, vec_type);
 					i += vec_len;
@@ -738,6 +759,10 @@ namespace lbAbiAmd64SysV {
 			}
 		}
 
+		GB_ASSERT(types.count != 0);
+		if (types.count == 1) {
+			return types[0];
+		}
 		return LLVMStructTypeInContext(c, types.data, cast(unsigned)types.count, false);
 	}
 
@@ -767,13 +792,18 @@ namespace lbAbiAmd64SysV {
 			break;
 		case LLVMStructTypeKind:
 			{
+				LLVMBool packed = LLVMIsPackedStruct(t);
 				unsigned field_count = LLVMCountStructElementTypes(t);
-				LLVMTypeRef *fields = gb_alloc_array(heap_allocator(), LLVMTypeRef, field_count); // HACK(bill): LEAK
-				defer (gb_free(heap_allocator(), fields));
-
-				LLVMGetStructElementTypes(t, fields);
 
-				classify_struct(fields, field_count, cls, ix, off, LLVMIsPackedStruct(t));
+				i64 field_off = off;
+				for (unsigned field_index = 0; field_index < field_count; field_index++) {
+					LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(t, field_index);
+					if (!packed) {
+						field_off = llvm_align_formula(field_off, lb_alignof(field_type));
+					}
+					classify_with(field_type, cls, ix, field_off);
+					field_off += lb_sizeof(field_type);
+				}
 			}
 			break;
 		case LLVMArrayTypeKind:
@@ -859,7 +889,7 @@ namespace lbAbiAmd64SysV {
 			case 4: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr);
 			case 8: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 64), nullptr, nullptr);
 			}
-			return lb_arg_type_indirect(LLVMPointerType(return_type, 0), lb_create_enum_attribute(c, "sret", true));
+			return lb_arg_type_indirect(return_type, lb_create_enum_attribute(c, "sret", true));
 		} else if (build_context.metrics.os == TargetOs_windows && lb_is_type_kind(return_type, LLVMIntegerTypeKind) && lb_sizeof(return_type) == 16) {
 			return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 128), nullptr, nullptr);
 		}

+ 125 - 35
src/llvm_backend.cpp

@@ -1380,7 +1380,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
 				LLVMTypeRef *params = gb_alloc_array(heap_allocator(), LLVMTypeRef, param_count);
 				if (type->Proc.result_count != 0) {
 					Type *single_ret = reduce_tuple_to_single_type(type->Proc.results);
-					ret = lb_type(m, type->Proc.results);
+					ret = lb_type(m, single_ret);
 					if (ret != nullptr) {
 						if (is_calling_convention_none(type->Proc.calling_convention) &&
 						    is_type_boolean(single_ret) &&
@@ -1399,13 +1399,15 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
 							continue;
 						}
 
+						Type *e_type = reduce_tuple_to_single_type(e->type);
+
 						LLVMTypeRef param_type = nullptr;
 						if (is_calling_convention_none(type->Proc.calling_convention) &&
-						    is_type_boolean(e->type) &&
-						    type_size_of(e->type) <= 1) {
+						    is_type_boolean(e_type) &&
+						    type_size_of(e_type) <= 1) {
 							param_type = LLVMInt1TypeInContext(m->ctx);
 						} else {
-							param_type = lb_type(m, e->type);
+							param_type = lb_type(m, e_type);
 						}
 						params[param_index++] =	param_type;
 					}
@@ -2511,7 +2513,13 @@ void lb_start_block(lbProcedure *p, lbBlock *b) {
 
 LLVMValueRef OdinLLVMBuildTransmute(lbProcedure *p, LLVMValueRef val, LLVMTypeRef dst_type) {
 	LLVMTypeRef src_type = LLVMTypeOf(val);
-	GB_ASSERT(lb_sizeof(src_type) == lb_sizeof(dst_type));
+	i64 src_size = lb_sizeof(src_type);
+	i64 dst_size = lb_sizeof(dst_type);
+	if (src_size != dst_size && (lb_is_type_kind(src_type, LLVMVectorTypeKind) ^ lb_is_type_kind(dst_type, LLVMVectorTypeKind))) {
+		// Okay
+	} else {
+		GB_ASSERT_MSG(src_size == dst_size, "%s == %s", LLVMPrintTypeToString(src_type), LLVMPrintTypeToString(dst_type));
+	}
 
 	LLVMTypeKind src_kind = LLVMGetTypeKind(src_type);
 	LLVMTypeKind dst_kind = LLVMGetTypeKind(dst_type);
@@ -4538,27 +4546,51 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
 		}
 
 
-		if (p->type->Proc.return_by_pointer) {
-			if (res.value != nullptr) {
-				lb_addr_store(p, p->return_ptr, res);
+		if (p->abi_function_type) {
+			if (p->abi_function_type->ret.kind == lbArg_Indirect) {
+				if (res.value != nullptr) {
+					LLVMBuildStore(p->builder, res.value, p->return_ptr.addr.value);
+				} else {
+					LLVMBuildStore(p->builder, LLVMConstNull(p->abi_function_type->ret.type), p->return_ptr.addr.value);
+				}
+
+				lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+
+				LLVMBuildRetVoid(p->builder);
 			} else {
-				lb_addr_store(p, p->return_ptr, lb_const_nil(p->module, p->type->Proc.abi_compat_result_type));
+				LLVMValueRef ret_val = res.value;
+				if (p->abi_function_type->ret.cast_type != nullptr) {
+					ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.cast_type);
+				}
+				lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+				LLVMBuildRet(p->builder, ret_val);
 			}
+		} else {
+			GB_ASSERT(!USE_LLVM_ABI);
 
-			lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+			if (p->type->Proc.return_by_pointer) {
+				if (res.value != nullptr) {
+					lb_addr_store(p, p->return_ptr, res);
+				} else {
+					lb_addr_store(p, p->return_ptr, lb_const_nil(p->module, p->type->Proc.abi_compat_result_type));
+				}
 
-			LLVMBuildRetVoid(p->builder);
-		} else {
-			GB_ASSERT_MSG(res.value != nullptr, "%.*s", LIT(p->name));
-			Type *abi_rt = p->type->Proc.abi_compat_result_type;
-			if (!are_types_identical(res.type, abi_rt)) {
-				res = lb_emit_transmute(p, res, abi_rt);
-			}
+				lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
 
-			lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+				LLVMBuildRetVoid(p->builder);
+			} else {
+				GB_ASSERT_MSG(res.value != nullptr, "%.*s", LIT(p->name));
 
-			LLVMBuildRet(p->builder, res.value);
+				Type *abi_rt = p->type->Proc.abi_compat_result_type;
+				if (!are_types_identical(res.type, abi_rt)) {
+					res = lb_emit_transmute(p, res, abi_rt);
+				}
+				lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+				LLVMBuildRet(p->builder, res.value);
+			}
 		}
+
+
 	case_end;
 
 	case_ast_node(is, IfStmt, node);
@@ -6585,8 +6617,6 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 		return res;
 	}
 
-
-
 	// []byte/[]u8 <-> string
 	if (is_type_u8_slice(src) && is_type_string(dst)) {
 		return lb_emit_transmute(p, value, t);
@@ -6636,6 +6666,34 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 		return lb_addr_load(p, result);
 	}
 
+
+	i64 src_sz = type_size_of(src);
+	i64 dst_sz = type_size_of(dst);
+
+	if (src_sz == dst_sz) {
+		// bit_set <-> integer
+		if (is_type_integer(src) && is_type_bit_set(dst)) {
+			lbValue res = lb_emit_conv(p, value, bit_set_to_int(dst));
+			res.type = dst;
+			return res;
+		}
+		if (is_type_bit_set(src) && is_type_integer(dst)) {
+			lbValue bs = value;
+			bs.type = bit_set_to_int(src);
+			return lb_emit_conv(p, bs, dst);
+		}
+
+		// typeid <-> integer
+		if (is_type_integer(src) && is_type_typeid(dst)) {
+			return lb_emit_transmute(p, value, dst);
+		}
+		if (is_type_typeid(src) && is_type_integer(dst)) {
+			return lb_emit_transmute(p, value, dst);
+		}
+	}
+
+
+
 	if (is_type_untyped(src)) {
 		if (is_type_string(src) && is_type_string(dst)) {
 			lbAddr result = lb_add_local_generated(p, t, false);
@@ -6716,6 +6774,14 @@ lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t) {
 	i64 sz = type_size_of(src);
 	i64 dz = type_size_of(dst);
 
+	if (sz != dz) {
+		LLVMTypeRef s = lb_type(m, src);
+		LLVMTypeRef d = lb_type(m, dst);
+		i64 llvm_sz = lb_sizeof(s);
+		i64 llvm_dz = lb_sizeof(d);
+		GB_ASSERT_MSG(llvm_sz == llvm_dz, "%s %s", LLVMPrintTypeToString(s), LLVMPrintTypeToString(d));
+	}
+
 	GB_ASSERT_MSG(sz == dz, "Invalid transmute conversion: '%s' to '%s'", type_to_string(src_type), type_to_string(t));
 
 	// NOTE(bill): Casting between an integer and a pointer cannot be done through a bitcast
@@ -7353,8 +7419,8 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
 		}
 		GB_ASSERT(ft_found != nullptr);
 
-		lbFunctionType *abi_ft = *ft_found;
-		bool return_by_pointer = abi_ft->ret.kind == lbArg_Indirect;
+		lbFunctionType *ft = *ft_found;
+		bool return_by_pointer = ft->ret.kind == lbArg_Indirect;
 
 		unsigned param_index = 0;
 		for (isize i = 0; i < param_count; i++) {
@@ -7365,7 +7431,7 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
 			GB_ASSERT(e->flags & EntityFlag_Param);
 
 			Type *original_type = e->type;
-			lbArgType *arg = &abi_ft->args[param_index];
+			lbArgType *arg = &ft->args[param_index];
 			if (arg->kind == lbArg_Ignore) {
 				continue;
 			}
@@ -7381,9 +7447,15 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
 				if (xt == abi_type) {
 					array_add(&processed_args, x);
 				} else {
-					Type *at = lb_abi_to_odin_type(abi_type);
+					Type *at = lb_abi_to_odin_type(abi_type, false);
 					if (at == t_llvm_bool) {
 						x = lb_emit_conv(p, x, at);
+					} else if (is_type_simd_vector(at) && lb_sizeof(abi_type) > lb_sizeof(xt)) {
+						lbAddr v = lb_add_local_generated(p, at, false);
+						lbValue ptr = lb_addr_get_ptr(p, v);
+						ptr = lb_emit_conv(p, ptr, alloc_type_pointer(x.type));
+						lb_emit_store(p, ptr, x);
+						x = lb_addr_load(p, v);
 					} else {
 						x = lb_emit_transmute(p, x, at);
 					}
@@ -7420,16 +7492,27 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
 			GB_ASSERT(is_type_pointer(return_ptr.type));
 			lb_emit_call_internal(p, value, return_ptr, processed_args, nullptr, context_ptr, inlining);
 			result = lb_emit_load(p, return_ptr);
-		} else {
-			LLVMTypeRef ret_type = abi_ft->ret.cast_type;
+		} else if (rt != nullptr) {
+			LLVMTypeRef ret_type = ft->ret.cast_type;
 			if (!ret_type) {
-				ret_type = abi_ft->ret.type;
+				ret_type = ft->ret.type;
 			}
-			Type *abi_rt = lb_abi_to_odin_type(ret_type);
+			Type *abi_rt = lb_abi_to_odin_type(ret_type, true);
 			result = lb_emit_call_internal(p, value, {}, processed_args, abi_rt, context_ptr, inlining);
-			if (abi_rt != rt) {
-				result = lb_emit_transmute(p, result, rt);
+			if (ret_type != lb_type(m, rt)) {
+				if (is_type_simd_vector(abi_rt) && lb_sizeof(ret_type) > type_size_of(rt)) {
+					lbValue ptr = lb_address_from_load_or_generate_local(p, result);
+					ptr = lb_emit_conv(p, ptr, alloc_type_pointer(rt));
+					result = lb_emit_load(p, ptr);
+				} else {
+					result = lb_emit_transmute(p, result, rt);
+				}
 			}
+			if (!is_type_tuple(rt)) {
+				result = lb_emit_conv(p, result, rt);
+			}
+		} else {
+			lb_emit_call_internal(p, value, {}, processed_args, nullptr, context_ptr, inlining);
 		}
 
 	} else {
@@ -12856,6 +12939,10 @@ void lb_generate_code(lbGenerator *gen) {
 		LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
 	}
 
+
+	String filepath_ll  = concatenate_strings(heap_allocator(), gen->output_base, STR_LIT(".ll"));
+	defer (gb_free(heap_allocator(), filepath_ll.text));
+
 	TIME_SECTION("LLVM Procedure Generation");
 	for_array(i, m->procedures_to_generate) {
 		lbProcedure *p = m->procedures_to_generate[i];
@@ -12886,7 +12973,11 @@ void lb_generate_code(lbGenerator *gen) {
 			gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
 			LLVMDumpValue(p->value);
 			gb_printf_err("\n\n\n\n");
-			LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
+			if (LLVMPrintModuleToFile(mod, cast(char const *)filepath_ll.text, &llvm_error)) {
+				gb_printf_err("LLVM Error: %s\n", llvm_error);
+			}
+			LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
+			gb_exit(1);
 		}
 	}
 
@@ -12933,9 +13024,6 @@ void lb_generate_code(lbGenerator *gen) {
 	llvm_error = nullptr;
 	defer (LLVMDisposeMessage(llvm_error));
 
-	String filepath_ll  = concatenate_strings(heap_allocator(), gen->output_base, STR_LIT(".ll"));
-	defer (gb_free(heap_allocator(), filepath_ll.text));
-
 	String filepath_obj = {};
 	LLVMCodeGenFileType code_gen_file_type = LLVMObjectFile;
 
@@ -12962,6 +13050,7 @@ void lb_generate_code(lbGenerator *gen) {
 	LLVMDIBuilderFinalize(m->debug_builder);
 	if (LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error)) {
 		gb_printf_err("LLVM Error: %s\n", llvm_error);
+		gb_exit(1);
 		return;
 	}
 	llvm_error = nullptr;
@@ -12969,6 +13058,7 @@ void lb_generate_code(lbGenerator *gen) {
 		TIME_SECTION("LLVM Print Module to File");
 		if (LLVMPrintModuleToFile(mod, cast(char const *)filepath_ll.text, &llvm_error)) {
 			gb_printf_err("LLVM Error: %s\n", llvm_error);
+			gb_exit(1);
 			return;
 		}
 	}

+ 0 - 1
src/types.cpp

@@ -2388,7 +2388,6 @@ Selection lookup_field_from_index(Type *type, i64 index) {
 	return empty_selection;
 }
 
-
 Entity *scope_lookup_current(Scope *s, String const &name);
 
 Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel, bool allow_blank_ident) {