Browse Source

Merge branch 'master' into directx-packages

gingerBill 3 years ago
parent
commit
8e8a075a22

+ 5 - 0
core/runtime/core.odin

@@ -33,6 +33,11 @@ Calling_Convention :: enum u8 {
 
 	None        = 6,
 	Naked       = 7,
+
+	_           = 8, // reserved
+
+	Win64       = 9,
+	SysV        = 10,
 }
 
 Type_Info_Enum_Value :: distinct i64

+ 7 - 7
core/runtime/error_checks.odin

@@ -25,7 +25,7 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index
 		print_caller_location(Source_Code_Location{file, line, column, ""})
 		print_string(" Index ")
 		print_i64(i64(index))
-		print_string(" is out of bounds range 0:")
+		print_string(" is out of range 0..<")
 		print_i64(i64(count))
 		print_byte('\n')
 		bounds_trap()
@@ -35,11 +35,11 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index
 
 slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! {
 	print_caller_location(Source_Code_Location{file, line, column, ""})
-	print_string(" Invalid slice indices: ")
+	print_string(" Invalid slice indices ")
 	print_i64(i64(lo))
 	print_string(":")
 	print_i64(i64(hi))
-	print_string(":")
+	print_string(" is out of range 0..<")
 	print_i64(i64(len))
 	print_byte('\n')
 	bounds_trap()
@@ -47,7 +47,7 @@ slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, h
 
 multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! {
 	print_caller_location(Source_Code_Location{file, line, column, ""})
-	print_string(" Invalid slice indices: ")
+	print_string(" Invalid slice indices ")
 	print_i64(i64(lo))
 	print_string(":")
 	print_i64(i64(hi))
@@ -83,11 +83,11 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32,
 	}
 	handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) {
 		print_caller_location(Source_Code_Location{file, line, column, ""})
-		print_string(" Invalid dynamic array values: ")
+		print_string(" Invalid dynamic array indices ")
 		print_i64(i64(low))
 		print_string(":")
 		print_i64(i64(high))
-		print_string(":")
+		print_string(" is out of range 0..<")
 		print_i64(i64(max))
 		print_byte('\n')
 		bounds_trap()
@@ -107,7 +107,7 @@ matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32
 		print_i64(i64(row_index))
 		print_string(", ")
 		print_i64(i64(column_index))
-		print_string(" is out of bounds range [0..<")
+		print_string(" is out of range [0..<")
 		print_i64(i64(row_count))
 		print_string(", 0..<")
 		print_i64(i64(column_count))

+ 19 - 0
src/check_type.cpp

@@ -1928,6 +1928,25 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
 		c->scope->flags &= ~ScopeFlag_ContextDefined;
 	}
 
+	TargetArchKind arch = build_context.metrics.arch;
+	switch (cc) {
+	case ProcCC_StdCall:
+	case ProcCC_FastCall:
+		if (arch != TargetArch_i386 || arch != TargetArch_amd64) {
+			error(proc_type_node, "Invalid procedure calling convention \"%s\" for target architecture, expected either i386 or amd64, got %.*s",
+			      proc_calling_convention_strings[cc], LIT(target_arch_names[arch]));
+		}
+		break;
+	case ProcCC_Win64:
+	case ProcCC_SysV:
+		if (arch != TargetArch_amd64) {
+			error(proc_type_node, "Invalid procedure calling convention \"%s\" for target architecture, expected amd64, got %.*s",
+			      proc_calling_convention_strings[cc], LIT(target_arch_names[arch]));
+		}
+		break;
+	}
+
+
 	bool variadic = false;
 	isize variadic_index = -1;
 	bool success = true;

+ 1 - 34
src/docs_writer.cpp

@@ -683,40 +683,7 @@ OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) {
 			types[1] = odin_doc_type(w, type->Proc.results);
 			doc_type.types = odin_write_slice(w, types, gb_count_of(types));
 
-			String calling_convention = {};
-			switch (type->Proc.calling_convention) {
-			case ProcCC_Invalid:
-				// no need
-				break;
-			case ProcCC_Odin:
-				if (default_calling_convention() != ProcCC_Odin) {
-					calling_convention = str_lit("odin");
-				}
-				break;
-			case ProcCC_Contextless:
-				if (default_calling_convention() != ProcCC_Contextless) {
-					calling_convention = str_lit("contextless");
-				}
-				break;
-			case ProcCC_CDecl:
-				calling_convention = str_lit("cdecl");
-				break;
-			case ProcCC_StdCall:
-				calling_convention = str_lit("stdcall");
-				break;
-			case ProcCC_FastCall:
-				calling_convention = str_lit("fastcall");
-				break;
-			case ProcCC_None:
-				calling_convention = str_lit("none");
-				break;
-			case ProcCC_Naked:
-				calling_convention = str_lit("naked");
-				break;
-			case ProcCC_InlineAsm:
-				calling_convention = str_lit("inline-assembly");
-				break;
-			}
+			String calling_convention = make_string_c(proc_calling_convention_strings[type->Proc.calling_convention]);
 			doc_type.calling_convention = odin_doc_write_string(w, calling_convention);
 		}
 		break;

+ 6 - 0
src/llvm_abi.cpp

@@ -1184,6 +1184,12 @@ LB_ABI_INFO(lb_get_abi_info) {
 			ft->calling_convention = calling_convention;
 			return ft;
 		}
+	case ProcCC_Win64:
+		GB_ASSERT(build_context.metrics.arch == TargetArch_amd64);
+		return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
+	case ProcCC_SysV:
+		GB_ASSERT(build_context.metrics.arch == TargetArch_amd64);
+		return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
 	}
 
 	switch (build_context.metrics.arch) {

+ 4 - 0
src/llvm_backend.hpp

@@ -548,6 +548,10 @@ lbCallingConventionKind const lb_calling_convention_map[ProcCC_MAX] = {
 	lbCallingConvention_C,            // ProcCC_None,
 	lbCallingConvention_C,            // ProcCC_Naked,
 	lbCallingConvention_C,            // ProcCC_InlineAsm,
+
+	lbCallingConvention_Win64,        // ProcCC_Win64,
+	lbCallingConvention_X86_64_SysV,  // ProcCC_SysV,
+
 };
 
 enum : LLVMDWARFTypeEncoding {

+ 14 - 14
src/llvm_backend_debug.cpp

@@ -958,15 +958,15 @@ void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T
 	);
 
 	LLVMValueRef storage = ptr;
-	LLVMValueRef instr = ptr;
+	LLVMBasicBlockRef block = p->decl_block->block;
 	LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos);
 	LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0);
 	lb_set_llvm_metadata(m, ptr, llvm_expr);
-	LLVMDIBuilderInsertDeclareBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr);
+	LLVMDIBuilderInsertDbgValueAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block);
 }
 
 
-void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, Token const &token, unsigned arg_number) {
+void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, Token const &token, unsigned arg_number, lbBlock *block) {
 	if (p->debug_info == nullptr) {
 		return;
 	}
@@ -1020,19 +1020,14 @@ void lb_add_debug_param_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T
 	);
 
 	LLVMValueRef storage = ptr;
-	LLVMValueRef instr = ptr;
-	LLVMBasicBlockRef block = p->decl_block->block;
 	LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos);
 	LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0);
 	lb_set_llvm_metadata(m, ptr, llvm_expr);
-	if (LLVMIsAAllocaInst(instr)) {
-		LLVMDIBuilderInsertDeclareBefore(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, instr);
-	} else {
-		// NOTE(bill, 2022-02-01): For parameter values, you must insert them at the end of the decl block
-		// The reason is that if the parameter is at index 0 and a pointer, there is not such things as an
-		// instruction "before" it.
-		LLVMDIBuilderInsertDeclareAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block);
-	}
+
+	// NOTE(bill, 2022-02-01): For parameter values, you must insert them at the end of the decl block
+	// The reason is that if the parameter is at index 0 and a pointer, there is not such things as an
+	// instruction "before" it.
+	LLVMDIBuilderInsertDbgValueAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block->block);
 }
 
 
@@ -1055,5 +1050,10 @@ void lb_add_debug_context_variable(lbProcedure *p, lbAddr const &ctx) {
 	token.string = str_lit("context");
 	token.pos = pos;
 
-	lb_add_debug_local_variable(p, ctx.addr.value, t_context, token);
+	LLVMValueRef ptr = ctx.addr.value;
+	while (LLVMIsABitCastInst(ptr)) {
+		ptr = LLVMGetOperand(ptr, 0);
+	}
+
+	lb_add_debug_local_variable(p, ptr, t_context, token);
 }

+ 1 - 1
src/llvm_backend_opt.cpp

@@ -56,7 +56,7 @@ LLVMBool lb_must_preserve_predicate_callback(LLVMValueRef value, void *user_data
 #endif
 
 void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, i32 optimization_level) {
-	if (optimization_level == 0 && build_context.ODIN_DEBUG) {
+	if (false && optimization_level == 0 && build_context.ODIN_DEBUG) {
 		LLVMAddMergedLoadStoreMotionPass(fpm);
 	} else {
 		LLVMAddPromoteMemoryToRegisterPass(fpm);

+ 13 - 5
src/llvm_backend_proc.cpp

@@ -480,9 +480,8 @@ void lb_begin_procedure_body(lbProcedure *p) {
 				} else if (arg_type->kind == lbArg_Direct) {
 					if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) {
 						LLVMTypeRef param_type = lb_type(p->module, e->type);
-						LLVMValueRef value = LLVMGetParam(p->value, param_offset+param_index);
-
-						value = OdinLLVMBuildTransmute(p, value, param_type);
+						LLVMValueRef original_value = LLVMGetParam(p->value, param_offset+param_index);
+						LLVMValueRef value = OdinLLVMBuildTransmute(p, original_value, param_type);
 
 						lbValue param = {};
 						param.value = value;
@@ -491,7 +490,16 @@ void lb_begin_procedure_body(lbProcedure *p) {
 						lbValue ptr = lb_address_from_load_or_generate_local(p, param);
 						GB_ASSERT(LLVMIsAAllocaInst(ptr.value));
 						lb_add_entity(p->module, e, ptr);
-						lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1);
+
+						lbBlock *block = p->decl_block;
+						if (original_value != value) {
+							block = p->curr_block;
+						}
+						LLVMValueRef debug_storage_value = value;
+						if (original_value != value && LLVMIsALoadInst(value)) {
+							debug_storage_value = LLVMGetOperand(value, 0);
+						}
+						lb_add_debug_param_variable(p, debug_storage_value, e->type, e->token, param_index+1, block);
 					}
 				} else if (arg_type->kind == lbArg_Indirect) {
 					if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) {
@@ -499,7 +507,7 @@ void lb_begin_procedure_body(lbProcedure *p) {
 						ptr.value = LLVMGetParam(p->value, param_offset+param_index);
 						ptr.type = alloc_type_pointer(e->type);
 						lb_add_entity(p->module, e, ptr);
-						lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1);
+						lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1, p->decl_block);
 					}
 				}
 			}

+ 6 - 0
src/parser.cpp

@@ -3412,12 +3412,18 @@ ProcCallingConvention string_to_calling_convention(String s) {
 	if (s == "fast")        return ProcCC_FastCall;
 	if (s == "none")        return ProcCC_None;
 	if (s == "naked")       return ProcCC_Naked;
+
+	if (s == "win64")	return ProcCC_Win64;
+	if (s == "sysv")        return ProcCC_SysV;
+
 	if (s == "system") {
 		if (build_context.metrics.os == TargetOs_windows) {
 			return ProcCC_StdCall;
 		}
 		return ProcCC_CDecl;
 	}
+
+
 	return ProcCC_Invalid;
 }
 

+ 18 - 0
src/parser.hpp

@@ -249,12 +249,30 @@ enum ProcCallingConvention : i32 {
 
 	ProcCC_InlineAsm   = 8,
 
+	ProcCC_Win64       = 9,
+	ProcCC_SysV        = 10,
+
+
 	ProcCC_MAX,
 
 
 	ProcCC_ForeignBlockDefault = -1,
 };
 
+char const *proc_calling_convention_strings[ProcCC_MAX] = {
+	"",
+	"odin",
+	"contextless",
+	"cdecl",
+	"stdcall",
+	"fastcall",
+	"none",
+	"naked",
+	"inlineasm",
+	"win64",
+	"sysv",
+};
+
 ProcCallingConvention default_calling_convention(void) {
 	return ProcCC_Odin;
 }