Bläddra i källkod

Tuple debug info (untested). Generated locals now flow through debug info.

lachsinc 7 år sedan
förälder
incheckning
11ea03d2e8
2 ändrade filer med 64 tillägg och 25 borttagningar
  1. 60 22
      src/ir.cpp
  2. 4 3
      src/ir_print.cpp

+ 60 - 22
src/ir.cpp

@@ -1430,13 +1430,15 @@ irValue *ir_add_local(irProcedure *proc, Entity *e, Ast *expr, bool zero_initial
 		ir_emit_zero_init(proc, instr, expr);
 	}
 
-	if (expr != nullptr && proc->entity != nullptr) {	
-		GB_ASSERT_NOT_NULL(proc->debug_scope);
-		
-		ir_emit(proc, ir_instr_debug_declare(proc, expr, e, true, instr));
-
-		// TODO(lachsinc): "Arg" is not used yet but should be eventually, if applicable, set to param index.
-		ir_add_debug_info_local(proc, e, param_index);
+	// if (proc->module->generate_debug_info && expr != nullptr && proc->entity != nullptr) {
+	if (proc->module->generate_debug_info && proc->entity != nullptr) {
+		// GB_ASSERT_NOT_NULL(proc->debug_scope);
+		if (expr != nullptr) {
+			ir_emit(proc, ir_instr_debug_declare(proc, expr, e, true, instr));
+		}
+		if (e->scope != nullptr && proc->debug_scope != nullptr) {
+			irDebugInfo *di_local = ir_add_debug_info_local(proc, e, param_index);
+		}
 	}
 
 	return instr;
@@ -1689,15 +1691,24 @@ irDebugInfo *ir_add_debug_info_field(irModule *module, irDebugInfo *scope, Entit
 	void *ptr_to_hash = nullptr;
 	if (scope_type) {
 		Type *scope_base = base_type(scope_type);
-		if (is_type_struct(scope_type)) {
-			if (scope_base->Struct.are_offsets_set) {
+		if (is_type_struct(scope_type) || is_type_tuple(scope_type)) {
+			if (is_type_struct(scope_type) && scope_base->Struct.are_offsets_set) {
 				di->DerivedType.offset = ir_debug_info_bits(scope_base->Struct.offsets[index]);
+			} else if (is_type_tuple(scope_type) && scope_base->Tuple.are_offsets_set) {
+				di->DerivedType.offset = ir_debug_info_bits(scope_base->Tuple.offsets[index]);
 			} else {
 				di->DerivedType.offset = ir_debug_info_bits(type_offset_of(scope_base, index));
 			}
 			if (e) {
 				ptr_to_hash = e;
 				di->DerivedType.name = e->token.string;
+				if (e->token.string.len == 0) {
+					// If no name available for field, use its field index as its name.
+					isize max_len = 8;
+					u8 *str = cast(u8 *)gb_alloc_array(heap_allocator(), u8, max_len);
+					isize len = gb_snprintf(cast(char *)str, 8, "%d", index);
+					di->DerivedType.name = make_string(str, len-1);
+				}
 				di->DerivedType.pos = e->token.pos;
 			} else {
 				GB_PANIC("Unreachable"); // struct field Entity's should be provided.
@@ -2011,7 +2022,8 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD
 		if (named_base->kind != Type_Struct &&
 			named_base->kind != Type_Union &&
 			named_base->kind != Type_Enum &&
-			named_base->kind != Type_BitField) {
+			named_base->kind != Type_BitField &&
+			named_base->kind != Type_Tuple) {
 			// distinct / typedef etc.
 			irDebugInfo *di = ir_alloc_debug_info(irDebugInfo_DerivedType);
 			if (type->kind == Type_Named) {
@@ -2084,7 +2096,7 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD
 		return di;
 	}
 
-	if (is_type_struct(type) || is_type_union(type) || is_type_enum(type)) {
+	if (is_type_struct(type) || is_type_union(type) || is_type_enum(type) || is_type_tuple(type)) {
 		if (type->kind == Type_Named) {
 			// NOTE(lachsinc): Named named's should always be handled prior as typedefs.
 			GB_ASSERT(type->Named.base->kind != Type_Named);
@@ -2111,13 +2123,13 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD
 				GB_ASSERT_NOT_NULL(scope);
 				di->CompositeType.scope = scope;
 			}
+			di->CompositeType.tag = irDebugBasicEncoding_structure_type;
 			di->CompositeType.elements = ir_add_debug_info_array(module, 0, base->Struct.fields.count);
 			for_array(field_index, base->Struct.fields) {
 				array_add(&di->CompositeType.elements->DebugInfoArray.elements,
 				          ir_add_debug_info_field(module, di, base->Struct.fields[field_index], type,
 				                                  cast(i32)field_index, base->Struct.fields[field_index]->type, file));
 			}
-			di->CompositeType.tag = irDebugBasicEncoding_structure_type;
 		} else if (is_type_union(type)) {
 			GB_ASSERT(base->kind == Type_Union);
 			if (!is_type_named(type)) {
@@ -2144,17 +2156,32 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD
 				GB_ASSERT_NOT_NULL(scope);
 				di->CompositeType.scope = scope;
 			}
+			di->CompositeType.tag = irDebugBasicEncoding_enumeration_type;
 			di->CompositeType.base_type = ir_add_debug_info_type(module, base->Enum.base_type, e, scope, file);
 			di->CompositeType.elements = ir_add_debug_info_array(module, 0, base->Enum.fields.count);
 			for_array(field_index, base->Enum.fields) {
 				array_add(&di->CompositeType.elements->DebugInfoArray.elements,
 				          ir_add_debug_info_enumerator(module, base->Enum.fields[field_index]));
 			}
-			di->CompositeType.tag = irDebugBasicEncoding_enumeration_type;
 
 			// TODO(lachsinc): Do we want to ensure this is an enum in the global scope before
 			// adding it into the modules enum array ??
 			array_add(&module->debug_compile_unit->CompileUnit.enums->DebugInfoArray.elements, di);
+		} else if (is_type_tuple(type)) {
+			GB_ASSERT(base->kind == Type_Tuple);
+			if (!is_type_named(type)) {
+				di->CompositeType.name = str_lit("tuple");
+				GB_ASSERT_NOT_NULL(scope);
+				di->CompositeType.scope = scope;
+			}
+			di->CompositeType.tag = irDebugBasicEncoding_structure_type;
+			di->CompositeType.elements = ir_add_debug_info_array(module, 0, base->Tuple.variables.count);
+			// TODO(lachsinc): Ensure offsets are set properly?
+			for_array(var_index, base->Tuple.variables) {
+				array_add(&di->CompositeType.elements->DebugInfoArray.elements,
+				          ir_add_debug_info_field(module, di, base->Tuple.variables[var_index], type,
+				                                  cast(i32)var_index, base->Tuple.variables[var_index]->type, file));
+			}
 		}
 
 		return di;
@@ -2250,6 +2277,10 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD
 		return ir_add_debug_info_type_bit_set(module, type, e, scope, file);
 	}
 
+	if (is_type_tuple(type)) {
+		int i = 0;
+	}
+
 	//
 	// TODO(lachsinc): HACK For now any remaining types interpreted as a rawptr.
 	//
@@ -2267,9 +2298,9 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD
 }
 
 irDebugInfo *ir_add_debug_info_global(irModule *module, irValue *v) {
-	// if (!proc->module->generate_debug_info) {
-	// 	return nullptr;
-	// }
+	if (!module->generate_debug_info) {
+		return nullptr;
+	}
 
 	Entity *e = v->Global.entity;
 
@@ -2333,11 +2364,17 @@ irDebugInfo *ir_add_debug_info_block(irProcedure *proc, Scope *scope) {
 }
 
 irDebugInfo *ir_add_debug_info_local(irProcedure *proc, Entity *e, i32 arg_id) {
+	// TODO(lachsinc): Not sure if this handles generated locals properly as they may not have
+	// enough information inside "e".
+
 	irModule *module = proc->module;
+	if (!module->generate_debug_info) {
+		return nullptr;
+	}
 
 	irDebugInfo *scope = nullptr;
 	irDebugInfo *file = nullptr;
-	if (e->scope->node->kind == Ast_ProcType) {
+	if (e->scope && e->scope->node->kind == Ast_ProcType) {
 		scope = proc->debug_scope;
 		file = proc->debug_scope->Proc.file;
 	} else {
@@ -2360,9 +2397,10 @@ irDebugInfo *ir_add_debug_info_local(irProcedure *proc, Entity *e, i32 arg_id) {
 }
 
 irDebugInfo *ir_add_debug_info_proc(irProcedure *proc) {
-	// if (!proc->module->generate_debug_info) {
-	// 	return nullptr;
-	// }
+	irModule *module = proc->module;
+	if (!module->generate_debug_info) {
+		return nullptr;
+	}
 
 	Entity *entity = proc->entity;
 
@@ -8280,14 +8318,14 @@ void ir_begin_procedure_body(irProcedure *proc) {
 
 	// NOTE(lachsinc): This is somewhat of a fallback/catch-all; We use the procedure's identifer as a debug location..
 	// Additional debug locations should be pushed for the procedures statements/expressions themselves.
-	if (proc->entity && proc->entity->identifier) { // TODO(lachsinc): Better way to determine if these procs are main/runtime_startup.
+	if (proc->module->generate_debug_info && proc->entity && proc->entity->identifier) { // TODO(lachsinc): Better way to determine if these procs are main/runtime_startup.
 		// TODO(lachsinc): Passing the file for the scope may not be correct for nested procedures? This should probably be
 		// handled all inside push_debug_location, with just the Ast * we can pull out everything we need to construct scope/file debug info etc.
 		ir_add_debug_info_proc(proc); 
 		ir_push_debug_location(proc->module, proc->entity->identifier, proc->debug_scope);
 		GB_ASSERT_NOT_NULL(proc->debug_scope);
 	} else {
-		GB_ASSERT(proc->is_entry_point || (string_compare(proc->name, str_lit(IR_STARTUP_RUNTIME_PROC_NAME)) == 0));
+		// GB_ASSERT(proc->is_entry_point || (string_compare(proc->name, str_lit(IR_STARTUP_RUNTIME_PROC_NAME)) == 0));
 		ir_push_debug_location(proc->module, nullptr, nullptr);
 	}
 

+ 4 - 3
src/ir_print.cpp

@@ -2044,16 +2044,17 @@ void print_llvm_ir(irGen *ir) {
 			}
 			case irDebugInfo_LocalVariable: {
 				ir_fprintf(f, "!DILocalVariable("
-				              "name: \"%.*s\""
-				            ", scope: !%d"
+				              "scope: !%d"
 				            ", file: !%d"
 				            ", line: %d"
 				            ", type: !%d",
-				            LIT(di->LocalVariable.name),
 				            di->LocalVariable.scope->id,
 				            di->LocalVariable.file->id,
 				            di->LocalVariable.pos.line,
 				            di->LocalVariable.type->id);
+				if (di->DerivedType.name.len > 0) {
+					ir_fprintf(f, ", name: \"%.*s\"", LIT(di->LocalVariable.name));
+				}
 				if (di->LocalVariable.arg > 0) {
 					ir_fprintf(f, ", arg: %d", di->LocalVariable.arg);
 				}