checker.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. // checker.hpp
  2. struct Type;
  3. struct Entity;
  4. struct Scope;
  5. struct DeclInfo;
  6. struct AstFile;
  7. struct Checker;
  8. struct CheckerInfo;
  9. struct CheckerContext;
  10. enum AddressingMode;
  11. struct TypeAndValue;
  12. // ExprInfo stores information used for "untyped" expressions
  13. struct ExprInfo {
  14. AddressingMode mode;
  15. Type * type;
  16. ExactValue value;
  17. bool is_lhs; // Debug info
  18. };
  19. gb_inline ExprInfo make_expr_info(AddressingMode mode, Type *type, ExactValue value, bool is_lhs) {
  20. ExprInfo ei = {};
  21. ei.mode = mode;
  22. ei.type = type;
  23. ei.value = value;
  24. ei.is_lhs = is_lhs;
  25. return ei;
  26. }
  27. enum ExprKind {
  28. Expr_Expr,
  29. Expr_Stmt,
  30. };
  31. // Statements and Declarations
  32. enum StmtFlag {
  33. Stmt_BreakAllowed = 1<<0,
  34. Stmt_ContinueAllowed = 1<<1,
  35. Stmt_FallthroughAllowed = 1<<2,
  36. Stmt_TypeSwitch = 1<<4,
  37. Stmt_CheckScopeDecls = 1<<5,
  38. };
  39. enum BuiltinProcPkg {
  40. BuiltinProcPkg_builtin,
  41. BuiltinProcPkg_intrinsics,
  42. };
  43. struct BuiltinProc {
  44. String name;
  45. isize arg_count;
  46. bool variadic;
  47. ExprKind kind;
  48. BuiltinProcPkg pkg;
  49. bool diverging;
  50. };
  51. #include "checker_builtin_procs.hpp"
  52. // Operand is used as an intermediate value whilst checking
  53. // Operands store an addressing mode, the expression being evaluated,
  54. // its type and node, and other specific information for certain
  55. // addressing modes
  56. // Its zero-value is a valid "invalid operand"
  57. struct Operand {
  58. AddressingMode mode;
  59. Type * type;
  60. ExactValue value;
  61. Ast * expr;
  62. BuiltinProcId builtin_id;
  63. Entity * proc_group;
  64. };
  65. struct BlockLabel {
  66. String name;
  67. Ast *label; // Ast_Label;
  68. };
  69. enum DeferredProcedureKind {
  70. DeferredProcedure_none,
  71. DeferredProcedure_in,
  72. DeferredProcedure_out,
  73. DeferredProcedure_in_out,
  74. };
  75. struct DeferredProcedure {
  76. DeferredProcedureKind kind;
  77. Entity *entity;
  78. };
  79. struct AttributeContext {
  80. bool is_export;
  81. bool is_static;
  82. bool require_results;
  83. bool require_declaration;
  84. bool has_disabled_proc;
  85. bool disabled_proc;
  86. bool test;
  87. bool set_cold;
  88. String link_name;
  89. String link_prefix;
  90. isize init_expr_list_count;
  91. String thread_local_model;
  92. String deprecated_message;
  93. DeferredProcedure deferred_procedure;
  94. u32 optimization_mode; // ProcedureOptimizationMode
  95. struct TypeAtomOpTable *atom_op_table;
  96. };
  97. AttributeContext make_attribute_context(String link_prefix) {
  98. AttributeContext ac = {};
  99. ac.link_prefix = link_prefix;
  100. return ac;
  101. }
  102. #define DECL_ATTRIBUTE_PROC(_name) bool _name(CheckerContext *c, Ast *elem, String name, Ast *value, AttributeContext *ac)
  103. typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc);
  104. void check_decl_attributes(CheckerContext *c, Array<Ast *> const &attributes, DeclAttributeProc *proc, AttributeContext *ac);
  105. // DeclInfo is used to store information of certain declarations to allow for "any order" usage
  106. struct DeclInfo {
  107. DeclInfo * parent; // NOTE(bill): only used for procedure literals at the moment
  108. Scope * scope;
  109. Entity *entity;
  110. Ast * decl_node;
  111. Ast * type_expr;
  112. Ast * init_expr;
  113. Array<Ast *> attributes;
  114. Ast * proc_lit; // Ast_ProcLit
  115. Type * gen_proc_type; // Precalculated
  116. bool is_using;
  117. bool where_clauses_evaluated;
  118. CommentGroup *comment;
  119. CommentGroup *docs;
  120. PtrSet<Entity *> deps;
  121. PtrSet<Type *> type_info_deps;
  122. Array<BlockLabel> labels;
  123. };
  124. // ProcInfo stores the information needed for checking a procedure
  125. struct ProcInfo {
  126. AstFile * file;
  127. Token token;
  128. DeclInfo *decl;
  129. Type * type; // Type_Procedure
  130. Ast * body; // Ast_BlockStmt
  131. u64 tags;
  132. bool generated_from_polymorphic;
  133. Ast * poly_def_node;
  134. };
  135. enum ScopeFlag : i32 {
  136. ScopeFlag_Pkg = 1<<1,
  137. ScopeFlag_Builtin = 1<<2,
  138. ScopeFlag_Global = 1<<3,
  139. ScopeFlag_File = 1<<4,
  140. ScopeFlag_Init = 1<<5,
  141. ScopeFlag_Proc = 1<<6,
  142. ScopeFlag_Type = 1<<7,
  143. ScopeFlag_HasBeenImported = 1<<10, // This is only applicable to file scopes
  144. ScopeFlag_ContextDefined = 1<<16,
  145. };
  146. enum { DEFAULT_SCOPE_CAPACITY = 29 };
  147. struct Scope {
  148. Ast * node;
  149. Scope * parent;
  150. Scope * prev;
  151. Scope * next;
  152. Scope * first_child;
  153. Scope * last_child;
  154. StringMap<Entity *> elements;
  155. Array<Ast *> delayed_directives;
  156. Array<Ast *> delayed_imports;
  157. PtrSet<Scope *> imported;
  158. i32 flags; // ScopeFlag
  159. union {
  160. AstPackage *pkg;
  161. AstFile * file;
  162. Entity * procedure_entity;
  163. };
  164. };
  165. struct EntityGraphNode;
  166. typedef PtrSet<EntityGraphNode *> EntityGraphNodeSet;
  167. struct EntityGraphNode {
  168. Entity * entity; // Procedure, Variable, Constant
  169. EntityGraphNodeSet pred;
  170. EntityGraphNodeSet succ;
  171. isize index; // Index in array/queue
  172. isize dep_count;
  173. };
  174. struct ImportGraphNode;
  175. typedef PtrSet<ImportGraphNode *> ImportGraphNodeSet;
  176. struct ImportGraphNode {
  177. AstPackage * pkg;
  178. Scope * scope;
  179. ImportGraphNodeSet pred;
  180. ImportGraphNodeSet succ;
  181. isize index; // Index in array/queue
  182. isize dep_count;
  183. };
  184. enum EntityVisiblityKind {
  185. EntityVisiblity_Public,
  186. EntityVisiblity_PrivateToPackage,
  187. EntityVisiblity_PrivateToFile,
  188. };
  189. struct ForeignContext {
  190. Ast * curr_library;
  191. ProcCallingConvention default_cc;
  192. String link_prefix;
  193. EntityVisiblityKind visibility_kind;
  194. };
  195. typedef Array<Entity *> CheckerTypePath;
  196. typedef Array<Type *> CheckerPolyPath;
  197. struct AtomOpMapEntry {
  198. u32 kind;
  199. Ast *node;
  200. };
  201. struct CheckerContext;
  202. // CheckerInfo stores all the symbol information for a type-checked program
  203. struct CheckerInfo {
  204. Checker *checker;
  205. Map<ExprInfo> untyped; // Key: Ast * | Expression -> ExprInfo
  206. // NOTE(bill): This needs to be a map and not on the Ast
  207. // as it needs to be iterated across
  208. StringMap<AstFile *> files; // Key (full path)
  209. StringMap<AstPackage *> packages; // Key (full path)
  210. StringMap<Entity *> foreigns;
  211. Array<Entity *> definitions;
  212. Array<Entity *> entities;
  213. Array<DeclInfo *> variable_init_order;
  214. Map<Array<Entity *> > gen_procs; // Key: Ast * | Identifier -> Entity
  215. Map<Array<Entity *> > gen_types; // Key: Type *
  216. Array<Type *> type_info_types;
  217. Map<isize> type_info_map; // Key: Type *
  218. AstPackage * builtin_package;
  219. AstPackage * runtime_package;
  220. AstPackage * init_package;
  221. Scope * init_scope;
  222. Entity * entry_point;
  223. PtrSet<Entity *> minimum_dependency_set;
  224. PtrSet<isize> minimum_dependency_type_info_set;
  225. Array<Entity *> required_foreign_imports_through_force;
  226. Array<Entity *> required_global_variables;
  227. Map<AtomOpMapEntry> atom_op_map; // Key: Ast *
  228. Array<Entity *> testing_procedures;
  229. bool allow_identifier_uses;
  230. Array<Ast *> identifier_uses; // only used by 'odin query'
  231. };
  232. struct CheckerContext {
  233. Checker * checker;
  234. CheckerInfo * info;
  235. AstPackage * pkg;
  236. AstFile * file;
  237. Scope * scope;
  238. DeclInfo * decl;
  239. u32 state_flags;
  240. bool in_defer; // TODO(bill): Actually handle correctly
  241. Type * type_hint;
  242. String proc_name;
  243. DeclInfo * curr_proc_decl;
  244. Type * curr_proc_sig;
  245. ProcCallingConvention curr_proc_calling_convention;
  246. bool in_proc_sig;
  247. ForeignContext foreign_context;
  248. CheckerTypePath *type_path;
  249. isize type_level; // TODO(bill): Actually handle correctly
  250. CheckerPolyPath *poly_path;
  251. isize poly_level; // TODO(bill): Actually handle correctly
  252. #define MAX_INLINE_FOR_DEPTH 1024ll
  253. i64 inline_for_depth;
  254. bool in_enum_type;
  255. bool collect_delayed_decls;
  256. bool allow_polymorphic_types;
  257. bool no_polymorphic_errors;
  258. bool hide_polymorphic_errors;
  259. bool in_polymorphic_specialization;
  260. bool allow_arrow_right_selector_expr;
  261. Scope * polymorphic_scope;
  262. Ast *assignment_lhs_hint;
  263. Ast *unary_address_hint;
  264. };
  265. struct Checker {
  266. Parser * parser;
  267. CheckerInfo info;
  268. Array<ProcInfo> procs_to_check;
  269. Array<Entity *> procs_with_deferred_to_check;
  270. CheckerContext *curr_ctx;
  271. CheckerContext init_ctx;
  272. };
  273. gb_global AstPackage *builtin_pkg = nullptr;
  274. gb_global AstPackage *intrinsics_pkg = nullptr;
  275. gb_global AstPackage *config_pkg = nullptr;
  276. HashKey hash_node (Ast *node) { return hash_pointer(node); }
  277. HashKey hash_ast_file (AstFile *file) { return hash_pointer(file); }
  278. HashKey hash_entity (Entity *e) { return hash_pointer(e); }
  279. HashKey hash_type (Type *t) { return hash_pointer(t); }
  280. HashKey hash_decl_info(DeclInfo *decl) { return hash_pointer(decl); }
  281. // CheckerInfo API
  282. TypeAndValue type_and_value_of_expr (Ast *expr);
  283. Type * type_of_expr (Ast *expr);
  284. Entity * implicit_entity_of_node(Ast *clause);
  285. Scope * scope_of_node (Ast *node);
  286. DeclInfo * decl_info_of_ident (Ast *ident);
  287. DeclInfo * decl_info_of_entity (Entity * e);
  288. AstFile * ast_file_of_filename (CheckerInfo *i, String filename);
  289. // IMPORTANT: Only to use once checking is done
  290. isize type_info_index (CheckerInfo *i, Type *type, bool error_on_failure);
  291. // Will return nullptr if not found
  292. Entity *entity_of_node(Ast *expr);
  293. Entity *scope_lookup_current(Scope *s, String const &name);
  294. Entity *scope_lookup (Scope *s, String const &name);
  295. void scope_lookup_parent (Scope *s, String const &name, Scope **scope_, Entity **entity_);
  296. Entity *scope_insert (Scope *s, Entity *entity);
  297. ExprInfo *check_get_expr_info (CheckerInfo *i, Ast *expr);
  298. void check_set_expr_info (CheckerInfo *i, Ast *expr, ExprInfo info);
  299. void check_remove_expr_info (CheckerInfo *i, Ast *expr);
  300. void add_untyped (CheckerInfo *i, Ast *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value);
  301. void add_type_and_value (CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value);
  302. void add_entity_use (CheckerContext *c, Ast *identifier, Entity *entity);
  303. void add_implicit_entity (CheckerContext *c, Ast *node, Entity *e);
  304. void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, DeclInfo *d, bool is_exported=true);
  305. void add_type_info_type (CheckerContext *c, Type *t);
  306. void check_add_import_decl(CheckerContext *c, Ast *decl);
  307. void check_add_foreign_import_decl(CheckerContext *c, Ast *decl);
  308. void check_entity_decl(CheckerContext *c, Entity *e, DeclInfo *d, Type *named_type);
  309. void check_const_decl(CheckerContext *c, Entity *e, Ast *type_expr, Ast *init_expr, Type *named_type);
  310. void check_type_decl(CheckerContext *c, Entity *e, Ast *type_expr, Type *def);
  311. bool check_arity_match(CheckerContext *c, AstValueDecl *vd, bool is_global = false);
  312. void check_collect_entities(CheckerContext *c, Slice<Ast *> const &nodes);
  313. void check_collect_entities_from_when_stmt(CheckerContext *c, AstWhenStmt *ws);
  314. void check_delayed_file_import_entity(CheckerContext *c, Ast *decl);
  315. CheckerTypePath *new_checker_type_path();
  316. void destroy_checker_type_path(CheckerTypePath *tp);
  317. void check_type_path_push(CheckerContext *c, Entity *e);
  318. Entity *check_type_path_pop (CheckerContext *c);
  319. CheckerPolyPath *new_checker_poly_path();
  320. void destroy_checker_poly_path(CheckerPolyPath *);
  321. void check_poly_path_push(CheckerContext *c, Type *t);
  322. Type *check_poly_path_pop (CheckerContext *c);
  323. void init_core_context(Checker *c);