mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-15 15:44:04 +00:00
Merge branch 'master' into directx-packages
This commit is contained in:
@@ -33,6 +33,11 @@ Calling_Convention :: enum u8 {
|
||||
|
||||
None = 6,
|
||||
Naked = 7,
|
||||
|
||||
_ = 8, // reserved
|
||||
|
||||
Win64 = 9,
|
||||
SysV = 10,
|
||||
}
|
||||
|
||||
Type_Info_Enum_Value :: distinct i64
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user