| author | |
| committer | |
| log | e4cb28dbf2d0bc70581502d751ba9e4f7a46ed93 |
| tree | 632db4aa17921b6fbb256b2c5d9bf0c5735a02c5 |
| parent | 4d45d14b557365bfb5b9059347ec144784d481b7 |
5 files changed, 142 insertions(+), 33 deletions(-)
src/analyze.cpp+71-31| ... | ... | @@ -114,6 +114,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool |
| 114 | 114 | buf_appendf(&entry->name, "&%s%s", is_const ? "const " : "", buf_ptr(&child_type->name)); |
| 115 | 115 | entry->size_in_bits = g->pointer_size_bytes * 8; |
| 116 | 116 | entry->align_in_bits = g->pointer_size_bytes * 8; |
| 117 | assert(child_type->di_type); | |
| 117 | 118 | entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type, |
| 118 | 119 | entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name)); |
| 119 | 120 | entry->data.pointer.child_type = child_type; |
| ... | ... | @@ -269,6 +270,70 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_ |
| 269 | 270 | } |
| 270 | 271 | } |
| 271 | 272 | |
| 273 | static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type) { | |
| 274 | assert(struct_type->id == TypeTableEntryIdStruct); | |
| 275 | ||
| 276 | AstNode *decl_node = struct_type->data.structure.decl_node; | |
| 277 | ||
| 278 | assert(struct_type->di_type); | |
| 279 | assert(!struct_type->data.structure.fields); | |
| 280 | ||
| 281 | int field_count = decl_node->data.struct_decl.fields.length; | |
| 282 | struct_type->data.structure.field_count = field_count; | |
| 283 | struct_type->data.structure.fields = allocate<TypeStructField>(field_count); | |
| 284 | ||
| 285 | LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count); | |
| 286 | LLVMZigDIType **di_element_types = allocate<LLVMZigDIType*>(field_count); | |
| 287 | ||
| 288 | uint64_t total_size_in_bits = 0; | |
| 289 | uint64_t first_field_align_in_bits = 0; | |
| 290 | uint64_t offset_in_bits = 0; | |
| 291 | ||
| 292 | for (int i = 0; i < field_count; i += 1) { | |
| 293 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); | |
| 294 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | |
| 295 | type_struct_field->name = &field_node->data.struct_field.name; | |
| 296 | type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type); | |
| 297 | ||
| 298 | if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) { | |
| 299 | resolve_struct_type(g, import, type_struct_field->type_entry); | |
| 300 | } | |
| 301 | ||
| 302 | di_element_types[i] = LLVMZigCreateDebugMemberType(g->dbuilder, | |
| 303 | LLVMZigTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), | |
| 304 | import->di_file, field_node->line + 1, | |
| 305 | type_struct_field->type_entry->size_in_bits, | |
| 306 | type_struct_field->type_entry->align_in_bits, | |
| 307 | offset_in_bits, 0, type_struct_field->type_entry->di_type); | |
| 308 | ||
| 309 | element_types[i] = type_struct_field->type_entry->type_ref; | |
| 310 | assert(di_element_types[i]); | |
| 311 | assert(element_types[i]); | |
| 312 | ||
| 313 | total_size_in_bits += type_struct_field->type_entry->size_in_bits; | |
| 314 | if (first_field_align_in_bits == 0) { | |
| 315 | first_field_align_in_bits = type_struct_field->type_entry->align_in_bits; | |
| 316 | } | |
| 317 | offset_in_bits += type_struct_field->type_entry->size_in_bits; | |
| 318 | ||
| 319 | } | |
| 320 | ||
| 321 | LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false); | |
| 322 | ||
| 323 | struct_type->align_in_bits = first_field_align_in_bits; | |
| 324 | struct_type->size_in_bits = total_size_in_bits; | |
| 325 | ||
| 326 | LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder, | |
| 327 | LLVMZigFileToScope(import->di_file), | |
| 328 | buf_ptr(&decl_node->data.struct_decl.name), | |
| 329 | import->di_file, decl_node->line + 1, struct_type->size_in_bits, struct_type->align_in_bits, 0, | |
| 330 | nullptr, di_element_types, field_count, 0, nullptr, ""); | |
| 331 | ||
| 332 | LLVMZigReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); | |
| 333 | struct_type->di_type = replacement_di_type; | |
| 334 | } | |
| 335 | ||
| 336 | ||
| 272 | 337 | static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 273 | 338 | switch (node->type) { |
| 274 | 339 | case NodeTypeExternBlock: |
| ... | ... | @@ -414,37 +479,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 414 | 479 | StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node; |
| 415 | 480 | TypeTableEntry *type_entry = struct_codegen->type_entry; |
| 416 | 481 | |
| 417 | int field_count = node->data.struct_decl.fields.length;; | |
| 418 | type_entry->data.structure.field_count = field_count; | |
| 419 | type_entry->data.structure.fields = allocate<TypeStructField>(field_count); | |
| 420 | ||
| 421 | LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count); | |
| 422 | LLVMZigDIType **di_element_types = allocate<LLVMZigDIType*>(field_count); | |
| 423 | ||
| 424 | uint64_t total_size_in_bits = 0; | |
| 425 | ||
| 426 | for (int i = 0; i < field_count; i += 1) { | |
| 427 | AstNode *field_node = node->data.struct_decl.fields.at(i); | |
| 428 | TypeStructField *type_struct_field = &type_entry->data.structure.fields[i]; | |
| 429 | type_struct_field->name = &field_node->data.struct_field.name; | |
| 430 | type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type); | |
| 431 | ||
| 432 | total_size_in_bits = type_struct_field->type_entry->size_in_bits; | |
| 433 | di_element_types[i] = type_struct_field->type_entry->di_type; | |
| 434 | ||
| 435 | element_types[i] = type_struct_field->type_entry->type_ref; | |
| 436 | } | |
| 437 | LLVMStructSetBody(type_entry->type_ref, element_types, field_count, false); | |
| 438 | ||
| 439 | // TODO re-evaluate this align in bits and size in bits | |
| 440 | type_entry->align_in_bits = 0; | |
| 441 | type_entry->size_in_bits = total_size_in_bits; | |
| 442 | type_entry->di_type = LLVMZigCreateDebugStructType(g->dbuilder, | |
| 443 | LLVMZigFileToScope(import->di_file), | |
| 444 | buf_ptr(&node->data.struct_decl.name), | |
| 445 | import->di_file, node->line + 1, type_entry->size_in_bits, type_entry->align_in_bits, 0, | |
| 446 | nullptr, di_element_types, field_count, 0, nullptr, ""); | |
| 447 | ||
| 482 | resolve_struct_type(g, import, type_entry); | |
| 448 | 483 | break; |
| 449 | 484 | } |
| 450 | 485 | case NodeTypeUse: |
| ... | ... | @@ -496,6 +531,11 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 496 | 531 | } else { |
| 497 | 532 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); |
| 498 | 533 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name)); |
| 534 | entry->data.structure.decl_node = node; | |
| 535 | entry->di_type = LLVMZigCreateReplaceableCompositeType(g->dbuilder, | |
| 536 | LLVMZigTag_DW_structure_type(), buf_ptr(&node->data.struct_decl.name), | |
| 537 | LLVMZigFileToScope(import->di_file), import->di_file, node->line + 1); | |
| 538 | ||
| 499 | 539 | buf_init_from_buf(&entry->name, name); |
| 500 | 540 | // put off adding the debug type until we do the full struct body |
| 501 | 541 | // this type is incomplete until we do another pass |
src/analyze.hpp+1| ... | ... | @@ -39,6 +39,7 @@ struct TypeStructField { |
| 39 | 39 | }; |
| 40 | 40 | |
| 41 | 41 | struct TypeTableEntryStruct { |
| 42 | AstNode *decl_node; | |
| 42 | 43 | bool is_packed; |
| 43 | 44 | int field_count; |
| 44 | 45 | TypeStructField *fields; |
src/codegen.cpp+1-2| ... | ... | @@ -215,8 +215,7 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou |
| 215 | 215 | |
| 216 | 216 | /* |
| 217 | 217 | if (struct_type->id == TypeTableEntryIdPointer) { |
| 218 | add_debug_source_node(g, node); | |
| 219 | struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, ""); | |
| 218 | zig_panic("TODO pointer field struct access"); | |
| 220 | 219 | } |
| 221 | 220 | */ |
| 222 | 221 |
src/zig_llvm.cpp+54| ... | ... | @@ -161,6 +161,18 @@ LLVMZigDIType *LLVMZigCreateDebugArrayType(LLVMZigDIBuilder *dibuilder, uint64_t |
| 161 | 161 | return reinterpret_cast<LLVMZigDIType*>(di_type); |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | LLVMZigDIType *LLVMZigCreateDebugMemberType(LLVMZigDIBuilder *dibuilder, LLVMZigDIScope *scope, | |
| 165 | const char *name, LLVMZigDIFile *file, unsigned line, uint64_t size_in_bits, | |
| 166 | uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags, LLVMZigDIType *type) | |
| 167 | { | |
| 168 | DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createMemberType( | |
| 169 | reinterpret_cast<DIScope*>(scope), | |
| 170 | name, | |
| 171 | reinterpret_cast<DIFile*>(file), | |
| 172 | line, size_in_bits, align_in_bits, offset_in_bits, flags, | |
| 173 | reinterpret_cast<DIType*>(type)); | |
| 174 | return reinterpret_cast<LLVMZigDIType*>(di_type); | |
| 175 | } | |
| 164 | 176 | |
| 165 | 177 | LLVMZigDIType *LLVMZigCreateDebugStructType(LLVMZigDIBuilder *dibuilder, LLVMZigDIScope *scope, |
| 166 | 178 | const char *name, LLVMZigDIFile *file, unsigned line_number, uint64_t size_in_bits, |
| ... | ... | @@ -186,6 +198,39 @@ LLVMZigDIType *LLVMZigCreateDebugStructType(LLVMZigDIBuilder *dibuilder, LLVMZig |
| 186 | 198 | return reinterpret_cast<LLVMZigDIType*>(di_type); |
| 187 | 199 | } |
| 188 | 200 | |
| 201 | LLVMZigDIType *LLVMZigCreateReplaceableCompositeType(LLVMZigDIBuilder *dibuilder, unsigned tag, | |
| 202 | const char *name, LLVMZigDIScope *scope, LLVMZigDIFile *file, unsigned line) | |
| 203 | { | |
| 204 | DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createReplaceableCompositeType( | |
| 205 | tag, name, | |
| 206 | reinterpret_cast<DIScope*>(scope), | |
| 207 | reinterpret_cast<DIFile*>(file), | |
| 208 | line); | |
| 209 | return reinterpret_cast<LLVMZigDIType*>(di_type); | |
| 210 | } | |
| 211 | ||
| 212 | void LLVMZigReplaceTemporary(LLVMZigDIBuilder *dibuilder, LLVMZigDIType *type, | |
| 213 | LLVMZigDIType *replacement) | |
| 214 | { | |
| 215 | reinterpret_cast<DIBuilder*>(dibuilder)->replaceTemporary( | |
| 216 | TempDIType(reinterpret_cast<DIType*>(type)), | |
| 217 | reinterpret_cast<DIType*>(replacement)); | |
| 218 | } | |
| 219 | ||
| 220 | void LLVMZigReplaceDebugArrays(LLVMZigDIBuilder *dibuilder, LLVMZigDIType *type, | |
| 221 | LLVMZigDIType **types_array, int types_array_len) | |
| 222 | { | |
| 223 | SmallVector<Metadata *, 8> fields; | |
| 224 | for (int i = 0; i < types_array_len; i += 1) { | |
| 225 | DIType *ditype = reinterpret_cast<DIType*>(types_array[i]); | |
| 226 | fields.push_back(ditype); | |
| 227 | } | |
| 228 | DICompositeType *composite_type = (DICompositeType*)reinterpret_cast<DIType*>(type); | |
| 229 | reinterpret_cast<DIBuilder*>(dibuilder)->replaceArrays( | |
| 230 | composite_type, | |
| 231 | reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(fields)); | |
| 232 | } | |
| 233 | ||
| 189 | 234 | LLVMZigDISubroutineType *LLVMZigCreateSubroutineType(LLVMZigDIBuilder *dibuilder_wrapped, |
| 190 | 235 | LLVMZigDIFile *file, LLVMZigDIType **types_array, int types_array_len, unsigned flags) |
| 191 | 236 | { |
| ... | ... | @@ -226,6 +271,10 @@ unsigned LLVMZigTag_DW_arg_variable(void) { |
| 226 | 271 | return dwarf::DW_TAG_arg_variable; |
| 227 | 272 | } |
| 228 | 273 | |
| 274 | unsigned LLVMZigTag_DW_structure_type(void) { | |
| 275 | return dwarf::DW_TAG_structure_type; | |
| 276 | } | |
| 277 | ||
| 229 | 278 | LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) { |
| 230 | 279 | DIBuilder *di_builder = new DIBuilder(*unwrap(module), allow_unresolved); |
| 231 | 280 | return reinterpret_cast<LLVMZigDIBuilder *>(di_builder); |
| ... | ... | @@ -286,6 +335,11 @@ LLVMZigDIScope *LLVMZigSubprogramToScope(LLVMZigDISubprogram *subprogram) { |
| 286 | 335 | return reinterpret_cast<LLVMZigDIScope*>(scope); |
| 287 | 336 | } |
| 288 | 337 | |
| 338 | LLVMZigDIScope *LLVMZigTypeToScope(LLVMZigDIType *type) { | |
| 339 | DIScope *scope = reinterpret_cast<DIType*>(type); | |
| 340 | return reinterpret_cast<LLVMZigDIScope*>(scope); | |
| 341 | } | |
| 342 | ||
| 289 | 343 | LLVMZigDICompileUnit *LLVMZigCreateCompileUnit(LLVMZigDIBuilder *dibuilder, |
| 290 | 344 | unsigned lang, const char *file, const char *dir, const char *producer, |
| 291 | 345 | bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name, |
src/zig_llvm.hpp+15| ... | ... | @@ -55,6 +55,19 @@ LLVMZigDIType *LLVMZigCreateDebugStructType(LLVMZigDIBuilder *dibuilder, LLVMZig |
| 55 | 55 | LLVMZigDIType **types_array, int types_array_len, unsigned run_time_lang, LLVMZigDIType *vtable_holder, |
| 56 | 56 | const char *unique_id); |
| 57 | 57 | |
| 58 | LLVMZigDIType *LLVMZigCreateDebugMemberType(LLVMZigDIBuilder *dibuilder, LLVMZigDIScope *scope, | |
| 59 | const char *name, LLVMZigDIFile *file, unsigned line, uint64_t size_in_bits, | |
| 60 | uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags, LLVMZigDIType *type); | |
| 61 | ||
| 62 | LLVMZigDIType *LLVMZigCreateReplaceableCompositeType(LLVMZigDIBuilder *dibuilder, unsigned tag, | |
| 63 | const char *name, LLVMZigDIScope *scope, LLVMZigDIFile *file, unsigned line); | |
| 64 | ||
| 65 | void LLVMZigReplaceTemporary(LLVMZigDIBuilder *dibuilder, LLVMZigDIType *type, | |
| 66 | LLVMZigDIType *replacement); | |
| 67 | ||
| 68 | void LLVMZigReplaceDebugArrays(LLVMZigDIBuilder *dibuilder, LLVMZigDIType *type, | |
| 69 | LLVMZigDIType **types_array, int types_array_len); | |
| 70 | ||
| 58 | 71 | LLVMZigDISubroutineType *LLVMZigCreateSubroutineType(LLVMZigDIBuilder *dibuilder_wrapped, |
| 59 | 72 | LLVMZigDIFile *file, LLVMZigDIType **types_array, int types_array_len, unsigned flags); |
| 60 | 73 | |
| ... | ... | @@ -64,6 +77,7 @@ unsigned LLVMZigEncoding_DW_ATE_float(void); |
| 64 | 77 | unsigned LLVMZigLang_DW_LANG_C99(void); |
| 65 | 78 | unsigned LLVMZigTag_DW_auto_variable(void); |
| 66 | 79 | unsigned LLVMZigTag_DW_arg_variable(void); |
| 80 | unsigned LLVMZigTag_DW_structure_type(void); | |
| 67 | 81 | |
| 68 | 82 | LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved); |
| 69 | 83 | |
| ... | ... | @@ -73,6 +87,7 @@ LLVMZigDIScope *LLVMZigLexicalBlockToScope(LLVMZigDILexicalBlock *lexical_block) |
| 73 | 87 | LLVMZigDIScope *LLVMZigCompileUnitToScope(LLVMZigDICompileUnit *compile_unit); |
| 74 | 88 | LLVMZigDIScope *LLVMZigFileToScope(LLVMZigDIFile *difile); |
| 75 | 89 | LLVMZigDIScope *LLVMZigSubprogramToScope(LLVMZigDISubprogram *subprogram); |
| 90 | LLVMZigDIScope *LLVMZigTypeToScope(LLVMZigDIType *type); | |
| 76 | 91 | |
| 77 | 92 | LLVMZigDILocalVariable *LLVMZigCreateLocalVariable(LLVMZigDIBuilder *dbuilder, unsigned tag, |
| 78 | 93 | LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_no, |