| author | |
| committer | |
| log | 3ef2f7058b0bbe2c81f79f990398aaab2e5a7a2f |
| tree | d5c6033ff111ff126dc14844ee85edbc0a0828b9 |
| parent | d4b8852d784b6f180e5329efa8d418397ee7f1ef |
7 files changed, 1345 insertions(+), 1103 deletions(-)
src/all_types.hpp created+928| ... | @@ -0,0 +1,928 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef ZIG_ALL_TYPES_HPP | ||
| 9 | #define ZIG_ALL_TYPES_HPP | ||
| 10 | |||
| 11 | #include "list.hpp" | ||
| 12 | #include "buffer.hpp" | ||
| 13 | #include "zig_llvm.hpp" | ||
| 14 | #include "hash_map.hpp" | ||
| 15 | #include "errmsg.hpp" | ||
| 16 | |||
| 17 | struct AstNode; | ||
| 18 | struct ImportTableEntry; | ||
| 19 | struct AsmToken; | ||
| 20 | struct FnTableEntry; | ||
| 21 | struct BlockContext; | ||
| 22 | struct TypeTableEntry; | ||
| 23 | struct VariableTableEntry; | ||
| 24 | struct Cast; | ||
| 25 | struct BuiltinFnEntry; | ||
| 26 | struct LabelTableEntry; | ||
| 27 | struct TypeStructField; | ||
| 28 | struct CodeGen; | ||
| 29 | |||
| 30 | enum OutType { | ||
| 31 | OutTypeUnknown, | ||
| 32 | OutTypeExe, | ||
| 33 | OutTypeLib, | ||
| 34 | OutTypeObj, | ||
| 35 | }; | ||
| 36 | |||
| 37 | enum CodeGenBuildType { | ||
| 38 | CodeGenBuildTypeDebug, | ||
| 39 | CodeGenBuildTypeRelease, | ||
| 40 | }; | ||
| 41 | |||
| 42 | enum CastOp { | ||
| 43 | CastOpNothing, | ||
| 44 | CastOpPtrToInt, | ||
| 45 | CastOpIntWidenOrShorten, | ||
| 46 | CastOpToUnknownSizeArray, | ||
| 47 | CastOpMaybeWrap, | ||
| 48 | CastOpPointerReinterpret, | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct Cast { | ||
| 52 | CastOp op; | ||
| 53 | // if op is CastOpArrayToString, this will be a pointer to | ||
| 54 | // the string struct on the stack | ||
| 55 | LLVMValueRef ptr; | ||
| 56 | TypeTableEntry *after_type; | ||
| 57 | AstNode *source_node; | ||
| 58 | }; | ||
| 59 | |||
| 60 | struct Expr { | ||
| 61 | TypeTableEntry *type_entry; | ||
| 62 | // the context in which this expression is evaluated. | ||
| 63 | // for blocks, this points to the containing scope, not the block's own scope for its children. | ||
| 64 | BlockContext *block_context; | ||
| 65 | |||
| 66 | // may be null for no cast | ||
| 67 | Cast implicit_cast; // happens first | ||
| 68 | Cast implicit_maybe_cast; // happens second | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct NumLitCodeGen { | ||
| 72 | TypeTableEntry *resolved_type; | ||
| 73 | }; | ||
| 74 | |||
| 75 | struct StructValExprCodeGen { | ||
| 76 | TypeTableEntry *type_entry; | ||
| 77 | LLVMValueRef ptr; | ||
| 78 | AstNode *source_node; | ||
| 79 | }; | ||
| 80 | |||
| 81 | struct TopLevelDecl { | ||
| 82 | // reminder: hash tables must be initialized before use | ||
| 83 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> deps; | ||
| 84 | Buf *name; | ||
| 85 | ImportTableEntry *import; | ||
| 86 | // set this flag temporarily to detect infinite loops | ||
| 87 | bool in_current_deps; | ||
| 88 | }; | ||
| 89 | |||
| 90 | enum NodeType { | ||
| 91 | NodeTypeRoot, | ||
| 92 | NodeTypeRootExportDecl, | ||
| 93 | NodeTypeFnProto, | ||
| 94 | NodeTypeFnDef, | ||
| 95 | NodeTypeFnDecl, | ||
| 96 | NodeTypeParamDecl, | ||
| 97 | NodeTypeType, | ||
| 98 | NodeTypeBlock, | ||
| 99 | NodeTypeExternBlock, | ||
| 100 | NodeTypeDirective, | ||
| 101 | NodeTypeReturnExpr, | ||
| 102 | NodeTypeVariableDeclaration, | ||
| 103 | NodeTypeBinOpExpr, | ||
| 104 | NodeTypeCastExpr, | ||
| 105 | NodeTypeNumberLiteral, | ||
| 106 | NodeTypeStringLiteral, | ||
| 107 | NodeTypeCharLiteral, | ||
| 108 | NodeTypeUnreachable, | ||
| 109 | NodeTypeSymbol, | ||
| 110 | NodeTypePrefixOpExpr, | ||
| 111 | NodeTypeFnCallExpr, | ||
| 112 | NodeTypeArrayAccessExpr, | ||
| 113 | NodeTypeSliceExpr, | ||
| 114 | NodeTypeFieldAccessExpr, | ||
| 115 | NodeTypeUse, | ||
| 116 | NodeTypeVoid, | ||
| 117 | NodeTypeBoolLiteral, | ||
| 118 | NodeTypeNullLiteral, | ||
| 119 | NodeTypeIfBoolExpr, | ||
| 120 | NodeTypeIfVarExpr, | ||
| 121 | NodeTypeWhileExpr, | ||
| 122 | NodeTypeLabel, | ||
| 123 | NodeTypeGoto, | ||
| 124 | NodeTypeBreak, | ||
| 125 | NodeTypeContinue, | ||
| 126 | NodeTypeAsmExpr, | ||
| 127 | NodeTypeStructDecl, | ||
| 128 | NodeTypeStructField, | ||
| 129 | NodeTypeStructValueExpr, | ||
| 130 | NodeTypeStructValueField, | ||
| 131 | NodeTypeEnumDecl, | ||
| 132 | NodeTypeEnumField, | ||
| 133 | NodeTypeCompilerFnExpr, | ||
| 134 | NodeTypeCompilerFnType, | ||
| 135 | }; | ||
| 136 | |||
| 137 | struct AstNodeRoot { | ||
| 138 | ZigList<AstNode *> top_level_decls; | ||
| 139 | }; | ||
| 140 | |||
| 141 | enum VisibMod { | ||
| 142 | VisibModPrivate, | ||
| 143 | VisibModPub, | ||
| 144 | VisibModExport, | ||
| 145 | }; | ||
| 146 | |||
| 147 | struct AstNodeFnProto { | ||
| 148 | ZigList<AstNode *> *directives; | ||
| 149 | VisibMod visib_mod; | ||
| 150 | Buf name; | ||
| 151 | ZigList<AstNode *> params; | ||
| 152 | AstNode *return_type; | ||
| 153 | bool is_var_args; | ||
| 154 | |||
| 155 | // populated by semantic analyzer: | ||
| 156 | |||
| 157 | // the extern block this fn proto is inside. can be null. | ||
| 158 | AstNode *extern_node; | ||
| 159 | // the struct decl node this fn proto is inside. can be null. | ||
| 160 | AstNode *struct_node; | ||
| 161 | // the function definition this fn proto is inside. can be null. | ||
| 162 | AstNode *fn_def_node; | ||
| 163 | FnTableEntry *fn_table_entry; | ||
| 164 | bool skip; | ||
| 165 | TopLevelDecl top_level_decl; | ||
| 166 | }; | ||
| 167 | |||
| 168 | struct AstNodeFnDef { | ||
| 169 | AstNode *fn_proto; | ||
| 170 | AstNode *body; | ||
| 171 | |||
| 172 | // populated by semantic analyzer | ||
| 173 | TypeTableEntry *implicit_return_type; | ||
| 174 | BlockContext *block_context; | ||
| 175 | }; | ||
| 176 | |||
| 177 | struct AstNodeFnDecl { | ||
| 178 | AstNode *fn_proto; | ||
| 179 | }; | ||
| 180 | |||
| 181 | struct AstNodeParamDecl { | ||
| 182 | Buf name; | ||
| 183 | AstNode *type; | ||
| 184 | |||
| 185 | // populated by semantic analyzer | ||
| 186 | VariableTableEntry *variable; | ||
| 187 | }; | ||
| 188 | |||
| 189 | enum AstNodeTypeType { | ||
| 190 | AstNodeTypeTypePrimitive, | ||
| 191 | AstNodeTypeTypePointer, | ||
| 192 | AstNodeTypeTypeArray, | ||
| 193 | AstNodeTypeTypeMaybe, | ||
| 194 | AstNodeTypeTypeCompilerExpr, | ||
| 195 | }; | ||
| 196 | |||
| 197 | struct AstNodeType { | ||
| 198 | AstNodeTypeType type; | ||
| 199 | Buf primitive_name; | ||
| 200 | AstNode *child_type; | ||
| 201 | AstNode *array_size; // can be null | ||
| 202 | bool is_const; | ||
| 203 | bool is_noalias; | ||
| 204 | AstNode *compiler_expr; | ||
| 205 | |||
| 206 | // populated by semantic analyzer | ||
| 207 | TypeTableEntry *entry; | ||
| 208 | }; | ||
| 209 | |||
| 210 | struct AstNodeBlock { | ||
| 211 | ZigList<AstNode *> statements; | ||
| 212 | |||
| 213 | // populated by semantic analyzer | ||
| 214 | BlockContext *block_context; | ||
| 215 | Expr resolved_expr; | ||
| 216 | }; | ||
| 217 | |||
| 218 | struct AstNodeReturnExpr { | ||
| 219 | // might be null in case of return void; | ||
| 220 | AstNode *expr; | ||
| 221 | |||
| 222 | // populated by semantic analyzer: | ||
| 223 | Expr resolved_expr; | ||
| 224 | }; | ||
| 225 | |||
| 226 | struct AstNodeVariableDeclaration { | ||
| 227 | Buf symbol; | ||
| 228 | bool is_const; | ||
| 229 | VisibMod visib_mod; | ||
| 230 | // one or both of type and expr will be non null | ||
| 231 | AstNode *type; | ||
| 232 | AstNode *expr; | ||
| 233 | |||
| 234 | // populated by semantic analyzer | ||
| 235 | TopLevelDecl top_level_decl; | ||
| 236 | Expr resolved_expr; | ||
| 237 | }; | ||
| 238 | |||
| 239 | enum BinOpType { | ||
| 240 | BinOpTypeInvalid, | ||
| 241 | BinOpTypeAssign, | ||
| 242 | BinOpTypeAssignTimes, | ||
| 243 | BinOpTypeAssignDiv, | ||
| 244 | BinOpTypeAssignMod, | ||
| 245 | BinOpTypeAssignPlus, | ||
| 246 | BinOpTypeAssignMinus, | ||
| 247 | BinOpTypeAssignBitShiftLeft, | ||
| 248 | BinOpTypeAssignBitShiftRight, | ||
| 249 | BinOpTypeAssignBitAnd, | ||
| 250 | BinOpTypeAssignBitXor, | ||
| 251 | BinOpTypeAssignBitOr, | ||
| 252 | BinOpTypeAssignBoolAnd, | ||
| 253 | BinOpTypeAssignBoolOr, | ||
| 254 | BinOpTypeBoolOr, | ||
| 255 | BinOpTypeBoolAnd, | ||
| 256 | BinOpTypeCmpEq, | ||
| 257 | BinOpTypeCmpNotEq, | ||
| 258 | BinOpTypeCmpLessThan, | ||
| 259 | BinOpTypeCmpGreaterThan, | ||
| 260 | BinOpTypeCmpLessOrEq, | ||
| 261 | BinOpTypeCmpGreaterOrEq, | ||
| 262 | BinOpTypeBinOr, | ||
| 263 | BinOpTypeBinXor, | ||
| 264 | BinOpTypeBinAnd, | ||
| 265 | BinOpTypeBitShiftLeft, | ||
| 266 | BinOpTypeBitShiftRight, | ||
| 267 | BinOpTypeAdd, | ||
| 268 | BinOpTypeSub, | ||
| 269 | BinOpTypeMult, | ||
| 270 | BinOpTypeDiv, | ||
| 271 | BinOpTypeMod, | ||
| 272 | BinOpTypeUnwrapMaybe, | ||
| 273 | }; | ||
| 274 | |||
| 275 | struct AstNodeBinOpExpr { | ||
| 276 | AstNode *op1; | ||
| 277 | BinOpType bin_op; | ||
| 278 | AstNode *op2; | ||
| 279 | |||
| 280 | // populated by semantic analyzer: | ||
| 281 | // for when op is BinOpTypeAssign | ||
| 282 | VariableTableEntry *var_entry; | ||
| 283 | Expr resolved_expr; | ||
| 284 | }; | ||
| 285 | |||
| 286 | struct AstNodeFnCallExpr { | ||
| 287 | AstNode *fn_ref_expr; | ||
| 288 | ZigList<AstNode *> params; | ||
| 289 | bool is_builtin; | ||
| 290 | |||
| 291 | // populated by semantic analyzer: | ||
| 292 | BuiltinFnEntry *builtin_fn; | ||
| 293 | Expr resolved_expr; | ||
| 294 | }; | ||
| 295 | |||
| 296 | struct AstNodeArrayAccessExpr { | ||
| 297 | AstNode *array_ref_expr; | ||
| 298 | AstNode *subscript; | ||
| 299 | |||
| 300 | // populated by semantic analyzer: | ||
| 301 | Expr resolved_expr; | ||
| 302 | }; | ||
| 303 | |||
| 304 | struct AstNodeSliceExpr { | ||
| 305 | AstNode *array_ref_expr; | ||
| 306 | AstNode *start; | ||
| 307 | AstNode *end; | ||
| 308 | bool is_const; | ||
| 309 | |||
| 310 | // populated by semantic analyzer: | ||
| 311 | Expr resolved_expr; | ||
| 312 | StructValExprCodeGen resolved_struct_val_expr; | ||
| 313 | }; | ||
| 314 | |||
| 315 | struct AstNodeFieldAccessExpr { | ||
| 316 | AstNode *struct_expr; | ||
| 317 | Buf field_name; | ||
| 318 | |||
| 319 | // populated by semantic analyzer | ||
| 320 | int field_index; | ||
| 321 | TypeStructField *type_struct_field; | ||
| 322 | Expr resolved_expr; | ||
| 323 | }; | ||
| 324 | |||
| 325 | struct AstNodeExternBlock { | ||
| 326 | ZigList<AstNode *> *directives; | ||
| 327 | ZigList<AstNode *> fn_decls; | ||
| 328 | }; | ||
| 329 | |||
| 330 | struct AstNodeDirective { | ||
| 331 | Buf name; | ||
| 332 | Buf param; | ||
| 333 | }; | ||
| 334 | |||
| 335 | struct AstNodeRootExportDecl { | ||
| 336 | Buf type; | ||
| 337 | Buf name; | ||
| 338 | ZigList<AstNode *> *directives; | ||
| 339 | }; | ||
| 340 | |||
| 341 | struct AstNodeCastExpr { | ||
| 342 | AstNode *expr; | ||
| 343 | AstNode *type; | ||
| 344 | |||
| 345 | // populated by semantic analyzer | ||
| 346 | Cast cast; | ||
| 347 | Expr resolved_expr; | ||
| 348 | }; | ||
| 349 | |||
| 350 | enum PrefixOp { | ||
| 351 | PrefixOpInvalid, | ||
| 352 | PrefixOpBoolNot, | ||
| 353 | PrefixOpBinNot, | ||
| 354 | PrefixOpNegation, | ||
| 355 | PrefixOpAddressOf, | ||
| 356 | PrefixOpConstAddressOf, | ||
| 357 | PrefixOpDereference, | ||
| 358 | }; | ||
| 359 | |||
| 360 | struct AstNodePrefixOpExpr { | ||
| 361 | PrefixOp prefix_op; | ||
| 362 | AstNode *primary_expr; | ||
| 363 | |||
| 364 | // populated by semantic analyzer | ||
| 365 | Expr resolved_expr; | ||
| 366 | }; | ||
| 367 | |||
| 368 | struct AstNodeUse { | ||
| 369 | Buf path; | ||
| 370 | ZigList<AstNode *> *directives; | ||
| 371 | |||
| 372 | // populated by semantic analyzer | ||
| 373 | ImportTableEntry *import; | ||
| 374 | }; | ||
| 375 | |||
| 376 | struct AstNodeIfBoolExpr { | ||
| 377 | AstNode *condition; | ||
| 378 | AstNode *then_block; | ||
| 379 | AstNode *else_node; // null, block node, or other if expr node | ||
| 380 | |||
| 381 | // populated by semantic analyzer | ||
| 382 | Expr resolved_expr; | ||
| 383 | }; | ||
| 384 | |||
| 385 | struct AstNodeIfVarExpr { | ||
| 386 | AstNodeVariableDeclaration var_decl; | ||
| 387 | AstNode *then_block; | ||
| 388 | AstNode *else_node; // null, block node, or other if expr node | ||
| 389 | |||
| 390 | // populated by semantic analyzer | ||
| 391 | TypeTableEntry *type; | ||
| 392 | BlockContext *block_context; | ||
| 393 | Expr resolved_expr; | ||
| 394 | }; | ||
| 395 | |||
| 396 | struct AstNodeWhileExpr { | ||
| 397 | AstNode *condition; | ||
| 398 | AstNode *body; | ||
| 399 | |||
| 400 | // populated by semantic analyzer | ||
| 401 | bool condition_always_true; | ||
| 402 | bool contains_break; | ||
| 403 | Expr resolved_expr; | ||
| 404 | }; | ||
| 405 | |||
| 406 | struct AstNodeLabel { | ||
| 407 | Buf name; | ||
| 408 | |||
| 409 | // populated by semantic analyzer | ||
| 410 | LabelTableEntry *label_entry; | ||
| 411 | Expr resolved_expr; | ||
| 412 | }; | ||
| 413 | |||
| 414 | struct AstNodeGoto { | ||
| 415 | Buf name; | ||
| 416 | |||
| 417 | // populated by semantic analyzer | ||
| 418 | LabelTableEntry *label_entry; | ||
| 419 | Expr resolved_expr; | ||
| 420 | }; | ||
| 421 | |||
| 422 | struct AsmOutput { | ||
| 423 | Buf asm_symbolic_name; | ||
| 424 | Buf constraint; | ||
| 425 | Buf variable_name; | ||
| 426 | AstNode *return_type; // null unless "=r" and return | ||
| 427 | }; | ||
| 428 | |||
| 429 | struct AsmInput { | ||
| 430 | Buf asm_symbolic_name; | ||
| 431 | Buf constraint; | ||
| 432 | AstNode *expr; | ||
| 433 | }; | ||
| 434 | |||
| 435 | struct SrcPos { | ||
| 436 | int line; | ||
| 437 | int column; | ||
| 438 | }; | ||
| 439 | |||
| 440 | struct AstNodeAsmExpr { | ||
| 441 | bool is_volatile; | ||
| 442 | Buf asm_template; | ||
| 443 | ZigList<SrcPos> offset_map; | ||
| 444 | ZigList<AsmToken> token_list; | ||
| 445 | ZigList<AsmOutput*> output_list; | ||
| 446 | ZigList<AsmInput*> input_list; | ||
| 447 | ZigList<Buf*> clobber_list; | ||
| 448 | |||
| 449 | // populated by semantic analyzer | ||
| 450 | int return_count; | ||
| 451 | Expr resolved_expr; | ||
| 452 | }; | ||
| 453 | |||
| 454 | struct AstNodeStructDecl { | ||
| 455 | Buf name; | ||
| 456 | ZigList<AstNode *> fields; | ||
| 457 | ZigList<AstNode *> fns; | ||
| 458 | ZigList<AstNode *> *directives; | ||
| 459 | VisibMod visib_mod; | ||
| 460 | |||
| 461 | // populated by semantic analyzer | ||
| 462 | TypeTableEntry *type_entry; | ||
| 463 | TopLevelDecl top_level_decl; | ||
| 464 | }; | ||
| 465 | |||
| 466 | struct AstNodeStructField { | ||
| 467 | Buf name; | ||
| 468 | AstNode *type; | ||
| 469 | ZigList<AstNode *> *directives; | ||
| 470 | }; | ||
| 471 | |||
| 472 | struct AstNodeEnumDecl { | ||
| 473 | Buf name; | ||
| 474 | ZigList<AstNode *> fields; | ||
| 475 | ZigList<AstNode *> *directives; | ||
| 476 | VisibMod visib_mod; | ||
| 477 | }; | ||
| 478 | |||
| 479 | struct AstNodeEnumField { | ||
| 480 | Buf name; | ||
| 481 | ZigList<AstNode *> fields; // length 0 means simple enum | ||
| 482 | AstNode *val_expr; | ||
| 483 | }; | ||
| 484 | |||
| 485 | struct AstNodeStringLiteral { | ||
| 486 | Buf buf; | ||
| 487 | bool c; | ||
| 488 | |||
| 489 | // populated by semantic analyzer: | ||
| 490 | Expr resolved_expr; | ||
| 491 | }; | ||
| 492 | |||
| 493 | struct AstNodeCharLiteral { | ||
| 494 | uint8_t value; | ||
| 495 | |||
| 496 | // populated by semantic analyzer: | ||
| 497 | Expr resolved_expr; | ||
| 498 | }; | ||
| 499 | |||
| 500 | enum NumLit { | ||
| 501 | NumLitF32, | ||
| 502 | NumLitF64, | ||
| 503 | NumLitF128, | ||
| 504 | NumLitU8, | ||
| 505 | NumLitU16, | ||
| 506 | NumLitU32, | ||
| 507 | NumLitU64, | ||
| 508 | NumLitI8, | ||
| 509 | NumLitI16, | ||
| 510 | NumLitI32, | ||
| 511 | NumLitI64, | ||
| 512 | |||
| 513 | NumLitCount | ||
| 514 | }; | ||
| 515 | |||
| 516 | struct AstNodeNumberLiteral { | ||
| 517 | NumLit kind; | ||
| 518 | |||
| 519 | // overflow is true if when parsing the number, we discovered it would not | ||
| 520 | // fit without losing data in a uint64_t, int64_t, or double | ||
| 521 | bool overflow; | ||
| 522 | |||
| 523 | union { | ||
| 524 | uint64_t x_uint; | ||
| 525 | int64_t x_int; | ||
| 526 | double x_float; | ||
| 527 | } data; | ||
| 528 | |||
| 529 | // populated by semantic analyzer | ||
| 530 | NumLitCodeGen codegen; | ||
| 531 | Expr resolved_expr; | ||
| 532 | }; | ||
| 533 | |||
| 534 | struct AstNodeStructValueField { | ||
| 535 | Buf name; | ||
| 536 | AstNode *expr; | ||
| 537 | |||
| 538 | // populated by semantic analyzer | ||
| 539 | int index; | ||
| 540 | }; | ||
| 541 | |||
| 542 | struct AstNodeStructValueExpr { | ||
| 543 | AstNode *type; | ||
| 544 | ZigList<AstNode *> fields; | ||
| 545 | |||
| 546 | // populated by semantic analyzer | ||
| 547 | StructValExprCodeGen codegen; | ||
| 548 | Expr resolved_expr; | ||
| 549 | }; | ||
| 550 | |||
| 551 | struct AstNodeCompilerFnExpr { | ||
| 552 | Buf name; | ||
| 553 | AstNode *expr; | ||
| 554 | |||
| 555 | // populated by semantic analyzer | ||
| 556 | Expr resolved_expr; | ||
| 557 | }; | ||
| 558 | |||
| 559 | struct AstNodeCompilerFnType { | ||
| 560 | Buf name; | ||
| 561 | AstNode *type; | ||
| 562 | |||
| 563 | // populated by semantic analyzer | ||
| 564 | Expr resolved_expr; | ||
| 565 | NumLitCodeGen resolved_num_lit; | ||
| 566 | }; | ||
| 567 | |||
| 568 | struct AstNodeNullLiteral { | ||
| 569 | // populated by semantic analyzer | ||
| 570 | StructValExprCodeGen resolved_struct_val_expr; | ||
| 571 | Expr resolved_expr; | ||
| 572 | }; | ||
| 573 | |||
| 574 | struct AstNodeVoidExpr { | ||
| 575 | // populated by semantic analyzer | ||
| 576 | Expr resolved_expr; | ||
| 577 | }; | ||
| 578 | |||
| 579 | struct AstNodeUnreachableExpr { | ||
| 580 | // populated by semantic analyzer | ||
| 581 | Expr resolved_expr; | ||
| 582 | }; | ||
| 583 | |||
| 584 | struct AstNodeSymbolExpr { | ||
| 585 | Buf symbol; | ||
| 586 | |||
| 587 | // populated by semantic analyzer | ||
| 588 | Expr resolved_expr; | ||
| 589 | }; | ||
| 590 | |||
| 591 | struct AstNodeBoolLiteral { | ||
| 592 | bool value; | ||
| 593 | |||
| 594 | // populated by semantic analyzer | ||
| 595 | Expr resolved_expr; | ||
| 596 | }; | ||
| 597 | |||
| 598 | struct AstNodeBreakExpr { | ||
| 599 | // populated by semantic analyzer | ||
| 600 | Expr resolved_expr; | ||
| 601 | }; | ||
| 602 | |||
| 603 | struct AstNodeContinueExpr { | ||
| 604 | // populated by semantic analyzer | ||
| 605 | Expr resolved_expr; | ||
| 606 | }; | ||
| 607 | |||
| 608 | struct AstNode { | ||
| 609 | enum NodeType type; | ||
| 610 | int line; | ||
| 611 | int column; | ||
| 612 | uint32_t create_index; // for determinism purposes | ||
| 613 | ImportTableEntry *owner; | ||
| 614 | union { | ||
| 615 | AstNodeRoot root; | ||
| 616 | AstNodeRootExportDecl root_export_decl; | ||
| 617 | AstNodeFnDef fn_def; | ||
| 618 | AstNodeFnDecl fn_decl; | ||
| 619 | AstNodeFnProto fn_proto; | ||
| 620 | AstNodeType type; | ||
| 621 | AstNodeParamDecl param_decl; | ||
| 622 | AstNodeBlock block; | ||
| 623 | AstNodeReturnExpr return_expr; | ||
| 624 | AstNodeVariableDeclaration variable_declaration; | ||
| 625 | AstNodeBinOpExpr bin_op_expr; | ||
| 626 | AstNodeExternBlock extern_block; | ||
| 627 | AstNodeDirective directive; | ||
| 628 | AstNodeCastExpr cast_expr; | ||
| 629 | AstNodePrefixOpExpr prefix_op_expr; | ||
| 630 | AstNodeFnCallExpr fn_call_expr; | ||
| 631 | AstNodeArrayAccessExpr array_access_expr; | ||
| 632 | AstNodeSliceExpr slice_expr; | ||
| 633 | AstNodeUse use; | ||
| 634 | AstNodeIfBoolExpr if_bool_expr; | ||
| 635 | AstNodeIfVarExpr if_var_expr; | ||
| 636 | AstNodeWhileExpr while_expr; | ||
| 637 | AstNodeLabel label; | ||
| 638 | AstNodeGoto goto_expr; | ||
| 639 | AstNodeAsmExpr asm_expr; | ||
| 640 | AstNodeFieldAccessExpr field_access_expr; | ||
| 641 | AstNodeStructDecl struct_decl; | ||
| 642 | AstNodeStructField struct_field; | ||
| 643 | AstNodeEnumDecl enum_decl; | ||
| 644 | AstNodeEnumField enum_field; | ||
| 645 | AstNodeStringLiteral string_literal; | ||
| 646 | AstNodeCharLiteral char_literal; | ||
| 647 | AstNodeNumberLiteral number_literal; | ||
| 648 | AstNodeStructValueExpr struct_val_expr; | ||
| 649 | AstNodeStructValueField struct_val_field; | ||
| 650 | AstNodeCompilerFnExpr compiler_fn_expr; | ||
| 651 | AstNodeCompilerFnType compiler_fn_type; | ||
| 652 | AstNodeNullLiteral null_literal; | ||
| 653 | AstNodeVoidExpr void_expr; | ||
| 654 | AstNodeUnreachableExpr unreachable_expr; | ||
| 655 | AstNodeSymbolExpr symbol_expr; | ||
| 656 | AstNodeBoolLiteral bool_literal; | ||
| 657 | AstNodeBreakExpr break_expr; | ||
| 658 | AstNodeContinueExpr continue_expr; | ||
| 659 | } data; | ||
| 660 | }; | ||
| 661 | |||
| 662 | enum AsmTokenId { | ||
| 663 | AsmTokenIdTemplate, | ||
| 664 | AsmTokenIdPercent, | ||
| 665 | AsmTokenIdVar, | ||
| 666 | }; | ||
| 667 | |||
| 668 | struct AsmToken { | ||
| 669 | enum AsmTokenId id; | ||
| 670 | int start; | ||
| 671 | int end; | ||
| 672 | }; | ||
| 673 | |||
| 674 | struct TypeTableEntryPointer { | ||
| 675 | TypeTableEntry *child_type; | ||
| 676 | bool is_const; | ||
| 677 | bool is_noalias; | ||
| 678 | }; | ||
| 679 | |||
| 680 | struct TypeTableEntryInt { | ||
| 681 | bool is_signed; | ||
| 682 | }; | ||
| 683 | |||
| 684 | struct TypeTableEntryArray { | ||
| 685 | TypeTableEntry *child_type; | ||
| 686 | uint64_t len; | ||
| 687 | }; | ||
| 688 | |||
| 689 | struct TypeStructField { | ||
| 690 | Buf *name; | ||
| 691 | TypeTableEntry *type_entry; | ||
| 692 | }; | ||
| 693 | |||
| 694 | struct TypeTableEntryStruct { | ||
| 695 | AstNode *decl_node; | ||
| 696 | bool is_packed; | ||
| 697 | int field_count; | ||
| 698 | TypeStructField *fields; | ||
| 699 | uint64_t size_bytes; | ||
| 700 | bool is_invalid; // true if any fields are invalid | ||
| 701 | bool is_unknown_size_array; | ||
| 702 | // reminder: hash tables must be initialized before use | ||
| 703 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; | ||
| 704 | |||
| 705 | // set this flag temporarily to detect infinite loops | ||
| 706 | bool embedded_in_current; | ||
| 707 | bool reported_infinite_err; | ||
| 708 | }; | ||
| 709 | |||
| 710 | struct TypeTableEntryNumLit { | ||
| 711 | NumLit kind; | ||
| 712 | }; | ||
| 713 | |||
| 714 | struct TypeTableEntryMaybe { | ||
| 715 | TypeTableEntry *child_type; | ||
| 716 | }; | ||
| 717 | |||
| 718 | enum TypeTableEntryId { | ||
| 719 | TypeTableEntryIdInvalid, | ||
| 720 | TypeTableEntryIdVoid, | ||
| 721 | TypeTableEntryIdBool, | ||
| 722 | TypeTableEntryIdUnreachable, | ||
| 723 | TypeTableEntryIdInt, | ||
| 724 | TypeTableEntryIdFloat, | ||
| 725 | TypeTableEntryIdPointer, | ||
| 726 | TypeTableEntryIdArray, | ||
| 727 | TypeTableEntryIdStruct, | ||
| 728 | TypeTableEntryIdNumberLiteral, | ||
| 729 | TypeTableEntryIdMaybe, | ||
| 730 | }; | ||
| 731 | |||
| 732 | struct TypeTableEntry { | ||
| 733 | TypeTableEntryId id; | ||
| 734 | |||
| 735 | LLVMTypeRef type_ref; | ||
| 736 | LLVMZigDIType *di_type; | ||
| 737 | uint64_t size_in_bits; | ||
| 738 | uint64_t align_in_bits; | ||
| 739 | |||
| 740 | Buf name; | ||
| 741 | |||
| 742 | union { | ||
| 743 | TypeTableEntryPointer pointer; | ||
| 744 | TypeTableEntryInt integral; | ||
| 745 | TypeTableEntryArray array; | ||
| 746 | TypeTableEntryStruct structure; | ||
| 747 | TypeTableEntryNumLit num_lit; | ||
| 748 | TypeTableEntryMaybe maybe; | ||
| 749 | } data; | ||
| 750 | |||
| 751 | // use these fields to make sure we don't duplicate type table entries for the same type | ||
| 752 | TypeTableEntry *pointer_parent[2][2]; // 0 - const. 1 - noalias | ||
| 753 | TypeTableEntry *unknown_size_array_parent[2][2]; // 0 - const. 1 - noalias | ||
| 754 | HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size; | ||
| 755 | TypeTableEntry *maybe_parent; | ||
| 756 | |||
| 757 | }; | ||
| 758 | |||
| 759 | struct ImporterInfo { | ||
| 760 | ImportTableEntry *import; | ||
| 761 | AstNode *source_node; | ||
| 762 | }; | ||
| 763 | |||
| 764 | struct ImportTableEntry { | ||
| 765 | AstNode *root; | ||
| 766 | Buf *path; // relative to root_source_dir | ||
| 767 | LLVMZigDIFile *di_file; | ||
| 768 | Buf *source_code; | ||
| 769 | ZigList<int> *line_offsets; | ||
| 770 | BlockContext *block_context; | ||
| 771 | ZigList<ImporterInfo> importers; | ||
| 772 | |||
| 773 | // reminder: hash tables must be initialized before use | ||
| 774 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; | ||
| 775 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table; | ||
| 776 | }; | ||
| 777 | |||
| 778 | struct LabelTableEntry { | ||
| 779 | AstNode *label_node; | ||
| 780 | LLVMBasicBlockRef basic_block; | ||
| 781 | bool used; | ||
| 782 | bool entered_from_fallthrough; | ||
| 783 | }; | ||
| 784 | |||
| 785 | enum FnAttrId { | ||
| 786 | FnAttrIdNaked, | ||
| 787 | FnAttrIdAlwaysInline, | ||
| 788 | }; | ||
| 789 | |||
| 790 | struct FnTableEntry { | ||
| 791 | LLVMValueRef fn_value; | ||
| 792 | AstNode *proto_node; | ||
| 793 | AstNode *fn_def_node; | ||
| 794 | bool is_extern; | ||
| 795 | bool internal_linkage; | ||
| 796 | unsigned calling_convention; | ||
| 797 | ImportTableEntry *import_entry; | ||
| 798 | ZigList<FnAttrId> fn_attr_list; | ||
| 799 | // Required to be a pre-order traversal of the AST. (parents must come before children) | ||
| 800 | ZigList<BlockContext *> all_block_contexts; | ||
| 801 | TypeTableEntry *member_of_struct; | ||
| 802 | Buf symbol_name; | ||
| 803 | |||
| 804 | // reminder: hash tables must be initialized before use | ||
| 805 | HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table; | ||
| 806 | }; | ||
| 807 | |||
| 808 | enum BuiltinFnId { | ||
| 809 | BuiltinFnIdInvalid, | ||
| 810 | BuiltinFnIdArithmeticWithOverflow, | ||
| 811 | BuiltinFnIdMemcpy, | ||
| 812 | BuiltinFnIdMemset, | ||
| 813 | }; | ||
| 814 | |||
| 815 | struct BuiltinFnEntry { | ||
| 816 | BuiltinFnId id; | ||
| 817 | Buf name; | ||
| 818 | int param_count; | ||
| 819 | TypeTableEntry *return_type; | ||
| 820 | TypeTableEntry **param_types; | ||
| 821 | LLVMValueRef fn_val; | ||
| 822 | }; | ||
| 823 | |||
| 824 | struct CodeGen { | ||
| 825 | LLVMModuleRef module; | ||
| 826 | ZigList<ErrorMsg*> errors; | ||
| 827 | LLVMBuilderRef builder; | ||
| 828 | LLVMZigDIBuilder *dbuilder; | ||
| 829 | LLVMZigDICompileUnit *compile_unit; | ||
| 830 | |||
| 831 | ZigList<Buf *> lib_search_paths; | ||
| 832 | |||
| 833 | // reminder: hash tables must be initialized before use | ||
| 834 | HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table; | ||
| 835 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table; | ||
| 836 | HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table; | ||
| 837 | HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table; | ||
| 838 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table; | ||
| 839 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls; | ||
| 840 | |||
| 841 | uint32_t next_unresolved_index; | ||
| 842 | |||
| 843 | struct { | ||
| 844 | TypeTableEntry *entry_bool; | ||
| 845 | TypeTableEntry *entry_u8; | ||
| 846 | TypeTableEntry *entry_u16; | ||
| 847 | TypeTableEntry *entry_u32; | ||
| 848 | TypeTableEntry *entry_u64; | ||
| 849 | TypeTableEntry *entry_i8; | ||
| 850 | TypeTableEntry *entry_i16; | ||
| 851 | TypeTableEntry *entry_i32; | ||
| 852 | TypeTableEntry *entry_i64; | ||
| 853 | TypeTableEntry *entry_isize; | ||
| 854 | TypeTableEntry *entry_usize; | ||
| 855 | TypeTableEntry *entry_f32; | ||
| 856 | TypeTableEntry *entry_f64; | ||
| 857 | TypeTableEntry *entry_c_string_literal; | ||
| 858 | TypeTableEntry *entry_void; | ||
| 859 | TypeTableEntry *entry_unreachable; | ||
| 860 | TypeTableEntry *entry_invalid; | ||
| 861 | } builtin_types; | ||
| 862 | |||
| 863 | TypeTableEntry *num_lit_types[NumLitCount]; | ||
| 864 | |||
| 865 | LLVMTargetDataRef target_data_ref; | ||
| 866 | unsigned pointer_size_bytes; | ||
| 867 | bool is_static; | ||
| 868 | bool strip_debug_symbols; | ||
| 869 | bool have_exported_main; | ||
| 870 | bool link_libc; | ||
| 871 | Buf *libc_path; | ||
| 872 | CodeGenBuildType build_type; | ||
| 873 | LLVMTargetMachineRef target_machine; | ||
| 874 | LLVMZigDIFile *dummy_di_file; | ||
| 875 | bool is_native_target; | ||
| 876 | Buf *root_source_dir; | ||
| 877 | Buf *root_out_name; | ||
| 878 | |||
| 879 | // The function definitions this module includes. There must be a corresponding | ||
| 880 | // fn_protos entry. | ||
| 881 | ZigList<FnTableEntry *> fn_defs; | ||
| 882 | // The function prototypes this module includes. In the case of external declarations, | ||
| 883 | // there will not be a corresponding fn_defs entry. | ||
| 884 | ZigList<FnTableEntry *> fn_protos; | ||
| 885 | ZigList<VariableTableEntry *> global_vars; | ||
| 886 | |||
| 887 | OutType out_type; | ||
| 888 | FnTableEntry *cur_fn; | ||
| 889 | BlockContext *cur_block_context; | ||
| 890 | ZigList<LLVMBasicBlockRef> break_block_stack; | ||
| 891 | ZigList<LLVMBasicBlockRef> continue_block_stack; | ||
| 892 | bool c_stdint_used; | ||
| 893 | AstNode *root_export_decl; | ||
| 894 | int version_major; | ||
| 895 | int version_minor; | ||
| 896 | int version_patch; | ||
| 897 | bool verbose; | ||
| 898 | ErrColor err_color; | ||
| 899 | ImportTableEntry *root_import; | ||
| 900 | ImportTableEntry *bootstrap_import; | ||
| 901 | LLVMValueRef memcpy_fn_val; | ||
| 902 | bool error_during_imports; | ||
| 903 | }; | ||
| 904 | |||
| 905 | struct VariableTableEntry { | ||
| 906 | Buf name; | ||
| 907 | TypeTableEntry *type; | ||
| 908 | LLVMValueRef value_ref; | ||
| 909 | bool is_const; | ||
| 910 | bool is_ptr; // if true, value_ref is a pointer | ||
| 911 | AstNode *decl_node; | ||
| 912 | LLVMZigDILocalVariable *di_loc_var; | ||
| 913 | int arg_index; | ||
| 914 | }; | ||
| 915 | |||
| 916 | struct BlockContext { | ||
| 917 | AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or NodeTypeRoot | ||
| 918 | FnTableEntry *fn_entry; // null at the module scope | ||
| 919 | BlockContext *parent; // null when this is the root | ||
| 920 | HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table; | ||
| 921 | ZigList<Cast *> cast_expr_alloca_list; | ||
| 922 | ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list; | ||
| 923 | AstNode *parent_loop_node; | ||
| 924 | AstNode *next_child_parent_loop_node; | ||
| 925 | LLVMZigDIScope *di_scope; | ||
| 926 | }; | ||
| 927 | |||
| 928 | #endif | ||
src/analyze.cpp+353-177| ... | @@ -6,6 +6,7 @@ | ... | @@ -6,6 +6,7 @@ |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include "analyze.hpp" | 8 | #include "analyze.hpp" |
| 9 | #include "parser.hpp" | ||
| 9 | #include "error.hpp" | 10 | #include "error.hpp" |
| 10 | #include "zig_llvm.hpp" | 11 | #include "zig_llvm.hpp" |
| 11 | #include "os.hpp" | 12 | #include "os.hpp" |
| ... | @@ -14,7 +15,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -14,7 +15,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 14 | TypeTableEntry *expected_type, AstNode *node); | 15 | TypeTableEntry *expected_type, AstNode *node); |
| 15 | static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, | 16 | static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, |
| 16 | AstNode *node, AstNodeNumberLiteral *out_number_literal); | 17 | AstNode *node, AstNodeNumberLiteral *out_number_literal); |
| 17 | static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, DeclNode *decl_node); | 18 | static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, TopLevelDecl *decl_node); |
| 18 | static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, | 19 | static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, |
| 19 | BlockContext *context, TypeTableEntry *expected_type, AstNode *node); | 20 | BlockContext *context, TypeTableEntry *expected_type, AstNode *node); |
| 20 | 21 | ||
| ... | @@ -317,7 +318,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context, | ... | @@ -317,7 +318,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context, |
| 317 | out_number_literal->kind = NumLitU8; | 318 | out_number_literal->kind = NumLitU8; |
| 318 | out_number_literal->overflow = false; | 319 | out_number_literal->overflow = false; |
| 319 | out_number_literal->data.x_uint = (op1_lit.data.x_uint != op2_lit.data.x_uint); | 320 | out_number_literal->data.x_uint = (op1_lit.data.x_uint != op2_lit.data.x_uint); |
| 320 | return node->codegen_node->expr_node.type_entry; | 321 | return get_resolved_expr(node)->type_entry; |
| 321 | } else { | 322 | } else { |
| 322 | return g->builtin_types.entry_invalid; | 323 | return g->builtin_types.entry_invalid; |
| 323 | } | 324 | } |
| ... | @@ -330,7 +331,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context, | ... | @@ -330,7 +331,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context, |
| 330 | out_number_literal->kind = NumLitU8; | 331 | out_number_literal->kind = NumLitU8; |
| 331 | out_number_literal->overflow = false; | 332 | out_number_literal->overflow = false; |
| 332 | out_number_literal->data.x_uint = (op1_lit.data.x_uint < op2_lit.data.x_uint); | 333 | out_number_literal->data.x_uint = (op1_lit.data.x_uint < op2_lit.data.x_uint); |
| 333 | return node->codegen_node->expr_node.type_entry; | 334 | return get_resolved_expr(node)->type_entry; |
| 334 | } else { | 335 | } else { |
| 335 | return g->builtin_types.entry_invalid; | 336 | return g->builtin_types.entry_invalid; |
| 336 | } | 337 | } |
| ... | @@ -343,7 +344,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context, | ... | @@ -343,7 +344,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context, |
| 343 | out_number_literal->kind = NumLitU64; | 344 | out_number_literal->kind = NumLitU64; |
| 344 | out_number_literal->overflow = false; | 345 | out_number_literal->overflow = false; |
| 345 | out_number_literal->data.x_uint = (op1_lit.data.x_uint % op2_lit.data.x_uint); | 346 | out_number_literal->data.x_uint = (op1_lit.data.x_uint % op2_lit.data.x_uint); |
| 346 | return node->codegen_node->expr_node.type_entry; | 347 | return get_resolved_expr(node)->type_entry; |
| 347 | } else { | 348 | } else { |
| 348 | return g->builtin_types.entry_invalid; | 349 | return g->builtin_types.entry_invalid; |
| 349 | } | 350 | } |
| ... | @@ -390,20 +391,20 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, | ... | @@ -390,20 +391,20 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, |
| 390 | switch (node->type) { | 391 | switch (node->type) { |
| 391 | case NodeTypeNumberLiteral: | 392 | case NodeTypeNumberLiteral: |
| 392 | *out_number_literal = node->data.number_literal; | 393 | *out_number_literal = node->data.number_literal; |
| 393 | return node->codegen_node->expr_node.type_entry; | 394 | return get_resolved_expr(node)->type_entry; |
| 394 | case NodeTypeBoolLiteral: | 395 | case NodeTypeBoolLiteral: |
| 395 | out_number_literal->data.x_uint = node->data.bool_literal ? 1 : 0; | 396 | out_number_literal->data.x_uint = node->data.bool_literal.value ? 1 : 0; |
| 396 | return node->codegen_node->expr_node.type_entry; | 397 | return get_resolved_expr(node)->type_entry; |
| 397 | case NodeTypeNullLiteral: | 398 | case NodeTypeNullLiteral: |
| 398 | return node->codegen_node->expr_node.type_entry; | 399 | return get_resolved_expr(node)->type_entry; |
| 399 | case NodeTypeBinOpExpr: | 400 | case NodeTypeBinOpExpr: |
| 400 | return eval_const_expr_bin_op(g, context, node, out_number_literal); | 401 | return eval_const_expr_bin_op(g, context, node, out_number_literal); |
| 401 | case NodeTypeCompilerFnType: | 402 | case NodeTypeCompilerFnType: |
| 402 | { | 403 | { |
| 403 | Buf *name = &node->data.compiler_fn_type.name; | 404 | Buf *name = &node->data.compiler_fn_type.name; |
| 404 | TypeTableEntry *expr_type = node->codegen_node->expr_node.type_entry; | 405 | TypeTableEntry *expr_type = get_resolved_expr(node)->type_entry; |
| 405 | if (buf_eql_str(name, "sizeof")) { | 406 | if (buf_eql_str(name, "sizeof")) { |
| 406 | TypeTableEntry *target_type = node->data.compiler_fn_type.type->codegen_node->data.type_node.entry; | 407 | TypeTableEntry *target_type = node->data.compiler_fn_type.type->data.type.entry; |
| 407 | out_number_literal->overflow = false; | 408 | out_number_literal->overflow = false; |
| 408 | out_number_literal->data.x_uint = target_type->size_in_bits / 8; | 409 | out_number_literal->data.x_uint = target_type->size_in_bits / 8; |
| 409 | out_number_literal->kind = get_number_literal_kind_unsigned(out_number_literal->data.x_uint); | 410 | out_number_literal->kind = get_number_literal_kind_unsigned(out_number_literal->data.x_uint); |
| ... | @@ -420,11 +421,11 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, | ... | @@ -420,11 +421,11 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, |
| 420 | } | 421 | } |
| 421 | case NodeTypeSymbol: | 422 | case NodeTypeSymbol: |
| 422 | { | 423 | { |
| 423 | VariableTableEntry *var = find_variable(context, &node->data.symbol); | 424 | VariableTableEntry *var = find_variable(context, &node->data.symbol_expr.symbol); |
| 424 | assert(var); | 425 | assert(var); |
| 425 | AstNode *decl_node = var->decl_node; | 426 | AstNode *decl_node = var->decl_node; |
| 426 | AstNode *expr_node = decl_node->data.variable_declaration.expr; | 427 | AstNode *expr_node = decl_node->data.variable_declaration.expr; |
| 427 | BlockContext *next_context = expr_node->codegen_node->expr_node.block_context; | 428 | BlockContext *next_context = get_resolved_expr(expr_node)->block_context; |
| 428 | return eval_const_expr(g, next_context, expr_node, out_number_literal); | 429 | return eval_const_expr(g, next_context, expr_node, out_number_literal); |
| 429 | } | 430 | } |
| 430 | default: | 431 | default: |
| ... | @@ -436,8 +437,6 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -436,8 +437,6 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 436 | BlockContext *context, bool noalias_allowed) | 437 | BlockContext *context, bool noalias_allowed) |
| 437 | { | 438 | { |
| 438 | assert(node->type == NodeTypeType); | 439 | assert(node->type == NodeTypeType); |
| 439 | alloc_codegen_node(node); | ||
| 440 | TypeNode *type_node = &node->codegen_node->data.type_node; | ||
| 441 | switch (node->data.type.type) { | 440 | switch (node->data.type.type) { |
| 442 | case AstNodeTypeTypePrimitive: | 441 | case AstNodeTypeTypePrimitive: |
| 443 | { | 442 | { |
| ... | @@ -447,13 +446,13 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -447,13 +446,13 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 447 | table_entry = g->primitive_type_table.maybe_get(name); | 446 | table_entry = g->primitive_type_table.maybe_get(name); |
| 448 | } | 447 | } |
| 449 | if (table_entry) { | 448 | if (table_entry) { |
| 450 | type_node->entry = table_entry->value; | 449 | node->data.type.entry = table_entry->value; |
| 451 | } else { | 450 | } else { |
| 452 | add_node_error(g, node, | 451 | add_node_error(g, node, |
| 453 | buf_sprintf("invalid type name: '%s'", buf_ptr(name))); | 452 | buf_sprintf("invalid type name: '%s'", buf_ptr(name))); |
| 454 | type_node->entry = g->builtin_types.entry_invalid; | 453 | node->data.type.entry = g->builtin_types.entry_invalid; |
| 455 | } | 454 | } |
| 456 | return type_node->entry; | 455 | return node->data.type.entry; |
| 457 | } | 456 | } |
| 458 | case AstNodeTypeTypePointer: | 457 | case AstNodeTypeTypePointer: |
| 459 | { | 458 | { |
| ... | @@ -468,19 +467,19 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -468,19 +467,19 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 468 | } | 467 | } |
| 469 | 468 | ||
| 470 | resolve_type(g, node->data.type.child_type, import, context, false); | 469 | resolve_type(g, node->data.type.child_type, import, context, false); |
| 471 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; | 470 | TypeTableEntry *child_type = node->data.type.child_type->data.type.entry; |
| 472 | assert(child_type); | 471 | assert(child_type); |
| 473 | if (child_type->id == TypeTableEntryIdUnreachable) { | 472 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| 474 | add_node_error(g, node, | 473 | add_node_error(g, node, |
| 475 | buf_create_from_str("pointer to unreachable not allowed")); | 474 | buf_create_from_str("pointer to unreachable not allowed")); |
| 476 | type_node->entry = g->builtin_types.entry_invalid; | 475 | node->data.type.entry = g->builtin_types.entry_invalid; |
| 477 | return type_node->entry; | 476 | return node->data.type.entry; |
| 478 | } else if (child_type->id == TypeTableEntryIdInvalid) { | 477 | } else if (child_type->id == TypeTableEntryIdInvalid) { |
| 479 | type_node->entry = child_type; | 478 | node->data.type.entry = child_type; |
| 480 | return child_type; | 479 | return child_type; |
| 481 | } else { | 480 | } else { |
| 482 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const, use_noalias); | 481 | node->data.type.entry = get_pointer_to_type(g, child_type, node->data.type.is_const, use_noalias); |
| 483 | return type_node->entry; | 482 | return node->data.type.entry; |
| 484 | } | 483 | } |
| 485 | } | 484 | } |
| 486 | case AstNodeTypeTypeArray: | 485 | case AstNodeTypeTypeArray: |
| ... | @@ -501,16 +500,16 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -501,16 +500,16 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 501 | if (child_type->id == TypeTableEntryIdUnreachable) { | 500 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| 502 | add_node_error(g, node, | 501 | add_node_error(g, node, |
| 503 | buf_create_from_str("array of unreachable not allowed")); | 502 | buf_create_from_str("array of unreachable not allowed")); |
| 504 | type_node->entry = g->builtin_types.entry_invalid; | 503 | node->data.type.entry = g->builtin_types.entry_invalid; |
| 505 | return type_node->entry; | 504 | return node->data.type.entry; |
| 506 | } | 505 | } |
| 507 | 506 | ||
| 508 | if (size_node) { | 507 | if (size_node) { |
| 509 | TypeTableEntry *size_type = analyze_expression(g, import, context, | 508 | TypeTableEntry *size_type = analyze_expression(g, import, context, |
| 510 | g->builtin_types.entry_usize, size_node); | 509 | g->builtin_types.entry_usize, size_node); |
| 511 | if (size_type->id == TypeTableEntryIdInvalid) { | 510 | if (size_type->id == TypeTableEntryIdInvalid) { |
| 512 | type_node->entry = g->builtin_types.entry_invalid; | 511 | node->data.type.entry = g->builtin_types.entry_invalid; |
| 513 | return type_node->entry; | 512 | return node->data.type.entry; |
| 514 | } | 513 | } |
| 515 | 514 | ||
| 516 | AstNodeNumberLiteral number_literal; | 515 | AstNodeNumberLiteral number_literal; |
| ... | @@ -520,27 +519,27 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -520,27 +519,27 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 520 | if (resolved_type->data.integral.is_signed) { | 519 | if (resolved_type->data.integral.is_signed) { |
| 521 | add_node_error(g, size_node, | 520 | add_node_error(g, size_node, |
| 522 | buf_create_from_str("array size must be unsigned integer")); | 521 | buf_create_from_str("array size must be unsigned integer")); |
| 523 | type_node->entry = g->builtin_types.entry_invalid; | 522 | node->data.type.entry = g->builtin_types.entry_invalid; |
| 524 | } else { | 523 | } else { |
| 525 | type_node->entry = get_array_type(g, import, child_type, number_literal.data.x_uint); | 524 | node->data.type.entry = get_array_type(g, import, child_type, number_literal.data.x_uint); |
| 526 | } | 525 | } |
| 527 | } else { | 526 | } else { |
| 528 | add_node_error(g, size_node, | 527 | add_node_error(g, size_node, |
| 529 | buf_create_from_str("unable to resolve constant expression")); | 528 | buf_create_from_str("unable to resolve constant expression")); |
| 530 | type_node->entry = g->builtin_types.entry_invalid; | 529 | node->data.type.entry = g->builtin_types.entry_invalid; |
| 531 | } | 530 | } |
| 532 | return type_node->entry; | 531 | return node->data.type.entry; |
| 533 | } else { | 532 | } else { |
| 534 | type_node->entry = get_unknown_size_array_type(g, import, child_type, | 533 | node->data.type.entry = get_unknown_size_array_type(g, import, child_type, |
| 535 | node->data.type.is_const, use_noalias); | 534 | node->data.type.is_const, use_noalias); |
| 536 | return type_node->entry; | 535 | return node->data.type.entry; |
| 537 | } | 536 | } |
| 538 | 537 | ||
| 539 | } | 538 | } |
| 540 | case AstNodeTypeTypeMaybe: | 539 | case AstNodeTypeTypeMaybe: |
| 541 | { | 540 | { |
| 542 | resolve_type(g, node->data.type.child_type, import, context, false); | 541 | resolve_type(g, node->data.type.child_type, import, context, false); |
| 543 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; | 542 | TypeTableEntry *child_type = node->data.type.child_type->data.type.entry; |
| 544 | assert(child_type); | 543 | assert(child_type); |
| 545 | if (child_type->id == TypeTableEntryIdUnreachable) { | 544 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| 546 | add_node_error(g, node, | 545 | add_node_error(g, node, |
| ... | @@ -548,22 +547,22 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -548,22 +547,22 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 548 | } else if (child_type->id == TypeTableEntryIdInvalid) { | 547 | } else if (child_type->id == TypeTableEntryIdInvalid) { |
| 549 | return child_type; | 548 | return child_type; |
| 550 | } | 549 | } |
| 551 | type_node->entry = get_maybe_type(g, import, child_type); | 550 | node->data.type.entry = get_maybe_type(g, import, child_type); |
| 552 | return type_node->entry; | 551 | return node->data.type.entry; |
| 553 | } | 552 | } |
| 554 | case AstNodeTypeTypeCompilerExpr: | 553 | case AstNodeTypeTypeCompilerExpr: |
| 555 | { | 554 | { |
| 556 | AstNode *compiler_expr_node = node->data.type.compiler_expr; | 555 | AstNode *compiler_expr_node = node->data.type.compiler_expr; |
| 557 | Buf *fn_name = &compiler_expr_node->data.compiler_fn_expr.name; | 556 | Buf *fn_name = &compiler_expr_node->data.compiler_fn_expr.name; |
| 558 | if (buf_eql_str(fn_name, "typeof")) { | 557 | if (buf_eql_str(fn_name, "typeof")) { |
| 559 | type_node->entry = analyze_expression(g, import, context, nullptr, | 558 | node->data.type.entry = analyze_expression(g, import, context, nullptr, |
| 560 | compiler_expr_node->data.compiler_fn_expr.expr); | 559 | compiler_expr_node->data.compiler_fn_expr.expr); |
| 561 | } else { | 560 | } else { |
| 562 | add_node_error(g, node, | 561 | add_node_error(g, node, |
| 563 | buf_sprintf("invalid compiler function: '%s'", buf_ptr(fn_name))); | 562 | buf_sprintf("invalid compiler function: '%s'", buf_ptr(fn_name))); |
| 564 | type_node->entry = g->builtin_types.entry_invalid; | 563 | node->data.type.entry = g->builtin_types.entry_invalid; |
| 565 | } | 564 | } |
| 566 | return type_node->entry; | 565 | return node->data.type.entry; |
| 567 | } | 566 | } |
| 568 | } | 567 | } |
| 569 | zig_unreachable(); | 568 | zig_unreachable(); |
| ... | @@ -631,8 +630,7 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_ | ... | @@ -631,8 +630,7 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_ |
| 631 | Buf *name = &label_node->data.label.name; | 630 | Buf *name = &label_node->data.label.name; |
| 632 | fn_table_entry->label_table.put(name, label_entry); | 631 | fn_table_entry->label_table.put(name, label_entry); |
| 633 | 632 | ||
| 634 | alloc_codegen_node(label_node); | 633 | label_node->data.label.label_entry = label_entry; |
| 635 | label_node->codegen_node->data.label_entry = label_entry; | ||
| 636 | } | 634 | } |
| 637 | } | 635 | } |
| 638 | 636 | ||
| ... | @@ -732,7 +730,8 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, | ... | @@ -732,7 +730,8 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, |
| 732 | AstNode *struct_node = proto_node->data.fn_proto.struct_node; | 730 | AstNode *struct_node = proto_node->data.fn_proto.struct_node; |
| 733 | TypeTableEntry *struct_type; | 731 | TypeTableEntry *struct_type; |
| 734 | if (struct_node) { | 732 | if (struct_node) { |
| 735 | struct_type = struct_node->codegen_node->data.struct_decl_node.type_entry; | 733 | assert(struct_node->type == NodeTypeStructDecl); |
| 734 | struct_type = struct_node->data.struct_decl.type_entry; | ||
| 736 | } else { | 735 | } else { |
| 737 | struct_type = nullptr; | 736 | struct_type = nullptr; |
| 738 | } | 737 | } |
| ... | @@ -749,13 +748,14 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, | ... | @@ -749,13 +748,14 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, |
| 749 | if (entry) { | 748 | if (entry) { |
| 750 | add_node_error(g, proto_node, | 749 | add_node_error(g, proto_node, |
| 751 | buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); | 750 | buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); |
| 752 | proto_node->codegen_node->data.fn_proto_node.skip = true; | 751 | proto_node->data.fn_proto.skip = true; |
| 753 | skip = true; | 752 | skip = true; |
| 754 | } else if (is_pub) { | 753 | } else if (is_pub) { |
| 754 | // TODO is this else if branch a mistake? | ||
| 755 | auto entry = fn_table->maybe_get(proto_name); | 755 | auto entry = fn_table->maybe_get(proto_name); |
| 756 | if (entry) { | 756 | if (entry) { |
| 757 | add_node_error(g, proto_node, buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); | 757 | add_node_error(g, proto_node, buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); |
| 758 | proto_node->codegen_node->data.fn_proto_node.skip = true; | 758 | proto_node->data.fn_proto.skip = true; |
| 759 | skip = true; | 759 | skip = true; |
| 760 | } | 760 | } |
| 761 | } | 761 | } |
| ... | @@ -804,7 +804,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, | ... | @@ -804,7 +804,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, |
| 804 | resolve_function_proto(g, proto_node, fn_table_entry, import); | 804 | resolve_function_proto(g, proto_node, fn_table_entry, import); |
| 805 | 805 | ||
| 806 | 806 | ||
| 807 | proto_node->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry; | 807 | proto_node->data.fn_proto.fn_table_entry = fn_table_entry; |
| 808 | 808 | ||
| 809 | if (fn_def_node) { | 809 | if (fn_def_node) { |
| 810 | preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry); | 810 | preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry); |
| ... | @@ -888,8 +888,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -888,8 +888,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 888 | break; | 888 | break; |
| 889 | case NodeTypeStructDecl: | 889 | case NodeTypeStructDecl: |
| 890 | { | 890 | { |
| 891 | StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node; | 891 | TypeTableEntry *type_entry = node->data.struct_decl.type_entry; |
| 892 | TypeTableEntry *type_entry = struct_codegen->type_entry; | ||
| 893 | 892 | ||
| 894 | resolve_struct_type(g, import, type_entry); | 893 | resolve_struct_type(g, import, type_entry); |
| 895 | 894 | ||
| ... | @@ -962,8 +961,8 @@ static TypeTableEntry *get_return_type(BlockContext *context) { | ... | @@ -962,8 +961,8 @@ static TypeTableEntry *get_return_type(BlockContext *context) { |
| 962 | AstNode *fn_proto_node = fn_entry->proto_node; | 961 | AstNode *fn_proto_node = fn_entry->proto_node; |
| 963 | assert(fn_proto_node->type == NodeTypeFnProto); | 962 | assert(fn_proto_node->type == NodeTypeFnProto); |
| 964 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; | 963 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| 965 | assert(return_type_node->codegen_node); | 964 | assert(return_type_node->type == NodeTypeType); |
| 966 | return return_type_node->codegen_node->data.type_node.entry; | 965 | return return_type_node->data.type.entry; |
| 967 | } | 966 | } |
| 968 | 967 | ||
| 969 | static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) { | 968 | static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) { |
| ... | @@ -1003,15 +1002,14 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, | ... | @@ -1003,15 +1002,14 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, |
| 1003 | zig_unreachable(); | 1002 | zig_unreachable(); |
| 1004 | } | 1003 | } |
| 1005 | 1004 | ||
| 1006 | static TypeTableEntry * resolve_rhs_number_literal(CodeGen *g, AstNode *non_literal_node, | 1005 | static TypeTableEntry *resolve_rhs_number_literal(CodeGen *g, AstNode *non_literal_node, |
| 1007 | TypeTableEntry *non_literal_type, AstNode *literal_node, TypeTableEntry *literal_type) | 1006 | TypeTableEntry *non_literal_type, AstNode *literal_node, TypeTableEntry *literal_type) |
| 1008 | { | 1007 | { |
| 1009 | assert(literal_node->codegen_node); | 1008 | NumLitCodeGen *num_lit_codegen = get_resolved_num_lit(literal_node); |
| 1010 | NumberLiteralNode *codegen_num_lit = &literal_node->codegen_node->data.num_lit_node; | ||
| 1011 | 1009 | ||
| 1012 | if (non_literal_type && num_lit_fits_in_other_type(g, literal_type, non_literal_type)) { | 1010 | if (non_literal_type && num_lit_fits_in_other_type(g, literal_type, non_literal_type)) { |
| 1013 | assert(!codegen_num_lit->resolved_type); | 1011 | assert(!num_lit_codegen->resolved_type); |
| 1014 | codegen_num_lit->resolved_type = non_literal_type; | 1012 | num_lit_codegen->resolved_type = non_literal_type; |
| 1015 | return non_literal_type; | 1013 | return non_literal_type; |
| 1016 | } else { | 1014 | } else { |
| 1017 | return nullptr; | 1015 | return nullptr; |
| ... | @@ -1024,11 +1022,8 @@ static TypeTableEntry * resolve_number_literals(CodeGen *g, AstNode *node1, AstN | ... | @@ -1024,11 +1022,8 @@ static TypeTableEntry * resolve_number_literals(CodeGen *g, AstNode *node1, AstN |
| 1024 | if (type1->id == TypeTableEntryIdNumberLiteral && | 1022 | if (type1->id == TypeTableEntryIdNumberLiteral && |
| 1025 | type2->id == TypeTableEntryIdNumberLiteral) | 1023 | type2->id == TypeTableEntryIdNumberLiteral) |
| 1026 | { | 1024 | { |
| 1027 | assert(node1->codegen_node); | 1025 | NumLitCodeGen *codegen_num_lit_1 = get_resolved_num_lit(node1); |
| 1028 | assert(node2->codegen_node); | 1026 | NumLitCodeGen *codegen_num_lit_2 = get_resolved_num_lit(node2); |
| 1029 | |||
| 1030 | NumberLiteralNode *codegen_num_lit_1 = &node1->codegen_node->data.num_lit_node; | ||
| 1031 | NumberLiteralNode *codegen_num_lit_2 = &node2->codegen_node->data.num_lit_node; | ||
| 1032 | 1027 | ||
| 1033 | assert(!codegen_num_lit_1->resolved_type); | 1028 | assert(!codegen_num_lit_1->resolved_type); |
| 1034 | assert(!codegen_num_lit_2->resolved_type); | 1029 | assert(!codegen_num_lit_2->resolved_type); |
| ... | @@ -1113,9 +1108,10 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont | ... | @@ -1113,9 +1108,10 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1113 | if (actual_type->id == TypeTableEntryIdNumberLiteral && | 1108 | if (actual_type->id == TypeTableEntryIdNumberLiteral && |
| 1114 | num_lit_fits_in_other_type(g, actual_type, expected_type)) | 1109 | num_lit_fits_in_other_type(g, actual_type, expected_type)) |
| 1115 | { | 1110 | { |
| 1116 | assert(!node->codegen_node->data.num_lit_node.resolved_type || | 1111 | NumLitCodeGen *num_lit_code_gen = get_resolved_num_lit(node); |
| 1117 | node->codegen_node->data.num_lit_node.resolved_type == expected_type); | 1112 | assert(!num_lit_code_gen->resolved_type || |
| 1118 | node->codegen_node->data.num_lit_node.resolved_type = expected_type; | 1113 | num_lit_code_gen->resolved_type == expected_type); |
| 1114 | num_lit_code_gen->resolved_type = expected_type; | ||
| 1119 | return expected_type; | 1115 | return expected_type; |
| 1120 | } | 1116 | } |
| 1121 | 1117 | ||
| ... | @@ -1134,10 +1130,11 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont | ... | @@ -1134,10 +1130,11 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1134 | if (resolved_type->id == TypeTableEntryIdInvalid) { | 1130 | if (resolved_type->id == TypeTableEntryIdInvalid) { |
| 1135 | return resolved_type; | 1131 | return resolved_type; |
| 1136 | } | 1132 | } |
| 1137 | node->codegen_node->expr_node.implicit_maybe_cast.op = CastOpMaybeWrap; | 1133 | Expr *expr = get_resolved_expr(node); |
| 1138 | node->codegen_node->expr_node.implicit_maybe_cast.after_type = expected_type; | 1134 | expr->implicit_maybe_cast.op = CastOpMaybeWrap; |
| 1139 | node->codegen_node->expr_node.implicit_maybe_cast.source_node = node; | 1135 | expr->implicit_maybe_cast.after_type = expected_type; |
| 1140 | context->cast_expr_alloca_list.append(&node->codegen_node->expr_node.implicit_maybe_cast); | 1136 | expr->implicit_maybe_cast.source_node = node; |
| 1137 | context->cast_expr_alloca_list.append(&expr->implicit_maybe_cast); | ||
| 1141 | return expected_type; | 1138 | return expected_type; |
| 1142 | } | 1139 | } |
| 1143 | 1140 | ||
| ... | @@ -1147,9 +1144,10 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont | ... | @@ -1147,9 +1144,10 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1147 | expected_type->data.integral.is_signed == actual_type->data.integral.is_signed && | 1144 | expected_type->data.integral.is_signed == actual_type->data.integral.is_signed && |
| 1148 | expected_type->size_in_bits > actual_type->size_in_bits) | 1145 | expected_type->size_in_bits > actual_type->size_in_bits) |
| 1149 | { | 1146 | { |
| 1150 | node->codegen_node->expr_node.implicit_cast.after_type = expected_type; | 1147 | Expr *expr = get_resolved_expr(node); |
| 1151 | node->codegen_node->expr_node.implicit_cast.op = CastOpIntWidenOrShorten; | 1148 | expr->implicit_cast.after_type = expected_type; |
| 1152 | node->codegen_node->expr_node.implicit_cast.source_node = node; | 1149 | expr->implicit_cast.op = CastOpIntWidenOrShorten; |
| 1150 | expr->implicit_cast.source_node = node; | ||
| 1153 | return expected_type; | 1151 | return expected_type; |
| 1154 | } | 1152 | } |
| 1155 | 1153 | ||
| ... | @@ -1159,10 +1157,11 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont | ... | @@ -1159,10 +1157,11 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1159 | actual_type->id == TypeTableEntryIdArray && | 1157 | actual_type->id == TypeTableEntryIdArray && |
| 1160 | actual_type->data.array.child_type == expected_type->data.structure.fields[0].type_entry->data.pointer.child_type) | 1158 | actual_type->data.array.child_type == expected_type->data.structure.fields[0].type_entry->data.pointer.child_type) |
| 1161 | { | 1159 | { |
| 1162 | node->codegen_node->expr_node.implicit_cast.after_type = expected_type; | 1160 | Expr *expr = get_resolved_expr(node); |
| 1163 | node->codegen_node->expr_node.implicit_cast.op = CastOpToUnknownSizeArray; | 1161 | expr->implicit_cast.after_type = expected_type; |
| 1164 | node->codegen_node->expr_node.implicit_cast.source_node = node; | 1162 | expr->implicit_cast.op = CastOpToUnknownSizeArray; |
| 1165 | context->cast_expr_alloca_list.append(&node->codegen_node->expr_node.implicit_cast); | 1163 | expr->implicit_cast.source_node = node; |
| 1164 | context->cast_expr_alloca_list.append(&expr->implicit_cast); | ||
| 1166 | return expected_type; | 1165 | return expected_type; |
| 1167 | } | 1166 | } |
| 1168 | 1167 | ||
| ... | @@ -1225,7 +1224,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) { | ... | @@ -1225,7 +1224,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) { |
| 1225 | 1224 | ||
| 1226 | if (node && node->type == NodeTypeFnDef) { | 1225 | if (node && node->type == NodeTypeFnDef) { |
| 1227 | AstNode *fn_proto_node = node->data.fn_def.fn_proto; | 1226 | AstNode *fn_proto_node = node->data.fn_def.fn_proto; |
| 1228 | context->fn_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry; | 1227 | context->fn_entry = fn_proto_node->data.fn_proto.fn_table_entry; |
| 1229 | } else if (parent) { | 1228 | } else if (parent) { |
| 1230 | context->fn_entry = parent->fn_entry; | 1229 | context->fn_entry = parent->fn_entry; |
| 1231 | } | 1230 | } |
| ... | @@ -1275,6 +1274,8 @@ static void get_struct_field(TypeTableEntry *struct_type, Buf *name, TypeStructF | ... | @@ -1275,6 +1274,8 @@ static void get_struct_field(TypeTableEntry *struct_type, Buf *name, TypeStructF |
| 1275 | static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1274 | static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1276 | AstNode *node) | 1275 | AstNode *node) |
| 1277 | { | 1276 | { |
| 1277 | assert(node->type == NodeTypeFieldAccessExpr); | ||
| 1278 | |||
| 1278 | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, | 1279 | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, |
| 1279 | node->data.field_access_expr.struct_expr); | 1280 | node->data.field_access_expr.struct_expr); |
| 1280 | 1281 | ||
| ... | @@ -1283,20 +1284,16 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -1283,20 +1284,16 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 1283 | if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer && | 1284 | if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer && |
| 1284 | struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) | 1285 | struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) |
| 1285 | { | 1286 | { |
| 1286 | assert(node->codegen_node); | ||
| 1287 | FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node; | ||
| 1288 | assert(codegen_field_access); | ||
| 1289 | |||
| 1290 | Buf *field_name = &node->data.field_access_expr.field_name; | 1287 | Buf *field_name = &node->data.field_access_expr.field_name; |
| 1291 | 1288 | ||
| 1292 | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ? | 1289 | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ? |
| 1293 | struct_type : struct_type->data.pointer.child_type; | 1290 | struct_type : struct_type->data.pointer.child_type; |
| 1294 | 1291 | ||
| 1295 | get_struct_field(bare_struct_type, field_name, | 1292 | get_struct_field(bare_struct_type, field_name, |
| 1296 | &codegen_field_access->type_struct_field, | 1293 | &node->data.field_access_expr.type_struct_field, |
| 1297 | &codegen_field_access->field_index); | 1294 | &node->data.field_access_expr.field_index); |
| 1298 | if (codegen_field_access->type_struct_field) { | 1295 | if (node->data.field_access_expr.type_struct_field) { |
| 1299 | return_type = codegen_field_access->type_struct_field->type_entry; | 1296 | return_type = node->data.field_access_expr.type_struct_field->type_entry; |
| 1300 | } else { | 1297 | } else { |
| 1301 | add_node_error(g, node, | 1298 | add_node_error(g, node, |
| 1302 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name))); | 1299 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name))); |
| ... | @@ -1329,6 +1326,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -1329,6 +1326,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 1329 | static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1326 | static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1330 | AstNode *node) | 1327 | AstNode *node) |
| 1331 | { | 1328 | { |
| 1329 | assert(node->type == NodeTypeSliceExpr); | ||
| 1330 | |||
| 1332 | TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr, | 1331 | TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr, |
| 1333 | node->data.slice_expr.array_ref_expr); | 1332 | node->data.slice_expr.array_ref_expr); |
| 1334 | 1333 | ||
| ... | @@ -1355,10 +1354,9 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1355,10 +1354,9 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, |
| 1355 | } | 1354 | } |
| 1356 | 1355 | ||
| 1357 | if (return_type->id != TypeTableEntryIdInvalid) { | 1356 | if (return_type->id != TypeTableEntryIdInvalid) { |
| 1358 | assert(node->codegen_node); | 1357 | node->data.slice_expr.resolved_struct_val_expr.type_entry = return_type; |
| 1359 | node->codegen_node->data.struct_val_expr_node.type_entry = return_type; | 1358 | node->data.slice_expr.resolved_struct_val_expr.source_node = node; |
| 1360 | node->codegen_node->data.struct_val_expr_node.source_node = node; | 1359 | context->struct_val_expr_alloca_list.append(&node->data.slice_expr.resolved_struct_val_expr); |
| 1361 | context->struct_val_expr_alloca_list.append(&node->codegen_node->data.struct_val_expr_node); | ||
| 1362 | } | 1360 | } |
| 1363 | 1361 | ||
| 1364 | analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.start); | 1362 | analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.start); |
| ... | @@ -1463,6 +1461,8 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { | ... | @@ -1463,6 +1461,8 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { |
| 1463 | static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1461 | static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1464 | TypeTableEntry *expected_type, AstNode *node) | 1462 | TypeTableEntry *expected_type, AstNode *node) |
| 1465 | { | 1463 | { |
| 1464 | assert(node->type == NodeTypeCastExpr); | ||
| 1465 | |||
| 1466 | TypeTableEntry *wanted_type = resolve_type(g, node->data.cast_expr.type, import, context, false); | 1466 | TypeTableEntry *wanted_type = resolve_type(g, node->data.cast_expr.type, import, context, false); |
| 1467 | TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr); | 1467 | TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr); |
| 1468 | 1468 | ||
| ... | @@ -1472,43 +1472,41 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B | ... | @@ -1472,43 +1472,41 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 1472 | return g->builtin_types.entry_invalid; | 1472 | return g->builtin_types.entry_invalid; |
| 1473 | } | 1473 | } |
| 1474 | 1474 | ||
| 1475 | CastNode *cast_node = &node->codegen_node->data.cast_node; | 1475 | Cast *cast = &node->data.cast_expr.cast; |
| 1476 | cast_node->source_node = node; | 1476 | cast->source_node = node; |
| 1477 | cast_node->after_type = wanted_type; | 1477 | cast->after_type = wanted_type; |
| 1478 | 1478 | ||
| 1479 | // special casing this for now, TODO think about casting and do a general solution | ||
| 1480 | if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) && | 1479 | if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) && |
| 1481 | actual_type->id == TypeTableEntryIdPointer) | 1480 | actual_type->id == TypeTableEntryIdPointer) |
| 1482 | { | 1481 | { |
| 1483 | cast_node->op = CastOpPtrToInt; | 1482 | cast->op = CastOpPtrToInt; |
| 1484 | return wanted_type; | 1483 | return wanted_type; |
| 1485 | } else if (wanted_type->id == TypeTableEntryIdInt && | 1484 | } else if (wanted_type->id == TypeTableEntryIdInt && |
| 1486 | actual_type->id == TypeTableEntryIdInt) | 1485 | actual_type->id == TypeTableEntryIdInt) |
| 1487 | { | 1486 | { |
| 1488 | cast_node->op = CastOpIntWidenOrShorten; | 1487 | cast->op = CastOpIntWidenOrShorten; |
| 1489 | return wanted_type; | 1488 | return wanted_type; |
| 1490 | } else if (wanted_type->id == TypeTableEntryIdStruct && | 1489 | } else if (wanted_type->id == TypeTableEntryIdStruct && |
| 1491 | wanted_type->data.structure.is_unknown_size_array && | 1490 | wanted_type->data.structure.is_unknown_size_array && |
| 1492 | actual_type->id == TypeTableEntryIdArray && | 1491 | actual_type->id == TypeTableEntryIdArray && |
| 1493 | actual_type->data.array.child_type == wanted_type->data.structure.fields[0].type_entry) | 1492 | actual_type->data.array.child_type == wanted_type->data.structure.fields[0].type_entry) |
| 1494 | { | 1493 | { |
| 1495 | cast_node->op = CastOpToUnknownSizeArray; | 1494 | cast->op = CastOpToUnknownSizeArray; |
| 1496 | context->cast_expr_alloca_list.append(cast_node); | 1495 | context->cast_expr_alloca_list.append(cast); |
| 1497 | return wanted_type; | 1496 | return wanted_type; |
| 1498 | } else if (actual_type->id == TypeTableEntryIdNumberLiteral && | 1497 | } else if (actual_type->id == TypeTableEntryIdNumberLiteral && |
| 1499 | num_lit_fits_in_other_type(g, actual_type, wanted_type)) | 1498 | num_lit_fits_in_other_type(g, actual_type, wanted_type)) |
| 1500 | { | 1499 | { |
| 1501 | AstNode *literal_node = node->data.cast_expr.expr; | 1500 | AstNode *literal_node = node->data.cast_expr.expr; |
| 1502 | assert(literal_node->codegen_node); | 1501 | NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(literal_node); |
| 1503 | NumberLiteralNode *codegen_num_lit = &literal_node->codegen_node->data.num_lit_node; | ||
| 1504 | assert(!codegen_num_lit->resolved_type); | 1502 | assert(!codegen_num_lit->resolved_type); |
| 1505 | codegen_num_lit->resolved_type = wanted_type; | 1503 | codegen_num_lit->resolved_type = wanted_type; |
| 1506 | cast_node->op = CastOpNothing; | 1504 | cast->op = CastOpNothing; |
| 1507 | return wanted_type; | 1505 | return wanted_type; |
| 1508 | } else if (actual_type->id == TypeTableEntryIdPointer && | 1506 | } else if (actual_type->id == TypeTableEntryIdPointer && |
| 1509 | wanted_type->id == TypeTableEntryIdPointer) | 1507 | wanted_type->id == TypeTableEntryIdPointer) |
| 1510 | { | 1508 | { |
| 1511 | cast_node->op = CastOpPointerReinterpret; | 1509 | cast->op = CastOpPointerReinterpret; |
| 1512 | return wanted_type; | 1510 | return wanted_type; |
| 1513 | } else { | 1511 | } else { |
| 1514 | add_node_error(g, node, | 1512 | add_node_error(g, node, |
| ... | @@ -1529,7 +1527,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc | ... | @@ -1529,7 +1527,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc |
| 1529 | { | 1527 | { |
| 1530 | TypeTableEntry *expected_rhs_type = nullptr; | 1528 | TypeTableEntry *expected_rhs_type = nullptr; |
| 1531 | if (lhs_node->type == NodeTypeSymbol) { | 1529 | if (lhs_node->type == NodeTypeSymbol) { |
| 1532 | Buf *name = &lhs_node->data.symbol; | 1530 | Buf *name = &lhs_node->data.symbol_expr.symbol; |
| 1533 | VariableTableEntry *var = find_variable(block_context, name); | 1531 | VariableTableEntry *var = find_variable(block_context, name); |
| 1534 | if (var) { | 1532 | if (var) { |
| 1535 | if (purpose == LValPurposeAssign && var->is_const) { | 1533 | if (purpose == LValPurposeAssign && var->is_const) { |
| ... | @@ -1551,7 +1549,6 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc | ... | @@ -1551,7 +1549,6 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc |
| 1551 | } else if (lhs_node->type == NodeTypeArrayAccessExpr) { | 1549 | } else if (lhs_node->type == NodeTypeArrayAccessExpr) { |
| 1552 | expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node); | 1550 | expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node); |
| 1553 | } else if (lhs_node->type == NodeTypeFieldAccessExpr) { | 1551 | } else if (lhs_node->type == NodeTypeFieldAccessExpr) { |
| 1554 | alloc_codegen_node(lhs_node); | ||
| 1555 | expected_rhs_type = analyze_field_access_expr(g, import, block_context, lhs_node); | 1552 | expected_rhs_type = analyze_field_access_expr(g, import, block_context, lhs_node); |
| 1556 | } else if (lhs_node->type == NodeTypePrefixOpExpr && | 1553 | } else if (lhs_node->type == NodeTypePrefixOpExpr && |
| 1557 | lhs_node->data.prefix_op_expr.prefix_op == PrefixOpDereference) | 1554 | lhs_node->data.prefix_op_expr.prefix_op == PrefixOpDereference) |
| ... | @@ -1774,10 +1771,9 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -1774,10 +1771,9 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i |
| 1774 | if (expected_type) { | 1771 | if (expected_type) { |
| 1775 | assert(expected_type->id == TypeTableEntryIdMaybe); | 1772 | assert(expected_type->id == TypeTableEntryIdMaybe); |
| 1776 | 1773 | ||
| 1777 | assert(node->codegen_node); | 1774 | node->data.null_literal.resolved_struct_val_expr.type_entry = expected_type; |
| 1778 | node->codegen_node->data.struct_val_expr_node.type_entry = expected_type; | 1775 | node->data.null_literal.resolved_struct_val_expr.source_node = node; |
| 1779 | node->codegen_node->data.struct_val_expr_node.source_node = node; | 1776 | block_context->struct_val_expr_alloca_list.append(&node->data.null_literal.resolved_struct_val_expr); |
| 1780 | block_context->struct_val_expr_alloca_list.append(&node->codegen_node->data.struct_val_expr_node); | ||
| 1781 | 1777 | ||
| 1782 | return expected_type; | 1778 | return expected_type; |
| 1783 | } else { | 1779 | } else { |
| ... | @@ -1796,7 +1792,7 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry | ... | @@ -1796,7 +1792,7 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry |
| 1796 | buf_sprintf("number literal too large to be represented in any type")); | 1792 | buf_sprintf("number literal too large to be represented in any type")); |
| 1797 | return g->builtin_types.entry_invalid; | 1793 | return g->builtin_types.entry_invalid; |
| 1798 | } else if (expected_type) { | 1794 | } else if (expected_type) { |
| 1799 | NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node; | 1795 | NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node); |
| 1800 | assert(!codegen_num_lit->resolved_type); | 1796 | assert(!codegen_num_lit->resolved_type); |
| 1801 | TypeTableEntry *after_implicit_cast_resolved_type = | 1797 | TypeTableEntry *after_implicit_cast_resolved_type = |
| 1802 | resolve_type_compatibility(g, block_context, node, expected_type, num_lit_type); | 1798 | resolve_type_compatibility(g, block_context, node, expected_type, num_lit_type); |
| ... | @@ -1837,10 +1833,9 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp | ... | @@ -1837,10 +1833,9 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp |
| 1837 | return g->builtin_types.entry_invalid; | 1833 | return g->builtin_types.entry_invalid; |
| 1838 | } | 1834 | } |
| 1839 | 1835 | ||
| 1840 | assert(node->codegen_node); | 1836 | node->data.struct_val_expr.codegen.type_entry = type_entry; |
| 1841 | node->codegen_node->data.struct_val_expr_node.type_entry = type_entry; | 1837 | node->data.struct_val_expr.codegen.source_node = node; |
| 1842 | node->codegen_node->data.struct_val_expr_node.source_node = node; | 1838 | context->struct_val_expr_alloca_list.append(&node->data.struct_val_expr.codegen); |
| 1843 | context->struct_val_expr_alloca_list.append(&node->codegen_node->data.struct_val_expr_node); | ||
| 1844 | 1839 | ||
| 1845 | int expr_field_count = struct_val_expr->fields.length; | 1840 | int expr_field_count = struct_val_expr->fields.length; |
| 1846 | int actual_field_count = type_entry->data.structure.field_count; | 1841 | int actual_field_count = type_entry->data.structure.field_count; |
| ... | @@ -1848,6 +1843,8 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp | ... | @@ -1848,6 +1843,8 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp |
| 1848 | int *field_use_counts = allocate<int>(actual_field_count); | 1843 | int *field_use_counts = allocate<int>(actual_field_count); |
| 1849 | for (int i = 0; i < expr_field_count; i += 1) { | 1844 | for (int i = 0; i < expr_field_count; i += 1) { |
| 1850 | AstNode *val_field_node = struct_val_expr->fields.at(i); | 1845 | AstNode *val_field_node = struct_val_expr->fields.at(i); |
| 1846 | assert(val_field_node->type == NodeTypeStructValueField); | ||
| 1847 | |||
| 1851 | int field_index; | 1848 | int field_index; |
| 1852 | TypeStructField *type_field = find_struct_type_field(type_entry, | 1849 | TypeStructField *type_field = find_struct_type_field(type_entry, |
| 1853 | &val_field_node->data.struct_val_field.name, &field_index); | 1850 | &val_field_node->data.struct_val_field.name, &field_index); |
| ... | @@ -1865,8 +1862,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp | ... | @@ -1865,8 +1862,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp |
| 1865 | continue; | 1862 | continue; |
| 1866 | } | 1863 | } |
| 1867 | 1864 | ||
| 1868 | alloc_codegen_node(val_field_node); | 1865 | val_field_node->data.struct_val_field.index = field_index; |
| 1869 | val_field_node->codegen_node->data.struct_val_field_node.index = field_index; | ||
| 1870 | 1866 | ||
| 1871 | analyze_expression(g, import, context, type_field->type_entry, | 1867 | analyze_expression(g, import, context, type_field->type_entry, |
| 1872 | val_field_node->data.struct_val_field.expr); | 1868 | val_field_node->data.struct_val_field.expr); |
| ... | @@ -1885,6 +1881,8 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp | ... | @@ -1885,6 +1881,8 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp |
| 1885 | static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1881 | static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1886 | TypeTableEntry *expected_type, AstNode *node) | 1882 | TypeTableEntry *expected_type, AstNode *node) |
| 1887 | { | 1883 | { |
| 1884 | assert(node->type == NodeTypeWhileExpr); | ||
| 1885 | |||
| 1888 | AstNode *condition_node = node->data.while_expr.condition; | 1886 | AstNode *condition_node = node->data.while_expr.condition; |
| 1889 | AstNode *while_body_node = node->data.while_expr.body; | 1887 | AstNode *while_body_node = node->data.while_expr.body; |
| 1890 | TypeTableEntry *condition_type = analyze_expression(g, import, context, | 1888 | TypeTableEntry *condition_type = analyze_expression(g, import, context, |
| ... | @@ -1907,8 +1905,8 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1907,8 +1905,8 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, |
| 1907 | assert(resolved_type->id == TypeTableEntryIdBool); | 1905 | assert(resolved_type->id == TypeTableEntryIdBool); |
| 1908 | bool constant_cond_value = number_literal.data.x_uint; | 1906 | bool constant_cond_value = number_literal.data.x_uint; |
| 1909 | if (constant_cond_value) { | 1907 | if (constant_cond_value) { |
| 1910 | node->codegen_node->data.while_node.condition_always_true = true; | 1908 | node->data.while_expr.condition_always_true = true; |
| 1911 | if (!node->codegen_node->data.while_node.contains_break) { | 1909 | if (!node->data.while_expr.contains_break) { |
| 1912 | expr_return_type = g->builtin_types.entry_unreachable; | 1910 | expr_return_type = g->builtin_types.entry_unreachable; |
| 1913 | } | 1911 | } |
| 1914 | } | 1912 | } |
| ... | @@ -1921,12 +1919,14 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1921,12 +1919,14 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, |
| 1921 | static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1919 | static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1922 | TypeTableEntry *expected_type, AstNode *node) | 1920 | TypeTableEntry *expected_type, AstNode *node) |
| 1923 | { | 1921 | { |
| 1922 | assert(node->type == NodeTypeBreak); | ||
| 1923 | |||
| 1924 | AstNode *loop_node = context->parent_loop_node; | 1924 | AstNode *loop_node = context->parent_loop_node; |
| 1925 | if (loop_node) { | 1925 | if (loop_node) { |
| 1926 | loop_node->codegen_node->data.while_node.contains_break = true; | 1926 | assert(loop_node->type == NodeTypeWhileExpr); |
| 1927 | loop_node->data.while_expr.contains_break = true; | ||
| 1927 | } else { | 1928 | } else { |
| 1928 | add_node_error(g, node, | 1929 | add_node_error(g, node, buf_sprintf("'break' expression outside loop")); |
| 1929 | buf_sprintf("'break' expression outside loop")); | ||
| 1930 | } | 1930 | } |
| 1931 | return g->builtin_types.entry_unreachable; | 1931 | return g->builtin_types.entry_unreachable; |
| 1932 | } | 1932 | } |
| ... | @@ -1935,8 +1935,7 @@ static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *impor | ... | @@ -1935,8 +1935,7 @@ static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *impor |
| 1935 | TypeTableEntry *expected_type, AstNode *node) | 1935 | TypeTableEntry *expected_type, AstNode *node) |
| 1936 | { | 1936 | { |
| 1937 | if (!context->parent_loop_node) { | 1937 | if (!context->parent_loop_node) { |
| 1938 | add_node_error(g, node, | 1938 | add_node_error(g, node, buf_sprintf("'continue' expression outside loop")); |
| 1939 | buf_sprintf("'continue' expression outside loop")); | ||
| 1940 | } | 1939 | } |
| 1941 | return g->builtin_types.entry_unreachable; | 1940 | return g->builtin_types.entry_unreachable; |
| 1942 | } | 1941 | } |
| ... | @@ -1981,7 +1980,7 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1981,7 +1980,7 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, |
| 1981 | assert(node->type == NodeTypeIfVarExpr); | 1980 | assert(node->type == NodeTypeIfVarExpr); |
| 1982 | 1981 | ||
| 1983 | BlockContext *child_context = new_block_context(node, context); | 1982 | BlockContext *child_context = new_block_context(node, context); |
| 1984 | node->codegen_node->data.if_var_node.block_context = child_context; | 1983 | node->data.if_var_expr.block_context = child_context; |
| 1985 | 1984 | ||
| 1986 | analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true); | 1985 | analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true); |
| 1987 | 1986 | ||
| ... | @@ -2032,8 +2031,10 @@ static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *im | ... | @@ -2032,8 +2031,10 @@ static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *im |
| 2032 | static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 2031 | static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 2033 | TypeTableEntry *expected_type, AstNode *node) | 2032 | TypeTableEntry *expected_type, AstNode *node) |
| 2034 | { | 2033 | { |
| 2034 | assert(node->type == NodeTypeFnCallExpr); | ||
| 2035 | |||
| 2035 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | 2036 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; |
| 2036 | Buf *name = &fn_ref_expr->data.symbol; | 2037 | Buf *name = &fn_ref_expr->data.symbol_expr.symbol; |
| 2037 | 2038 | ||
| 2038 | auto entry = g->builtin_fn_table.maybe_get(name); | 2039 | auto entry = g->builtin_fn_table.maybe_get(name); |
| 2039 | 2040 | ||
| ... | @@ -2041,8 +2042,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry | ... | @@ -2041,8 +2042,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 2041 | BuiltinFnEntry *builtin_fn = entry->value; | 2042 | BuiltinFnEntry *builtin_fn = entry->value; |
| 2042 | int actual_param_count = node->data.fn_call_expr.params.length; | 2043 | int actual_param_count = node->data.fn_call_expr.params.length; |
| 2043 | 2044 | ||
| 2044 | assert(node->codegen_node); | 2045 | node->data.fn_call_expr.builtin_fn = builtin_fn; |
| 2045 | node->codegen_node->data.fn_call_node.builtin_fn = builtin_fn; | ||
| 2046 | 2046 | ||
| 2047 | if (builtin_fn->param_count != actual_param_count) { | 2047 | if (builtin_fn->param_count != actual_param_count) { |
| 2048 | add_node_error(g, node, | 2048 | add_node_error(g, node, |
| ... | @@ -2155,7 +2155,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import | ... | @@ -2155,7 +2155,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 2155 | if (node->data.fn_call_expr.is_builtin) { | 2155 | if (node->data.fn_call_expr.is_builtin) { |
| 2156 | return analyze_builtin_fn_call_expr(g, import, context, expected_type, node); | 2156 | return analyze_builtin_fn_call_expr(g, import, context, expected_type, node); |
| 2157 | } | 2157 | } |
| 2158 | name = &fn_ref_expr->data.symbol; | 2158 | name = &fn_ref_expr->data.symbol_expr.symbol; |
| 2159 | } else { | 2159 | } else { |
| 2160 | add_node_error(g, node, | 2160 | add_node_error(g, node, |
| 2161 | buf_sprintf("function pointers not yet supported")); | 2161 | buf_sprintf("function pointers not yet supported")); |
| ... | @@ -2210,13 +2210,15 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import | ... | @@ -2210,13 +2210,15 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 2210 | AstNode *param_decl_node = fn_proto->params.at(fn_proto_i); | 2210 | AstNode *param_decl_node = fn_proto->params.at(fn_proto_i); |
| 2211 | assert(param_decl_node->type == NodeTypeParamDecl); | 2211 | assert(param_decl_node->type == NodeTypeParamDecl); |
| 2212 | AstNode *param_type_node = param_decl_node->data.param_decl.type; | 2212 | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 2213 | if (param_type_node->codegen_node) | 2213 | assert(param_type_node->type == NodeTypeType); |
| 2214 | expected_param_type = param_type_node->codegen_node->data.type_node.entry; | 2214 | if (param_type_node->data.type.entry) { |
| 2215 | expected_param_type = param_type_node->data.type.entry; | ||
| 2216 | } | ||
| 2215 | } | 2217 | } |
| 2216 | analyze_expression(g, import, context, expected_param_type, child); | 2218 | analyze_expression(g, import, context, expected_param_type, child); |
| 2217 | } | 2219 | } |
| 2218 | 2220 | ||
| 2219 | return fn_proto->return_type->codegen_node->data.type_node.entry; | 2221 | return fn_proto->return_type->data.type.entry; |
| 2220 | } | 2222 | } |
| 2221 | } | 2223 | } |
| 2222 | 2224 | ||
| ... | @@ -2224,18 +2226,17 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -2224,18 +2226,17 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2224 | TypeTableEntry *expected_type, AstNode *node) | 2226 | TypeTableEntry *expected_type, AstNode *node) |
| 2225 | { | 2227 | { |
| 2226 | TypeTableEntry *return_type = nullptr; | 2228 | TypeTableEntry *return_type = nullptr; |
| 2227 | alloc_codegen_node(node); | ||
| 2228 | switch (node->type) { | 2229 | switch (node->type) { |
| 2229 | case NodeTypeBlock: | 2230 | case NodeTypeBlock: |
| 2230 | { | 2231 | { |
| 2231 | BlockContext *child_context = new_block_context(node, context); | 2232 | BlockContext *child_context = new_block_context(node, context); |
| 2232 | node->codegen_node->data.block_node.block_context = child_context; | 2233 | node->data.block.block_context = child_context; |
| 2233 | return_type = g->builtin_types.entry_void; | 2234 | return_type = g->builtin_types.entry_void; |
| 2234 | 2235 | ||
| 2235 | for (int i = 0; i < node->data.block.statements.length; i += 1) { | 2236 | for (int i = 0; i < node->data.block.statements.length; i += 1) { |
| 2236 | AstNode *child = node->data.block.statements.at(i); | 2237 | AstNode *child = node->data.block.statements.at(i); |
| 2237 | if (child->type == NodeTypeLabel) { | 2238 | if (child->type == NodeTypeLabel) { |
| 2238 | LabelTableEntry *label_entry = child->codegen_node->data.label_entry; | 2239 | LabelTableEntry *label_entry = child->data.label.label_entry; |
| 2239 | assert(label_entry); | 2240 | assert(label_entry); |
| 2240 | label_entry->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable); | 2241 | label_entry->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable); |
| 2241 | return_type = g->builtin_types.entry_void; | 2242 | return_type = g->builtin_types.entry_void; |
| ... | @@ -2288,13 +2289,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -2288,13 +2289,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2288 | case NodeTypeGoto: | 2289 | case NodeTypeGoto: |
| 2289 | { | 2290 | { |
| 2290 | FnTableEntry *fn_table_entry = get_context_fn_entry(context); | 2291 | FnTableEntry *fn_table_entry = get_context_fn_entry(context); |
| 2291 | auto table_entry = fn_table_entry->label_table.maybe_get(&node->data.go_to.name); | 2292 | auto table_entry = fn_table_entry->label_table.maybe_get(&node->data.goto_expr.name); |
| 2292 | if (table_entry) { | 2293 | if (table_entry) { |
| 2293 | node->codegen_node->data.label_entry = table_entry->value; | 2294 | node->data.goto_expr.label_entry = table_entry->value; |
| 2294 | table_entry->value->used = true; | 2295 | table_entry->value->used = true; |
| 2295 | } else { | 2296 | } else { |
| 2296 | add_node_error(g, node, | 2297 | add_node_error(g, node, |
| 2297 | buf_sprintf("use of undeclared label '%s'", buf_ptr(&node->data.go_to.name))); | 2298 | buf_sprintf("use of undeclared label '%s'", buf_ptr(&node->data.goto_expr.name))); |
| 2298 | } | 2299 | } |
| 2299 | return_type = g->builtin_types.entry_unreachable; | 2300 | return_type = g->builtin_types.entry_unreachable; |
| 2300 | break; | 2301 | break; |
| ... | @@ -2380,7 +2381,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -2380,7 +2381,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2380 | 2381 | ||
| 2381 | case NodeTypeSymbol: | 2382 | case NodeTypeSymbol: |
| 2382 | { | 2383 | { |
| 2383 | return_type = analyze_variable_name(g, import, context, node, &node->data.symbol); | 2384 | return_type = analyze_variable_name(g, import, context, node, &node->data.symbol_expr.symbol); |
| 2384 | break; | 2385 | break; |
| 2385 | } | 2386 | } |
| 2386 | case NodeTypeCastExpr: | 2387 | case NodeTypeCastExpr: |
| ... | @@ -2507,8 +2508,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -2507,8 +2508,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2507 | assert(return_type); | 2508 | assert(return_type); |
| 2508 | resolve_type_compatibility(g, context, node, expected_type, return_type); | 2509 | resolve_type_compatibility(g, context, node, expected_type, return_type); |
| 2509 | 2510 | ||
| 2510 | node->codegen_node->expr_node.type_entry = return_type; | 2511 | get_resolved_expr(node)->type_entry = return_type; |
| 2511 | node->codegen_node->expr_node.block_context = context; | 2512 | get_resolved_expr(node)->block_context = context; |
| 2512 | 2513 | ||
| 2513 | return return_type; | 2514 | return return_type; |
| 2514 | } | 2515 | } |
| ... | @@ -2519,15 +2520,14 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo | ... | @@ -2519,15 +2520,14 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo |
| 2519 | AstNode *fn_proto_node = node->data.fn_def.fn_proto; | 2520 | AstNode *fn_proto_node = node->data.fn_def.fn_proto; |
| 2520 | assert(fn_proto_node->type == NodeTypeFnProto); | 2521 | assert(fn_proto_node->type == NodeTypeFnProto); |
| 2521 | 2522 | ||
| 2522 | if (fn_proto_node->codegen_node->data.fn_proto_node.skip) { | 2523 | if (fn_proto_node->data.fn_proto.skip) { |
| 2523 | // we detected an error with this function definition which prevents us | 2524 | // we detected an error with this function definition which prevents us |
| 2524 | // from further analyzing it. | 2525 | // from further analyzing it. |
| 2525 | return; | 2526 | return; |
| 2526 | } | 2527 | } |
| 2527 | 2528 | ||
| 2528 | alloc_codegen_node(node); | ||
| 2529 | BlockContext *context = new_block_context(node, import->block_context); | 2529 | BlockContext *context = new_block_context(node, import->block_context); |
| 2530 | node->codegen_node->data.fn_def_node.block_context = context; | 2530 | node->data.fn_def.block_context = context; |
| 2531 | 2531 | ||
| 2532 | AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto; | 2532 | AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto; |
| 2533 | bool is_exported = (fn_proto->visib_mod == VisibModExport); | 2533 | bool is_exported = (fn_proto->visib_mod == VisibModExport); |
| ... | @@ -2538,7 +2538,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo | ... | @@ -2538,7 +2538,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo |
| 2538 | // define local variables for parameters | 2538 | // define local variables for parameters |
| 2539 | AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl; | 2539 | AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl; |
| 2540 | assert(param_decl->type->type == NodeTypeType); | 2540 | assert(param_decl->type->type == NodeTypeType); |
| 2541 | TypeTableEntry *type = param_decl->type->codegen_node->data.type_node.entry; | 2541 | TypeTableEntry *type = param_decl->type->data.type.entry; |
| 2542 | 2542 | ||
| 2543 | if (is_exported && type->id == TypeTableEntryIdStruct) { | 2543 | if (is_exported && type->id == TypeTableEntryIdStruct) { |
| 2544 | add_node_error(g, param_decl_node, | 2544 | add_node_error(g, param_decl_node, |
| ... | @@ -2552,8 +2552,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo | ... | @@ -2552,8 +2552,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo |
| 2552 | variable_entry->decl_node = param_decl_node; | 2552 | variable_entry->decl_node = param_decl_node; |
| 2553 | variable_entry->arg_index = i; | 2553 | variable_entry->arg_index = i; |
| 2554 | 2554 | ||
| 2555 | alloc_codegen_node(param_decl_node); | 2555 | param_decl_node->data.param_decl.variable = variable_entry; |
| 2556 | param_decl_node->codegen_node->data.param_decl_node.variable = variable_entry; | ||
| 2557 | 2556 | ||
| 2558 | VariableTableEntry *existing_entry = find_local_variable(context, &variable_entry->name); | 2557 | VariableTableEntry *existing_entry = find_local_variable(context, &variable_entry->name); |
| 2559 | if (!existing_entry) { | 2558 | if (!existing_entry) { |
| ... | @@ -2571,13 +2570,13 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo | ... | @@ -2571,13 +2570,13 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo |
| 2571 | } | 2570 | } |
| 2572 | } | 2571 | } |
| 2573 | 2572 | ||
| 2574 | TypeTableEntry *expected_type = fn_proto->return_type->codegen_node->data.type_node.entry; | 2573 | TypeTableEntry *expected_type = fn_proto->return_type->data.type.entry; |
| 2575 | TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body); | 2574 | TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body); |
| 2576 | 2575 | ||
| 2577 | node->codegen_node->data.fn_def_node.implicit_return_type = block_return_type; | 2576 | node->data.fn_def.implicit_return_type = block_return_type; |
| 2578 | 2577 | ||
| 2579 | { | 2578 | { |
| 2580 | FnTableEntry *fn_table_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry; | 2579 | FnTableEntry *fn_table_entry = fn_proto_node->data.fn_proto.fn_table_entry; |
| 2581 | auto it = fn_table_entry->label_table.entry_iterator(); | 2580 | auto it = fn_table_entry->label_table.entry_iterator(); |
| 2582 | for (;;) { | 2581 | for (;;) { |
| 2583 | auto *entry = it.next(); | 2582 | auto *entry = it.next(); |
| ... | @@ -2656,7 +2655,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -2656,7 +2655,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 2656 | } | 2655 | } |
| 2657 | 2656 | ||
| 2658 | static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *expr_node, | 2657 | static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *expr_node, |
| 2659 | DeclNode *decl_node) | 2658 | TopLevelDecl *decl_node) |
| 2660 | { | 2659 | { |
| 2661 | switch (expr_node->type) { | 2660 | switch (expr_node->type) { |
| 2662 | case NodeTypeNumberLiteral: | 2661 | case NodeTypeNumberLiteral: |
| ... | @@ -2672,7 +2671,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -2672,7 +2671,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode |
| 2672 | // no dependencies on other top level declarations | 2671 | // no dependencies on other top level declarations |
| 2673 | break; | 2672 | break; |
| 2674 | case NodeTypeSymbol: | 2673 | case NodeTypeSymbol: |
| 2675 | decl_node->deps.put(&expr_node->data.symbol, expr_node); | 2674 | decl_node->deps.put(&expr_node->data.symbol_expr.symbol, expr_node); |
| 2676 | break; | 2675 | break; |
| 2677 | case NodeTypeBinOpExpr: | 2676 | case NodeTypeBinOpExpr: |
| 2678 | collect_expr_decl_deps(g, import, expr_node->data.bin_op_expr.op1, decl_node); | 2677 | collect_expr_decl_deps(g, import, expr_node->data.bin_op_expr.op1, decl_node); |
| ... | @@ -2787,7 +2786,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -2787,7 +2786,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode |
| 2787 | } | 2786 | } |
| 2788 | } | 2787 | } |
| 2789 | 2788 | ||
| 2790 | static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, DeclNode *decl_node) { | 2789 | static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, TopLevelDecl *decl_node) { |
| 2791 | assert(type_node->type == NodeTypeType); | 2790 | assert(type_node->type == NodeTypeType); |
| 2792 | switch (type_node->data.type.type) { | 2791 | switch (type_node->data.type.type) { |
| 2793 | case AstNodeTypeTypePrimitive: | 2792 | case AstNodeTypeTypePrimitive: |
| ... | @@ -2824,16 +2823,13 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2824,16 +2823,13 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2824 | switch (node->type) { | 2823 | switch (node->type) { |
| 2825 | case NodeTypeStructDecl: | 2824 | case NodeTypeStructDecl: |
| 2826 | { | 2825 | { |
| 2827 | alloc_codegen_node(node); | ||
| 2828 | StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node; | ||
| 2829 | |||
| 2830 | Buf *name = &node->data.struct_decl.name; | 2826 | Buf *name = &node->data.struct_decl.name; |
| 2831 | auto table_entry = g->primitive_type_table.maybe_get(name); | 2827 | auto table_entry = g->primitive_type_table.maybe_get(name); |
| 2832 | if (!table_entry) { | 2828 | if (!table_entry) { |
| 2833 | table_entry = import->type_table.maybe_get(name); | 2829 | table_entry = import->type_table.maybe_get(name); |
| 2834 | } | 2830 | } |
| 2835 | if (table_entry) { | 2831 | if (table_entry) { |
| 2836 | struct_codegen->type_entry = table_entry->value; | 2832 | node->data.struct_decl.type_entry = table_entry->value; |
| 2837 | add_node_error(g, node, | 2833 | add_node_error(g, node, |
| 2838 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); | 2834 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 2839 | } else { | 2835 | } else { |
| ... | @@ -2848,7 +2844,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2848,7 +2844,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2848 | // put off adding the debug type until we do the full struct body | 2844 | // put off adding the debug type until we do the full struct body |
| 2849 | // this type is incomplete until we do another pass | 2845 | // this type is incomplete until we do another pass |
| 2850 | import->type_table.put(&entry->name, entry); | 2846 | import->type_table.put(&entry->name, entry); |
| 2851 | struct_codegen->type_entry = entry; | 2847 | node->data.struct_decl.type_entry = entry; |
| 2852 | 2848 | ||
| 2853 | bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate); | 2849 | bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate); |
| 2854 | if (is_pub) { | 2850 | if (is_pub) { |
| ... | @@ -2867,14 +2863,15 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2867,14 +2863,15 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2867 | } | 2863 | } |
| 2868 | 2864 | ||
| 2869 | // determine which other top level declarations this struct depends on. | 2865 | // determine which other top level declarations this struct depends on. |
| 2870 | DeclNode *decl_node = &node->codegen_node->decl_node; | 2866 | TopLevelDecl *decl_node = &node->data.struct_decl.top_level_decl; |
| 2867 | decl_node->deps.init(1); | ||
| 2871 | for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) { | 2868 | for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) { |
| 2872 | AstNode *field_node = node->data.struct_decl.fields.at(i); | 2869 | AstNode *field_node = node->data.struct_decl.fields.at(i); |
| 2873 | AstNode *type_node = field_node->data.struct_field.type; | 2870 | AstNode *type_node = field_node->data.struct_field.type; |
| 2874 | collect_type_decl_deps(g, import, type_node, decl_node); | 2871 | collect_type_decl_deps(g, import, type_node, decl_node); |
| 2875 | } | 2872 | } |
| 2876 | node->codegen_node->decl_node.name = name; | 2873 | decl_node->name = name; |
| 2877 | node->codegen_node->decl_node.import = import; | 2874 | decl_node->import = import; |
| 2878 | if (decl_node->deps.size() > 0) { | 2875 | if (decl_node->deps.size() > 0) { |
| 2879 | g->unresolved_top_level_decls.put(name, node); | 2876 | g->unresolved_top_level_decls.put(name, node); |
| 2880 | } else { | 2877 | } else { |
| ... | @@ -2913,8 +2910,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2913,8 +2910,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2913 | case NodeTypeVariableDeclaration: | 2910 | case NodeTypeVariableDeclaration: |
| 2914 | { | 2911 | { |
| 2915 | // determine which other top level declarations this variable declaration depends on. | 2912 | // determine which other top level declarations this variable declaration depends on. |
| 2916 | alloc_codegen_node(node); | 2913 | TopLevelDecl *decl_node = &node->data.variable_declaration.top_level_decl; |
| 2917 | DeclNode *decl_node = &node->codegen_node->decl_node; | 2914 | decl_node->deps.init(1); |
| 2918 | if (node->data.variable_declaration.type) { | 2915 | if (node->data.variable_declaration.type) { |
| 2919 | collect_type_decl_deps(g, import, node->data.variable_declaration.type, decl_node); | 2916 | collect_type_decl_deps(g, import, node->data.variable_declaration.type, decl_node); |
| 2920 | } | 2917 | } |
| ... | @@ -2922,8 +2919,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2922,8 +2919,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2922 | collect_expr_decl_deps(g, import, node->data.variable_declaration.expr, decl_node); | 2919 | collect_expr_decl_deps(g, import, node->data.variable_declaration.expr, decl_node); |
| 2923 | } | 2920 | } |
| 2924 | Buf *name = &node->data.variable_declaration.symbol; | 2921 | Buf *name = &node->data.variable_declaration.symbol; |
| 2925 | node->codegen_node->decl_node.name = name; | 2922 | decl_node->name = name; |
| 2926 | node->codegen_node->decl_node.import = import; | 2923 | decl_node->import = import; |
| 2927 | if (decl_node->deps.size() > 0) { | 2924 | if (decl_node->deps.size() > 0) { |
| 2928 | g->unresolved_top_level_decls.put(name, node); | 2925 | g->unresolved_top_level_decls.put(name, node); |
| 2929 | } else { | 2926 | } else { |
| ... | @@ -2934,8 +2931,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2934,8 +2931,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2934 | case NodeTypeFnProto: | 2931 | case NodeTypeFnProto: |
| 2935 | { | 2932 | { |
| 2936 | // determine which other top level declarations this function prototype depends on. | 2933 | // determine which other top level declarations this function prototype depends on. |
| 2937 | alloc_codegen_node(node); | 2934 | TopLevelDecl *decl_node = &node->data.fn_proto.top_level_decl; |
| 2938 | DeclNode *decl_node = &node->codegen_node->decl_node; | 2935 | decl_node->deps.init(1); |
| 2939 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { | 2936 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { |
| 2940 | AstNode *param_node = node->data.fn_proto.params.at(i); | 2937 | AstNode *param_node = node->data.fn_proto.params.at(i); |
| 2941 | assert(param_node->type == NodeTypeParamDecl); | 2938 | assert(param_node->type == NodeTypeParamDecl); |
| ... | @@ -2943,8 +2940,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2943,8 +2940,8 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2943 | } | 2940 | } |
| 2944 | 2941 | ||
| 2945 | Buf *name = &node->data.fn_proto.name; | 2942 | Buf *name = &node->data.fn_proto.name; |
| 2946 | node->codegen_node->decl_node.name = name; | 2943 | decl_node->name = name; |
| 2947 | node->codegen_node->decl_node.import = import; | 2944 | decl_node->import = import; |
| 2948 | if (decl_node->deps.size() > 0) { | 2945 | if (decl_node->deps.size() > 0) { |
| 2949 | g->unresolved_top_level_decls.put(name, node); | 2946 | g->unresolved_top_level_decls.put(name, node); |
| 2950 | } else { | 2947 | } else { |
| ... | @@ -2999,7 +2996,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2999,7 +2996,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2999 | } | 2996 | } |
| 3000 | 2997 | ||
| 3001 | static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { | 2998 | static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 3002 | auto it = node->codegen_node->decl_node.deps.entry_iterator(); | 2999 | auto it = get_resolved_top_level_decl(node)->deps.entry_iterator(); |
| 3003 | for (;;) { | 3000 | for (;;) { |
| 3004 | auto *entry = it.next(); | 3001 | auto *entry = it.next(); |
| 3005 | if (!entry) | 3002 | if (!entry) |
| ... | @@ -3012,23 +3009,24 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -3012,23 +3009,24 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 3012 | 3009 | ||
| 3013 | AstNode *child_node = unresolved_entry->value; | 3010 | AstNode *child_node = unresolved_entry->value; |
| 3014 | 3011 | ||
| 3015 | if (child_node->codegen_node->decl_node.in_current_deps) { | 3012 | if (get_resolved_top_level_decl(child_node)->in_current_deps) { |
| 3016 | // dependency loop. we'll let the fact that it's not in the respective | 3013 | // dependency loop. we'll let the fact that it's not in the respective |
| 3017 | // table cause an error in resolve_top_level_decl. | 3014 | // table cause an error in resolve_top_level_decl. |
| 3018 | continue; | 3015 | continue; |
| 3019 | } | 3016 | } |
| 3020 | 3017 | ||
| 3021 | // set temporary flag | 3018 | // set temporary flag |
| 3022 | child_node->codegen_node->decl_node.in_current_deps = true; | 3019 | TopLevelDecl *top_level_decl = get_resolved_top_level_decl(child_node); |
| 3020 | top_level_decl->in_current_deps = true; | ||
| 3023 | 3021 | ||
| 3024 | recursive_resolve_decl(g, child_node->codegen_node->decl_node.import, child_node); | 3022 | recursive_resolve_decl(g, top_level_decl->import, child_node); |
| 3025 | 3023 | ||
| 3026 | // unset temporary flag | 3024 | // unset temporary flag |
| 3027 | child_node->codegen_node->decl_node.in_current_deps = false; | 3025 | top_level_decl->in_current_deps = false; |
| 3028 | } | 3026 | } |
| 3029 | 3027 | ||
| 3030 | resolve_top_level_decl(g, import, node); | 3028 | resolve_top_level_decl(g, import, node); |
| 3031 | g->unresolved_top_level_decls.remove(node->codegen_node->decl_node.name); | 3029 | g->unresolved_top_level_decls.remove(get_resolved_top_level_decl(node)->name); |
| 3032 | } | 3030 | } |
| 3033 | 3031 | ||
| 3034 | static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { | 3032 | static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| ... | @@ -3051,12 +3049,13 @@ static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *im | ... | @@ -3051,12 +3049,13 @@ static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *im |
| 3051 | 3049 | ||
| 3052 | } | 3050 | } |
| 3053 | // set temporary flag | 3051 | // set temporary flag |
| 3054 | decl_node->codegen_node->decl_node.in_current_deps = true; | 3052 | TopLevelDecl *top_level_decl = get_resolved_top_level_decl(decl_node); |
| 3053 | top_level_decl->in_current_deps = true; | ||
| 3055 | 3054 | ||
| 3056 | recursive_resolve_decl(g, decl_node->codegen_node->decl_node.import, decl_node); | 3055 | recursive_resolve_decl(g, top_level_decl->import, decl_node); |
| 3057 | 3056 | ||
| 3058 | // unset temporary flag | 3057 | // unset temporary flag |
| 3059 | decl_node->codegen_node->decl_node.in_current_deps = false; | 3058 | top_level_decl->in_current_deps = false; |
| 3060 | } | 3059 | } |
| 3061 | } | 3060 | } |
| 3062 | 3061 | ||
| ... | @@ -3089,7 +3088,7 @@ void semantic_analyze(CodeGen *g) { | ... | @@ -3089,7 +3088,7 @@ void semantic_analyze(CodeGen *g) { |
| 3089 | buf_sprintf("invalid directive: '%s'", buf_ptr(name))); | 3088 | buf_sprintf("invalid directive: '%s'", buf_ptr(name))); |
| 3090 | } | 3089 | } |
| 3091 | 3090 | ||
| 3092 | ImportTableEntry *target_import = child->codegen_node->data.import_node.import; | 3091 | ImportTableEntry *target_import = child->data.use.import; |
| 3093 | assert(target_import); | 3092 | assert(target_import); |
| 3094 | 3093 | ||
| 3095 | target_import->importers.append({import, child}); | 3094 | target_import->importers.append({import, child}); |
| ... | @@ -3144,9 +3143,186 @@ void semantic_analyze(CodeGen *g) { | ... | @@ -3144,9 +3143,186 @@ void semantic_analyze(CodeGen *g) { |
| 3144 | } | 3143 | } |
| 3145 | } | 3144 | } |
| 3146 | 3145 | ||
| 3147 | void alloc_codegen_node(AstNode *node) { | 3146 | Expr *get_resolved_expr(AstNode *node) { |
| 3148 | assert(!node->codegen_node); | 3147 | switch (node->type) { |
| 3149 | node->codegen_node = allocate<CodeGenNode>(1); | 3148 | case NodeTypeReturnExpr: |
| 3150 | node->codegen_node->decl_node.deps.init(1); | 3149 | return &node->data.return_expr.resolved_expr; |
| 3150 | case NodeTypeBinOpExpr: | ||
| 3151 | return &node->data.bin_op_expr.resolved_expr; | ||
| 3152 | case NodeTypeCastExpr: | ||
| 3153 | return &node->data.cast_expr.resolved_expr; | ||
| 3154 | case NodeTypePrefixOpExpr: | ||
| 3155 | return &node->data.prefix_op_expr.resolved_expr; | ||
| 3156 | case NodeTypeFnCallExpr: | ||
| 3157 | return &node->data.fn_call_expr.resolved_expr; | ||
| 3158 | case NodeTypeArrayAccessExpr: | ||
| 3159 | return &node->data.array_access_expr.resolved_expr; | ||
| 3160 | case NodeTypeSliceExpr: | ||
| 3161 | return &node->data.slice_expr.resolved_expr; | ||
| 3162 | case NodeTypeFieldAccessExpr: | ||
| 3163 | return &node->data.field_access_expr.resolved_expr; | ||
| 3164 | case NodeTypeIfBoolExpr: | ||
| 3165 | return &node->data.if_bool_expr.resolved_expr; | ||
| 3166 | case NodeTypeIfVarExpr: | ||
| 3167 | return &node->data.if_var_expr.resolved_expr; | ||
| 3168 | case NodeTypeWhileExpr: | ||
| 3169 | return &node->data.while_expr.resolved_expr; | ||
| 3170 | case NodeTypeAsmExpr: | ||
| 3171 | return &node->data.asm_expr.resolved_expr; | ||
| 3172 | case NodeTypeStructValueExpr: | ||
| 3173 | return &node->data.struct_val_expr.resolved_expr; | ||
| 3174 | case NodeTypeNumberLiteral: | ||
| 3175 | return &node->data.number_literal.resolved_expr; | ||
| 3176 | case NodeTypeStringLiteral: | ||
| 3177 | return &node->data.string_literal.resolved_expr; | ||
| 3178 | case NodeTypeBlock: | ||
| 3179 | return &node->data.block.resolved_expr; | ||
| 3180 | case NodeTypeVoid: | ||
| 3181 | return &node->data.void_expr.resolved_expr; | ||
| 3182 | case NodeTypeUnreachable: | ||
| 3183 | return &node->data.unreachable_expr.resolved_expr; | ||
| 3184 | case NodeTypeSymbol: | ||
| 3185 | return &node->data.symbol_expr.resolved_expr; | ||
| 3186 | case NodeTypeVariableDeclaration: | ||
| 3187 | return &node->data.variable_declaration.resolved_expr; | ||
| 3188 | case NodeTypeCharLiteral: | ||
| 3189 | return &node->data.char_literal.resolved_expr; | ||
| 3190 | case NodeTypeBoolLiteral: | ||
| 3191 | return &node->data.bool_literal.resolved_expr; | ||
| 3192 | case NodeTypeNullLiteral: | ||
| 3193 | return &node->data.null_literal.resolved_expr; | ||
| 3194 | case NodeTypeGoto: | ||
| 3195 | return &node->data.goto_expr.resolved_expr; | ||
| 3196 | case NodeTypeBreak: | ||
| 3197 | return &node->data.break_expr.resolved_expr; | ||
| 3198 | case NodeTypeContinue: | ||
| 3199 | return &node->data.continue_expr.resolved_expr; | ||
| 3200 | case NodeTypeCompilerFnExpr: | ||
| 3201 | return &node->data.compiler_fn_expr.resolved_expr; | ||
| 3202 | case NodeTypeCompilerFnType: | ||
| 3203 | return &node->data.compiler_fn_type.resolved_expr; | ||
| 3204 | case NodeTypeLabel: | ||
| 3205 | return &node->data.label.resolved_expr; | ||
| 3206 | case NodeTypeRoot: | ||
| 3207 | case NodeTypeRootExportDecl: | ||
| 3208 | case NodeTypeFnProto: | ||
| 3209 | case NodeTypeFnDef: | ||
| 3210 | case NodeTypeFnDecl: | ||
| 3211 | case NodeTypeParamDecl: | ||
| 3212 | case NodeTypeType: | ||
| 3213 | case NodeTypeExternBlock: | ||
| 3214 | case NodeTypeDirective: | ||
| 3215 | case NodeTypeUse: | ||
| 3216 | case NodeTypeStructDecl: | ||
| 3217 | case NodeTypeStructField: | ||
| 3218 | case NodeTypeStructValueField: | ||
| 3219 | case NodeTypeEnumDecl: | ||
| 3220 | case NodeTypeEnumField: | ||
| 3221 | zig_unreachable(); | ||
| 3222 | } | ||
| 3223 | } | ||
| 3224 | |||
| 3225 | NumLitCodeGen *get_resolved_num_lit(AstNode *node) { | ||
| 3226 | switch (node->type) { | ||
| 3227 | case NodeTypeNumberLiteral: | ||
| 3228 | return &node->data.number_literal.codegen; | ||
| 3229 | case NodeTypeCompilerFnType: | ||
| 3230 | return &node->data.compiler_fn_type.resolved_num_lit; | ||
| 3231 | case NodeTypeReturnExpr: | ||
| 3232 | case NodeTypeBinOpExpr: | ||
| 3233 | case NodeTypeCastExpr: | ||
| 3234 | case NodeTypePrefixOpExpr: | ||
| 3235 | case NodeTypeFnCallExpr: | ||
| 3236 | case NodeTypeArrayAccessExpr: | ||
| 3237 | case NodeTypeSliceExpr: | ||
| 3238 | case NodeTypeFieldAccessExpr: | ||
| 3239 | case NodeTypeIfBoolExpr: | ||
| 3240 | case NodeTypeIfVarExpr: | ||
| 3241 | case NodeTypeWhileExpr: | ||
| 3242 | case NodeTypeAsmExpr: | ||
| 3243 | case NodeTypeStructValueExpr: | ||
| 3244 | case NodeTypeRoot: | ||
| 3245 | case NodeTypeRootExportDecl: | ||
| 3246 | case NodeTypeFnProto: | ||
| 3247 | case NodeTypeFnDef: | ||
| 3248 | case NodeTypeFnDecl: | ||
| 3249 | case NodeTypeParamDecl: | ||
| 3250 | case NodeTypeType: | ||
| 3251 | case NodeTypeBlock: | ||
| 3252 | case NodeTypeExternBlock: | ||
| 3253 | case NodeTypeDirective: | ||
| 3254 | case NodeTypeVariableDeclaration: | ||
| 3255 | case NodeTypeStringLiteral: | ||
| 3256 | case NodeTypeCharLiteral: | ||
| 3257 | case NodeTypeUnreachable: | ||
| 3258 | case NodeTypeSymbol: | ||
| 3259 | case NodeTypeUse: | ||
| 3260 | case NodeTypeVoid: | ||
| 3261 | case NodeTypeBoolLiteral: | ||
| 3262 | case NodeTypeNullLiteral: | ||
| 3263 | case NodeTypeLabel: | ||
| 3264 | case NodeTypeGoto: | ||
| 3265 | case NodeTypeBreak: | ||
| 3266 | case NodeTypeContinue: | ||
| 3267 | case NodeTypeStructDecl: | ||
| 3268 | case NodeTypeStructField: | ||
| 3269 | case NodeTypeStructValueField: | ||
| 3270 | case NodeTypeEnumDecl: | ||
| 3271 | case NodeTypeEnumField: | ||
| 3272 | case NodeTypeCompilerFnExpr: | ||
| 3273 | zig_unreachable(); | ||
| 3274 | } | ||
| 3151 | } | 3275 | } |
| 3152 | 3276 | ||
| 3277 | TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { | ||
| 3278 | switch (node->type) { | ||
| 3279 | case NodeTypeVariableDeclaration: | ||
| 3280 | return &node->data.variable_declaration.top_level_decl; | ||
| 3281 | case NodeTypeFnProto: | ||
| 3282 | return &node->data.fn_proto.top_level_decl; | ||
| 3283 | case NodeTypeStructDecl: | ||
| 3284 | return &node->data.struct_decl.top_level_decl; | ||
| 3285 | case NodeTypeNumberLiteral: | ||
| 3286 | case NodeTypeReturnExpr: | ||
| 3287 | case NodeTypeBinOpExpr: | ||
| 3288 | case NodeTypeCastExpr: | ||
| 3289 | case NodeTypePrefixOpExpr: | ||
| 3290 | case NodeTypeFnCallExpr: | ||
| 3291 | case NodeTypeArrayAccessExpr: | ||
| 3292 | case NodeTypeSliceExpr: | ||
| 3293 | case NodeTypeFieldAccessExpr: | ||
| 3294 | case NodeTypeIfBoolExpr: | ||
| 3295 | case NodeTypeIfVarExpr: | ||
| 3296 | case NodeTypeWhileExpr: | ||
| 3297 | case NodeTypeAsmExpr: | ||
| 3298 | case NodeTypeStructValueExpr: | ||
| 3299 | case NodeTypeRoot: | ||
| 3300 | case NodeTypeRootExportDecl: | ||
| 3301 | case NodeTypeFnDef: | ||
| 3302 | case NodeTypeFnDecl: | ||
| 3303 | case NodeTypeParamDecl: | ||
| 3304 | case NodeTypeType: | ||
| 3305 | case NodeTypeBlock: | ||
| 3306 | case NodeTypeExternBlock: | ||
| 3307 | case NodeTypeDirective: | ||
| 3308 | case NodeTypeStringLiteral: | ||
| 3309 | case NodeTypeCharLiteral: | ||
| 3310 | case NodeTypeUnreachable: | ||
| 3311 | case NodeTypeSymbol: | ||
| 3312 | case NodeTypeUse: | ||
| 3313 | case NodeTypeVoid: | ||
| 3314 | case NodeTypeBoolLiteral: | ||
| 3315 | case NodeTypeNullLiteral: | ||
| 3316 | case NodeTypeLabel: | ||
| 3317 | case NodeTypeGoto: | ||
| 3318 | case NodeTypeBreak: | ||
| 3319 | case NodeTypeContinue: | ||
| 3320 | case NodeTypeStructField: | ||
| 3321 | case NodeTypeStructValueField: | ||
| 3322 | case NodeTypeEnumDecl: | ||
| 3323 | case NodeTypeEnumField: | ||
| 3324 | case NodeTypeCompilerFnExpr: | ||
| 3325 | case NodeTypeCompilerFnType: | ||
| 3326 | zig_unreachable(); | ||
| 3327 | } | ||
| 3328 | } |
src/analyze.hpp+4-402| ... | @@ -8,414 +8,16 @@ | ... | @@ -8,414 +8,16 @@ |
| 8 | #ifndef ZIG_ANALYZE_HPP | 8 | #ifndef ZIG_ANALYZE_HPP |
| 9 | #define ZIG_ANALYZE_HPP | 9 | #define ZIG_ANALYZE_HPP |
| 10 | 10 | ||
| 11 | #include "codegen.hpp" | 11 | #include "all_types.hpp" |
| 12 | #include "hash_map.hpp" | ||
| 13 | #include "zig_llvm.hpp" | ||
| 14 | #include "errmsg.hpp" | ||
| 15 | |||
| 16 | struct FnTableEntry; | ||
| 17 | struct BlockContext; | ||
| 18 | struct TypeTableEntry; | ||
| 19 | struct VariableTableEntry; | ||
| 20 | struct CastNode; | ||
| 21 | struct StructValExprNode; | ||
| 22 | |||
| 23 | struct TypeTableEntryPointer { | ||
| 24 | TypeTableEntry *child_type; | ||
| 25 | bool is_const; | ||
| 26 | bool is_noalias; | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct TypeTableEntryInt { | ||
| 30 | bool is_signed; | ||
| 31 | }; | ||
| 32 | |||
| 33 | struct TypeTableEntryArray { | ||
| 34 | TypeTableEntry *child_type; | ||
| 35 | uint64_t len; | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct TypeStructField { | ||
| 39 | Buf *name; | ||
| 40 | TypeTableEntry *type_entry; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct TypeTableEntryStruct { | ||
| 44 | AstNode *decl_node; | ||
| 45 | bool is_packed; | ||
| 46 | int field_count; | ||
| 47 | TypeStructField *fields; | ||
| 48 | uint64_t size_bytes; | ||
| 49 | bool is_invalid; // true if any fields are invalid | ||
| 50 | bool is_unknown_size_array; | ||
| 51 | // reminder: hash tables must be initialized before use | ||
| 52 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; | ||
| 53 | |||
| 54 | // set this flag temporarily to detect infinite loops | ||
| 55 | bool embedded_in_current; | ||
| 56 | bool reported_infinite_err; | ||
| 57 | }; | ||
| 58 | |||
| 59 | struct TypeTableEntryNumLit { | ||
| 60 | NumLit kind; | ||
| 61 | }; | ||
| 62 | |||
| 63 | struct TypeTableEntryMaybe { | ||
| 64 | TypeTableEntry *child_type; | ||
| 65 | }; | ||
| 66 | |||
| 67 | enum TypeTableEntryId { | ||
| 68 | TypeTableEntryIdInvalid, | ||
| 69 | TypeTableEntryIdVoid, | ||
| 70 | TypeTableEntryIdBool, | ||
| 71 | TypeTableEntryIdUnreachable, | ||
| 72 | TypeTableEntryIdInt, | ||
| 73 | TypeTableEntryIdFloat, | ||
| 74 | TypeTableEntryIdPointer, | ||
| 75 | TypeTableEntryIdArray, | ||
| 76 | TypeTableEntryIdStruct, | ||
| 77 | TypeTableEntryIdNumberLiteral, | ||
| 78 | TypeTableEntryIdMaybe, | ||
| 79 | }; | ||
| 80 | |||
| 81 | struct TypeTableEntry { | ||
| 82 | TypeTableEntryId id; | ||
| 83 | |||
| 84 | LLVMTypeRef type_ref; | ||
| 85 | LLVMZigDIType *di_type; | ||
| 86 | uint64_t size_in_bits; | ||
| 87 | uint64_t align_in_bits; | ||
| 88 | |||
| 89 | Buf name; | ||
| 90 | |||
| 91 | union { | ||
| 92 | TypeTableEntryPointer pointer; | ||
| 93 | TypeTableEntryInt integral; | ||
| 94 | TypeTableEntryArray array; | ||
| 95 | TypeTableEntryStruct structure; | ||
| 96 | TypeTableEntryNumLit num_lit; | ||
| 97 | TypeTableEntryMaybe maybe; | ||
| 98 | } data; | ||
| 99 | |||
| 100 | // use these fields to make sure we don't duplicate type table entries for the same type | ||
| 101 | TypeTableEntry *pointer_parent[2][2]; // 0 - const. 1 - noalias | ||
| 102 | TypeTableEntry *unknown_size_array_parent[2][2]; // 0 - const. 1 - noalias | ||
| 103 | HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size; | ||
| 104 | TypeTableEntry *maybe_parent; | ||
| 105 | |||
| 106 | }; | ||
| 107 | |||
| 108 | struct ImporterInfo { | ||
| 109 | ImportTableEntry *import; | ||
| 110 | AstNode *source_node; | ||
| 111 | }; | ||
| 112 | |||
| 113 | struct ImportTableEntry { | ||
| 114 | AstNode *root; | ||
| 115 | Buf *path; // relative to root_source_dir | ||
| 116 | LLVMZigDIFile *di_file; | ||
| 117 | Buf *source_code; | ||
| 118 | ZigList<int> *line_offsets; | ||
| 119 | BlockContext *block_context; | ||
| 120 | ZigList<ImporterInfo> importers; | ||
| 121 | |||
| 122 | // reminder: hash tables must be initialized before use | ||
| 123 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; | ||
| 124 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table; | ||
| 125 | }; | ||
| 126 | |||
| 127 | struct LabelTableEntry { | ||
| 128 | AstNode *label_node; | ||
| 129 | LLVMBasicBlockRef basic_block; | ||
| 130 | bool used; | ||
| 131 | bool entered_from_fallthrough; | ||
| 132 | }; | ||
| 133 | |||
| 134 | enum FnAttrId { | ||
| 135 | FnAttrIdNaked, | ||
| 136 | FnAttrIdAlwaysInline, | ||
| 137 | }; | ||
| 138 | |||
| 139 | struct FnTableEntry { | ||
| 140 | LLVMValueRef fn_value; | ||
| 141 | AstNode *proto_node; | ||
| 142 | AstNode *fn_def_node; | ||
| 143 | bool is_extern; | ||
| 144 | bool internal_linkage; | ||
| 145 | unsigned calling_convention; | ||
| 146 | ImportTableEntry *import_entry; | ||
| 147 | ZigList<FnAttrId> fn_attr_list; | ||
| 148 | // Required to be a pre-order traversal of the AST. (parents must come before children) | ||
| 149 | ZigList<BlockContext *> all_block_contexts; | ||
| 150 | TypeTableEntry *member_of_struct; | ||
| 151 | Buf symbol_name; | ||
| 152 | |||
| 153 | // reminder: hash tables must be initialized before use | ||
| 154 | HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table; | ||
| 155 | }; | ||
| 156 | |||
| 157 | enum BuiltinFnId { | ||
| 158 | BuiltinFnIdInvalid, | ||
| 159 | BuiltinFnIdArithmeticWithOverflow, | ||
| 160 | BuiltinFnIdMemcpy, | ||
| 161 | BuiltinFnIdMemset, | ||
| 162 | }; | ||
| 163 | |||
| 164 | struct BuiltinFnEntry { | ||
| 165 | BuiltinFnId id; | ||
| 166 | Buf name; | ||
| 167 | int param_count; | ||
| 168 | TypeTableEntry *return_type; | ||
| 169 | TypeTableEntry **param_types; | ||
| 170 | LLVMValueRef fn_val; | ||
| 171 | }; | ||
| 172 | |||
| 173 | struct CodeGen { | ||
| 174 | LLVMModuleRef module; | ||
| 175 | ZigList<ErrorMsg*> errors; | ||
| 176 | LLVMBuilderRef builder; | ||
| 177 | LLVMZigDIBuilder *dbuilder; | ||
| 178 | LLVMZigDICompileUnit *compile_unit; | ||
| 179 | |||
| 180 | ZigList<Buf *> lib_search_paths; | ||
| 181 | |||
| 182 | // reminder: hash tables must be initialized before use | ||
| 183 | HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table; | ||
| 184 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table; | ||
| 185 | HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table; | ||
| 186 | HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table; | ||
| 187 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table; | ||
| 188 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls; | ||
| 189 | |||
| 190 | uint32_t next_unresolved_index; | ||
| 191 | |||
| 192 | struct { | ||
| 193 | TypeTableEntry *entry_bool; | ||
| 194 | TypeTableEntry *entry_u8; | ||
| 195 | TypeTableEntry *entry_u16; | ||
| 196 | TypeTableEntry *entry_u32; | ||
| 197 | TypeTableEntry *entry_u64; | ||
| 198 | TypeTableEntry *entry_i8; | ||
| 199 | TypeTableEntry *entry_i16; | ||
| 200 | TypeTableEntry *entry_i32; | ||
| 201 | TypeTableEntry *entry_i64; | ||
| 202 | TypeTableEntry *entry_isize; | ||
| 203 | TypeTableEntry *entry_usize; | ||
| 204 | TypeTableEntry *entry_f32; | ||
| 205 | TypeTableEntry *entry_f64; | ||
| 206 | TypeTableEntry *entry_c_string_literal; | ||
| 207 | TypeTableEntry *entry_void; | ||
| 208 | TypeTableEntry *entry_unreachable; | ||
| 209 | TypeTableEntry *entry_invalid; | ||
| 210 | } builtin_types; | ||
| 211 | |||
| 212 | TypeTableEntry *num_lit_types[NumLitCount]; | ||
| 213 | |||
| 214 | LLVMTargetDataRef target_data_ref; | ||
| 215 | unsigned pointer_size_bytes; | ||
| 216 | bool is_static; | ||
| 217 | bool strip_debug_symbols; | ||
| 218 | bool have_exported_main; | ||
| 219 | bool link_libc; | ||
| 220 | Buf *libc_path; | ||
| 221 | CodeGenBuildType build_type; | ||
| 222 | LLVMTargetMachineRef target_machine; | ||
| 223 | LLVMZigDIFile *dummy_di_file; | ||
| 224 | bool is_native_target; | ||
| 225 | Buf *root_source_dir; | ||
| 226 | Buf *root_out_name; | ||
| 227 | |||
| 228 | // The function definitions this module includes. There must be a corresponding | ||
| 229 | // fn_protos entry. | ||
| 230 | ZigList<FnTableEntry *> fn_defs; | ||
| 231 | // The function prototypes this module includes. In the case of external declarations, | ||
| 232 | // there will not be a corresponding fn_defs entry. | ||
| 233 | ZigList<FnTableEntry *> fn_protos; | ||
| 234 | ZigList<VariableTableEntry *> global_vars; | ||
| 235 | |||
| 236 | OutType out_type; | ||
| 237 | FnTableEntry *cur_fn; | ||
| 238 | BlockContext *cur_block_context; | ||
| 239 | ZigList<LLVMBasicBlockRef> break_block_stack; | ||
| 240 | ZigList<LLVMBasicBlockRef> continue_block_stack; | ||
| 241 | bool c_stdint_used; | ||
| 242 | AstNode *root_export_decl; | ||
| 243 | int version_major; | ||
| 244 | int version_minor; | ||
| 245 | int version_patch; | ||
| 246 | bool verbose; | ||
| 247 | ErrColor err_color; | ||
| 248 | ImportTableEntry *root_import; | ||
| 249 | ImportTableEntry *bootstrap_import; | ||
| 250 | LLVMValueRef memcpy_fn_val; | ||
| 251 | bool error_during_imports; | ||
| 252 | }; | ||
| 253 | |||
| 254 | struct VariableTableEntry { | ||
| 255 | Buf name; | ||
| 256 | TypeTableEntry *type; | ||
| 257 | LLVMValueRef value_ref; | ||
| 258 | bool is_const; | ||
| 259 | bool is_ptr; // if true, value_ref is a pointer | ||
| 260 | AstNode *decl_node; | ||
| 261 | LLVMZigDILocalVariable *di_loc_var; | ||
| 262 | int arg_index; | ||
| 263 | }; | ||
| 264 | |||
| 265 | struct BlockContext { | ||
| 266 | AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or NodeTypeRoot | ||
| 267 | FnTableEntry *fn_entry; // null at the module scope | ||
| 268 | BlockContext *parent; // null when this is the root | ||
| 269 | HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table; | ||
| 270 | ZigList<CastNode *> cast_expr_alloca_list; | ||
| 271 | ZigList<StructValExprNode *> struct_val_expr_alloca_list; | ||
| 272 | AstNode *parent_loop_node; | ||
| 273 | AstNode *next_child_parent_loop_node; | ||
| 274 | LLVMZigDIScope *di_scope; | ||
| 275 | }; | ||
| 276 | |||
| 277 | struct TypeNode { | ||
| 278 | TypeTableEntry *entry; | ||
| 279 | }; | ||
| 280 | |||
| 281 | struct FnProtoNode { | ||
| 282 | FnTableEntry *fn_table_entry; | ||
| 283 | bool skip; | ||
| 284 | }; | ||
| 285 | |||
| 286 | struct FnDefNode { | ||
| 287 | TypeTableEntry *implicit_return_type; | ||
| 288 | BlockContext *block_context; | ||
| 289 | }; | ||
| 290 | |||
| 291 | |||
| 292 | struct AssignNode { | ||
| 293 | VariableTableEntry *var_entry; | ||
| 294 | }; | ||
| 295 | |||
| 296 | struct BlockNode { | ||
| 297 | BlockContext *block_context; | ||
| 298 | }; | ||
| 299 | |||
| 300 | struct StructDeclNode { | ||
| 301 | TypeTableEntry *type_entry; | ||
| 302 | }; | ||
| 303 | |||
| 304 | struct FieldAccessNode { | ||
| 305 | int field_index; | ||
| 306 | TypeStructField *type_struct_field; | ||
| 307 | }; | ||
| 308 | |||
| 309 | enum CastOp { | ||
| 310 | CastOpNothing, | ||
| 311 | CastOpPtrToInt, | ||
| 312 | CastOpIntWidenOrShorten, | ||
| 313 | CastOpToUnknownSizeArray, | ||
| 314 | CastOpMaybeWrap, | ||
| 315 | CastOpPointerReinterpret, | ||
| 316 | }; | ||
| 317 | |||
| 318 | struct CastNode { | ||
| 319 | CastOp op; | ||
| 320 | // if op is CastOpArrayToString, this will be a pointer to | ||
| 321 | // the string struct on the stack | ||
| 322 | LLVMValueRef ptr; | ||
| 323 | TypeTableEntry *after_type; | ||
| 324 | AstNode *source_node; | ||
| 325 | }; | ||
| 326 | |||
| 327 | struct ExprNode { | ||
| 328 | TypeTableEntry *type_entry; | ||
| 329 | // the context in which this expression is evaluated. | ||
| 330 | // for blocks, this points to the containing scope, not the block's own scope for its children. | ||
| 331 | BlockContext *block_context; | ||
| 332 | |||
| 333 | // may be null for no cast | ||
| 334 | CastNode implicit_cast; // happens first | ||
| 335 | CastNode implicit_maybe_cast; // happens second | ||
| 336 | }; | ||
| 337 | |||
| 338 | struct NumberLiteralNode { | ||
| 339 | TypeTableEntry *resolved_type; | ||
| 340 | }; | ||
| 341 | |||
| 342 | struct VarDeclNode { | ||
| 343 | TypeTableEntry *type; | ||
| 344 | }; | ||
| 345 | |||
| 346 | struct StructValFieldNode { | ||
| 347 | int index; | ||
| 348 | }; | ||
| 349 | |||
| 350 | struct StructValExprNode { | ||
| 351 | TypeTableEntry *type_entry; | ||
| 352 | LLVMValueRef ptr; | ||
| 353 | AstNode *source_node; | ||
| 354 | }; | ||
| 355 | |||
| 356 | struct IfVarNode { | ||
| 357 | BlockContext *block_context; | ||
| 358 | }; | ||
| 359 | |||
| 360 | struct ParamDeclNode { | ||
| 361 | VariableTableEntry *variable; | ||
| 362 | }; | ||
| 363 | |||
| 364 | struct ImportNode { | ||
| 365 | ImportTableEntry *import; | ||
| 366 | }; | ||
| 367 | |||
| 368 | struct WhileNode { | ||
| 369 | bool condition_always_true; | ||
| 370 | bool contains_break; | ||
| 371 | }; | ||
| 372 | |||
| 373 | struct FnCallNode { | ||
| 374 | BuiltinFnEntry *builtin_fn; | ||
| 375 | }; | ||
| 376 | |||
| 377 | struct DeclNode { | ||
| 378 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> deps; | ||
| 379 | Buf *name; | ||
| 380 | ImportTableEntry *import; | ||
| 381 | // set this flag temporarily to detect infinite loops | ||
| 382 | bool in_current_deps; | ||
| 383 | }; | ||
| 384 | |||
| 385 | // TODO get rid of this structure and put the data directly in the appropriate AST node | ||
| 386 | struct CodeGenNode { | ||
| 387 | union { | ||
| 388 | TypeNode type_node; // for NodeTypeType | ||
| 389 | FnDefNode fn_def_node; // for NodeTypeFnDef | ||
| 390 | FnProtoNode fn_proto_node; // for NodeTypeFnProto | ||
| 391 | LabelTableEntry *label_entry; // for NodeTypeGoto and NodeTypeLabel | ||
| 392 | AssignNode assign_node; // for NodeTypeBinOpExpr where op is BinOpTypeAssign | ||
| 393 | BlockNode block_node; // for NodeTypeBlock | ||
| 394 | StructDeclNode struct_decl_node; // for NodeTypeStructDecl | ||
| 395 | FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr | ||
| 396 | CastNode cast_node; // for NodeTypeCastExpr | ||
| 397 | // note: I've been using this field on some non-number literal nodes too. | ||
| 398 | NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral | ||
| 399 | VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration | ||
| 400 | StructValFieldNode struct_val_field_node; // for NodeTypeStructValueField | ||
| 401 | // note: I've been using this field on some non-struct val expressions too. | ||
| 402 | StructValExprNode struct_val_expr_node; // for NodeTypeStructValueExpr | ||
| 403 | IfVarNode if_var_node; // for NodeTypeStructValueExpr | ||
| 404 | ParamDeclNode param_decl_node; // for NodeTypeParamDecl | ||
| 405 | ImportNode import_node; // for NodeTypeUse | ||
| 406 | WhileNode while_node; // for NodeTypeWhileExpr | ||
| 407 | FnCallNode fn_call_node; // for NodeTypeFnCallExpr | ||
| 408 | } data; | ||
| 409 | ExprNode expr_node; // for all the expression nodes | ||
| 410 | DeclNode decl_node; // for all top level decls | ||
| 411 | }; | ||
| 412 | 12 | ||
| 413 | void semantic_analyze(CodeGen *g); | 13 | void semantic_analyze(CodeGen *g); |
| 414 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); | 14 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 415 | void alloc_codegen_node(AstNode *node); | ||
| 416 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); | 15 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); |
| 417 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias); | 16 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias); |
| 418 | VariableTableEntry *find_variable(BlockContext *context, Buf *name); | 17 | VariableTableEntry *find_variable(BlockContext *context, Buf *name); |
| 419 | BlockContext *new_block_context(AstNode *node, BlockContext *parent); | 18 | BlockContext *new_block_context(AstNode *node, BlockContext *parent); |
| 19 | Expr *get_resolved_expr(AstNode *node); | ||
| 20 | NumLitCodeGen *get_resolved_num_lit(AstNode *node); | ||
| 21 | TopLevelDecl *get_resolved_top_level_decl(AstNode *node); | ||
| 420 | 22 | ||
| 421 | #endif | 23 | #endif |
src/codegen.cpp+50-61| ... | @@ -75,9 +75,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b | ... | @@ -75,9 +75,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b |
| 75 | 75 | ||
| 76 | static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) { | 76 | static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) { |
| 77 | assert(type_node->type == NodeTypeType); | 77 | assert(type_node->type == NodeTypeType); |
| 78 | assert(type_node->codegen_node); | 78 | return type_node->data.type.entry; |
| 79 | assert(type_node->codegen_node->data.type_node.entry); | ||
| 80 | return type_node->codegen_node->data.type_node.entry; | ||
| 81 | } | 79 | } |
| 82 | 80 | ||
| 83 | static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) { | 81 | static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) { |
| ... | @@ -138,15 +136,16 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str, bool c) { | ... | @@ -138,15 +136,16 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str, bool c) { |
| 138 | } | 136 | } |
| 139 | 137 | ||
| 140 | static TypeTableEntry *get_expr_type(AstNode *node) { | 138 | static TypeTableEntry *get_expr_type(AstNode *node) { |
| 141 | TypeTableEntry *cast_type = node->codegen_node->expr_node.implicit_cast.after_type; | 139 | Expr *expr = get_resolved_expr(node); |
| 142 | return cast_type ? cast_type : node->codegen_node->expr_node.type_entry; | 140 | TypeTableEntry *cast_type = expr->implicit_cast.after_type; |
| 141 | return cast_type ? cast_type : expr->type_entry; | ||
| 143 | } | 142 | } |
| 144 | 143 | ||
| 145 | static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { | 144 | static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 146 | assert(node->type == NodeTypeFnCallExpr); | 145 | assert(node->type == NodeTypeFnCallExpr); |
| 147 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | 146 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; |
| 148 | assert(fn_ref_expr->type == NodeTypeSymbol); | 147 | assert(fn_ref_expr->type == NodeTypeSymbol); |
| 149 | BuiltinFnEntry *builtin_fn = node->codegen_node->data.fn_call_node.builtin_fn; | 148 | BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn; |
| 150 | 149 | ||
| 151 | switch (builtin_fn->id) { | 150 | switch (builtin_fn->id) { |
| 152 | case BuiltinFnIdInvalid: | 151 | case BuiltinFnIdInvalid: |
| ... | @@ -265,7 +264,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { | ... | @@ -265,7 +264,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { |
| 265 | // Assume that the expression evaluates to a simple name and return the buf | 264 | // Assume that the expression evaluates to a simple name and return the buf |
| 266 | // TODO after we support function pointers we can make this generic | 265 | // TODO after we support function pointers we can make this generic |
| 267 | assert(fn_ref_expr->type == NodeTypeSymbol); | 266 | assert(fn_ref_expr->type == NodeTypeSymbol); |
| 268 | Buf *name = &fn_ref_expr->data.symbol; | 267 | Buf *name = &fn_ref_expr->data.symbol_expr.symbol; |
| 269 | 268 | ||
| 270 | struct_type = nullptr; | 269 | struct_type = nullptr; |
| 271 | first_param_expr = nullptr; | 270 | first_param_expr = nullptr; |
| ... | @@ -388,8 +387,8 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou | ... | @@ -388,8 +387,8 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou |
| 388 | 387 | ||
| 389 | LLVMValueRef struct_ptr; | 388 | LLVMValueRef struct_ptr; |
| 390 | if (struct_expr_node->type == NodeTypeSymbol) { | 389 | if (struct_expr_node->type == NodeTypeSymbol) { |
| 391 | VariableTableEntry *var = find_variable(struct_expr_node->codegen_node->expr_node.block_context, | 390 | VariableTableEntry *var = find_variable(get_resolved_expr(struct_expr_node)->block_context, |
| 392 | &struct_expr_node->data.symbol); | 391 | &struct_expr_node->data.symbol_expr.symbol); |
| 393 | assert(var); | 392 | assert(var); |
| 394 | 393 | ||
| 395 | if (var->is_ptr && var->type->id == TypeTableEntryIdPointer) { | 394 | if (var->is_ptr && var->type->id == TypeTableEntryIdPointer) { |
| ... | @@ -413,14 +412,12 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou | ... | @@ -413,14 +412,12 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou |
| 413 | assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind); | 412 | assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind); |
| 414 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind); | 413 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind); |
| 415 | 414 | ||
| 416 | FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node; | 415 | assert(node->data.field_access_expr.field_index >= 0); |
| 417 | 416 | ||
| 418 | assert(codegen_field_access->field_index >= 0); | 417 | *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry; |
| 419 | |||
| 420 | *out_type_entry = codegen_field_access->type_struct_field->type_entry; | ||
| 421 | 418 | ||
| 422 | add_debug_source_node(g, node); | 419 | add_debug_source_node(g, node); |
| 423 | return LLVMBuildStructGEP(g->builder, struct_ptr, codegen_field_access->field_index, ""); | 420 | return LLVMBuildStructGEP(g->builder, struct_ptr, node->data.field_access_expr.field_index, ""); |
| 424 | } | 421 | } |
| 425 | 422 | ||
| 426 | static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { | 423 | static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| ... | @@ -429,7 +426,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { | ... | @@ -429,7 +426,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| 429 | AstNode *array_ref_node = node->data.slice_expr.array_ref_expr; | 426 | AstNode *array_ref_node = node->data.slice_expr.array_ref_expr; |
| 430 | TypeTableEntry *array_type = get_expr_type(array_ref_node); | 427 | TypeTableEntry *array_type = get_expr_type(array_ref_node); |
| 431 | 428 | ||
| 432 | LLVMValueRef tmp_struct_ptr = node->codegen_node->data.struct_val_expr_node.ptr; | 429 | LLVMValueRef tmp_struct_ptr = node->data.slice_expr.resolved_struct_val_expr.ptr; |
| 433 | LLVMValueRef array_ptr = gen_array_base_ptr(g, array_ref_node); | 430 | LLVMValueRef array_ptr = gen_array_base_ptr(g, array_ref_node); |
| 434 | 431 | ||
| 435 | if (array_type->id == TypeTableEntryIdArray) { | 432 | if (array_type->id == TypeTableEntryIdArray) { |
| ... | @@ -545,8 +542,8 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, | ... | @@ -545,8 +542,8 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, |
| 545 | LLVMValueRef target_ref; | 542 | LLVMValueRef target_ref; |
| 546 | 543 | ||
| 547 | if (node->type == NodeTypeSymbol) { | 544 | if (node->type == NodeTypeSymbol) { |
| 548 | VariableTableEntry *var = find_variable(expr_node->codegen_node->expr_node.block_context, | 545 | VariableTableEntry *var = find_variable(get_resolved_expr(expr_node)->block_context, |
| 549 | &node->data.symbol); | 546 | &node->data.symbol_expr.symbol); |
| 550 | assert(var); | 547 | assert(var); |
| 551 | // semantic checking ensures no variables are constant | 548 | // semantic checking ensures no variables are constant |
| 552 | assert(!var->is_const); | 549 | assert(!var->is_const); |
| ... | @@ -630,7 +627,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { | ... | @@ -630,7 +627,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 630 | } | 627 | } |
| 631 | 628 | ||
| 632 | static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_val, | 629 | static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_val, |
| 633 | TypeTableEntry *actual_type, TypeTableEntry *wanted_type, CastNode *cast_node) | 630 | TypeTableEntry *actual_type, TypeTableEntry *wanted_type, Cast *cast_node) |
| 634 | { | 631 | { |
| 635 | switch (cast_node->op) { | 632 | switch (cast_node->op) { |
| 636 | case CastOpNothing: | 633 | case CastOpNothing: |
| ... | @@ -705,7 +702,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { | ... | @@ -705,7 +702,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 705 | TypeTableEntry *actual_type = get_expr_type(node->data.cast_expr.expr); | 702 | TypeTableEntry *actual_type = get_expr_type(node->data.cast_expr.expr); |
| 706 | TypeTableEntry *wanted_type = get_expr_type(node); | 703 | TypeTableEntry *wanted_type = get_expr_type(node); |
| 707 | 704 | ||
| 708 | CastNode *cast_node = &node->codegen_node->data.cast_node; | 705 | Cast *cast_node = &node->data.cast_expr.cast; |
| 709 | 706 | ||
| 710 | return gen_bare_cast(g, node, expr_val, actual_type, wanted_type, cast_node); | 707 | return gen_bare_cast(g, node, expr_val, actual_type, wanted_type, cast_node); |
| 711 | 708 | ||
| ... | @@ -1218,7 +1215,7 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { | ... | @@ -1218,7 +1215,7 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 1218 | assert(node->data.if_var_expr.var_decl.expr); | 1215 | assert(node->data.if_var_expr.var_decl.expr); |
| 1219 | 1216 | ||
| 1220 | BlockContext *old_block_context = g->cur_block_context; | 1217 | BlockContext *old_block_context = g->cur_block_context; |
| 1221 | BlockContext *new_block_context = node->codegen_node->data.if_var_node.block_context; | 1218 | BlockContext *new_block_context = node->data.if_var_expr.block_context; |
| 1222 | 1219 | ||
| 1223 | LLVMValueRef init_val; | 1220 | LLVMValueRef init_val; |
| 1224 | gen_var_decl_raw(g, node, &node->data.if_var_expr.var_decl, new_block_context, true, &init_val); | 1221 | gen_var_decl_raw(g, node, &node->data.if_var_expr.var_decl, new_block_context, true, &init_val); |
| ... | @@ -1242,7 +1239,7 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i | ... | @@ -1242,7 +1239,7 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i |
| 1242 | assert(block_node->type == NodeTypeBlock); | 1239 | assert(block_node->type == NodeTypeBlock); |
| 1243 | 1240 | ||
| 1244 | BlockContext *old_block_context = g->cur_block_context; | 1241 | BlockContext *old_block_context = g->cur_block_context; |
| 1245 | g->cur_block_context = block_node->codegen_node->data.block_node.block_context; | 1242 | g->cur_block_context = block_node->data.block.block_context; |
| 1246 | 1243 | ||
| 1247 | LLVMValueRef return_value; | 1244 | LLVMValueRef return_value; |
| 1248 | for (int i = 0; i < block_node->data.block.statements.length; i += 1) { | 1245 | for (int i = 0; i < block_node->data.block.statements.length; i += 1) { |
| ... | @@ -1347,7 +1344,7 @@ static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) { | ... | @@ -1347,7 +1344,7 @@ static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) { |
| 1347 | 1344 | ||
| 1348 | if (!is_return) { | 1345 | if (!is_return) { |
| 1349 | VariableTableEntry *variable = find_variable( | 1346 | VariableTableEntry *variable = find_variable( |
| 1350 | node->codegen_node->expr_node.block_context, | 1347 | get_resolved_expr(node)->block_context, |
| 1351 | &asm_output->variable_name); | 1348 | &asm_output->variable_name); |
| 1352 | assert(variable); | 1349 | assert(variable); |
| 1353 | param_types[param_index] = LLVMTypeOf(variable->value_ref); | 1350 | param_types[param_index] = LLVMTypeOf(variable->value_ref); |
| ... | @@ -1396,7 +1393,7 @@ static LLVMValueRef gen_null_literal(CodeGen *g, AstNode *node) { | ... | @@ -1396,7 +1393,7 @@ static LLVMValueRef gen_null_literal(CodeGen *g, AstNode *node) { |
| 1396 | TypeTableEntry *type_entry = get_expr_type(node); | 1393 | TypeTableEntry *type_entry = get_expr_type(node); |
| 1397 | assert(type_entry->id == TypeTableEntryIdMaybe); | 1394 | assert(type_entry->id == TypeTableEntryIdMaybe); |
| 1398 | 1395 | ||
| 1399 | LLVMValueRef tmp_struct_ptr = node->codegen_node->data.struct_val_expr_node.ptr; | 1396 | LLVMValueRef tmp_struct_ptr = node->data.null_literal.resolved_struct_val_expr.ptr; |
| 1400 | 1397 | ||
| 1401 | add_debug_source_node(g, node); | 1398 | add_debug_source_node(g, node); |
| 1402 | LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, ""); | 1399 | LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, ""); |
| ... | @@ -1416,12 +1413,13 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) { | ... | @@ -1416,12 +1413,13 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) { |
| 1416 | int field_count = type_entry->data.structure.field_count; | 1413 | int field_count = type_entry->data.structure.field_count; |
| 1417 | assert(field_count == node->data.struct_val_expr.fields.length); | 1414 | assert(field_count == node->data.struct_val_expr.fields.length); |
| 1418 | 1415 | ||
| 1419 | StructValExprNode *struct_val_expr_node = &node->codegen_node->data.struct_val_expr_node; | 1416 | StructValExprCodeGen *struct_val_expr_node = &node->data.struct_val_expr.codegen; |
| 1420 | LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr; | 1417 | LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr; |
| 1421 | 1418 | ||
| 1422 | for (int i = 0; i < field_count; i += 1) { | 1419 | for (int i = 0; i < field_count; i += 1) { |
| 1423 | AstNode *field_node = node->data.struct_val_expr.fields.at(i); | 1420 | AstNode *field_node = node->data.struct_val_expr.fields.at(i); |
| 1424 | int index = field_node->codegen_node->data.struct_val_field_node.index; | 1421 | assert(field_node->type == NodeTypeStructValueField); |
| 1422 | int index = field_node->data.struct_val_field.index; | ||
| 1425 | TypeStructField *type_struct_field = &type_entry->data.structure.fields[index]; | 1423 | TypeStructField *type_struct_field = &type_entry->data.structure.fields[index]; |
| 1426 | assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name)); | 1424 | assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name)); |
| 1427 | 1425 | ||
| ... | @@ -1439,8 +1437,8 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) { | ... | @@ -1439,8 +1437,8 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) { |
| 1439 | assert(node->data.while_expr.condition); | 1437 | assert(node->data.while_expr.condition); |
| 1440 | assert(node->data.while_expr.body); | 1438 | assert(node->data.while_expr.body); |
| 1441 | 1439 | ||
| 1442 | bool condition_always_true = node->codegen_node->data.while_node.condition_always_true; | 1440 | bool condition_always_true = node->data.while_expr.condition_always_true; |
| 1443 | bool contains_break = node->codegen_node->data.while_node.contains_break; | 1441 | bool contains_break = node->data.while_expr.contains_break; |
| 1444 | if (condition_always_true) { | 1442 | if (condition_always_true) { |
| 1445 | // generate a forever loop | 1443 | // generate a forever loop |
| 1446 | 1444 | ||
| ... | @@ -1559,17 +1557,17 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa | ... | @@ -1559,17 +1557,17 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa |
| 1559 | static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { | 1557 | static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { |
| 1560 | LLVMValueRef init_val; | 1558 | LLVMValueRef init_val; |
| 1561 | return gen_var_decl_raw(g, node, &node->data.variable_declaration, | 1559 | return gen_var_decl_raw(g, node, &node->data.variable_declaration, |
| 1562 | node->codegen_node->expr_node.block_context, false, &init_val); | 1560 | get_resolved_expr(node)->block_context, false, &init_val); |
| 1563 | } | 1561 | } |
| 1564 | 1562 | ||
| 1565 | static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node, | 1563 | static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node, |
| 1566 | NumberLiteralNode *codegen_num_lit, AstNodeNumberLiteral *num_lit_node) | 1564 | NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node) |
| 1567 | { | 1565 | { |
| 1568 | TypeTableEntry *type_entry = codegen_num_lit->resolved_type; | 1566 | TypeTableEntry *type_entry = codegen_num_lit->resolved_type; |
| 1569 | assert(type_entry); | 1567 | assert(type_entry); |
| 1570 | 1568 | ||
| 1571 | // override the expression type for number literals | 1569 | // override the expression type for number literals |
| 1572 | source_node->codegen_node->expr_node.type_entry = type_entry; | 1570 | get_resolved_expr(source_node)->type_entry = type_entry; |
| 1573 | 1571 | ||
| 1574 | if (type_entry->id == TypeTableEntryIdInt) { | 1572 | if (type_entry->id == TypeTableEntryIdInt) { |
| 1575 | // here the union has int64_t and uint64_t and we purposefully read | 1573 | // here the union has int64_t and uint64_t and we purposefully read |
| ... | @@ -1594,7 +1592,7 @@ static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) { | ... | @@ -1594,7 +1592,7 @@ static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) { |
| 1594 | Buf *name = &node->data.compiler_fn_type.name; | 1592 | Buf *name = &node->data.compiler_fn_type.name; |
| 1595 | TypeTableEntry *type_entry = get_type_for_type_node(g, node->data.compiler_fn_type.type); | 1593 | TypeTableEntry *type_entry = get_type_for_type_node(g, node->data.compiler_fn_type.type); |
| 1596 | if (buf_eql_str(name, "sizeof")) { | 1594 | if (buf_eql_str(name, "sizeof")) { |
| 1597 | NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node; | 1595 | NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node); |
| 1598 | AstNodeNumberLiteral num_lit_node; | 1596 | AstNodeNumberLiteral num_lit_node; |
| 1599 | num_lit_node.kind = type_entry->data.num_lit.kind; | 1597 | num_lit_node.kind = type_entry->data.num_lit.kind; |
| 1600 | num_lit_node.overflow = false; | 1598 | num_lit_node.overflow = false; |
| ... | @@ -1632,7 +1630,7 @@ static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) { | ... | @@ -1632,7 +1630,7 @@ static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) { |
| 1632 | static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *node) { | 1630 | static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *node) { |
| 1633 | assert(node->type == NodeTypeNumberLiteral); | 1631 | assert(node->type == NodeTypeNumberLiteral); |
| 1634 | 1632 | ||
| 1635 | NumberLiteralNode *codegen_num_lit = &node->codegen_node->data.num_lit_node; | 1633 | NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node); |
| 1636 | assert(codegen_num_lit); | 1634 | assert(codegen_num_lit); |
| 1637 | 1635 | ||
| 1638 | return gen_number_literal_raw(g, node, codegen_num_lit, &node->data.number_literal); | 1636 | return gen_number_literal_raw(g, node, codegen_num_lit, &node->data.number_literal); |
| ... | @@ -1664,7 +1662,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1664,7 +1662,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1664 | case NodeTypeVoid: | 1662 | case NodeTypeVoid: |
| 1665 | return nullptr; | 1663 | return nullptr; |
| 1666 | case NodeTypeBoolLiteral: | 1664 | case NodeTypeBoolLiteral: |
| 1667 | if (node->data.bool_literal) | 1665 | if (node->data.bool_literal.value) |
| 1668 | return LLVMConstAllOnes(LLVMInt1Type()); | 1666 | return LLVMConstAllOnes(LLVMInt1Type()); |
| 1669 | else | 1667 | else |
| 1670 | return LLVMConstNull(LLVMInt1Type()); | 1668 | return LLVMConstNull(LLVMInt1Type()); |
| ... | @@ -1696,8 +1694,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1696,8 +1694,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1696 | case NodeTypeSymbol: | 1694 | case NodeTypeSymbol: |
| 1697 | { | 1695 | { |
| 1698 | VariableTableEntry *variable = find_variable( | 1696 | VariableTableEntry *variable = find_variable( |
| 1699 | node->codegen_node->expr_node.block_context, | 1697 | get_resolved_expr(node)->block_context, |
| 1700 | &node->data.symbol); | 1698 | &node->data.symbol_expr.symbol); |
| 1701 | assert(variable); | 1699 | assert(variable); |
| 1702 | if (variable->type->id == TypeTableEntryIdVoid) { | 1700 | if (variable->type->id == TypeTableEntryIdVoid) { |
| 1703 | return nullptr; | 1701 | return nullptr; |
| ... | @@ -1721,14 +1719,14 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1721,14 +1719,14 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1721 | return gen_block(g, node, nullptr); | 1719 | return gen_block(g, node, nullptr); |
| 1722 | case NodeTypeGoto: | 1720 | case NodeTypeGoto: |
| 1723 | add_debug_source_node(g, node); | 1721 | add_debug_source_node(g, node); |
| 1724 | return LLVMBuildBr(g->builder, node->codegen_node->data.label_entry->basic_block); | 1722 | return LLVMBuildBr(g->builder, node->data.goto_expr.label_entry->basic_block); |
| 1725 | case NodeTypeBreak: | 1723 | case NodeTypeBreak: |
| 1726 | return gen_break(g, node); | 1724 | return gen_break(g, node); |
| 1727 | case NodeTypeContinue: | 1725 | case NodeTypeContinue: |
| 1728 | return gen_continue(g, node); | 1726 | return gen_continue(g, node); |
| 1729 | case NodeTypeLabel: | 1727 | case NodeTypeLabel: |
| 1730 | { | 1728 | { |
| 1731 | LabelTableEntry *label_entry = node->codegen_node->data.label_entry; | 1729 | LabelTableEntry *label_entry = node->data.label.label_entry; |
| 1732 | assert(label_entry); | 1730 | assert(label_entry); |
| 1733 | LLVMBasicBlockRef basic_block = label_entry->basic_block; | 1731 | LLVMBasicBlockRef basic_block = label_entry->basic_block; |
| 1734 | if (label_entry->entered_from_fallthrough) { | 1732 | if (label_entry->entered_from_fallthrough) { |
| ... | @@ -1770,19 +1768,19 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { | ... | @@ -1770,19 +1768,19 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 1770 | return val; | 1768 | return val; |
| 1771 | } | 1769 | } |
| 1772 | 1770 | ||
| 1773 | assert(node->codegen_node); | 1771 | Expr *expr = get_resolved_expr(node); |
| 1774 | 1772 | ||
| 1775 | TypeTableEntry *before_type = node->codegen_node->expr_node.type_entry; | 1773 | TypeTableEntry *before_type = expr->type_entry; |
| 1776 | if (before_type && before_type->id == TypeTableEntryIdUnreachable) { | 1774 | if (before_type && before_type->id == TypeTableEntryIdUnreachable) { |
| 1777 | return val; | 1775 | return val; |
| 1778 | } | 1776 | } |
| 1779 | CastNode *cast_node = &node->codegen_node->expr_node.implicit_cast; | 1777 | Cast *cast_node = &expr->implicit_cast; |
| 1780 | if (cast_node->after_type) { | 1778 | if (cast_node->after_type) { |
| 1781 | val = gen_bare_cast(g, node, val, before_type, cast_node->after_type, cast_node); | 1779 | val = gen_bare_cast(g, node, val, before_type, cast_node->after_type, cast_node); |
| 1782 | before_type = cast_node->after_type; | 1780 | before_type = cast_node->after_type; |
| 1783 | } | 1781 | } |
| 1784 | 1782 | ||
| 1785 | cast_node = &node->codegen_node->expr_node.implicit_maybe_cast; | 1783 | cast_node = &expr->implicit_maybe_cast; |
| 1786 | if (cast_node->after_type) { | 1784 | if (cast_node->after_type) { |
| 1787 | val = gen_bare_cast(g, node, val, before_type, cast_node->after_type, cast_node); | 1785 | val = gen_bare_cast(g, node, val, before_type, cast_node->after_type, cast_node); |
| 1788 | } | 1786 | } |
| ... | @@ -1798,7 +1796,7 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) { | ... | @@ -1798,7 +1796,7 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) { |
| 1798 | continue; | 1796 | continue; |
| 1799 | 1797 | ||
| 1800 | Buf *name = &label_node->data.label.name; | 1798 | Buf *name = &label_node->data.label.name; |
| 1801 | label_node->codegen_node->data.label_entry->basic_block = LLVMAppendBasicBlock( | 1799 | label_node->data.label.label_entry->basic_block = LLVMAppendBasicBlock( |
| 1802 | g->cur_fn->fn_value, buf_ptr(name)); | 1800 | g->cur_fn->fn_value, buf_ptr(name)); |
| 1803 | } | 1801 | } |
| 1804 | 1802 | ||
| ... | @@ -1944,13 +1942,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -1944,13 +1942,7 @@ static void do_code_gen(CodeGen *g) { |
| 1944 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry"); | 1942 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry"); |
| 1945 | LLVMPositionBuilderAtEnd(g->builder, entry_block); | 1943 | LLVMPositionBuilderAtEnd(g->builder, entry_block); |
| 1946 | 1944 | ||
| 1947 | CodeGenNode *codegen_node = fn_def_node->codegen_node; | 1945 | fn_def_node->data.fn_def.block_context->di_scope = LLVMZigSubprogramToScope(subprogram); |
| 1948 | assert(codegen_node); | ||
| 1949 | |||
| 1950 | FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node; | ||
| 1951 | assert(codegen_fn_def); | ||
| 1952 | |||
| 1953 | codegen_fn_def->block_context->di_scope = LLVMZigSubprogramToScope(subprogram); | ||
| 1954 | 1946 | ||
| 1955 | int non_void_param_count = count_non_void_params(g, &fn_proto->params); | 1947 | int non_void_param_count = count_non_void_params(g, &fn_proto->params); |
| 1956 | assert(non_void_param_count == (int)LLVMCountParams(fn)); | 1948 | assert(non_void_param_count == (int)LLVMCountParams(fn)); |
| ... | @@ -1963,7 +1955,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -1963,7 +1955,7 @@ static void do_code_gen(CodeGen *g) { |
| 1963 | assert(param_decl->type == NodeTypeParamDecl); | 1955 | assert(param_decl->type == NodeTypeParamDecl); |
| 1964 | if (is_param_decl_type_void(g, param_decl)) | 1956 | if (is_param_decl_type_void(g, param_decl)) |
| 1965 | continue; | 1957 | continue; |
| 1966 | VariableTableEntry *parameter_variable = fn_def_node->codegen_node->data.fn_def_node.block_context->variable_table.get(&param_decl->data.param_decl.name); | 1958 | VariableTableEntry *parameter_variable = fn_def_node->data.fn_def.block_context->variable_table.get(&param_decl->data.param_decl.name); |
| 1967 | parameter_variable->value_ref = params[non_void_index]; | 1959 | parameter_variable->value_ref = params[non_void_index]; |
| 1968 | non_void_index += 1; | 1960 | non_void_index += 1; |
| 1969 | } | 1961 | } |
| ... | @@ -2019,14 +2011,14 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -2019,14 +2011,14 @@ static void do_code_gen(CodeGen *g) { |
| 2019 | 2011 | ||
| 2020 | // allocate structs which are the result of casts | 2012 | // allocate structs which are the result of casts |
| 2021 | for (int cea_i = 0; cea_i < block_context->cast_expr_alloca_list.length; cea_i += 1) { | 2013 | for (int cea_i = 0; cea_i < block_context->cast_expr_alloca_list.length; cea_i += 1) { |
| 2022 | CastNode *cast_node = block_context->cast_expr_alloca_list.at(cea_i); | 2014 | Cast *cast_node = block_context->cast_expr_alloca_list.at(cea_i); |
| 2023 | add_debug_source_node(g, cast_node->source_node); | 2015 | add_debug_source_node(g, cast_node->source_node); |
| 2024 | cast_node->ptr = LLVMBuildAlloca(g->builder, cast_node->after_type->type_ref, ""); | 2016 | cast_node->ptr = LLVMBuildAlloca(g->builder, cast_node->after_type->type_ref, ""); |
| 2025 | } | 2017 | } |
| 2026 | 2018 | ||
| 2027 | // allocate structs which are struct value expressions | 2019 | // allocate structs which are struct value expressions |
| 2028 | for (int alloca_i = 0; alloca_i < block_context->struct_val_expr_alloca_list.length; alloca_i += 1) { | 2020 | for (int alloca_i = 0; alloca_i < block_context->struct_val_expr_alloca_list.length; alloca_i += 1) { |
| 2029 | StructValExprNode *struct_val_expr_node = block_context->struct_val_expr_alloca_list.at(alloca_i); | 2021 | StructValExprCodeGen *struct_val_expr_node = block_context->struct_val_expr_alloca_list.at(alloca_i); |
| 2030 | add_debug_source_node(g, struct_val_expr_node->source_node); | 2022 | add_debug_source_node(g, struct_val_expr_node->source_node); |
| 2031 | struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder, | 2023 | struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder, |
| 2032 | struct_val_expr_node->type_entry->type_ref, ""); | 2024 | struct_val_expr_node->type_entry->type_ref, ""); |
| ... | @@ -2041,15 +2033,15 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -2041,15 +2033,15 @@ static void do_code_gen(CodeGen *g) { |
| 2041 | if (is_param_decl_type_void(g, param_decl)) | 2033 | if (is_param_decl_type_void(g, param_decl)) |
| 2042 | continue; | 2034 | continue; |
| 2043 | 2035 | ||
| 2044 | VariableTableEntry *variable = param_decl->codegen_node->data.param_decl_node.variable; | 2036 | VariableTableEntry *variable = param_decl->data.param_decl.variable; |
| 2045 | 2037 | ||
| 2046 | LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(param_decl->line + 1, param_decl->column + 1, | 2038 | LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(param_decl->line + 1, param_decl->column + 1, |
| 2047 | codegen_fn_def->block_context->di_scope); | 2039 | fn_def_node->data.fn_def.block_context->di_scope); |
| 2048 | LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc, | 2040 | LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc, |
| 2049 | entry_block); | 2041 | entry_block); |
| 2050 | } | 2042 | } |
| 2051 | 2043 | ||
| 2052 | TypeTableEntry *implicit_return_type = codegen_fn_def->implicit_return_type; | 2044 | TypeTableEntry *implicit_return_type = fn_def_node->data.fn_def.implicit_return_type; |
| 2053 | gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type); | 2045 | gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type); |
| 2054 | 2046 | ||
| 2055 | } | 2047 | } |
| ... | @@ -2549,8 +2541,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, | ... | @@ -2549,8 +2541,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 2549 | Buf *import_code = buf_alloc(); | 2541 | Buf *import_code = buf_alloc(); |
| 2550 | bool found_it = false; | 2542 | bool found_it = false; |
| 2551 | 2543 | ||
| 2552 | alloc_codegen_node(top_level_decl); | ||
| 2553 | |||
| 2554 | for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) { | 2544 | for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) { |
| 2555 | Buf *search_path = g->lib_search_paths.at(path_i); | 2545 | Buf *search_path = g->lib_search_paths.at(path_i); |
| 2556 | os_path_join(search_path, import_target_path, &full_path); | 2546 | os_path_join(search_path, import_target_path, &full_path); |
| ... | @@ -2570,7 +2560,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, | ... | @@ -2570,7 +2560,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 2570 | auto entry = g->import_table.maybe_get(abs_full_path); | 2560 | auto entry = g->import_table.maybe_get(abs_full_path); |
| 2571 | if (entry) { | 2561 | if (entry) { |
| 2572 | found_it = true; | 2562 | found_it = true; |
| 2573 | top_level_decl->codegen_node->data.import_node.import = entry->value; | 2563 | top_level_decl->data.use.import = entry->value; |
| 2574 | } else { | 2564 | } else { |
| 2575 | if ((err = os_fetch_file_path(abs_full_path, import_code))) { | 2565 | if ((err = os_fetch_file_path(abs_full_path, import_code))) { |
| 2576 | if (err == ErrorFileNotFound) { | 2566 | if (err == ErrorFileNotFound) { |
| ... | @@ -2582,7 +2572,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, | ... | @@ -2582,7 +2572,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 2582 | goto done_looking_at_imports; | 2572 | goto done_looking_at_imports; |
| 2583 | } | 2573 | } |
| 2584 | } | 2574 | } |
| 2585 | top_level_decl->codegen_node->data.import_node.import = codegen_add_code(g, | 2575 | top_level_decl->data.use.import = codegen_add_code(g, |
| 2586 | abs_full_path, search_path, &top_level_decl->data.use.path, import_code); | 2576 | abs_full_path, search_path, &top_level_decl->data.use.path, import_code); |
| 2587 | found_it = true; | 2577 | found_it = true; |
| 2588 | } | 2578 | } |
| ... | @@ -2682,9 +2672,8 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou | ... | @@ -2682,9 +2672,8 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou |
| 2682 | 2672 | ||
| 2683 | static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) { | 2673 | static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) { |
| 2684 | assert(type_node->type == NodeTypeType); | 2674 | assert(type_node->type == NodeTypeType); |
| 2685 | assert(type_node->codegen_node); | ||
| 2686 | 2675 | ||
| 2687 | TypeTableEntry *type_entry = type_node->codegen_node->data.type_node.entry; | 2676 | TypeTableEntry *type_entry = type_node->data.type.entry; |
| 2688 | assert(type_entry); | 2677 | assert(type_entry); |
| 2689 | 2678 | ||
| 2690 | if (type_entry == g->builtin_types.entry_u8) { | 2679 | if (type_entry == g->builtin_types.entry_u8) { |
src/codegen.hpp-13| ... | @@ -11,21 +11,8 @@ | ... | @@ -11,21 +11,8 @@ |
| 11 | #include "parser.hpp" | 11 | #include "parser.hpp" |
| 12 | #include "errmsg.hpp" | 12 | #include "errmsg.hpp" |
| 13 | 13 | ||
| 14 | struct CodeGen; | ||
| 15 | |||
| 16 | enum OutType { | ||
| 17 | OutTypeUnknown, | ||
| 18 | OutTypeExe, | ||
| 19 | OutTypeLib, | ||
| 20 | OutTypeObj, | ||
| 21 | }; | ||
| 22 | |||
| 23 | CodeGen *codegen_create(Buf *root_source_dir); | 14 | CodeGen *codegen_create(Buf *root_source_dir); |
| 24 | 15 | ||
| 25 | enum CodeGenBuildType { | ||
| 26 | CodeGenBuildTypeDebug, | ||
| 27 | CodeGenBuildTypeRelease, | ||
| 28 | }; | ||
| 29 | void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type); | 16 | void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type); |
| 30 | void codegen_set_is_static(CodeGen *codegen, bool is_static); | 17 | void codegen_set_is_static(CodeGen *codegen, bool is_static); |
| 31 | void codegen_set_strip(CodeGen *codegen, bool strip); | 18 | void codegen_set_strip(CodeGen *codegen, bool strip); |
src/parser.cpp+9-9| ... | @@ -356,8 +356,7 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -356,8 +356,7 @@ void ast_print(AstNode *node, int indent) { |
| 356 | fprintf(stderr, "Unreachable\n"); | 356 | fprintf(stderr, "Unreachable\n"); |
| 357 | break; | 357 | break; |
| 358 | case NodeTypeSymbol: | 358 | case NodeTypeSymbol: |
| 359 | fprintf(stderr, "Symbol %s\n", | 359 | fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol)); |
| 360 | buf_ptr(&node->data.symbol)); | ||
| 361 | break; | 360 | break; |
| 362 | case NodeTypeUse: | 361 | case NodeTypeUse: |
| 363 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path)); | 362 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path)); |
| ... | @@ -366,7 +365,8 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -366,7 +365,8 @@ void ast_print(AstNode *node, int indent) { |
| 366 | fprintf(stderr, "%s\n", node_type_str(node->type)); | 365 | fprintf(stderr, "%s\n", node_type_str(node->type)); |
| 367 | break; | 366 | break; |
| 368 | case NodeTypeBoolLiteral: | 367 | case NodeTypeBoolLiteral: |
| 369 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), node->data.bool_literal ? "true" : "false"); | 368 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), |
| 369 | node->data.bool_literal.value ? "true" : "false"); | ||
| 370 | break; | 370 | break; |
| 371 | case NodeTypeNullLiteral: | 371 | case NodeTypeNullLiteral: |
| 372 | fprintf(stderr, "%s\n", node_type_str(node->type)); | 372 | fprintf(stderr, "%s\n", node_type_str(node->type)); |
| ... | @@ -401,7 +401,7 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -401,7 +401,7 @@ void ast_print(AstNode *node, int indent) { |
| 401 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name)); | 401 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name)); |
| 402 | break; | 402 | break; |
| 403 | case NodeTypeGoto: | 403 | case NodeTypeGoto: |
| 404 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.go_to.name)); | 404 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.goto_expr.name)); |
| 405 | break; | 405 | break; |
| 406 | case NodeTypeBreak: | 406 | case NodeTypeBreak: |
| 407 | fprintf(stderr, "%s\n", node_type_str(node->type)); | 407 | fprintf(stderr, "%s\n", node_type_str(node->type)); |
| ... | @@ -1369,12 +1369,12 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool | ... | @@ -1369,12 +1369,12 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool |
| 1369 | return node; | 1369 | return node; |
| 1370 | } else if (token->id == TokenIdKeywordTrue) { | 1370 | } else if (token->id == TokenIdKeywordTrue) { |
| 1371 | AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token); | 1371 | AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token); |
| 1372 | node->data.bool_literal = true; | 1372 | node->data.bool_literal.value = true; |
| 1373 | *token_index += 1; | 1373 | *token_index += 1; |
| 1374 | return node; | 1374 | return node; |
| 1375 | } else if (token->id == TokenIdKeywordFalse) { | 1375 | } else if (token->id == TokenIdKeywordFalse) { |
| 1376 | AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token); | 1376 | AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token); |
| 1377 | node->data.bool_literal = false; | 1377 | node->data.bool_literal.value = false; |
| 1378 | *token_index += 1; | 1378 | *token_index += 1; |
| 1379 | return node; | 1379 | return node; |
| 1380 | } else if (token->id == TokenIdKeywordNull) { | 1380 | } else if (token->id == TokenIdKeywordNull) { |
| ... | @@ -1385,7 +1385,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool | ... | @@ -1385,7 +1385,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool |
| 1385 | *token_index += 1; | 1385 | *token_index += 1; |
| 1386 | Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); | 1386 | Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); |
| 1387 | AstNode *name_node = ast_create_node(pc, NodeTypeSymbol, name_tok); | 1387 | AstNode *name_node = ast_create_node(pc, NodeTypeSymbol, name_tok); |
| 1388 | ast_buf_from_token(pc, name_tok, &name_node->data.symbol); | 1388 | ast_buf_from_token(pc, name_tok, &name_node->data.symbol_expr.symbol); |
| 1389 | 1389 | ||
| 1390 | AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token); | 1390 | AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token); |
| 1391 | node->data.fn_call_expr.fn_ref_expr = name_node; | 1391 | node->data.fn_call_expr.fn_ref_expr = name_node; |
| ... | @@ -1401,7 +1401,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool | ... | @@ -1401,7 +1401,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool |
| 1401 | } else { | 1401 | } else { |
| 1402 | *token_index += 1; | 1402 | *token_index += 1; |
| 1403 | AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); | 1403 | AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); |
| 1404 | ast_buf_from_token(pc, token, &node->data.symbol); | 1404 | ast_buf_from_token(pc, token, &node->data.symbol_expr.symbol); |
| 1405 | return node; | 1405 | return node; |
| 1406 | } | 1406 | } |
| 1407 | } else if (token->id == TokenIdKeywordGoto) { | 1407 | } else if (token->id == TokenIdKeywordGoto) { |
| ... | @@ -1412,7 +1412,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool | ... | @@ -1412,7 +1412,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool |
| 1412 | *token_index += 1; | 1412 | *token_index += 1; |
| 1413 | ast_expect_token(pc, dest_symbol, TokenIdSymbol); | 1413 | ast_expect_token(pc, dest_symbol, TokenIdSymbol); |
| 1414 | 1414 | ||
| 1415 | ast_buf_from_token(pc, dest_symbol, &node->data.go_to.name); | 1415 | ast_buf_from_token(pc, dest_symbol, &node->data.goto_expr.name); |
| 1416 | return node; | 1416 | return node; |
| 1417 | } else if (token->id == TokenIdKeywordBreak) { | 1417 | } else if (token->id == TokenIdKeywordBreak) { |
| 1418 | AstNode *node = ast_create_node(pc, NodeTypeBreak, token); | 1418 | AstNode *node = ast_create_node(pc, NodeTypeBreak, token); |
src/parser.hpp+1-441| ... | @@ -8,450 +8,10 @@ | ... | @@ -8,450 +8,10 @@ |
| 8 | #ifndef ZIG_PARSER_HPP | 8 | #ifndef ZIG_PARSER_HPP |
| 9 | #define ZIG_PARSER_HPP | 9 | #define ZIG_PARSER_HPP |
| 10 | 10 | ||
| 11 | #include "list.hpp" | 11 | #include "all_types.hpp" |
| 12 | #include "buffer.hpp" | ||
| 13 | #include "tokenizer.hpp" | 12 | #include "tokenizer.hpp" |
| 14 | #include "errmsg.hpp" | 13 | #include "errmsg.hpp" |
| 15 | 14 | ||
| 16 | struct AstNode; | ||
| 17 | struct CodeGenNode; | ||
| 18 | struct ImportTableEntry; | ||
| 19 | struct AsmToken; | ||
| 20 | |||
| 21 | enum NodeType { | ||
| 22 | NodeTypeRoot, | ||
| 23 | NodeTypeRootExportDecl, | ||
| 24 | NodeTypeFnProto, | ||
| 25 | NodeTypeFnDef, | ||
| 26 | NodeTypeFnDecl, | ||
| 27 | NodeTypeParamDecl, | ||
| 28 | NodeTypeType, | ||
| 29 | NodeTypeBlock, | ||
| 30 | NodeTypeExternBlock, | ||
| 31 | NodeTypeDirective, | ||
| 32 | NodeTypeReturnExpr, | ||
| 33 | NodeTypeVariableDeclaration, | ||
| 34 | NodeTypeBinOpExpr, | ||
| 35 | NodeTypeCastExpr, | ||
| 36 | NodeTypeNumberLiteral, | ||
| 37 | NodeTypeStringLiteral, | ||
| 38 | NodeTypeCharLiteral, | ||
| 39 | NodeTypeUnreachable, | ||
| 40 | NodeTypeSymbol, | ||
| 41 | NodeTypePrefixOpExpr, | ||
| 42 | NodeTypeFnCallExpr, | ||
| 43 | NodeTypeArrayAccessExpr, | ||
| 44 | NodeTypeSliceExpr, | ||
| 45 | NodeTypeFieldAccessExpr, | ||
| 46 | NodeTypeUse, | ||
| 47 | NodeTypeVoid, | ||
| 48 | NodeTypeBoolLiteral, | ||
| 49 | NodeTypeNullLiteral, | ||
| 50 | NodeTypeIfBoolExpr, | ||
| 51 | NodeTypeIfVarExpr, | ||
| 52 | NodeTypeWhileExpr, | ||
| 53 | NodeTypeLabel, | ||
| 54 | NodeTypeGoto, | ||
| 55 | NodeTypeBreak, | ||
| 56 | NodeTypeContinue, | ||
| 57 | NodeTypeAsmExpr, | ||
| 58 | NodeTypeStructDecl, | ||
| 59 | NodeTypeStructField, | ||
| 60 | NodeTypeStructValueExpr, | ||
| 61 | NodeTypeStructValueField, | ||
| 62 | NodeTypeEnumDecl, | ||
| 63 | NodeTypeEnumField, | ||
| 64 | NodeTypeCompilerFnExpr, | ||
| 65 | NodeTypeCompilerFnType, | ||
| 66 | }; | ||
| 67 | |||
| 68 | struct AstNodeRoot { | ||
| 69 | ZigList<AstNode *> top_level_decls; | ||
| 70 | }; | ||
| 71 | |||
| 72 | enum VisibMod { | ||
| 73 | VisibModPrivate, | ||
| 74 | VisibModPub, | ||
| 75 | VisibModExport, | ||
| 76 | }; | ||
| 77 | |||
| 78 | struct AstNodeFnProto { | ||
| 79 | ZigList<AstNode *> *directives; | ||
| 80 | VisibMod visib_mod; | ||
| 81 | Buf name; | ||
| 82 | ZigList<AstNode *> params; | ||
| 83 | AstNode *return_type; | ||
| 84 | bool is_var_args; | ||
| 85 | |||
| 86 | // the extern block this fn proto is inside. can be null. | ||
| 87 | // populated by semantic analyzer. | ||
| 88 | AstNode *extern_node; | ||
| 89 | // the struct decl node this fn proto is inside. can be null. | ||
| 90 | // populated by semantic analyzer. | ||
| 91 | AstNode *struct_node; | ||
| 92 | // the function definition this fn proto is inside. can be null. | ||
| 93 | // populated by semantic analyzer. | ||
| 94 | AstNode *fn_def_node; | ||
| 95 | }; | ||
| 96 | |||
| 97 | struct AstNodeFnDef { | ||
| 98 | AstNode *fn_proto; | ||
| 99 | AstNode *body; | ||
| 100 | }; | ||
| 101 | |||
| 102 | struct AstNodeFnDecl { | ||
| 103 | AstNode *fn_proto; | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct AstNodeParamDecl { | ||
| 107 | Buf name; | ||
| 108 | AstNode *type; | ||
| 109 | }; | ||
| 110 | |||
| 111 | enum AstNodeTypeType { | ||
| 112 | AstNodeTypeTypePrimitive, | ||
| 113 | AstNodeTypeTypePointer, | ||
| 114 | AstNodeTypeTypeArray, | ||
| 115 | AstNodeTypeTypeMaybe, | ||
| 116 | AstNodeTypeTypeCompilerExpr, | ||
| 117 | }; | ||
| 118 | |||
| 119 | struct AstNodeType { | ||
| 120 | AstNodeTypeType type; | ||
| 121 | Buf primitive_name; | ||
| 122 | AstNode *child_type; | ||
| 123 | AstNode *array_size; // can be null | ||
| 124 | bool is_const; | ||
| 125 | bool is_noalias; | ||
| 126 | AstNode *compiler_expr; | ||
| 127 | }; | ||
| 128 | |||
| 129 | struct AstNodeBlock { | ||
| 130 | ZigList<AstNode *> statements; | ||
| 131 | }; | ||
| 132 | |||
| 133 | struct AstNodeReturnExpr { | ||
| 134 | // might be null in case of return void; | ||
| 135 | AstNode *expr; | ||
| 136 | }; | ||
| 137 | |||
| 138 | struct AstNodeVariableDeclaration { | ||
| 139 | Buf symbol; | ||
| 140 | bool is_const; | ||
| 141 | VisibMod visib_mod; | ||
| 142 | // one or both of type and expr will be non null | ||
| 143 | AstNode *type; | ||
| 144 | AstNode *expr; | ||
| 145 | }; | ||
| 146 | |||
| 147 | enum BinOpType { | ||
| 148 | BinOpTypeInvalid, | ||
| 149 | BinOpTypeAssign, | ||
| 150 | BinOpTypeAssignTimes, | ||
| 151 | BinOpTypeAssignDiv, | ||
| 152 | BinOpTypeAssignMod, | ||
| 153 | BinOpTypeAssignPlus, | ||
| 154 | BinOpTypeAssignMinus, | ||
| 155 | BinOpTypeAssignBitShiftLeft, | ||
| 156 | BinOpTypeAssignBitShiftRight, | ||
| 157 | BinOpTypeAssignBitAnd, | ||
| 158 | BinOpTypeAssignBitXor, | ||
| 159 | BinOpTypeAssignBitOr, | ||
| 160 | BinOpTypeAssignBoolAnd, | ||
| 161 | BinOpTypeAssignBoolOr, | ||
| 162 | BinOpTypeBoolOr, | ||
| 163 | BinOpTypeBoolAnd, | ||
| 164 | BinOpTypeCmpEq, | ||
| 165 | BinOpTypeCmpNotEq, | ||
| 166 | BinOpTypeCmpLessThan, | ||
| 167 | BinOpTypeCmpGreaterThan, | ||
| 168 | BinOpTypeCmpLessOrEq, | ||
| 169 | BinOpTypeCmpGreaterOrEq, | ||
| 170 | BinOpTypeBinOr, | ||
| 171 | BinOpTypeBinXor, | ||
| 172 | BinOpTypeBinAnd, | ||
| 173 | BinOpTypeBitShiftLeft, | ||
| 174 | BinOpTypeBitShiftRight, | ||
| 175 | BinOpTypeAdd, | ||
| 176 | BinOpTypeSub, | ||
| 177 | BinOpTypeMult, | ||
| 178 | BinOpTypeDiv, | ||
| 179 | BinOpTypeMod, | ||
| 180 | BinOpTypeUnwrapMaybe, | ||
| 181 | }; | ||
| 182 | |||
| 183 | struct AstNodeBinOpExpr { | ||
| 184 | AstNode *op1; | ||
| 185 | BinOpType bin_op; | ||
| 186 | AstNode *op2; | ||
| 187 | }; | ||
| 188 | |||
| 189 | struct AstNodeFnCallExpr { | ||
| 190 | AstNode *fn_ref_expr; | ||
| 191 | ZigList<AstNode *> params; | ||
| 192 | bool is_builtin; | ||
| 193 | }; | ||
| 194 | |||
| 195 | struct AstNodeArrayAccessExpr { | ||
| 196 | AstNode *array_ref_expr; | ||
| 197 | AstNode *subscript; | ||
| 198 | }; | ||
| 199 | |||
| 200 | struct AstNodeSliceExpr { | ||
| 201 | AstNode *array_ref_expr; | ||
| 202 | AstNode *start; | ||
| 203 | AstNode *end; | ||
| 204 | bool is_const; | ||
| 205 | }; | ||
| 206 | |||
| 207 | struct AstNodeFieldAccessExpr { | ||
| 208 | AstNode *struct_expr; | ||
| 209 | Buf field_name; | ||
| 210 | }; | ||
| 211 | |||
| 212 | struct AstNodeExternBlock { | ||
| 213 | ZigList<AstNode *> *directives; | ||
| 214 | ZigList<AstNode *> fn_decls; | ||
| 215 | }; | ||
| 216 | |||
| 217 | struct AstNodeDirective { | ||
| 218 | Buf name; | ||
| 219 | Buf param; | ||
| 220 | }; | ||
| 221 | |||
| 222 | struct AstNodeRootExportDecl { | ||
| 223 | Buf type; | ||
| 224 | Buf name; | ||
| 225 | ZigList<AstNode *> *directives; | ||
| 226 | }; | ||
| 227 | |||
| 228 | struct AstNodeCastExpr { | ||
| 229 | AstNode *expr; | ||
| 230 | AstNode *type; | ||
| 231 | }; | ||
| 232 | |||
| 233 | enum PrefixOp { | ||
| 234 | PrefixOpInvalid, | ||
| 235 | PrefixOpBoolNot, | ||
| 236 | PrefixOpBinNot, | ||
| 237 | PrefixOpNegation, | ||
| 238 | PrefixOpAddressOf, | ||
| 239 | PrefixOpConstAddressOf, | ||
| 240 | PrefixOpDereference, | ||
| 241 | }; | ||
| 242 | |||
| 243 | struct AstNodePrefixOpExpr { | ||
| 244 | PrefixOp prefix_op; | ||
| 245 | AstNode *primary_expr; | ||
| 246 | }; | ||
| 247 | |||
| 248 | struct AstNodeUse { | ||
| 249 | Buf path; | ||
| 250 | ZigList<AstNode *> *directives; | ||
| 251 | }; | ||
| 252 | |||
| 253 | struct AstNodeIfBoolExpr { | ||
| 254 | AstNode *condition; | ||
| 255 | AstNode *then_block; | ||
| 256 | AstNode *else_node; // null, block node, or other if expr node | ||
| 257 | }; | ||
| 258 | |||
| 259 | struct AstNodeIfVarExpr { | ||
| 260 | AstNodeVariableDeclaration var_decl; | ||
| 261 | AstNode *then_block; | ||
| 262 | AstNode *else_node; // null, block node, or other if expr node | ||
| 263 | }; | ||
| 264 | |||
| 265 | struct AstNodeWhileExpr { | ||
| 266 | AstNode *condition; | ||
| 267 | AstNode *body; | ||
| 268 | }; | ||
| 269 | |||
| 270 | struct AstNodeLabel { | ||
| 271 | Buf name; | ||
| 272 | }; | ||
| 273 | |||
| 274 | struct AstNodeGoto { | ||
| 275 | Buf name; | ||
| 276 | }; | ||
| 277 | |||
| 278 | struct AsmOutput { | ||
| 279 | Buf asm_symbolic_name; | ||
| 280 | Buf constraint; | ||
| 281 | Buf variable_name; | ||
| 282 | AstNode *return_type; // null unless "=r" and return | ||
| 283 | }; | ||
| 284 | |||
| 285 | struct AsmInput { | ||
| 286 | Buf asm_symbolic_name; | ||
| 287 | Buf constraint; | ||
| 288 | AstNode *expr; | ||
| 289 | }; | ||
| 290 | |||
| 291 | struct SrcPos { | ||
| 292 | int line; | ||
| 293 | int column; | ||
| 294 | }; | ||
| 295 | |||
| 296 | struct AstNodeAsmExpr { | ||
| 297 | bool is_volatile; | ||
| 298 | Buf asm_template; | ||
| 299 | ZigList<SrcPos> offset_map; | ||
| 300 | ZigList<AsmToken> token_list; | ||
| 301 | ZigList<AsmOutput*> output_list; | ||
| 302 | ZigList<AsmInput*> input_list; | ||
| 303 | ZigList<Buf*> clobber_list; | ||
| 304 | int return_count; // populated by analyze | ||
| 305 | }; | ||
| 306 | |||
| 307 | struct AstNodeStructDecl { | ||
| 308 | Buf name; | ||
| 309 | ZigList<AstNode *> fields; | ||
| 310 | ZigList<AstNode *> fns; | ||
| 311 | ZigList<AstNode *> *directives; | ||
| 312 | VisibMod visib_mod; | ||
| 313 | }; | ||
| 314 | |||
| 315 | struct AstNodeStructField { | ||
| 316 | Buf name; | ||
| 317 | AstNode *type; | ||
| 318 | ZigList<AstNode *> *directives; | ||
| 319 | }; | ||
| 320 | |||
| 321 | struct AstNodeEnumDecl { | ||
| 322 | Buf name; | ||
| 323 | ZigList<AstNode *> fields; | ||
| 324 | ZigList<AstNode *> *directives; | ||
| 325 | VisibMod visib_mod; | ||
| 326 | }; | ||
| 327 | |||
| 328 | struct AstNodeEnumField { | ||
| 329 | Buf name; | ||
| 330 | ZigList<AstNode *> fields; // length 0 means simple enum | ||
| 331 | AstNode *val_expr; | ||
| 332 | }; | ||
| 333 | |||
| 334 | struct AstNodeStringLiteral { | ||
| 335 | Buf buf; | ||
| 336 | bool c; | ||
| 337 | }; | ||
| 338 | |||
| 339 | struct AstNodeCharLiteral { | ||
| 340 | uint8_t value; | ||
| 341 | }; | ||
| 342 | |||
| 343 | enum NumLit { | ||
| 344 | NumLitF32, | ||
| 345 | NumLitF64, | ||
| 346 | NumLitF128, | ||
| 347 | NumLitU8, | ||
| 348 | NumLitU16, | ||
| 349 | NumLitU32, | ||
| 350 | NumLitU64, | ||
| 351 | NumLitI8, | ||
| 352 | NumLitI16, | ||
| 353 | NumLitI32, | ||
| 354 | NumLitI64, | ||
| 355 | |||
| 356 | NumLitCount | ||
| 357 | }; | ||
| 358 | |||
| 359 | struct AstNodeNumberLiteral { | ||
| 360 | NumLit kind; | ||
| 361 | |||
| 362 | // overflow is true if when parsing the number, we discovered it would not | ||
| 363 | // fit without losing data in a uint64_t, int64_t, or double | ||
| 364 | bool overflow; | ||
| 365 | |||
| 366 | union { | ||
| 367 | uint64_t x_uint; | ||
| 368 | int64_t x_int; | ||
| 369 | double x_float; | ||
| 370 | } data; | ||
| 371 | }; | ||
| 372 | |||
| 373 | struct AstNodeStructValueField { | ||
| 374 | Buf name; | ||
| 375 | AstNode *expr; | ||
| 376 | }; | ||
| 377 | |||
| 378 | struct AstNodeStructValueExpr { | ||
| 379 | AstNode *type; | ||
| 380 | ZigList<AstNode *> fields; | ||
| 381 | }; | ||
| 382 | |||
| 383 | struct AstNodeCompilerFnExpr { | ||
| 384 | Buf name; | ||
| 385 | AstNode *expr; | ||
| 386 | }; | ||
| 387 | |||
| 388 | struct AstNodeCompilerFnType { | ||
| 389 | Buf name; | ||
| 390 | AstNode *type; | ||
| 391 | }; | ||
| 392 | |||
| 393 | struct AstNode { | ||
| 394 | enum NodeType type; | ||
| 395 | int line; | ||
| 396 | int column; | ||
| 397 | uint32_t create_index; // for determinism purposes | ||
| 398 | CodeGenNode *codegen_node; | ||
| 399 | ImportTableEntry *owner; | ||
| 400 | union { | ||
| 401 | AstNodeRoot root; | ||
| 402 | AstNodeRootExportDecl root_export_decl; | ||
| 403 | AstNodeFnDef fn_def; | ||
| 404 | AstNodeFnDecl fn_decl; | ||
| 405 | AstNodeFnProto fn_proto; | ||
| 406 | AstNodeType type; | ||
| 407 | AstNodeParamDecl param_decl; | ||
| 408 | AstNodeBlock block; | ||
| 409 | AstNodeReturnExpr return_expr; | ||
| 410 | AstNodeVariableDeclaration variable_declaration; | ||
| 411 | AstNodeBinOpExpr bin_op_expr; | ||
| 412 | AstNodeExternBlock extern_block; | ||
| 413 | AstNodeDirective directive; | ||
| 414 | AstNodeCastExpr cast_expr; | ||
| 415 | AstNodePrefixOpExpr prefix_op_expr; | ||
| 416 | AstNodeFnCallExpr fn_call_expr; | ||
| 417 | AstNodeArrayAccessExpr array_access_expr; | ||
| 418 | AstNodeSliceExpr slice_expr; | ||
| 419 | AstNodeUse use; | ||
| 420 | AstNodeIfBoolExpr if_bool_expr; | ||
| 421 | AstNodeIfVarExpr if_var_expr; | ||
| 422 | AstNodeWhileExpr while_expr; | ||
| 423 | AstNodeLabel label; | ||
| 424 | AstNodeGoto go_to; | ||
| 425 | AstNodeAsmExpr asm_expr; | ||
| 426 | AstNodeFieldAccessExpr field_access_expr; | ||
| 427 | AstNodeStructDecl struct_decl; | ||
| 428 | AstNodeStructField struct_field; | ||
| 429 | AstNodeEnumDecl enum_decl; | ||
| 430 | AstNodeEnumField enum_field; | ||
| 431 | AstNodeStringLiteral string_literal; | ||
| 432 | AstNodeCharLiteral char_literal; | ||
| 433 | AstNodeNumberLiteral number_literal; | ||
| 434 | AstNodeStructValueExpr struct_val_expr; | ||
| 435 | AstNodeStructValueField struct_val_field; | ||
| 436 | AstNodeCompilerFnExpr compiler_fn_expr; | ||
| 437 | AstNodeCompilerFnType compiler_fn_type; | ||
| 438 | Buf symbol; | ||
| 439 | bool bool_literal; | ||
| 440 | } data; | ||
| 441 | }; | ||
| 442 | |||
| 443 | enum AsmTokenId { | ||
| 444 | AsmTokenIdTemplate, | ||
| 445 | AsmTokenIdPercent, | ||
| 446 | AsmTokenIdVar, | ||
| 447 | }; | ||
| 448 | |||
| 449 | struct AsmToken { | ||
| 450 | enum AsmTokenId id; | ||
| 451 | int start; | ||
| 452 | int end; | ||
| 453 | }; | ||
| 454 | |||
| 455 | __attribute__ ((format (printf, 2, 3))) | 15 | __attribute__ ((format (printf, 2, 3))) |
| 456 | void ast_token_error(Token *token, const char *format, ...); | 16 | void ast_token_error(Token *token, const char *format, ...); |
| 457 | 17 |