Browse Source

Removed use of deprecated functions. Cleaned up most deprecated use of LLVMGetElementType.

Christoffer Lerno 3 years ago
parent
commit
9c0a3b6c60

+ 5 - 6
src/llvm_backend.cpp

@@ -739,11 +739,11 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start
 	lb_begin_procedure_body(p);
 
 	if (startup_type_info) {
-		LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, "");
+		LLVMBuildCall2(p->builder, lb_llvm_get_pointer_type(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, "");
 	}
 
 	if (objc_names) {
-		LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, objc_names->type)), objc_names->value, nullptr, 0, "");
+		LLVMBuildCall2(p->builder, lb_llvm_get_pointer_type(lb_type(main_module, objc_names->type)), objc_names->value, nullptr, 0, "");
 	}
 
 	for_array(i, global_variables) {
@@ -762,7 +762,7 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start
 		if (init_expr != nullptr)  {
 			lbValue init = lb_build_expr(p, init_expr);
 			if (init.value == nullptr) {
-				LLVMTypeRef global_type = LLVMGetElementType(LLVMTypeOf(var->var.value));
+				LLVMTypeRef global_type = llvm_addr_type(p->module, var->var);
 				if (is_type_untyped_undef(init.type)) {
 					// LLVMSetInitializer(var->var.value, LLVMGetUndef(global_type));
 					LLVMSetInitializer(var->var.value, LLVMConstNull(global_type));
@@ -805,8 +805,7 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start
 				lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr));
 				lb_emit_store(p, ti,   lb_type_info(main_module, var_type));
 			} else {
-				LLVMTypeRef pvt = LLVMTypeOf(var->var.value);
-				LLVMTypeRef vt = LLVMGetElementType(pvt);
+				LLVMTypeRef vt = llvm_addr_type(p->module, var->var);
 				lbValue src0 = lb_emit_conv(p, var->init, t);
 				LLVMValueRef src = OdinLLVMBuildTransmute(p, src0.value, vt);
 				LLVMValueRef dst = var->var.value;
@@ -933,7 +932,7 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
 			GB_ASSERT(LLVMIsConstant(vals[1]));
 			GB_ASSERT(LLVMIsConstant(vals[2]));
 
-			LLVMValueRef dst = LLVMConstInBoundsGEP(all_tests_array.value, indices, gb_count_of(indices));
+			LLVMValueRef dst = LLVMConstInBoundsGEP2(llvm_addr_type(m, all_tests_array), all_tests_array.value, indices, gb_count_of(indices));
 			LLVMValueRef src = llvm_const_named_struct(m, t_Internal_Test, vals, gb_count_of(vals));
 
 			LLVMBuildStore(p->builder, src, dst);

+ 20 - 2
src/llvm_backend.hpp

@@ -42,6 +42,18 @@
 #define ODIN_LLVM_MINIMUM_VERSION_12 0
 #endif
 
+#if LLVM_VERSION_MAJOR > 13 || (LLVM_VERSION_MAJOR == 13 && LLVM_VERSION_MINOR >= 0 && LLVM_VERSION_PATCH > 0)
+#define ODIN_LLVM_MINIMUM_VERSION_13 1
+#else
+#define ODIN_LLVM_MINIMUM_VERSION_13 0
+#endif
+
+#if LLVM_VERSION_MAJOR > 14 || (LLVM_VERSION_MAJOR == 14 && LLVM_VERSION_MINOR >= 0 && LLVM_VERSION_PATCH > 0)
+#define ODIN_LLVM_MINIMUM_VERSION_14 1
+#else
+#define ODIN_LLVM_MINIMUM_VERSION_14 0
+#endif
+
 struct lbProcedure;
 
 struct lbValue {
@@ -299,7 +311,11 @@ struct lbProcedure {
 
 
 
-
+#if !ODIN_LLVM_MINIMUM_VERSION_14
+#define LLVMConstGEP2(Ty__, ConstantVal__, ConstantIndices__, NumIndices__) LLVMConstGEP(ConstantVal__, ConstantIndices__, NumIndices__)
+#define LLVMConstInBoundsGEP2(Ty__, ConstantVal__, ConstantIndices__, NumIndices__) LLVMConstInBoundsGEP(ConstantVal__, ConstantIndices__, NumIndices__)
+#define LLVMBuildPtrDiff2(Builder__, Ty__, LHS__, RHS__, Name__) LLVMBuildPtrDiff(Builder__, LHS__, RHS__, Name__)
+#endif
 
 bool lb_init_generator(lbGenerator *gen, Checker *c);
 
@@ -327,7 +343,8 @@ lbValue lb_const_int(lbModule *m, Type *type, u64 value);
 
 lbAddr lb_addr(lbValue addr);
 Type *lb_addr_type(lbAddr const &addr);
-LLVMTypeRef lb_addr_lb_type(lbAddr const &addr);
+LLVMTypeRef lb_llvm_get_pointer_type(LLVMTypeRef type);
+LLVMTypeRef llvm_addr_type(lbModule *module, lbValue addr_val);
 void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value);
 lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr);
 lbValue lb_emit_load(lbProcedure *p, lbValue v);
@@ -480,6 +497,7 @@ LLVMTypeRef lb_type_padding_filler(lbModule *m, i64 padding, i64 padding_align);
 
 LLVMValueRef llvm_basic_shuffle(lbProcedure *p, LLVMValueRef vector, LLVMValueRef mask);
 
+LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLVMValueRef* args, unsigned arg_count, LLVMTypeRef* types, unsigned type_count);
 void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
 void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
 LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile);

+ 4 - 4
src/llvm_backend_const.cpp

@@ -10,7 +10,7 @@ bool lb_is_const(lbValue value) {
 	return false;
 }
 
-
+// TODO remove use of LLVMGetElementType
 bool lb_is_const_or_global(lbValue value) {
 	if (lb_is_const(value)) {
 		return true;
@@ -418,7 +418,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
 
 				{
 					LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
-					LLVMValueRef ptr = LLVMBuildInBoundsGEP(p->builder, array_data, indices, 2, "");
+					LLVMValueRef ptr = LLVMBuildInBoundsGEP2(p->builder, llvm_type, array_data, indices, 2, "");
 					LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
 					lbAddr slice = lb_add_local_generated(p, type, false);
 					lb_fill_slice(p, slice, {ptr, alloc_type_pointer(elem)}, {len, t_int});
@@ -445,7 +445,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
 
 				{
 					LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
-					LLVMValueRef ptr = LLVMConstInBoundsGEP(array_data, indices, 2);
+					LLVMValueRef ptr = LLVMConstInBoundsGEP2(lb_type(m, t), array_data, indices, 2);
 					LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
 					LLVMValueRef values[2] = {ptr, len};
 
@@ -1007,7 +1007,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
 				for (isize i = 0; i < value_count; i++) {
 					LLVMValueRef val = old_values[i];
 					if (!LLVMIsConstant(val)) {
-						LLVMValueRef dst = LLVMBuildStructGEP(p->builder, v.addr.value, cast(unsigned)i, "");
+						LLVMValueRef dst = LLVMBuildStructGEP2(p->builder, llvm_addr_type(p->module, v.addr), v.addr.value, cast(unsigned)i, "");
 						LLVMBuildStore(p->builder, val, dst);
 					}
 				}

+ 116 - 114
src/llvm_backend_expr.cpp

@@ -243,8 +243,9 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type)
 			LLVMValueRef v1 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 1, ""), "");
 
 			lbAddr addr = lb_add_local_generated(p, x.type, false);
-			LLVMBuildStore(p->builder, v0, LLVMBuildStructGEP(p->builder, addr.addr.value, 0, ""));
-			LLVMBuildStore(p->builder, v1, LLVMBuildStructGEP(p->builder, addr.addr.value, 1, ""));
+			LLVMTypeRef type = llvm_addr_type(p->module, addr.addr);
+			LLVMBuildStore(p->builder, v0, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 0, ""));
+			LLVMBuildStore(p->builder, v1, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 1, ""));
 			return lb_addr_load(p, addr);
 
 		} else if (is_type_quaternion(x.type)) {
@@ -254,10 +255,11 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type)
 			LLVMValueRef v3 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 3, ""), "");
 
 			lbAddr addr = lb_add_local_generated(p, x.type, false);
-			LLVMBuildStore(p->builder, v0, LLVMBuildStructGEP(p->builder, addr.addr.value, 0, ""));
-			LLVMBuildStore(p->builder, v1, LLVMBuildStructGEP(p->builder, addr.addr.value, 1, ""));
-			LLVMBuildStore(p->builder, v2, LLVMBuildStructGEP(p->builder, addr.addr.value, 2, ""));
-			LLVMBuildStore(p->builder, v3, LLVMBuildStructGEP(p->builder, addr.addr.value, 3, ""));
+			LLVMTypeRef type = llvm_addr_type(p->module, addr.addr);
+			LLVMBuildStore(p->builder, v0, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 0, ""));
+			LLVMBuildStore(p->builder, v1, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 1, ""));
+			LLVMBuildStore(p->builder, v2, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 2, ""));
+			LLVMBuildStore(p->builder, v3, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 3, ""));
 			return lb_addr_load(p, addr);
 		} else if (is_type_simd_vector(x.type)) {
 			Type *elem = base_array_type(x.type);
@@ -543,7 +545,7 @@ LLVMValueRef lb_matrix_to_vector(lbProcedure *p, lbValue matrix) {
 #if 1
 	LLVMValueRef ptr = lb_address_from_load_or_generate_local(p, matrix).value;
 	LLVMValueRef matrix_vector_ptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(total_matrix_type, 0), "");
-	LLVMValueRef matrix_vector = LLVMBuildLoad(p->builder, matrix_vector_ptr, "");
+	LLVMValueRef matrix_vector = LLVMBuildLoad2(p->builder, total_matrix_type, matrix_vector_ptr, "");
 	LLVMSetAlignment(matrix_vector, cast(unsigned)type_align_of(mt));
 	return matrix_vector;
 #else
@@ -555,7 +557,7 @@ LLVMValueRef lb_matrix_to_vector(lbProcedure *p, lbValue matrix) {
 LLVMValueRef lb_matrix_trimmed_vector_mask(lbProcedure *p, Type *mt) {
 	mt = base_type(mt);
 	GB_ASSERT(mt->kind == Type_Matrix);
-	
+
 	unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt);
 	unsigned row_count = cast(unsigned)mt->Matrix.row_count;
 	unsigned column_count = cast(unsigned)mt->Matrix.column_count;
@@ -567,23 +569,23 @@ LLVMValueRef lb_matrix_trimmed_vector_mask(lbProcedure *p, Type *mt) {
 			mask_elems[mask_elems_index++] = lb_const_int(p->module, t_u32, offset).value;
 		}
 	}
-	
+
 	LLVMValueRef mask = LLVMConstVector(mask_elems.data, cast(unsigned)mask_elems.count);
 	return mask;
 }
 
 LLVMValueRef lb_matrix_to_trimmed_vector(lbProcedure *p, lbValue m) {
 	LLVMValueRef vector = lb_matrix_to_vector(p, m);
-	
+
 	Type *mt = base_type(m.type);
 	GB_ASSERT(mt->kind == Type_Matrix);
-	
+
 	unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt);
 	unsigned row_count = cast(unsigned)mt->Matrix.row_count;
 	if (stride == row_count) {
 		return vector;
 	}
-	
+
 	LLVMValueRef mask = lb_matrix_trimmed_vector_mask(p, mt);
 	LLVMValueRef trimmed_vector = llvm_basic_shuffle(p, vector, mask);
 	return trimmed_vector;
@@ -619,28 +621,28 @@ lbValue lb_emit_matrix_tranpose(lbProcedure *p, lbValue m, Type *type) {
 	}
 	Type *mt = base_type(m.type);
 	GB_ASSERT(mt->kind == Type_Matrix);
-	
+
 	if (lb_is_matrix_simdable(mt)) {
 		unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt);
 		unsigned row_count    = cast(unsigned)mt->Matrix.row_count;
 		unsigned column_count = cast(unsigned)mt->Matrix.column_count;
-		
+
 		auto rows = slice_make<LLVMValueRef>(permanent_allocator(), row_count);
 		auto mask_elems = slice_make<LLVMValueRef>(permanent_allocator(), column_count);
-		
+
 		LLVMValueRef vector = lb_matrix_to_vector(p, m);
 		for (unsigned i = 0; i < row_count; i++) {
 			for (unsigned j = 0; j < column_count; j++) {
 				unsigned offset = stride*j + i;
 				mask_elems[j] = lb_const_int(p->module, t_u32, offset).value;
 			}
-			
+
 			// transpose mask
 			LLVMValueRef mask = LLVMConstVector(mask_elems.data, column_count);
 			LLVMValueRef row = llvm_basic_shuffle(p, vector, mask);
 			rows[i] = row;
 		}
-		
+
 		lbAddr res = lb_add_local_generated(p, type, true);
 		for_array(i, rows) {
 			LLVMValueRef row = rows[i];
@@ -649,12 +651,12 @@ lbValue lb_emit_matrix_tranpose(lbProcedure *p, lbValue m, Type *type) {
 			ptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(LLVMTypeOf(row), 0), "");
 			LLVMBuildStore(p->builder, row, ptr);
 		}
-		
+
 		return lb_addr_load(p, res);
 	}
-	
+
 	lbAddr res = lb_add_local_generated(p, type, true);
-	
+
 	i64 row_count = mt->Matrix.row_count;
 	i64 column_count = mt->Matrix.column_count;
 	for (i64 j = 0; j < column_count; j++) {
@@ -672,10 +674,10 @@ lbValue lb_matrix_cast_vector_to_type(lbProcedure *p, LLVMValueRef vector, Type
 	LLVMValueRef res_ptr = res.addr.value;
 	unsigned alignment = cast(unsigned)gb_max(type_align_of(type), lb_alignof(LLVMTypeOf(vector)));
 	LLVMSetAlignment(res_ptr, alignment);
-	
+
 	res_ptr = LLVMBuildPointerCast(p->builder, res_ptr, LLVMPointerType(LLVMTypeOf(vector), 0), "");
 	LLVMBuildStore(p->builder, vector, res_ptr);
-	
+
 	return lb_addr_load(p, res);
 }
 
@@ -687,14 +689,14 @@ lbValue lb_emit_matrix_flatten(lbProcedure *p, lbValue m, Type *type) {
 	}
 	Type *mt = base_type(m.type);
 	GB_ASSERT(mt->kind == Type_Matrix);
-	
+
 	if (lb_is_matrix_simdable(mt)) {
 		LLVMValueRef vector = lb_matrix_to_trimmed_vector(p, m);
 		return lb_matrix_cast_vector_to_type(p, vector, type);
 	}
-	
+
 	lbAddr res = lb_add_local_generated(p, type, true);
-	
+
 	i64 row_count = mt->Matrix.row_count;
 	i64 column_count = mt->Matrix.column_count;
 	for (i64 j = 0; j < column_count; j++) {
@@ -715,17 +717,17 @@ lbValue lb_emit_outer_product(lbProcedure *p, lbValue a, lbValue b, Type *type)
 	GB_ASSERT(mt->kind == Type_Matrix);
 	GB_ASSERT(at->kind == Type_Array);
 	GB_ASSERT(bt->kind == Type_Array);
-	
-	
+
+
 	i64 row_count = mt->Matrix.row_count;
 	i64 column_count = mt->Matrix.column_count;
-	
+
 	GB_ASSERT(row_count == at->Array.count);
 	GB_ASSERT(column_count == bt->Array.count);
-	
-	
+
+
 	lbAddr res = lb_add_local_generated(p, type, true);
-	
+
 	for (i64 j = 0; j < column_count; j++) {
 		for (i64 i = 0; i < row_count; i++) {
 			lbValue x = lb_emit_struct_ev(p, a, cast(i32)i);
@@ -741,51 +743,51 @@ lbValue lb_emit_outer_product(lbProcedure *p, lbValue a, lbValue b, Type *type)
 
 lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, Type *type) {
 	// TODO(bill): Handle edge case for f16 types on x86(-64) platforms
-	
+
 	Type *xt = base_type(lhs.type);
 	Type *yt = base_type(rhs.type);
-	
+
 	GB_ASSERT(is_type_matrix(type));
 	GB_ASSERT(is_type_matrix(xt));
 	GB_ASSERT(is_type_matrix(yt));
 	GB_ASSERT(xt->Matrix.column_count == yt->Matrix.row_count);
 	GB_ASSERT(are_types_identical(xt->Matrix.elem, yt->Matrix.elem));
-		
+
 	Type *elem = xt->Matrix.elem;
-	
+
 	unsigned outer_rows    = cast(unsigned)xt->Matrix.row_count;
 	unsigned inner         = cast(unsigned)xt->Matrix.column_count;
 	unsigned outer_columns = cast(unsigned)yt->Matrix.column_count;
-		
+
 	if (lb_is_matrix_simdable(xt)) {
 		unsigned x_stride = cast(unsigned)matrix_type_stride_in_elems(xt);
 		unsigned y_stride = cast(unsigned)matrix_type_stride_in_elems(yt);
-		
+
 		auto x_rows    = slice_make<LLVMValueRef>(permanent_allocator(), outer_rows);
 		auto y_columns = slice_make<LLVMValueRef>(permanent_allocator(), outer_columns);
-		
+
 		LLVMValueRef x_vector = lb_matrix_to_vector(p, lhs);
 		LLVMValueRef y_vector = lb_matrix_to_vector(p, rhs);
-		
+
 		auto mask_elems = slice_make<LLVMValueRef>(permanent_allocator(), inner);
 		for (unsigned i = 0; i < outer_rows; i++) {
 			for (unsigned j = 0; j < inner; j++) {
 				unsigned offset = x_stride*j + i;
 				mask_elems[j] = lb_const_int(p->module, t_u32, offset).value;
 			}
-			
+
 			// transpose mask
 			LLVMValueRef mask = LLVMConstVector(mask_elems.data, inner);
 			LLVMValueRef row = llvm_basic_shuffle(p, x_vector, mask);
 			x_rows[i] = row;
 		}
-		
+
 		for (unsigned i = 0; i < outer_columns; i++) {
 			LLVMValueRef mask = llvm_mask_iota(p->module, y_stride*i, inner);
 			LLVMValueRef column = llvm_basic_shuffle(p, y_vector, mask);
 			y_columns[i] = column;
 		}
-		
+
 		lbAddr res = lb_add_local_generated(p, type, true);
 		for_array(i, x_rows) {
 			LLVMValueRef x_row = x_rows[i];
@@ -795,15 +797,15 @@ lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, Type *type)
 				lbValue dst = lb_emit_matrix_epi(p, res.addr, i, j);
 				LLVMBuildStore(p->builder, elem, dst.value);
 			}
-		}		
+		}
 		return lb_addr_load(p, res);
 	}
-	
+
 	{
 		lbAddr res = lb_add_local_generated(p, type, true);
-		
+
 		auto inners = slice_make<lbValue[2]>(permanent_allocator(), inner);
-		
+
 		for (unsigned j = 0; j < outer_columns; j++) {
 			for (unsigned i = 0; i < outer_rows; i++) {
 				lbValue dst = lb_emit_matrix_epi(p, res.addr, i, j);
@@ -811,7 +813,7 @@ lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, Type *type)
 					inners[k][0] = lb_emit_matrix_ev(p, lhs, i, k);
 					inners[k][1] = lb_emit_matrix_ev(p, rhs, k, j);
 				}
-				
+
 				lbValue sum = lb_const_nil(p->module, elem);
 				for (unsigned k = 0; k < inner; k++) {
 					lbValue a = inners[k][0];
@@ -821,51 +823,51 @@ lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, Type *type)
 				lb_emit_store(p, dst, sum);
 			}
 		}
-		
+
 		return lb_addr_load(p, res);
 	}
 }
 
 lbValue lb_emit_matrix_mul_vector(lbProcedure *p, lbValue lhs, lbValue rhs, Type *type) {
 	// TODO(bill): Handle edge case for f16 types on x86(-64) platforms
-	
+
 	Type *mt = base_type(lhs.type);
 	Type *vt = base_type(rhs.type);
-	
+
 	GB_ASSERT(is_type_matrix(mt));
 	GB_ASSERT(is_type_array_like(vt));
-	
+
 	i64 vector_count = get_array_type_count(vt);
-	
+
 	GB_ASSERT(mt->Matrix.column_count == vector_count);
 	GB_ASSERT(are_types_identical(mt->Matrix.elem, base_array_type(vt)));
-	
+
 	Type *elem = mt->Matrix.elem;
-	
+
 	if (lb_is_matrix_simdable(mt)) {
 		unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt);
-		
+
 		unsigned row_count = cast(unsigned)mt->Matrix.row_count;
 		unsigned column_count = cast(unsigned)mt->Matrix.column_count;
 		auto m_columns = slice_make<LLVMValueRef>(permanent_allocator(), column_count);
 		auto v_rows = slice_make<LLVMValueRef>(permanent_allocator(), column_count);
-		
-		LLVMValueRef matrix_vector = lb_matrix_to_vector(p, lhs);		
-		
+
+		LLVMValueRef matrix_vector = lb_matrix_to_vector(p, lhs);
+
 		for (unsigned column_index = 0; column_index < column_count; column_index++) {
 			LLVMValueRef mask = llvm_mask_iota(p->module, stride*column_index, row_count);
 			LLVMValueRef column = llvm_basic_shuffle(p, matrix_vector, mask);
 			m_columns[column_index] = column;
 		}
-		
+
 		for (unsigned row_index = 0; row_index < column_count; row_index++) {
 			LLVMValueRef value = lb_emit_struct_ev(p, rhs, row_index).value;
 			LLVMValueRef row = llvm_vector_broadcast(p, value, row_count);
 			v_rows[row_index] = row;
 		}
-		
+
 		GB_ASSERT(column_count > 0);
-		
+
 		LLVMValueRef vector = nullptr;
 		for (i64 i = 0; i < column_count; i++) {
 			if (i == 0) {
@@ -874,51 +876,51 @@ lbValue lb_emit_matrix_mul_vector(lbProcedure *p, lbValue lhs, lbValue rhs, Type
 				vector = llvm_vector_mul_add(p, m_columns[i], v_rows[i], vector);
 			}
 		}
-		
+
 		return lb_matrix_cast_vector_to_type(p, vector, type);
 	}
-	
+
 	lbAddr res = lb_add_local_generated(p, type, true);
-	
+
 	for (i64 i = 0; i < mt->Matrix.row_count; i++) {
 		for (i64 j = 0; j < mt->Matrix.column_count; j++) {
 			lbValue dst = lb_emit_matrix_epi(p, res.addr, i, 0);
 			lbValue d0 = lb_emit_load(p, dst);
-			
+
 			lbValue a = lb_emit_matrix_ev(p, lhs, i, j);
 			lbValue b = lb_emit_struct_ev(p, rhs, cast(i32)j);
 			lbValue c = lb_emit_mul_add(p, a, b, d0, elem);
 			lb_emit_store(p, dst, c);
 		}
 	}
-	
+
 	return lb_addr_load(p, res);
 }
 
 lbValue lb_emit_vector_mul_matrix(lbProcedure *p, lbValue lhs, lbValue rhs, Type *type) {
 	// TODO(bill): Handle edge case for f16 types on x86(-64) platforms
-	
+
 	Type *mt = base_type(rhs.type);
 	Type *vt = base_type(lhs.type);
-	
+
 	GB_ASSERT(is_type_matrix(mt));
 	GB_ASSERT(is_type_array_like(vt));
-	
+
 	i64 vector_count = get_array_type_count(vt);
-	
+
 	GB_ASSERT(vector_count == mt->Matrix.row_count);
 	GB_ASSERT(are_types_identical(mt->Matrix.elem, base_array_type(vt)));
-	
+
 	Type *elem = mt->Matrix.elem;
-	
+
 	if (lb_is_matrix_simdable(mt)) {
 		unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt);
-		
+
 		unsigned row_count = cast(unsigned)mt->Matrix.row_count;
 		unsigned column_count = cast(unsigned)mt->Matrix.column_count; gb_unused(column_count);
 		auto m_columns = slice_make<LLVMValueRef>(permanent_allocator(), row_count);
 		auto v_rows = slice_make<LLVMValueRef>(permanent_allocator(), row_count);
-		
+
 		LLVMValueRef matrix_vector = lb_matrix_to_vector(p, rhs);
 
 		auto mask_elems = slice_make<LLVMValueRef>(permanent_allocator(), column_count);
@@ -927,21 +929,21 @@ lbValue lb_emit_vector_mul_matrix(lbProcedure *p, lbValue lhs, lbValue rhs, Type
 				unsigned offset = row_index + column_index*stride;
 				mask_elems[column_index] = lb_const_int(p->module, t_u32, offset).value;
 			}
-			
+
 			// transpose mask
 			LLVMValueRef mask = LLVMConstVector(mask_elems.data, column_count);
 			LLVMValueRef column = llvm_basic_shuffle(p, matrix_vector, mask);
 			m_columns[row_index] = column;
 		}
-		
+
 		for (unsigned column_index = 0; column_index < row_count; column_index++) {
 			LLVMValueRef value = lb_emit_struct_ev(p, lhs, column_index).value;
 			LLVMValueRef row = llvm_vector_broadcast(p, value, column_count);
 			v_rows[column_index] = row;
 		}
-		
+
 		GB_ASSERT(row_count > 0);
-		
+
 		LLVMValueRef vector = nullptr;
 		for (i64 i = 0; i < row_count; i++) {
 			if (i == 0) {
@@ -955,27 +957,27 @@ lbValue lb_emit_vector_mul_matrix(lbProcedure *p, lbValue lhs, lbValue rhs, Type
 		LLVMValueRef res_ptr = res.addr.value;
 		unsigned alignment = cast(unsigned)gb_max(type_align_of(type), lb_alignof(LLVMTypeOf(vector)));
 		LLVMSetAlignment(res_ptr, alignment);
-		
+
 		res_ptr = LLVMBuildPointerCast(p->builder, res_ptr, LLVMPointerType(LLVMTypeOf(vector), 0), "");
 		LLVMBuildStore(p->builder, vector, res_ptr);
-		
+
 		return lb_addr_load(p, res);
 	}
-	
+
 	lbAddr res = lb_add_local_generated(p, type, true);
-		
+
 	for (i64 j = 0; j < mt->Matrix.column_count; j++) {
 		for (i64 k = 0; k < mt->Matrix.row_count; k++) {
 			lbValue dst = lb_emit_matrix_epi(p, res.addr, 0, j);
 			lbValue d0 = lb_emit_load(p, dst);
-			
+
 			lbValue a = lb_emit_struct_ev(p, lhs, cast(i32)k);
 			lbValue b = lb_emit_matrix_ev(p, rhs, k, j);
 			lbValue c = lb_emit_mul_add(p, a, b, d0, elem);
 			lb_emit_store(p, dst, c);
 		}
 	}
-	
+
 	return lb_addr_load(p, res);
 }
 
@@ -984,12 +986,12 @@ lbValue lb_emit_vector_mul_matrix(lbProcedure *p, lbValue lhs, lbValue rhs, Type
 
 lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, bool component_wise) {
 	GB_ASSERT(is_type_matrix(lhs.type) || is_type_matrix(rhs.type));
-	
-	
+
+
 	if (op == Token_Mul && !component_wise) {
 		Type *xt = base_type(lhs.type);
 		Type *yt = base_type(rhs.type);
-		
+
 		if (xt->kind == Type_Matrix) {
 			if (yt->kind == Type_Matrix) {
 				return lb_emit_matrix_mul(p, lhs, rhs, type);
@@ -1000,17 +1002,17 @@ lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue
 			GB_ASSERT(yt->kind == Type_Matrix);
 			return lb_emit_vector_mul_matrix(p, lhs, rhs, type);
 		}
-		
+
 	} else {
 		if (is_type_matrix(lhs.type)) {
 			rhs = lb_emit_conv(p, rhs, lhs.type);
 		} else {
 			lhs = lb_emit_conv(p, lhs, rhs.type);
 		}
-		
+
 		Type *xt = base_type(lhs.type);
 		Type *yt = base_type(rhs.type);
-		
+
 		GB_ASSERT_MSG(are_types_identical(xt, yt), "%s %.*s %s", type_to_string(lhs.type), LIT(token_strings[op]), type_to_string(rhs.type));
 		GB_ASSERT(xt->kind == Type_Matrix);
 		// element-wise arithmetic
@@ -1019,8 +1021,8 @@ lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue
 		lbValue array_rhs = rhs;
 		Type *array_type = alloc_type_array(xt->Matrix.elem, matrix_type_total_internal_elems(xt));
 		GB_ASSERT(type_size_of(array_type) == type_size_of(xt));
-		
-		array_lhs.type = array_type; 
+
+		array_lhs.type = array_type;
 		array_rhs.type = array_type;
 
 		if (token_is_comparison(op)) {
@@ -1033,7 +1035,7 @@ lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue
 		}
 
 	}
-	
+
 	GB_PANIC("TODO: lb_emit_arith_matrix");
 
 	return {};
@@ -1314,13 +1316,13 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
 	ast_node(be, BinaryExpr, expr);
 
 	TypeAndValue tv = type_and_value_of_expr(expr);
-	
+
 	if (is_type_matrix(be->left->tav.type) || is_type_matrix(be->right->tav.type)) {
 		lbValue left = lb_build_expr(p, be->left);
 		lbValue right = lb_build_expr(p, be->right);
 		return lb_emit_arith_matrix(p, be->op.kind, left, right, default_type(tv.type));
 	}
-	
+
 
 	switch (be->op.kind) {
 	case Token_Add:
@@ -1690,7 +1692,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 		}
 		return res;
 	}
-	
+
 
 	if (is_type_complex(src) && is_type_complex(dst)) {
 		Type *ft = base_complex_elem_type(dst);
@@ -1780,7 +1782,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 			}
 			return lb_emit_conv(p, res, t);
 		}
-		
+
 		if (is_type_integer_128bit(dst)) {
 			auto args = array_make<lbValue>(temporary_allocator(), 1);
 			args[0] = value;
@@ -2053,10 +2055,10 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 		}
 		return lb_addr_load(p, v);
 	}
-	
+
 	if (is_type_matrix(dst) && !is_type_matrix(src)) {
 		GB_ASSERT_MSG(dst->Matrix.row_count == dst->Matrix.column_count, "%s <- %s", type_to_string(dst), type_to_string(src));
-		
+
 		Type *elem = base_array_type(dst);
 		lbValue e = lb_emit_conv(p, value, elem);
 		lbAddr v = lb_add_local_generated(p, t, false);
@@ -2065,16 +2067,16 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 			lbValue ptr = lb_emit_matrix_epi(p, v.addr, j, j);
 			lb_emit_store(p, ptr, e);
 		}
-		
-		
+
+
 		return lb_addr_load(p, v);
 	}
-	
+
 	if (is_type_matrix(dst) && is_type_matrix(src)) {
 		GB_ASSERT(dst->kind == Type_Matrix);
 		GB_ASSERT(src->kind == Type_Matrix);
 		lbAddr v = lb_add_local_generated(p, t, true);
-		
+
 		if (is_matrix_square(dst) && is_matrix_square(dst)) {
 			for (i64 j = 0; j < dst->Matrix.column_count; j++) {
 				for (i64 i = 0; i < dst->Matrix.row_count; i++) {
@@ -2093,15 +2095,15 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 			i64 dst_count = dst->Matrix.row_count*dst->Matrix.column_count;
 			i64 src_count = src->Matrix.row_count*src->Matrix.column_count;
 			GB_ASSERT(dst_count == src_count);
-			
+
 			lbValue pdst = v.addr;
 			lbValue psrc = lb_address_from_load_or_generate_local(p, value);
-			
+
 			bool same_elem_base_types = are_types_identical(
 				base_type(dst->Matrix.elem),
 				base_type(src->Matrix.elem)
 			);
-			
+
 			if (same_elem_base_types && type_size_of(dst) == type_size_of(src)) {
 				lb_mem_copy_overlapping(p, v.addr, psrc, lb_const_int(p->module, t_int, type_size_of(dst)));
 			} else {
@@ -2115,9 +2117,9 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 			}
 		}
 		return lb_addr_load(p, v);
-	}	
-	
-	
+	}
+
+
 
 	if (is_type_any(dst)) {
 		if (is_type_untyped_nil(src)) {
@@ -2724,7 +2726,7 @@ lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, lbValue x) {
 			unsigned indices[2] = {0, 0};
 			lbValue hashes_data = lb_emit_struct_ep(p, map_ptr, 0);
 			lbValue hashes_data_ptr_ptr = lb_emit_struct_ep(p, hashes_data, 0);
-			LLVMValueRef hashes_data_ptr = LLVMBuildLoad(p->builder, hashes_data_ptr_ptr.value, "");
+			LLVMValueRef hashes_data_ptr = LLVMBuildLoad2(p->builder, llvm_addr_type(p->module, hashes_data_ptr_ptr), hashes_data_ptr_ptr.value, "");
 
 			if (op_kind == Token_CmpEq) {
 				res.value = LLVMBuildIsNull(p->builder, hashes_data_ptr, "");
@@ -3325,7 +3327,7 @@ lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
 		default: GB_PANIC("Unhandled inline asm dialect"); break;
 		}
 
-		LLVMTypeRef func_type = LLVMGetElementType(lb_type(p->module, t));
+		LLVMTypeRef func_type = lb_llvm_get_pointer_type(lb_type(p->module, t));
 		LLVMValueRef the_asm = llvm_get_inline_asm(func_type, asm_string, constraints_string, ia->has_side_effects, ia->has_side_effects, dialect);
 		GB_ASSERT(the_asm != nullptr);
 		return {the_asm, t};
@@ -3791,7 +3793,7 @@ lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
 			lbValue v = {};
 
 			LLVMValueRef indices[1] = {index.value};
-			v.value = LLVMBuildGEP(p->builder, multi_ptr.value, indices, 1, "");
+			v.value = LLVMBuildGEP2(p->builder, lb_type(p->module, t->MultiPointer.elem), multi_ptr.value, indices, 1, "foo");
 			v.type = alloc_type_pointer(t->MultiPointer.elem);
 			return lb_addr(v);
 		}
@@ -3967,7 +3969,7 @@ lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
 			if (se->high == nullptr) {
 				lbValue offset = base;
 				LLVMValueRef indices[1] = {low.value};
-				offset.value = LLVMBuildGEP(p->builder, offset.value, indices, 1, "");
+				offset.value = LLVMBuildGEP2(p->builder, lb_type(p->module, offset.type->MultiPointer.elem), offset.value, indices, 1, "");
 				lb_addr_store(p, res, offset);
 			} else {
 				low = lb_emit_conv(p, low, t_int);
@@ -3976,7 +3978,7 @@ lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
 				lb_emit_multi_pointer_slice_bounds_check(p, se->open, low, high);
 
 				LLVMValueRef indices[1] = {low.value};
-				LLVMValueRef ptr = LLVMBuildGEP(p->builder, base.value, indices, 1, "");
+				LLVMValueRef ptr = LLVMBuildGEP2(p->builder, lb_type(p->module, base.type->MultiPointer.elem), base.value, indices, 1, "");
 				LLVMValueRef len = LLVMBuildSub(p->builder, high.value, low.value, "");
 				
 				LLVMValueRef gep0 = lb_emit_struct_ep(p, res.addr, 0).value;

+ 16 - 17
src/llvm_backend_general.cpp

@@ -341,9 +341,6 @@ Type *lb_addr_type(lbAddr const &addr) {
 	}
 	return type_deref(addr.addr.type);
 }
-LLVMTypeRef lb_addr_lb_type(lbAddr const &addr) {
-	return LLVMGetElementType(LLVMTypeOf(addr.addr.value));
-}
 
 lbValue lb_addr_get_ptr(lbProcedure *p, lbAddr const &addr) {
 	if (addr.addr.value == nullptr) {
@@ -854,7 +851,7 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
 	Type *a = type_deref(ptr.type);
 
 	if (LLVMIsNull(value.value)) {
-		LLVMTypeRef src_t = LLVMGetElementType(LLVMTypeOf(ptr.value));
+		LLVMTypeRef src_t = llvm_addr_type(p->module, ptr);
 		if (lb_sizeof(src_t) <= lb_max_zero_init_size()) {
 			LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value);
 		} else {
@@ -904,8 +901,8 @@ void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
 	}
 }
 
-LLVMTypeRef llvm_addr_type(lbValue addr_val) {
-	return LLVMGetElementType(LLVMTypeOf(addr_val.value));
+LLVMTypeRef llvm_addr_type(lbModule *module, lbValue addr_val) {
+	return lb_type(module, type_deref(addr_val.type));
 }
 
 lbValue lb_emit_load(lbProcedure *p, lbValue value) {
@@ -914,12 +911,12 @@ lbValue lb_emit_load(lbProcedure *p, lbValue value) {
 		Type *vt = base_type(value.type);
 		GB_ASSERT(vt->kind == Type_MultiPointer);
 		Type *t = vt->MultiPointer.elem;
-		LLVMValueRef v = LLVMBuildLoad2(p->builder, llvm_addr_type(value), value.value, "");
+		LLVMValueRef v = LLVMBuildLoad2(p->builder, lb_type(p->module, t), value.value, "");
 		return lbValue{v, t};
 	}
 	GB_ASSERT(is_type_pointer(value.type));
 	Type *t = type_deref(value.type);
-	LLVMValueRef v = LLVMBuildLoad2(p->builder, llvm_addr_type(value), value.value, "");
+	LLVMValueRef v = LLVMBuildLoad2(p->builder, lb_type(p->module, t), value.value, "");
 	return lbValue{v, t};
 }
 
@@ -1184,12 +1181,12 @@ lbValue lb_emit_union_tag_ptr(lbProcedure *p, lbValue u) {
 
 	Type *tag_type = union_tag_type(ut);
 
-	LLVMTypeRef uvt = LLVMGetElementType(LLVMTypeOf(u.value));
+	LLVMTypeRef uvt = llvm_addr_type(p->module, u);
 	unsigned element_count = LLVMCountStructElementTypes(uvt);
 	GB_ASSERT_MSG(element_count >= 2, "element_count=%u (%s) != (%s)", element_count, type_to_string(ut), LLVMPrintTypeToString(uvt));
 
 	lbValue tag_ptr = {};
-	tag_ptr.value = LLVMBuildStructGEP(p->builder, u.value, 1, "");
+	tag_ptr.value = LLVMBuildStructGEP2(p->builder, uvt, u.value, 1, "");
 	tag_ptr.type = alloc_type_pointer(tag_type);
 	return tag_ptr;
 }
@@ -2006,7 +2003,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
 
 			map_set(&m->function_type_map, type, ft);
 			LLVMTypeRef new_abi_fn_ptr_type = lb_function_type_to_llvm_ptr(ft, type->Proc.c_vararg);
-			LLVMTypeRef new_abi_fn_type = LLVMGetElementType(new_abi_fn_ptr_type);
+			LLVMTypeRef new_abi_fn_type = lb_llvm_get_pointer_type(new_abi_fn_ptr_type);
 
 			GB_ASSERT_MSG(LLVMGetTypeContext(new_abi_fn_type) == m->ctx,
 			              "\n\tFuncTypeCtx: %p\n\tCurrentCtx:  %p\n\tGlobalCtx:   %p",
@@ -2329,7 +2326,7 @@ general_end:;
 	if (LLVMIsALoadInst(val) && (src_size >= dst_size && src_align >= dst_align)) {
 		LLVMValueRef val_ptr = LLVMGetOperand(val, 0);
 		val_ptr = LLVMBuildPointerCast(p->builder, val_ptr, LLVMPointerType(dst_type, 0), "");
-		LLVMValueRef loaded_val = LLVMBuildLoad(p->builder, val_ptr, "");
+		LLVMValueRef loaded_val = LLVMBuildLoad2(p->builder, dst_type, val_ptr, "");
 
 		// LLVMSetAlignment(loaded_val, gb_min(src_align, dst_align));
 
@@ -2345,7 +2342,7 @@ general_end:;
 		LLVMValueRef nptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(src_type, 0), "");
 		LLVMBuildStore(p->builder, val, nptr);
 
-		return LLVMBuildLoad(p->builder, ptr, "");
+		return LLVMBuildLoad2(p->builder, dst_type, ptr, "");
 	}
 }
 
@@ -2371,14 +2368,15 @@ LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String const &str) {
 		isize len = gb_snprintf(name, max_len, "csbs$%x", id);
 		len -= 1;
 
-		LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name);
+		LLVMTypeRef type = LLVMTypeOf(data);
+		LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name);
 		LLVMSetInitializer(global_data, data);
 		LLVMSetLinkage(global_data, LLVMPrivateLinkage);
 		LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr);
 		LLVMSetAlignment(global_data, 1);
 		LLVMSetGlobalConstant(global_data, true);
 
-		LLVMValueRef ptr = LLVMConstInBoundsGEP(global_data, indices, 2);
+		LLVMValueRef ptr = LLVMConstInBoundsGEP2(type, global_data, indices, 2);
 		string_map_set(&m->const_strings, key, ptr);
 		return ptr;
 	}
@@ -2416,7 +2414,8 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str)
 		isize len = gb_snprintf(name, max_len, "csbs$%x", id);
 		len -= 1;
 	}
-	LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(data), name);
+	LLVMTypeRef type = LLVMTypeOf(data);
+	LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name);
 	LLVMSetInitializer(global_data, data);
 	LLVMSetLinkage(global_data, LLVMPrivateLinkage);
 	LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr);
@@ -2425,7 +2424,7 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str)
 
 	LLVMValueRef ptr = nullptr;
 	if (str.len != 0) {
-		ptr = LLVMConstInBoundsGEP(global_data, indices, 2);
+		ptr = LLVMConstInBoundsGEP2(type, global_data, indices, 2);
 	} else {
 		ptr = LLVMConstNull(lb_type(m, t_u8_ptr));
 	}

+ 72 - 131
src/llvm_backend_proc.cpp

@@ -1,3 +1,13 @@
+
+LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLVMValueRef* args, unsigned arg_count, LLVMTypeRef* types, unsigned type_count)
+{
+	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
+	GB_ASSERT_MSG(id != 0, "Unable to find %s", name);
+	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, type_count);
+	LLVMTypeRef call_type = LLVMIntrinsicGetType(p->module->ctx, id, types, type_count);
+	return LLVMBuildCall2(p->builder, call_type, ip, args, arg_count, "");
+}
+
 void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile) {
 	dst = lb_emit_conv(p, dst, t_rawptr);
 	src = lb_emit_conv(p, src, t_rawptr);
@@ -10,23 +20,23 @@ void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue l
 			name = "llvm.memmove.inline";
 		}
 	}
-
 	LLVMTypeRef types[3] = {
 		lb_type(p->module, t_rawptr),
 		lb_type(p->module, t_rawptr),
 		lb_type(p->module, t_int)
 	};
-	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]), LLVMPrintTypeToString(types[2]));
-	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-
-	LLVMValueRef args[4] = {};
-	args[0] = dst.value;
-	args[1] = src.value;
-	args[2] = len.value;
-	args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, is_volatile);
-	LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+	LLVMValueRef args[4] = {
+		dst.value,
+		src.value,
+		len.value,
+		LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, is_volatile)
+	};
+
+	lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 }
+
+
+
 void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile) {
 	dst = lb_emit_conv(p, dst, t_rawptr);
 	src = lb_emit_conv(p, src, t_rawptr);
@@ -45,16 +55,14 @@ void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbVal
 		lb_type(p->module, t_rawptr),
 		lb_type(p->module, t_int)
 	};
-	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]), LLVMPrintTypeToString(types[2]));
-	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-
-	LLVMValueRef args[4] = {};
-	args[0] = dst.value;
-	args[1] = src.value;
-	args[2] = len.value;
-	args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, is_volatile);
-	LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+
+	LLVMValueRef args[4] = {
+			dst.value,
+			src.value,
+			len.value,
+			LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, is_volatile) };
+
+	lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 }
 
 
@@ -122,7 +130,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
 
 	char *c_link_name = alloc_cstring(permanent_allocator(), p->name);
 	LLVMTypeRef func_ptr_type = lb_type(m, p->type);
-	LLVMTypeRef func_type = LLVMGetElementType(func_ptr_type);
+	LLVMTypeRef func_type = lb_llvm_get_pointer_type(func_ptr_type);
 
 	p->value = LLVMAddFunction(m->mod, c_link_name, func_type);
 
@@ -347,7 +355,7 @@ lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type
 
 	char *c_link_name = alloc_cstring(permanent_allocator(), p->name);
 	LLVMTypeRef func_ptr_type = lb_type(m, p->type);
-	LLVMTypeRef func_type = LLVMGetElementType(func_ptr_type);
+	LLVMTypeRef func_type = lb_llvm_get_pointer_type(func_ptr_type);
 
 	p->value = LLVMAddFunction(m->mod, c_link_name, func_type);
 
@@ -750,7 +758,7 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
 		if (!lb_is_type_kind(LLVMTypeOf(value.value), LLVMFunctionTypeKind)) {
 			fn = LLVMBuildPointerCast(p->builder, fn, ftp, "");
 		}
-		LLVMTypeRef fnp = LLVMGetElementType(LLVMTypeOf(fn));
+		LLVMTypeRef fnp = lb_llvm_get_pointer_type(LLVMTypeOf(fn));
 		GB_ASSERT_MSG(lb_is_type_kind(fnp, LLVMFunctionTypeKind), "%s", LLVMPrintTypeToString(fnp));
 
 		{
@@ -1264,13 +1272,8 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const
 			}
 			args[args_count++] = arg0.value;
 
-
 			LLVMTypeRef types[1] = {lb_type(p->module, arg0.type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-
-			res.value = LLVMBuildCall(p->builder, ip, args, cast(unsigned)args_count, "");
+			res.value = lb_call_intrinsic(p, name, args, cast(unsigned)args_count, types, gb_count_of(types));
 			return res;
 		}
 	case BuiltinProc_simd_reduce_min:
@@ -1303,15 +1306,11 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const
 			case BuiltinProc_simd_reduce_or:  name = "llvm.vector.reduce.or";  break;
 			case BuiltinProc_simd_reduce_xor: name = "llvm.vector.reduce.xor"; break;
 			}
-			LLVMTypeRef types[1] = {lb_type(p->module, arg0.type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
-			LLVMValueRef args[1] = {};
-			args[0] = arg0.value;
+			LLVMTypeRef types[1] = { lb_type(p->module, arg0.type) };
+			LLVMValueRef args[1] = { arg0.value };
 
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			return res;
 		}
 
@@ -1360,15 +1359,10 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const
 			case BuiltinProc_simd_nearest: name = "llvm.nearbyint"; break;
 			}
 
-			LLVMTypeRef types[1] = {lb_type(p->module, arg0.type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-
-			LLVMValueRef args[1] = {};
-			args[0] = arg0.value;
+			LLVMTypeRef types[1] = { lb_type(p->module, arg0.type) };
+			LLVMValueRef args[1] = { arg0.value };
 
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			return res;
 		}
 
@@ -1432,15 +1426,10 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const
 			}
 
 			LLVMTypeRef types[1] = {lb_type(p->module, arg0.type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
-			LLVMValueRef args[2] = {};
-			args[0] = arg0.value;
-			args[1] = arg1.value;
+			LLVMValueRef args[2] = { arg0.value, arg1.value };
 
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			return res;
 		}
 
@@ -1903,11 +1892,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			case BuiltinProc_trap:       name = "llvm.trap";      break;
 			}
 
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s", name);
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, nullptr, 0);
-
-			LLVMBuildCall(p->builder, ip, nullptr, 0, "");
+			lb_call_intrinsic(p, name, nullptr, 0, nullptr, 0);
 			if (id == BuiltinProc_trap) {
 				LLVMBuildUnreachable(p->builder);
 			}
@@ -1927,11 +1912,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 				res.value = LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, "");
 			} else {
 				char const *name = "llvm.readcyclecounter";
-				unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-				GB_ASSERT_MSG(id != 0, "Unable to find %s", name);
-				LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, nullptr, 0);
-
-				res.value = LLVMBuildCall(p->builder, ip, nullptr, 0, "");
+				res.value = lb_call_intrinsic(p, name, nullptr, 0, nullptr, 0);
 			}
 			return res;
 		}
@@ -1986,16 +1967,11 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 				}
 			}
 			LLVMTypeRef types[1] = {lb_type(p->module, type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
-			LLVMValueRef args[2] = {};
-			args[0] = x.value;
-			args[1] = y.value;
+			LLVMValueRef args[2] = { x.value, y.value };
 
 			lbValue res = {};
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 
 			if (is_type_tuple(main_type)) {
 				Type *res_type = nullptr;
@@ -2022,15 +1998,11 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 
 			char const *name = "llvm.sqrt";
 			LLVMTypeRef types[1] = {lb_type(p->module, type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
-			LLVMValueRef args[1] = {};
-			args[0] = x.value;
+			LLVMValueRef args[1] = { x.value };
 
 			lbValue res = {};
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			res.type = type;
 			return res;
 		}
@@ -2045,17 +2017,11 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 
 			char const *name = "llvm.fma";
 			LLVMTypeRef types[1] = {lb_type(p->module, type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
-			LLVMValueRef args[3] = {};
-			args[0] = x.value;
-			args[1] = y.value;
-			args[2] = z.value;
+			LLVMValueRef args[3] = { x.value, y.value, z.value };
 
 			lbValue res = {};
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			res.type = type;
 			return res;
 		}
@@ -2114,7 +2080,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 
 			lbValue res = {};
 			res.type = tv.type;
-			res.value = LLVMBuildGEP(p->builder, ptr.value, indices, gb_count_of(indices), "");
+			res.value = LLVMBuildGEP2(p->builder, lb_type(p->module, type_deref(tv.type)), ptr.value, indices, gb_count_of(indices), "");
 			return res;
 		}
 	case BuiltinProc_ptr_sub:
@@ -2123,7 +2089,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			lbValue ptr1 = lb_build_expr(p, ce->args[1]);
 
 			LLVMTypeRef type_int = lb_type(p->module, t_int);
-			LLVMValueRef diff = LLVMBuildPtrDiff(p->builder, ptr0.value, ptr1.value, "");
+			LLVMValueRef diff = LLVMBuildPtrDiff2(p->builder, lb_type(p->module, ptr0.type), ptr0.value, ptr1.value, "");
 			diff = LLVMBuildIntCast2(p->builder, diff, type_int, /*signed*/true, "");
 
 			lbValue res = {};
@@ -2174,7 +2140,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 	case BuiltinProc_atomic_load_explicit: {
 		lbValue dst = lb_build_expr(p, ce->args[0]);
 
-		LLVMValueRef instr = LLVMBuildLoad(p->builder, dst.value, "");
+		LLVMValueRef instr = LLVMBuildLoad2(p->builder,  lb_type(p->module, type_deref(dst.type)), dst.value, "");
 		switch (id) {
 		case BuiltinProc_non_temporal_load:
 			{
@@ -2348,18 +2314,14 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			GB_ASSERT(name != nullptr);
 
 			LLVMTypeRef types[1] = {lb_type(p->module, platform_type)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-
 			lbValue res = {};
 
-			LLVMValueRef args[3] = {};
-			args[0] = x.value;
-			args[1] = y.value;
-			args[2] = scale.value;
+			LLVMValueRef args[3] = {
+					x.value,
+					y.value,
+					scale.value };
 
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			res.type = platform_type;
 			return lb_emit_conv(p, res, tv.type);
 		}
@@ -2373,17 +2335,10 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			char const *name = "llvm.expect";
 
 			LLVMTypeRef types[1] = {lb_type(p->module, t)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-
 			lbValue res = {};
+			LLVMValueRef args[2] = { x.value, y.value };
 
-			LLVMValueRef args[2] = {};
-			args[0] = x.value;
-			args[1] = y.value;
-
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			res.type = t;
 			return lb_emit_conv(p, res, t);
 		}
@@ -2419,9 +2374,6 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			char const *name = "llvm.prefetch";
 
 			LLVMTypeRef types[1] = {lb_type(p->module, t_rawptr)};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
 			LLVMTypeRef llvm_i32 = lb_type(p->module, t_i32);
 			LLVMValueRef args[4] = {};
@@ -2431,7 +2383,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			args[3] = LLVMConstInt(llvm_i32, cache, false);
 
 			lbValue res = {};
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			res.type = nullptr;
 			return res;
 		}
@@ -2677,7 +2629,8 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 				isize len = gb_snprintf(name, max_len, "csbs$%x", id);
 				len -= 1;
 			}
-			LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(array), name);
+			LLVMTypeRef type = LLVMTypeOf(array);
+			LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name);
 			LLVMSetInitializer(global_data, array);
 			LLVMSetLinkage(global_data, LLVMInternalLinkage);
 
@@ -2689,7 +2642,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			};
 			lbValue res = {};
 			res.type = tv.type;
-			res.value = LLVMBuildInBoundsGEP(p->builder, global_data, indices, gb_count_of(indices), "");
+			res.value = LLVMBuildInBoundsGEP2(p->builder, type, global_data, indices, gb_count_of(indices), "");
 			return res;
 
 		}
@@ -2700,9 +2653,6 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			LLVMTypeRef types[1] = {
 				lb_type(p->module, t_uintptr),
 			};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
 			LLVMValueRef args[2] = {};
 			args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_uintptr).value;
@@ -2710,7 +2660,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 
 			lbValue res = {};
 			res.type = tv.type;
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			return res;
 		}
 	case BuiltinProc_wasm_memory_size:
@@ -2719,16 +2669,13 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			LLVMTypeRef types[1] = {
 				lb_type(p->module, t_uintptr),
 			};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
 			LLVMValueRef args[1] = {};
 			args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_uintptr).value;
 
 			lbValue res = {};
 			res.type = tv.type;
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			return res;
 		}
 
@@ -2738,9 +2685,6 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			LLVMTypeRef types[1] = {
 				lb_type(p->module, t_u32),
 			};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, nullptr, 0); // types, gb_count_of(types));
 
 			Type *t_u32_ptr = alloc_type_pointer(t_u32);
 
@@ -2751,7 +2695,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 
 			lbValue res = {};
 			res.type = tv.type;
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			return res;
 		}
 
@@ -2761,19 +2705,16 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 			LLVMTypeRef types[1] = {
 				lb_type(p->module, t_u32),
 			};
-			unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-			GB_ASSERT_MSG(id != 0, "Unable to find %s", name, LLVMPrintTypeToString(types[0]));
-			LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, nullptr, 0); // types, gb_count_of(types));
 
 			Type *t_u32_ptr = alloc_type_pointer(t_u32);
 
-			LLVMValueRef args[2] = {};
-			args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_u32_ptr).value;
-			args[1] = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_u32).value;
+			LLVMValueRef args[2] = {
+					lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_u32_ptr).value,
+					lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_u32).value };
 
 			lbValue res = {};
 			res.type = tv.type;
-			res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+			res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 			return res;
 		}
 
@@ -2782,7 +2723,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 		{
 			Type *param_types[2] = {t_u32, t_u32};
 			Type *type = alloc_type_proc_from_types(param_types, gb_count_of(param_types), tv.type, false, ProcCC_None);
-			LLVMTypeRef func_type = LLVMGetElementType(lb_type(p->module, type));
+			LLVMTypeRef func_type = lb_llvm_get_pointer_type(lb_type(p->module, type));
 			LLVMValueRef the_asm = llvm_get_inline_asm(
 				func_type,
 				str_lit("cpuid"),
@@ -2802,7 +2743,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 	case BuiltinProc_x86_xgetbv:
 		{
 			Type *type = alloc_type_proc_from_types(&t_u32, 1, tv.type, false, ProcCC_None);
-			LLVMTypeRef func_type = LLVMGetElementType(lb_type(p->module, type));
+			LLVMTypeRef func_type = lb_llvm_get_pointer_type(lb_type(p->module, type));
 			LLVMValueRef the_asm = llvm_get_inline_asm(
 				func_type,
 				str_lit("xgetbv"),

+ 11 - 4
src/llvm_backend_type.cpp

@@ -104,7 +104,8 @@ lbValue lb_type_info(lbModule *m, Type *type) {
 	};
 
 	lbValue value = {};
-	value.value = LLVMConstGEP(lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices));
+	lbValue data = lb_global_type_info_data_ptr(m);
+	value.value = LLVMConstGEP2(lb_type(m, type_deref(data.type)), data.value, indices, gb_count_of(indices));
 	value.type = t_type_info_ptr;
 	return value;
 }
@@ -123,10 +124,16 @@ lbValue lb_get_type_info_ptr(lbModule *m, Type *type) {
 
 	lbValue res = {};
 	res.type = t_type_info_ptr;
-	res.value = LLVMConstGEP(lb_global_type_info_data_ptr(m).value, indices, cast(unsigned)gb_count_of(indices));
+	lbValue data = lb_global_type_info_data_ptr(m);
+	res.value = LLVMConstGEP2(lb_type(m, type_deref(data.type)), data.value, indices, cast(unsigned)gb_count_of(indices));
 	return res;
 }
 
+// The use of this method needs to be eliminated.
+LLVMTypeRef lb_llvm_get_pointer_type(LLVMTypeRef type)
+{
+	return LLVMGetElementType(type);
+}
 
 lbValue lb_type_info_member_types_offset(lbProcedure *p, isize count) {
 	GB_ASSERT(p->module == &p->module->gen->default_module);
@@ -178,10 +185,10 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
 
 		LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
 		LLVMValueRef values[2] = {
-			LLVMConstInBoundsGEP(lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices)),
+			LLVMConstInBoundsGEP2(lb_type(m, lb_global_type_info_data_entity->type), lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices)),
 			LLVMConstInt(lb_type(m, t_int), type->Array.count, true),
 		};
-		LLVMValueRef slice = llvm_const_named_struct_internal(llvm_addr_type(global_type_table), values, gb_count_of(values));
+		LLVMValueRef slice = llvm_const_named_struct_internal(lb_type(m, type_deref(global_type_table.type)), values, gb_count_of(values));
 
 		LLVMSetInitializer(global_type_table.value, slice);
 	}

+ 66 - 146
src/llvm_backend_utility.cpp

@@ -79,9 +79,6 @@ LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValu
 		lb_type(p->module, t_int)
 	};
 	if (true || is_inlinable) {
-		unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-		GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]));
-		LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
 		LLVMValueRef args[4] = {};
 		args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
@@ -89,16 +86,20 @@ LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValu
 		args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
 		args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), is_volatile, false);
 
-		return LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+		return lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 	} else {
-		LLVMValueRef ip = lb_lookup_runtime_procedure(p->module, str_lit("memset")).value;
+		lbValue pr = lb_lookup_runtime_procedure(p->module, str_lit("memset"));
 
 		LLVMValueRef args[3] = {};
 		args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
 		args[1] = LLVMConstInt(LLVMInt32TypeInContext(p->module->ctx), 0, false);
 		args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
 
-		return LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+		// We always get the function pointer type rather than the function and there is apparently no way around that?
+		LLVMTypeRef type = lb_type(p->module, pr.type);
+
+		type = lb_llvm_get_pointer_type(type);
+		return LLVMBuildCall2(p->builder, type, pr.value, args, gb_count_of(args), "");
 	}
 
 }
@@ -483,15 +484,11 @@ lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *end_type) {
 
 	char const *name = "llvm.bswap";
 	LLVMTypeRef types[1] = {lb_type(p->module, value.type)};
-	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
-	LLVMValueRef args[1] = {};
-	args[0] = value.value;
+	LLVMValueRef args[1] = { value.value };
 
 	lbValue res = {};
-	res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+	res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 	res.type = value.type;
 
 	if (is_type_float(original_type)) {
@@ -509,15 +506,10 @@ lbValue lb_emit_count_ones(lbProcedure *p, lbValue x, Type *type) {
 
 	char const *name = "llvm.ctpop";
 	LLVMTypeRef types[1] = {lb_type(p->module, type)};
-	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-
-	LLVMValueRef args[1] = {};
-	args[0] = x.value;
+	LLVMValueRef args[1] = { x.value };
 
 	lbValue res = {};
-	res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+	res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 	res.type = type;
 	return res;
 }
@@ -538,16 +530,13 @@ lbValue lb_emit_count_trailing_zeros(lbProcedure *p, lbValue x, Type *type) {
 
 	char const *name = "llvm.cttz";
 	LLVMTypeRef types[1] = {lb_type(p->module, type)};
-	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
-	LLVMValueRef args[2] = {};
-	args[0] = x.value;
-	args[1] = LLVMConstNull(LLVMInt1TypeInContext(p->module->ctx));
+	LLVMValueRef args[2] = {
+			x.value,
+			LLVMConstNull(LLVMInt1TypeInContext(p->module->ctx)) };
 
 	lbValue res = {};
-	res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+	res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 	res.type = type;
 	return res;
 }
@@ -557,16 +546,13 @@ lbValue lb_emit_count_leading_zeros(lbProcedure *p, lbValue x, Type *type) {
 
 	char const *name = "llvm.ctlz";
 	LLVMTypeRef types[1] = {lb_type(p->module, type)};
-	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
-	LLVMValueRef args[2] = {};
-	args[0] = x.value;
-	args[1] = LLVMConstNull(LLVMInt1TypeInContext(p->module->ctx));
+	LLVMValueRef args[2] = {
+			x.value,
+			LLVMConstNull(LLVMInt1TypeInContext(p->module->ctx)) };
 
 	lbValue res = {};
-	res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+	res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 	res.type = type;
 	return res;
 }
@@ -578,15 +564,11 @@ lbValue lb_emit_reverse_bits(lbProcedure *p, lbValue x, Type *type) {
 
 	char const *name = "llvm.bitreverse";
 	LLVMTypeRef types[1] = {lb_type(p->module, type)};
-	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-	GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
-	LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
 
-	LLVMValueRef args[1] = {};
-	args[0] = x.value;
+	LLVMValueRef args[1] = { x.value };
 
 	lbValue res = {};
-	res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
+	res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
 	res.type = type;
 	return res;
 }
@@ -1020,12 +1002,12 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
 		lbModule *m = p->module;
 		lbValue res = {};
 		LLVMValueRef indices[2] = {llvm_zero(m), LLVMConstInt(lb_type(m, t_i32), index, false)};
-		res.value = LLVMConstGEP(s.value, indices, gb_count_of(indices));
+		res.value = LLVMConstGEP2(lb_type(m, type_deref(s.type)), s.value, indices, gb_count_of(indices));
 		res.type = alloc_type_pointer(result_type);
 		return res;
 	} else {
 		lbValue res = {};
-		LLVMTypeRef st = LLVMGetElementType(LLVMTypeOf(s.value));
+		LLVMTypeRef st = lb_type(p->module, type_deref(s.type));
 		// gb_printf_err("%s\n", type_to_string(s.type));
 		// gb_printf_err("%s\n", LLVMPrintTypeToString(LLVMTypeOf(s.value)));
 		// gb_printf_err("%d\n", index);
@@ -1033,7 +1015,7 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
 		unsigned count = LLVMCountStructElementTypes(st);
 		GB_ASSERT_MSG(count >= cast(unsigned)index, "%u %d %d", count, index, original_index);
 		
-		res.value = LLVMBuildStructGEP(p->builder, s.value, cast(unsigned)index, "");
+		res.value = LLVMBuildStructGEP2(p->builder, st, s.value, cast(unsigned)index, "");
 		res.type = alloc_type_pointer(result_type);
 		return res;
 	}
@@ -1239,46 +1221,50 @@ lbValue lb_emit_array_ep(lbProcedure *p, lbValue s, lbValue index) {
 
 	Type *ptr = base_array_type(st);
 	lbValue res = {};
-	res.value = LLVMBuildGEP(p->builder, s.value, indices, 2, "");
+	res.value = LLVMBuildGEP2(p->builder, lb_type(p->module, st), s.value, indices, 2, "");
 	res.type = alloc_type_pointer(ptr);
 	return res;
 }
 
-lbValue lb_emit_array_epi(lbProcedure *p, lbValue s, isize index) {
-	Type *t = s.type;
-	GB_ASSERT(is_type_pointer(t));
-	Type *st = base_type(type_deref(t));
-	GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st) || is_type_matrix(st), "%s", type_to_string(st));
-
-	GB_ASSERT(0 <= index);
-	Type *ptr = base_array_type(st);
-
-
+// This emits a GEP at 0, index
+static inline lbValue lb_emit_gep(lbProcedure *p, Type *type, LLVMValueRef value, isize index)
+{
 	LLVMValueRef indices[2] = {
 		LLVMConstInt(lb_type(p->module, t_int), 0, false),
 		LLVMConstInt(lb_type(p->module, t_int), cast(unsigned)index, false),
 	};
-
+	LLVMTypeRef llvm_type = lb_type(p->module, type);
 	lbValue res = {};
-	if (lb_is_const(s)) {
-		res.value = LLVMConstGEP(s.value, indices, gb_count_of(indices));
+	Type *ptr = base_array_type(type);
+	res.type = alloc_type_pointer(ptr);
+	if (LLVMIsConstant(value)) {
+		res.value = LLVMConstGEP2(llvm_type, value, indices, gb_count_of(indices));
 	} else {
-		res.value = LLVMBuildGEP(p->builder, s.value, indices, gb_count_of(indices), "");
+		res.value = LLVMBuildGEP2(p->builder, llvm_type, value, indices, gb_count_of(indices), "");
 	}
-	res.type = alloc_type_pointer(ptr);
 	return res;
 }
 
+lbValue lb_emit_array_epi(lbProcedure *p, lbValue s, isize index) {
+	Type *t = s.type;
+	GB_ASSERT(is_type_pointer(t));
+	Type *st = base_type(type_deref(t));
+	GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st) || is_type_matrix(st), "%s", type_to_string(st));
+	GB_ASSERT(0 <= index);
+	return lb_emit_gep(p, st, s.value, index);
+}
+
 lbValue lb_emit_ptr_offset(lbProcedure *p, lbValue ptr, lbValue index) {
 	index = lb_emit_conv(p, index, t_int);
 	LLVMValueRef indices[1] = {index.value};
 	lbValue res = {};
 	res.type = ptr.type;
+	LLVMTypeRef type = lb_type(p->module, type_deref(ptr.type));
 
 	if (lb_is_const(ptr) && lb_is_const(index)) {
-		res.value = LLVMConstGEP(ptr.value, indices, 1);
+		res.value = LLVMConstGEP2(type, ptr.value, indices, 1);
 	} else {
-		res.value = LLVMBuildGEP(p->builder, ptr.value, indices, 1, "");
+		res.value = LLVMBuildGEP2(p->builder, type, ptr.value, indices, 1, "");
 	}
 	return res;
 }
@@ -1287,63 +1273,18 @@ lbValue lb_emit_matrix_epi(lbProcedure *p, lbValue s, isize row, isize column) {
 	Type *t = s.type;
 	GB_ASSERT(is_type_pointer(t));
 	Type *mt = base_type(type_deref(t));
-	
-	Type *ptr = base_array_type(mt);
-	
 	if (column == 0) {
 		GB_ASSERT_MSG(is_type_matrix(mt) || is_type_array_like(mt), "%s", type_to_string(mt));
-		
-		LLVMValueRef indices[2] = {
-			LLVMConstInt(lb_type(p->module, t_int), 0, false),
-			LLVMConstInt(lb_type(p->module, t_int), cast(unsigned)row, false),
-		};
-		
-		lbValue res = {};
-		if (lb_is_const(s)) {
-			res.value = LLVMConstGEP(s.value, indices, gb_count_of(indices));
-		} else {
-			res.value = LLVMBuildGEP(p->builder, s.value, indices, gb_count_of(indices), "");
-		}
-		
-		Type *ptr = base_array_type(mt);
-		res.type = alloc_type_pointer(ptr);
-		return res;
+		return lb_emit_gep(p, mt, s.value, row);
 	} else if (row == 0 && is_type_array_like(mt)) {
-		LLVMValueRef indices[2] = {
-			LLVMConstInt(lb_type(p->module, t_int), 0, false),
-			LLVMConstInt(lb_type(p->module, t_int), cast(unsigned)column, false),
-		};
-		
-		lbValue res = {};
-		if (lb_is_const(s)) {
-			res.value = LLVMConstGEP(s.value, indices, gb_count_of(indices));
-		} else {
-			res.value = LLVMBuildGEP(p->builder, s.value, indices, gb_count_of(indices), "");
-		}
-		
-		Type *ptr = base_array_type(mt);
-		res.type = alloc_type_pointer(ptr);
-		return res;
+		return lb_emit_gep(p, mt, s.value, column);
 	}
 	
 	
 	GB_ASSERT_MSG(is_type_matrix(mt), "%s", type_to_string(mt));
 	
 	isize offset = matrix_indices_to_offset(mt, row, column);
-
-	LLVMValueRef indices[2] = {
-		LLVMConstInt(lb_type(p->module, t_int), 0, false),
-		LLVMConstInt(lb_type(p->module, t_int), cast(unsigned)offset, false),
-	};
-
-	lbValue res = {};
-	if (lb_is_const(s)) {
-		res.value = LLVMConstGEP(s.value, indices, gb_count_of(indices));
-	} else {
-		res.value = LLVMBuildGEP(p->builder, s.value, indices, gb_count_of(indices), "");
-	}
-	res.type = alloc_type_pointer(ptr);
-	return res;
+	return lb_emit_gep(p, mt, s.value, offset);
 }
 
 lbValue lb_emit_matrix_ep(lbProcedure *p, lbValue s, lbValue row, lbValue column) {
@@ -1366,11 +1307,12 @@ lbValue lb_emit_matrix_ep(lbProcedure *p, lbValue s, lbValue row, lbValue column
 		index,
 	};
 
+	LLVMTypeRef type = lb_type(p->module, mt);
 	lbValue res = {};
 	if (lb_is_const(s)) {
-		res.value = LLVMConstGEP(s.value, indices, gb_count_of(indices));
+		res.value = LLVMConstGEP2(type, s.value, indices, gb_count_of(indices));
 	} else {
-		res.value = LLVMBuildGEP(p->builder, s.value, indices, gb_count_of(indices), "");
+		res.value = LLVMBuildGEP2(p->builder, type, s.value, indices, gb_count_of(indices), "");
 	}
 	res.type = alloc_type_pointer(ptr);
 	return res;
@@ -1574,18 +1516,12 @@ lbValue lb_emit_mul_add(lbProcedure *p, lbValue a, lbValue b, lbValue c, Type *t
 
 	if (is_possible) {
 		char const *name = "llvm.fma";
-		unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-		GB_ASSERT_MSG(id != 0, "Unable to find %s", name);
-		
-		LLVMTypeRef types[1] = {};
-		types[0] = lb_type(m, t);
-		
-		LLVMValueRef ip = LLVMGetIntrinsicDeclaration(m->mod, id, types, gb_count_of(types));
-		LLVMValueRef values[3] = {};
-		values[0] = a.value;
-		values[1] = b.value;
-		values[2] = c.value;
-		LLVMValueRef call = LLVMBuildCall(p->builder, ip, values, gb_count_of(values), "");
+		LLVMTypeRef types[1] = { lb_type(m, t) };
+		LLVMValueRef values[3] = {
+				a.value,
+				b.value,
+				c.value };
+		LLVMValueRef call = lb_call_intrinsic(p, name, values, gb_count_of(values), types, gb_count_of(types));
 		return {call, t};
 	} else {
 		lbValue x = lb_emit_arith(p, Token_Mul, a, b, t);
@@ -1714,15 +1650,9 @@ LLVMValueRef llvm_vector_reduce_add(lbProcedure *p, LLVMValueRef value) {
 
 	unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
 	if (id != 0 && false) {
-		LLVMTypeRef types[1] = {};
-		types[0] = type;
-		
-		LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
-		LLVMValueRef values[2] = {};
-		values[0] = LLVMConstNull(elem);
-		values[1] = value;
-		LLVMValueRef call = LLVMBuildCall(p->builder, ip, values+value_offset, value_count, "");
-		return call;
+		LLVMTypeRef types[1] = { type };
+		LLVMValueRef values[2] = { LLVMConstNull(elem), value };
+		return lb_call_intrinsic(p, name, values + value_offset, value_count, types, gb_count_of(types));
 	}
 
 	// Manual reduce
@@ -1791,8 +1721,7 @@ LLVMValueRef llvm_vector_dot(lbProcedure *p, LLVMValueRef a, LLVMValueRef b) {
 }
 
 LLVMValueRef llvm_vector_mul_add(lbProcedure *p, LLVMValueRef a, LLVMValueRef b, LLVMValueRef c) {
-	lbModule *m = p->module;
-	
+
 	LLVMTypeRef t = LLVMTypeOf(a);
 	GB_ASSERT(t == LLVMTypeOf(b));
 	GB_ASSERT(t == LLVMTypeOf(c));
@@ -1814,18 +1743,9 @@ LLVMValueRef llvm_vector_mul_add(lbProcedure *p, LLVMValueRef a, LLVMValueRef b,
 
 	if (is_possible) {
 		char const *name = "llvm.fmuladd";
-		unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
-		GB_ASSERT_MSG(id != 0, "Unable to find %s", name);
-		
-		LLVMTypeRef types[1] = {};
-		types[0] = t;
-		
-		LLVMValueRef ip = LLVMGetIntrinsicDeclaration(m->mod, id, types, gb_count_of(types));
-		LLVMValueRef values[3] = {};
-		values[0] = a;
-		values[1] = b;
-		values[2] = c;
-		LLVMValueRef call = LLVMBuildCall(p->builder, ip, values, gb_count_of(values), "");
+		LLVMTypeRef types[1] = { t };
+		LLVMValueRef values[3] = { a, b, c};
+		LLVMValueRef call = lb_call_intrinsic(p, name, values, gb_count_of(values), types, gb_count_of(types));
 		return call;
 	} else {
 		LLVMValueRef x = llvm_vector_mul(p, a, b);
@@ -1840,7 +1760,7 @@ LLVMValueRef llvm_get_inline_asm(LLVMTypeRef func_type, String const &str, Strin
 		cast(char *)clobbers.text, cast(size_t)clobbers.len,
 		has_side_effects, is_align_stack,
 		dialect
-	#if LLVM_VERSION_MAJOR >= 13 
+	#if LLVM_VERSION_MAJOR >= 13
 		, /*CanThrow*/false
 	#endif
 	);