diff options
Diffstat (limited to 'src/dump_analysis.cpp')
| -rw-r--r-- | src/dump_analysis.cpp | 393 |
1 files changed, 382 insertions, 11 deletions
diff --git a/src/dump_analysis.cpp b/src/dump_analysis.cpp index 220019c184..168d86a21f 100644 --- a/src/dump_analysis.cpp +++ b/src/dump_analysis.cpp @@ -351,6 +351,15 @@ struct AnalDumpCtx { ZigList<Tld *> decl_list; HashMap<const Tld *, uint32_t, tld_ptr_hash, tld_ptr_eql> decl_map; + + ZigList<ZigFn *> fn_list; + HashMap<const ZigFn *, uint32_t, fn_ptr_hash, fn_ptr_eql> fn_map; + + ZigList<AstNode *> node_list; + HashMap<const AstNode *, uint32_t, node_ptr_hash, node_ptr_eql> node_map; + + ZigList<ErrorTableEntry *> err_list; + HashMap<const ErrorTableEntry *, uint32_t, err_ptr_hash, err_ptr_eql> err_map; }; static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty); @@ -416,6 +425,39 @@ static uint32_t anal_dump_get_file_id(AnalDumpCtx *ctx, Buf *file) { return file_id; } +static uint32_t anal_dump_get_node_id(AnalDumpCtx *ctx, AstNode *node) { + uint32_t node_id = ctx->node_list.length; + auto existing_entry = ctx->node_map.put_unique(node, node_id); + if (existing_entry == nullptr) { + ctx->node_list.append(node); + } else { + node_id = existing_entry->value; + } + return node_id; +} + +static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) { + uint32_t fn_id = ctx->fn_list.length; + auto existing_entry = ctx->fn_map.put_unique(fn, fn_id); + if (existing_entry == nullptr) { + ctx->fn_list.append(fn); + } else { + fn_id = existing_entry->value; + } + return fn_id; +} + +static uint32_t anal_dump_get_err_id(AnalDumpCtx *ctx, ErrorTableEntry *err) { + uint32_t err_id = ctx->err_list.length; + auto existing_entry = ctx->err_map.put_unique(err, err_id); + if (existing_entry == nullptr) { + ctx->err_list.append(err); + } else { + err_id = existing_entry->value; + } + return err_id; +} + static uint32_t anal_dump_get_decl_id(AnalDumpCtx *ctx, Tld *tld) { uint32_t decl_id = ctx->decl_list.length; auto existing_entry = ctx->decl_map.put_unique(tld, decl_id); @@ -475,6 +517,21 @@ static void anal_dump_file_ref(AnalDumpCtx *ctx, Buf *file) { jw_int(&ctx->jw, file_id); } +static void anal_dump_node_ref(AnalDumpCtx *ctx, AstNode *node) { + uint32_t node_id = anal_dump_get_node_id(ctx, node); + jw_int(&ctx->jw, node_id); +} + +static void anal_dump_fn_ref(AnalDumpCtx *ctx, ZigFn *fn) { + uint32_t fn_id = anal_dump_get_fn_id(ctx, fn); + jw_int(&ctx->jw, fn_id); +} + +static void anal_dump_err_ref(AnalDumpCtx *ctx, ErrorTableEntry *err) { + uint32_t err_id = anal_dump_get_err_id(ctx, err); + jw_int(&ctx->jw, err_id); +} + static void anal_dump_decl_ref(AnalDumpCtx *ctx, Tld *tld) { uint32_t decl_id = anal_dump_get_decl_id(ctx, tld); jw_int(&ctx->jw, decl_id); @@ -536,11 +593,8 @@ static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) { jw_object_field(jw, "import"); anal_dump_type_ref(ctx, tld->import); - jw_object_field(jw, "line"); - jw_int(jw, tld->source_node->line); - - jw_object_field(jw, "col"); - jw_int(jw, tld->source_node->column); + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, tld->source_node); jw_object_field(jw, "name"); jw_string(jw, buf_ptr(tld->name)); @@ -584,8 +638,10 @@ static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) { jw_object_field(jw, "type"); anal_dump_type_ref(ctx, fn->type_entry); - } + jw_object_field(jw, "value"); + anal_dump_fn_ref(ctx, fn); + } break; } default: @@ -626,6 +682,19 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, anal_dump_type_ref(ctx, val_ty); return; } + case ZigTypeIdFn: { + if (value->data.x_ptr.special == ConstPtrSpecialFunction) { + ZigFn *val_fn = value->data.x_ptr.data.fn.fn_entry; + if (val_fn->type_entry->data.fn.is_generic) { + anal_dump_node_ref(ctx, val_fn->proto_node); + } else { + anal_dump_fn_ref(ctx, val_fn); + } + } else { + jw_null(&ctx->jw); + } + return; + } default: jw_null(&ctx->jw); return; @@ -633,24 +702,75 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, zig_unreachable(); } -static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { +static void anal_dump_pointer_attrs(AnalDumpCtx *ctx, ZigType *ty) { JsonWriter *jw = &ctx->jw; - jw_array_elem(jw); + if (ty->data.pointer.explicit_alignment != 0) { + jw_object_field(jw, "align"); + jw_int(jw, ty->data.pointer.explicit_alignment); + } + if (ty->data.pointer.is_const) { + jw_object_field(jw, "const"); + jw_bool(jw, true); + } + if (ty->data.pointer.is_volatile) { + jw_object_field(jw, "volatile"); + jw_bool(jw, true); + } + if (ty->data.pointer.allow_zero) { + jw_object_field(jw, "allowZero"); + jw_bool(jw, true); + } + if (ty->data.pointer.host_int_bytes != 0) { + jw_object_field(jw, "hostIntBytes"); + jw_int(jw, ty->data.pointer.host_int_bytes); + + jw_object_field(jw, "bitOffsetInHost"); + jw_int(jw, ty->data.pointer.bit_offset_in_host); + } + + jw_object_field(jw, "elem"); + anal_dump_type_ref(ctx, ty->data.pointer.child_type); +} + +static void anal_dump_struct_field(AnalDumpCtx *ctx, const TypeStructField *struct_field) { + JsonWriter *jw = &ctx->jw; + jw_begin_object(jw); jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&ty->name)); + jw_string(jw, buf_ptr(struct_field->name)); + + jw_object_field(jw, "type"); + anal_dump_type_ref(ctx, struct_field->type_entry); + + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, struct_field->decl_node); + + jw_end_object(jw); +} + +static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { + JsonWriter *jw = &ctx->jw; + jw_array_elem(jw); + jw_begin_object(jw); jw_object_field(jw, "kind"); jw_int(jw, type_id_index(ty)); switch (ty->id) { + case ZigTypeIdMetaType: + case ZigTypeIdBool: + break; case ZigTypeIdStruct: { if (ty->data.structure.is_slice) { - // TODO + jw_object_field(jw, "len"); + jw_int(jw, 2); + anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index].type_entry); break; } + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); { jw_object_field(jw, "pubDecls"); jw_begin_array(jw); @@ -691,6 +811,17 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { jw_end_array(jw); } + { + jw_object_field(jw, "fields"); + jw_begin_array(jw); + + for(size_t i = 0; i < ty->data.structure.src_field_count; i += 1) { + jw_array_elem(jw); + anal_dump_struct_field(ctx, &ty->data.structure.fields[i]); + } + jw_end_array(jw); + } + if (ty->data.structure.root_struct != nullptr) { Buf *path_buf = ty->data.structure.root_struct->path; @@ -705,13 +836,167 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { jw_int(jw, ty->data.floating.bit_count); break; } + case ZigTypeIdInt: { + if (ty->data.integral.is_signed) { + jw_object_field(jw, "i"); + } else { + jw_object_field(jw, "u"); + } + jw_int(jw, ty->data.integral.bit_count); + break; + } + case ZigTypeIdFn: { + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); + + jw_object_field(jw, "generic"); + jw_bool(jw, ty->data.fn.is_generic); + + if (ty->data.fn.fn_type_id.return_type != nullptr) { + jw_object_field(jw, "ret"); + anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.return_type); + } + + if (ty->data.fn.fn_type_id.param_count != 0) { + jw_object_field(jw, "args"); + jw_begin_array(jw); + for (size_t i = 0; i < ty->data.fn.fn_type_id.param_count; i += 1) { + jw_array_elem(jw); + if (ty->data.fn.fn_type_id.param_info[i].type != nullptr) { + anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.param_info[i].type); + } else { + jw_null(jw); + } + } + jw_end_array(jw); + } + break; + } + case ZigTypeIdPointer: { + switch (ty->data.pointer.ptr_len) { + case PtrLenSingle: + break; + case PtrLenUnknown: + jw_object_field(jw, "len"); + jw_int(jw, 1); + break; + case PtrLenC: + jw_object_field(jw, "len"); + jw_int(jw, 3); + break; + } + anal_dump_pointer_attrs(ctx, ty); + break; + } + case ZigTypeIdErrorSet: { + if (type_is_global_error_set(ty)) { + break; + } + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); + + if (ty->data.error_set.infer_fn != nullptr) { + jw_object_field(jw, "fn"); + anal_dump_fn_ref(ctx, ty->data.error_set.infer_fn); + } + jw_object_field(jw, "errors"); + jw_begin_array(jw); + for (uint32_t i = 0; i < ty->data.error_set.err_count; i += 1) { + jw_array_elem(jw); + ErrorTableEntry *err = ty->data.error_set.errors[i]; + anal_dump_err_ref(ctx, err); + } + jw_end_array(jw); + break; + } + case ZigTypeIdErrorUnion: { + jw_object_field(jw, "err"); + anal_dump_type_ref(ctx, ty->data.error_union.err_set_type); + + jw_object_field(jw, "payload"); + anal_dump_type_ref(ctx, ty->data.error_union.payload_type); + + break; + } default: - // TODO + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); break; } jw_end_object(jw); } +static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { + JsonWriter *jw = &ctx->jw; + + jw_begin_object(jw); + + jw_object_field(jw, "file"); + anal_dump_file_ref(ctx, node->owner->data.structure.root_struct->path); + + jw_object_field(jw, "line"); + jw_int(jw, node->line); + + jw_object_field(jw, "col"); + jw_int(jw, node->column); + + const Buf *doc_comments_buf; + switch (node->type) { + case NodeTypeParamDecl: + doc_comments_buf = &node->data.param_decl.doc_comments; + break; + case NodeTypeFnProto: + doc_comments_buf = &node->data.fn_proto.doc_comments; + break; + case NodeTypeVariableDeclaration: + doc_comments_buf = &node->data.variable_declaration.doc_comments; + break; + case NodeTypeErrorSetField: + doc_comments_buf = &node->data.err_set_field.doc_comments; + break; + case NodeTypeStructField: + doc_comments_buf = &node->data.struct_field.doc_comments; + break; + default: + doc_comments_buf = nullptr; + break; + } + if (doc_comments_buf != nullptr && doc_comments_buf->list.length != 0) { + jw_object_field(jw, "docs"); + jw_string(jw, buf_ptr(doc_comments_buf)); + } + + jw_end_object(jw); +} + +static void anal_dump_err(AnalDumpCtx *ctx, const ErrorTableEntry *err) { + JsonWriter *jw = &ctx->jw; + + jw_begin_object(jw); + + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, err->decl_node); + + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&err->name)); + + jw_end_object(jw); +} + +static void anal_dump_fn(AnalDumpCtx *ctx, ZigFn *fn) { + JsonWriter *jw = &ctx->jw; + + jw_begin_object(jw); + + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, fn->proto_node); + + jw_object_field(jw, "type"); + anal_dump_type_ref(ctx, fn->type_entry); + + jw_end_object(jw); +} + void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl) { Error err; AnalDumpCtx ctx = {}; @@ -722,6 +1007,9 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const ctx.pkg_map.init(16); ctx.file_map.init(16); ctx.decl_map.init(16); + ctx.node_map.init(16); + ctx.fn_map.init(16); + ctx.err_map.init(16); jw_begin_object(jw); @@ -761,6 +1049,71 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const jw_object_field(jw, "rootPkg"); anal_dump_pkg_ref(&ctx, g->root_package); + // Poke the functions + for (size_t i = 0; i < g->fn_defs.length; i += 1) { + ZigFn *fn = g->fn_defs.at(i); + (void)anal_dump_get_fn_id(&ctx, fn); + } + + jw_object_field(jw, "calls"); + jw_begin_array(jw); + { + auto it = g->memoized_fn_eval_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + jw_array_elem(jw); + jw_begin_object(jw); + + jw_object_field(jw, "args"); + jw_begin_object(jw); + + Scope *scope = entry->key; + while (scope != nullptr) { + if (scope->id == ScopeIdVarDecl) { + ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var; + jw_object_field(jw, var->name); + jw_begin_object(jw); + jw_object_field(jw, "type"); + anal_dump_type_ref(&ctx, var->var_type); + jw_object_field(jw, "value"); + anal_dump_value(&ctx, scope->source_node, var->var_type, var->const_value); + jw_end_object(jw); + } else if (scope->id == ScopeIdFnDef) { + jw_end_object(jw); + + jw_object_field(jw, "fn"); + ZigFn *fn = reinterpret_cast<ScopeFnDef *>(scope)->fn_entry; + anal_dump_fn_ref(&ctx, fn); + + ConstExprValue *result = entry->value; + jw_object_field(jw, "result"); + jw_begin_object(jw); + jw_object_field(jw, "type"); + anal_dump_type_ref(&ctx, result->type); + jw_object_field(jw, "value"); + anal_dump_value(&ctx, scope->source_node, result->type, result); + jw_end_object(jw); + break; + } + scope = scope->parent; + } + jw_end_object(jw); + } + } + jw_end_array(jw); + + jw_object_field(jw, "fns"); + jw_begin_array(jw); + for (uint32_t i = 0; i < ctx.fn_list.length; i += 1) { + ZigFn *fn = ctx.fn_list.at(i); + jw_array_elem(jw); + anal_dump_fn(&ctx, fn); + } + jw_end_array(jw); + jw_object_field(jw, "packages"); jw_begin_array(jw); for (uint32_t i = 0; i < ctx.pkg_list.length; i += 1) { @@ -794,5 +1147,23 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const } jw_end_array(jw); + jw_object_field(jw, "errors"); + jw_begin_array(jw); + for (uint32_t i = 0; i < ctx.err_list.length; i += 1) { + const ErrorTableEntry *err = ctx.err_list.at(i); + jw_array_elem(jw); + anal_dump_err(&ctx, err); + } + jw_end_array(jw); + + jw_object_field(jw, "astNodes"); + jw_begin_array(jw); + for (uint32_t i = 0; i < ctx.node_list.length; i += 1) { + const AstNode *node = ctx.node_list.at(i); + jw_array_elem(jw); + anal_dump_node(&ctx, node); + } + jw_end_array(jw); + jw_end_object(jw); } |
