Prechádzať zdrojové kódy

Begin with on debugging symbol; fix version number 0.7.0

gingerBill 7 rokov pred
rodič
commit
2b0521347b
3 zmenil súbory, kde vykonal 203 pridanie a 102 odobranie
  1. 1 1
      src/build_settings.cpp
  2. 74 8
      src/ir.cpp
  3. 128 93
      src/ir_print.cpp

+ 1 - 1
src/build_settings.cpp

@@ -307,7 +307,7 @@ String get_fullpath_core(gbAllocator a, String path) {
 }
 
 
-String const ODIN_VERSION = str_lit("0.6.2");
+String const ODIN_VERSION = str_lit("0.7.0");
 
 void init_build_context(void) {
 	BuildContext *bc = &build_context;

+ 74 - 8
src/ir.cpp

@@ -11,7 +11,7 @@ struct irModule {
 	gbArena       tmp_arena;
 	gbAllocator   allocator;
 	gbAllocator   tmp_allocator;
-	// bool generate_debug_info;
+	bool generate_debug_info;
 
 	u64 stmt_state_flags;
 
@@ -26,6 +26,9 @@ struct irModule {
 	Map<irDebugInfo *>    debug_info;          // Key: Unique pointer
 	Map<irValue *>        anonymous_proc_lits; // Key: AstNode *
 
+	irDebugInfo *         debug_compile_unit;
+
+
 	i32                   global_string_index;
 	i32                   global_array_index; // For ConstantSlice
 	i32                   global_generated_index;
@@ -228,6 +231,7 @@ struct irProcedure {
 		irValue **args;                                               \
 		isize     arg_count;                                          \
 		irValue * context_ptr;                                        \
+		irDebugInfo *debug_location;                                  \
 	})                                                                \
 	IR_INSTR_KIND(StartupRuntime, i32)                                \
 	IR_INSTR_KIND(DebugDeclare, struct {                              \
@@ -486,6 +490,8 @@ enum irDebugInfoKind {
 	irDebugInfo_Proc,
 	irDebugInfo_AllProcs,
 
+	irDebugInfo_Location,
+
 	irDebugInfo_BasicType,      // basic types
 	irDebugInfo_ProcType,
 	irDebugInfo_DerivedType,    // pointer, typedef
@@ -528,6 +534,10 @@ struct irDebugInfo {
 		struct {
 			Array<irDebugInfo *> procs;
 		} AllProcs;
+		struct {
+			irDebugInfo *scope;
+			TokenPos     pos;
+		} Location;
 
 
 		struct {
@@ -1060,6 +1070,18 @@ irValue *ir_instr_call(irProcedure *p, irValue *value, irValue *return_ptr, irVa
 	v->Instr.Call.arg_count   = arg_count;
 	v->Instr.Call.type        = result_type;
 	v->Instr.Call.context_ptr = context_ptr;
+
+	irDebugInfo **pp = map_get(&p->module->debug_info, hash_entity(p->entity));
+	if (pp != nullptr) {
+		GB_ASSERT_MSG(pp != nullptr, "%.*s %p", LIT(p->name), p->entity);
+		irDebugInfo *dl = ir_alloc_debug_info(p->module->allocator, irDebugInfo_Location);
+		dl->Location.scope = *pp;
+		dl->Location.pos = p->entity->token.pos;
+		map_set(&p->module->debug_info, hash_pointer(v), dl);
+
+		v->Instr.Call.debug_location = dl;
+	}
+
 	return v;
 }
 
@@ -2483,6 +2505,49 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
 
 #endif
 
+	if (is_type_string(a)) {
+		char *runtime_proc = nullptr;
+		switch (op_kind) {
+		case Token_CmpEq: runtime_proc = "__string_eq"; break;
+		case Token_NotEq: runtime_proc = "__string_ne"; break;
+		case Token_Lt:    runtime_proc = "__string_lt"; break;
+		case Token_Gt:    runtime_proc = "__string_gt"; break;
+		case Token_LtEq:  runtime_proc = "__string_le"; break;
+		case Token_GtEq:  runtime_proc = "__string_gt"; break;
+		}
+		GB_ASSERT(runtime_proc != nullptr);
+
+		irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 2);
+		args[0] = left;
+		args[1] = right;
+		return ir_emit_global_call(proc, runtime_proc, args, 2);
+	}
+
+	if (is_type_complex(a)) {
+		char *runtime_proc = "";
+		i64 sz = 8*type_size_of(proc->module->allocator, a);
+		switch (sz) {
+		case 64:
+			switch (op_kind) {
+			case Token_CmpEq: runtime_proc = "__complex64_eq"; break;
+			case Token_NotEq: runtime_proc = "__complex64_ne"; break;
+			}
+			break;
+		case 128:
+			switch (op_kind) {
+			case Token_CmpEq: runtime_proc = "__complex128_eq"; break;
+			case Token_NotEq: runtime_proc = "__complex128_ne"; break;
+			}
+			break;
+		}
+		GB_ASSERT(runtime_proc != nullptr);
+
+		irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 2);
+		args[0] = left;
+		args[1] = right;
+		return ir_emit_global_call(proc, runtime_proc, args, 2);
+	}
+
 
 	return ir_emit(proc, ir_instr_binary_op(proc, op_kind, left, right, result));
 }
@@ -7600,6 +7665,8 @@ void ir_init_module(irModule *m, Checker *c) {
 	m->tmp_allocator = gb_arena_allocator(&m->tmp_arena);
 	m->info = &c->info;
 
+	m->generate_debug_info = build_context.ODIN_OS == "windows" && build_context.word_size == 8;
+
 	map_init(&m->values,                  heap_allocator());
 	map_init(&m->members,                 heap_allocator());
 	map_init(&m->debug_info,              heap_allocator());
@@ -7706,6 +7773,8 @@ void ir_init_module(irModule *m, Checker *c) {
 		di->CompileUnit.producer = str_lit("odin");
 
 		map_set(&m->debug_info, hash_pointer(m), di);
+
+		m->debug_compile_unit = di;
 	}
 }
 
@@ -8466,9 +8535,7 @@ void ir_gen_tree(irGen *s) {
 
 	isize all_proc_max_count = 0;
 	for_array(i, m->debug_info.entries) {
-		auto *entry = &m->debug_info.entries[i];
-		irDebugInfo *di = entry->value;
-		di->id = cast(i32)i;
+		irDebugInfo *di = m->debug_info.entries[i].value;
 		if (di->kind == irDebugInfo_Proc) {
 			all_proc_max_count++;
 		}
@@ -8480,13 +8547,13 @@ void ir_gen_tree(irGen *s) {
 
 
 	for_array(i, m->debug_info.entries) {
-		auto *entry = &m->debug_info.entries[i];
-		irDebugInfo *di = entry->value;
+		irDebugInfo *di = m->debug_info.entries[i].value;
 		if (di->kind == irDebugInfo_Proc) {
 			array_add(&all_procs->AllProcs.procs, di);
 		}
 	}
 
+
 #if defined(GB_SYSTEM_WINDOWS)
 	if (build_context.is_dll && !has_dll_main) {
 		// DllMain :: proc(inst: rawptr, reason: u32, reserved: rawptr) -> i32
@@ -8754,11 +8821,10 @@ void ir_gen_tree(irGen *s) {
 	for_array(i, m->debug_info.entries) {
 		auto *entry = &m->debug_info.entries[i];
 		irDebugInfo *di = entry->value;
-		di->id = cast(i32)i;
+		di->id = cast(i32)(i+1);
 	}
 
 
-
 	// m->layout = str_lit("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
 }
 

+ 128 - 93
src/ir_print.cpp

@@ -139,6 +139,49 @@ void ir_print_escape_string(irFileBuffer *f, String name, bool print_quotes, boo
 }
 
 
+void ir_print_escape_path(irFileBuffer *f, String path) {
+	isize extra = 0;
+	for (isize i = 0; i < path.len; i++) {
+		u8 c = path[i];
+		if (!ir_valid_char(c)) {
+			extra += 2;
+		}
+	}
+
+	if (extra == 0) {
+		ir_write_string(f, path);
+		return;
+	}
+
+
+	char hex_table[] = "0123456789ABCDEF";
+	isize buf_len = path.len + extra + 2 + 1;
+
+	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
+
+	u8 *buf = gb_alloc_array(string_buffer_allocator, u8, buf_len);
+
+	isize j = 0;
+
+	for (isize i = 0; i < path.len; i++) {
+		u8 c = path[i];
+		if (ir_valid_char(c) || c == ':') {
+			buf[j++] = c;
+		} else if (c == '\\') {
+			buf[j++] = '/';
+		} else {
+			buf[j] = '\\';
+			buf[j+1] = hex_table[c >> 4];
+			buf[j+2] = hex_table[c & 0x0f];
+			j += 3;
+		}
+	}
+
+	ir_file_write(f, buf, j);
+
+	gb_temp_arena_memory_end(tmp);
+}
+
 
 void ir_print_encoded_local(irFileBuffer *f, String name) {
 	ir_write_byte(f, '%');
@@ -1245,32 +1288,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 
 		if (gb_is_between(bo->op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
 			if (is_type_string(elem_type)) {
-				ir_write_string(f, "call ");
-				ir_print_calling_convention(f, m, ProcCC_Odin);
-				ir_print_type(f, m, t_bool);
-				char *runtime_proc = "";
-				switch (bo->op) {
-				case Token_CmpEq: runtime_proc = "__string_eq"; break;
-				case Token_NotEq: runtime_proc = "__string_ne"; break;
-				case Token_Lt:    runtime_proc = "__string_lt"; break;
-				case Token_Gt:    runtime_proc = "__string_gt"; break;
-				case Token_LtEq:  runtime_proc = "__string_le"; break;
-				case Token_GtEq:  runtime_proc = "__string_gt"; break;
-				}
-
-				ir_write_byte(f, ' ');
-				ir_print_encoded_global(f, make_string_c(runtime_proc), false);
-				ir_write_byte(f, '(');
-				ir_print_type(f, m, type);
-				ir_write_byte(f, ' ');
-				ir_print_value(f, m, bo->left, type);
-				ir_write_string(f, str_lit(", "));
-				ir_print_type(f, m, type);
-				ir_write_byte(f, ' ');
-				ir_print_value(f, m, bo->right, type);
-				ir_write_string(f, ")\n");
-				return;
-
+				GB_PANIC("Unhandled string type");
 			} else if (is_type_float(elem_type)) {
 				ir_write_string(f, "fcmp ");
 				switch (bo->op) {
@@ -1282,37 +1300,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 				case Token_GtEq:  ir_write_string(f, "oge"); break;
 				}
 			} else if (is_type_complex(elem_type)) {
-				ir_write_string(f, "call ");
-				ir_print_calling_convention(f, m, ProcCC_Odin);
-				ir_print_type(f, m, t_bool);
-				char *runtime_proc = "";
-				i64 sz = 8*type_size_of(m->allocator, elem_type);
-				switch (sz) {
-				case 64:
-					switch (bo->op) {
-					case Token_CmpEq: runtime_proc = "__complex64_eq"; break;
-					case Token_NotEq: runtime_proc = "__complex64_ne"; break;
-					}
-					break;
-				case 128:
-					switch (bo->op) {
-					case Token_CmpEq: runtime_proc = "__complex128_eq"; break;
-					case Token_NotEq: runtime_proc = "__complex128_ne"; break;
-					}
-					break;
-				}
-
-				ir_write_byte(f, ' ');
-				ir_print_encoded_global(f, make_string_c(runtime_proc), false);
-				ir_write_byte(f, '(');
-				ir_print_type(f, m, type);
-				ir_write_byte(f, ' ');
-				ir_print_value(f, m, bo->left, type);
-				ir_write_string(f, str_lit(", "));
-				ir_print_type(f, m, type);
-				ir_write_byte(f, ' ');
-				ir_print_value(f, m, bo->right, type);
-				ir_write_string(f, ")\n");
+				GB_PANIC("Unhandled complex type");
 				return;
 			} else {
 				ir_write_string(f, "icmp ");
@@ -1475,7 +1463,13 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 			ir_write_string(f, " noalias nonnull ");
 			ir_print_value(f, m, call->context_ptr, t_context_ptr);
 		}
-		ir_write_string(f, ")\n");
+		ir_write_string(f, ")");
+
+		if (m->generate_debug_info && call->debug_location) {
+			ir_fprintf(f, ", !dbg !%d", call->debug_location->id);
+		}
+
+		ir_write_string(f, "\n");
 
 		break;
 	}
@@ -1644,8 +1638,11 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		Entity *e = dd->entity;
 		String name = e->token.string;
 		TokenPos pos = e->token.pos;
-		// gb_printf("debug_declare %.*s\n", LIT(dd->entity->token.string));
-		ir_write_string(f, "; ");
+
+
+		if (!m->generate_debug_info) {
+			ir_write_string(f, "; ");
+		}
 		ir_write_string(f, "call void @llvm.dbg.declare(");
 		ir_write_string(f, "metadata ");
 		ir_print_type(f, m, vt);
@@ -1752,11 +1749,16 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 	ir_write_string(f, ") ");
 
 	switch (proc->inlining) {
+	default:
+		ir_fprintf(f, "#0 ");
+		break;
 	case ProcInlining_no_inline:
 		ir_write_string(f, "noinline ");
+		ir_fprintf(f, "#0 ");
 		break;
 	case ProcInlining_inline:
 		ir_write_string(f, "alwaysinline ");
+		ir_fprintf(f, "#1 ");
 		break;
 	}
 
@@ -1766,12 +1768,13 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 			if (di_ != nullptr) {
 				irDebugInfo *di = *di_;
 				GB_ASSERT(di->kind == irDebugInfo_Proc);
-				// ir_fprintf(f, "!dbg !%d ", di->id);
+				ir_fprintf(f, "!dbg !%d ", di->id);
 			}
 		}
 	}
 
 
+
 	if (proc->body != nullptr) {
 		// ir_fprintf(f, "nounwind uwtable {\n");
 
@@ -1844,6 +1847,13 @@ void print_llvm_ir(irGen *ir) {
 	irFileBuffer buf = {}, *f = &buf;
 	ir_file_buffer_init(f, &ir->output_file);
 
+	if (m->generate_debug_info) {
+		ir_write_string(f, "target datalayout = \"e-m:w-i64:64-f80:128-n8:16:32:64-S128\"\n");
+		ir_write_string(f, "target triple = \"x86_64-pc-windows-msvc19.11.25508\"\n\n");
+	}
+
+
+
 	ir_print_encoded_local(f, str_lit("..opaque"));
 	ir_write_string(f, str_lit(" = type {};\n"));
 	ir_print_encoded_local(f, str_lit("..string"));
@@ -1970,23 +1980,28 @@ void print_llvm_ir(irGen *ir) {
 	}
 
 
-#if 0
-	// if (m->generate_debug_info) {
-	{
+	if (m->generate_debug_info) {
 		ir_write_byte(f, '\n');
 
 		i32 diec = m->debug_info.entries.count;
 
-		ir_fprintf(f, "!llvm.dbg.cu = !{!0}\n");
-		ir_fprintf(f, "!llvm.ident = !{!%d}\n", diec+3);
-		ir_fprintf(f, "!%d = !{i32 2, !\"Dwarf Version\", i32 4}\n", diec+0);
-		ir_fprintf(f, "!%d = !{i32 2, !\"Debug Info Version\", i32 3}\n", diec+1);
-		ir_fprintf(f, "!%d = !{i32 1, !\"PIC Level\", i32 2}\n", diec+2);
-		ir_fprintf(f, "!%d = !{!\"clang version 3.9.0 (branches/release_39)\"}\n", diec+3);
+		i32 di_version    = diec+1;
+		i32 di_debug_info = diec+2;
+		i32 di_code_view  = diec+3;
+		i32 di_wchar_size = diec+4;
+
+		ir_fprintf(f, "attributes #0 = {nounwind noinline optnone uwtable}\n");
+		ir_fprintf(f, "attributes #1 = {nounwind alwaysinline uwtable}\n");
+
+
+		ir_fprintf(f, "!llvm.dbg.cu = !{!%d}\n", m->debug_compile_unit->id);
+		ir_fprintf(f, "!llvm.ident = !{!%d}\n", di_version);
+		ir_fprintf(f, "!llvm.module.flags = !{!%d, !%d, !%d}\n", di_debug_info, di_code_view, di_wchar_size);
+
+		ir_fprintf(f, "!0 = !{}\n");
 
 		for_array(di_index, m->debug_info.entries) {
-			MapIrDebugInfoEntry *entry = &m->debug_info.entries[di_index];
-			irDebugInfo *di = entry->value;
+			irDebugInfo *di = m->debug_info.entries[di_index].value;
 			ir_fprintf(f, "!%d = ", di->id);
 
 			switch (di->kind) {
@@ -1994,38 +2009,42 @@ void print_llvm_ir(irGen *ir) {
 				irDebugInfo *file = *map_get(&m->debug_info, hash_pointer(di->CompileUnit.file));
 				ir_fprintf(f,
 				            "distinct !DICompileUnit("
-				            "language: DW_LANG_Go, " // Is this good enough?
-				            "file: !%d, "
-				            "producer: \"clang version 3.9.0 (branches/release_39)\", "
-				            "flags: \"\", "
-				            "runtimeVersion: 0, "
-				            "isOptimized: false, "
-				            "emissionKind: FullDebug"
+				              "language: DW_LANG_C_plus_plus" // Is this good enough?
+				            ", file: !%d"
+				            ", producer: \"Odin %.*s\""
+				            ", flags: \"\""
+				            ", runtimeVersion: 0"
+				            ", isOptimized: false"
+				            ", emissionKind: FullDebug"
 				            ")",
-				            file->id);
+				            file->id, LIT(build_context.ODIN_VERSION));
 
 				break;
 			}
 			case irDebugInfo_File:
 				ir_fprintf(f, "!DIFile(filename: \"");
-				ir_print_escape_string(f, di->File.filename, false);
+				ir_print_escape_path(f, di->File.filename);
 				ir_fprintf(f, "\", directory: \"");
-				ir_print_escape_string(f, di->File.directory, false);
-				ir_fprintf(f, "\")");
+				ir_print_escape_path(f, di->File.directory);
+				ir_fprintf(f, "\"");
+				ir_fprintf(f, ")");
 				break;
 			case irDebugInfo_Proc:
 				ir_fprintf(f, "distinct !DISubprogram("
-				            "name: \"%.*s\", "
-				            // "linkageName: \"\", "
-				            "file: !%d, "
-				            "line: %td, "
-				            "isDefinition: true, "
-				            "isLocal: false, "
-				            "unit: !0"
+				              "name: \"%.*s\""
+				            ", linkageName: \"%.*s\""
+				            ", file: !%d"
+				            ", line: %td"
+				            ", isDefinition: true"
+				            ", isLocal: true"
+				            ", flags: DIFlagPrototyped"
+				            ", isOptimized: false"
+				            ", unit: !%d"
 				            ")",
+				            LIT(di->Proc.entity->token.string),
 				            LIT(di->Proc.name),
-				            di->Proc.file->id,
-				            di->Proc.pos.line);
+				            di->Proc.file->id, di->Proc.pos.line,
+				            m->debug_compile_unit->id);
 				break;
 
 			case irDebugInfo_AllProcs:
@@ -2037,11 +2056,27 @@ void print_llvm_ir(irGen *ir) {
 				}
 				ir_write_byte(f, '}');
 				break;
+
+			case irDebugInfo_Location:
+				GB_ASSERT(di->Location.scope != nullptr);
+				ir_fprintf(f, "!DILocation(line: %td, column: %td, scope: !%d)",
+				           di->Location.pos.line, di->Location.pos.column, di->Location.scope->id);
+				break;
+
+			default:
+				GB_PANIC("Unhandled irDebugInfo kind %d", di->kind);
+				break;
 			}
 
 			ir_write_byte(f, '\n');
 		}
+
+
+		ir_fprintf(f, "!%d = !{!\"Odin version %.*s \"}\n", di_version, LIT(build_context.ODIN_VERSION));
+		ir_fprintf(f, "!%d = !{i32 2, !\"Debug Info Version\", i32 3}\n", di_debug_info);
+		ir_fprintf(f, "!%d = !{i32 2, !\"CodeView\", i32 1}\n",           di_code_view);
+		ir_fprintf(f, "!%d = !{i32 1, !\"wchar_size\", i32 2}\n",         di_wchar_size);
 	}
-#endif
+
 	ir_file_buffer_destroy(f);
 }