authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 01:20:47-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-31 01:20:47-07:00
log3c2093fec64c38b2895fb162b7fe58e6ec232bc6
tree0c4dbb7cf5667d6e972035798fe5d9f1cf20d4c9
parent436e35516ac997ec5fc0d769386d9b1128195b16

parseh understands types better and handles some situations better

See #88 Also, includes partial implementation of typedef top level declaration. See #95 Also, fix function types. Previously the way we were deduping function type pointers was incorrect.

14 files changed, 1192 insertions(+), 672 deletions(-)

doc/langref.md+13-9
......@@ -5,15 +5,17 @@
55```
66Root = many(TopLevelDecl) "EOF"
77
8TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl)
8TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl | TypeDecl)
99
1010CImportDecl = "c_import" Block
1111
12TypeDecl = "type" "Symbol" "=" TypeExpr ";"
13
1214ErrorValueDecl = "error" "Symbol" ";"
1315
1416GlobalVarDecl = VariableDeclaration ";"
1517
16VariableDeclaration = ("var" | "const") "Symbol" option(":" PrefixOpExpression) "=" Expression
18VariableDeclaration = ("var" | "const") "Symbol" option(":" TypeExpr) "=" Expression
1719
1820ContainerDecl = ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
1921
......@@ -27,7 +29,7 @@ RootExportDecl = "export" "Symbol" "String" ";"
2729
2830ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
2931
30FnProto = "fn" option("Symbol") ParamDeclList option("->" PrefixOpExpression)
32FnProto = "fn" option("Symbol") ParamDeclList option("->" TypeExpr)
3133
3234Directive = "#" "Symbol" "(" "String" ")"
3335
......@@ -37,7 +39,7 @@ FnDef = FnProto Block
3739
3840ParamDeclList = "(" list(ParamDecl, ",") ")"
3941
40ParamDecl = option("noalias") option("Symbol" ":") PrefixOpExpression | "..."
42ParamDecl = option("noalias") option("Symbol" ":") TypeExpr | "..."
4143
4244Block = "{" list(option(Statement), ";") "}"
4345
......@@ -47,6 +49,8 @@ Label = "Symbol" ":"
4749
4850Expression = BlockExpression | NonBlockExpression
4951
52TypeExpr = PrefixOpExpression
53
5054NonBlockExpression = ReturnExpression | AssignmentExpression
5155
5256AsmExpression = "asm" option("volatile") "(" "String" option(AsmOutput) ")"
......@@ -55,7 +59,7 @@ AsmOutput = ":" list(AsmOutputItem, ",") option(AsmInput)
5559
5660AsmInput = ":" list(AsmInputItem, ",") option(AsmClobbers)
5761
58AsmOutputItem = "[" "Symbol" "]" "String" "(" ("Symbol" | "->" PrefixOpExpression) ")"
62AsmOutputItem = "[" "Symbol" "]" "String" "(" ("Symbol" | "->" TypeExpr) ")"
5963
6064AsmInputItem = "[" "Symbol" "]" "String" "(" Expression ")"
6165
......@@ -91,7 +95,7 @@ IfExpression = IfVarExpression | IfBoolExpression
9195
9296IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
9397
94IfVarExpression = "if" "(" ("const" | "var") "Symbol" option(":" PrefixOpExpression) "?=" Expression ")" Expression Option(Else)
98IfVarExpression = "if" "(" ("const" | "var") "Symbol" option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)
9599
96100Else = "else" Expression
97101
......@@ -117,7 +121,7 @@ AdditionOperator = "+" | "-" | "++"
117121
118122MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
119123
120CurlySuffixExpression = PrefixOpExpression option(ContainerInitExpression)
124CurlySuffixExpression = TypeExpr option(ContainerInitExpression)
121125
122126MultiplyOperator = "*" | "/" | "%"
123127
......@@ -143,13 +147,13 @@ PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%"
143147
144148PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol")
145149
146ArrayType = "[" option(Expression) "]" option("const") PrefixOpExpression
150ArrayType = "[" option(Expression) "]" option("const") TypeExpr
147151
148152GotoExpression = "goto" "Symbol"
149153
150154GroupedExpression = "(" Expression ")"
151155
152KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error"
156KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type"
153157```
154158
155159## Operator Precedence
src/all_types.hpp+69-17
......@@ -124,6 +124,7 @@ enum NodeType {
124124 NodeTypeDirective,
125125 NodeTypeReturnExpr,
126126 NodeTypeVariableDeclaration,
127 NodeTypeTypeDecl,
127128 NodeTypeErrorValueDecl,
128129 NodeTypeBinOpExpr,
129130 NodeTypeUnwrapErrorExpr,
......@@ -159,6 +160,7 @@ enum NodeType {
159160 NodeTypeStructValueField,
160161 NodeTypeArrayType,
161162 NodeTypeErrorType,
163 NodeTypeTypeLiteral,
162164};
163165
164166struct AstNodeRoot {
......@@ -212,9 +214,6 @@ struct AstNodeParamDecl {
212214
213215 // populated by semantic analyzer
214216 VariableTableEntry *variable;
215 bool is_byval;
216 int src_index;
217 int gen_index;
218217};
219218
220219struct AstNodeBlock {
......@@ -256,6 +255,19 @@ struct AstNodeVariableDeclaration {
256255 VariableTableEntry *variable;
257256};
258257
258struct AstNodeTypeDecl {
259 VisibMod visib_mod;
260 ZigList<AstNode *> *directives;
261 Buf symbol;
262 AstNode *child_type;
263
264 // populated by semantic analyzer
265 TopLevelDecl top_level_decl;
266 // if this is set, don't process the node; we've already done so
267 // and here is the type (with id TypeTableEntryIdTypeDecl)
268 TypeTableEntry *override_type;
269};
270
259271struct AstNodeErrorValueDecl {
260272 Buf name;
261273 VisibMod visib_mod;
......@@ -684,6 +696,11 @@ struct AstNodeErrorType {
684696 Expr resolved_expr;
685697};
686698
699struct AstNodeTypeLiteral {
700 // populated by semantic analyzer
701 Expr resolved_expr;
702};
703
687704struct AstNode {
688705 enum NodeType type;
689706 int line;
......@@ -704,6 +721,7 @@ struct AstNode {
704721 AstNodeBlock block;
705722 AstNodeReturnExpr return_expr;
706723 AstNodeVariableDeclaration variable_declaration;
724 AstNodeTypeDecl type_decl;
707725 AstNodeErrorValueDecl error_value_decl;
708726 AstNodeBinOpExpr bin_op_expr;
709727 AstNodeUnwrapErrorExpr unwrap_err_expr;
......@@ -740,6 +758,7 @@ struct AstNode {
740758 AstNodeContinueExpr continue_expr;
741759 AstNodeArrayType array_type;
742760 AstNodeErrorType error_type;
761 AstNodeTypeLiteral type_literal;
743762 } data;
744763};
745764
......@@ -755,6 +774,24 @@ struct AsmToken {
755774 int end;
756775};
757776
777struct FnTypeParamInfo {
778 bool is_noalias;
779 TypeTableEntry *type;
780};
781
782struct FnTypeId {
783 TypeTableEntry *return_type;
784 FnTypeParamInfo *param_info;
785 int param_count;
786 bool is_var_args;
787 bool is_naked;
788 bool is_extern;
789};
790
791uint32_t fn_type_id_hash(FnTypeId);
792bool fn_type_id_eql(FnTypeId a, FnTypeId b);
793
794
758795struct TypeTableEntryPointer {
759796 TypeTableEntry *child_type;
760797 bool is_const;
......@@ -820,17 +857,25 @@ struct TypeTableEntryEnum {
820857 bool complete;
821858};
822859
860struct FnGenParamInfo {
861 int src_index;
862 int gen_index;
863 bool is_byval;
864};
865
823866struct TypeTableEntryFn {
824 TypeTableEntry *src_return_type;
867 FnTypeId fn_type_id;
825868 TypeTableEntry *gen_return_type;
826 TypeTableEntry **param_types;
827 int src_param_count;
828 LLVMTypeRef raw_type_ref;
829 bool is_var_args;
830869 int gen_param_count;
870 FnGenParamInfo *gen_param_info;
871
872 LLVMTypeRef raw_type_ref;
831873 LLVMCallConv calling_convention;
832 bool is_extern;
833 bool is_naked;
874};
875
876struct TypeTableEntryTypeDecl {
877 TypeTableEntry *child_type;
878 TypeTableEntry *canonical_type;
834879};
835880
836881enum TypeTableEntryId {
......@@ -852,6 +897,7 @@ enum TypeTableEntryId {
852897 TypeTableEntryIdPureError,
853898 TypeTableEntryIdEnum,
854899 TypeTableEntryIdFn,
900 TypeTableEntryIdTypeDecl,
855901};
856902
857903struct TypeTableEntry {
......@@ -873,6 +919,7 @@ struct TypeTableEntry {
873919 TypeTableEntryError error;
874920 TypeTableEntryEnum enumeration;
875921 TypeTableEntryFn fn;
922 TypeTableEntryTypeDecl type_decl;
876923 } data;
877924
878925 // use these fields to make sure we don't duplicate type table entries for the same type
......@@ -900,7 +947,6 @@ struct ImportTableEntry {
900947
901948 // reminder: hash tables must be initialized before use
902949 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
903 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> fn_type_table;
904950};
905951
906952struct LabelTableEntry {
......@@ -969,12 +1015,14 @@ struct CodeGen {
9691015 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
9701016 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
9711017 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls;
1018 HashMap<FnTypeId, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
9721019
9731020 uint32_t next_unresolved_index;
9741021
9751022 struct {
9761023 TypeTableEntry *entry_bool;
9771024 TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64]
1025 TypeTableEntry *entry_c_int[8];
9781026 TypeTableEntry *entry_u8;
9791027 TypeTableEntry *entry_u16;
9801028 TypeTableEntry *entry_u32;
......@@ -1082,12 +1130,16 @@ struct BlockContext {
10821130 Buf *c_import_buf;
10831131};
10841132
1085struct ParseH {
1086 ZigList<ErrorMsg*> errors;
1087 ZigList<AstNode *> fn_list;
1088 ZigList<AstNode *> struct_list;
1089 ZigList<AstNode *> var_list;
1090 ZigList<AstNode *> incomplete_struct_list;
1133enum CIntType {
1134 CIntTypeShort,
1135 CIntTypeUShort,
1136 CIntTypeInt,
1137 CIntTypeUInt,
1138 CIntTypeLong,
1139 CIntTypeULong,
1140 CIntTypeLongLong,
1141 CIntTypeULongLong,
10911142};
10921143
1144
10931145#endif
src/analyze.cpp+377-166
......@@ -56,6 +56,7 @@ static AstNode *first_executing_node(AstNode *node) {
5656 case NodeTypeDirective:
5757 case NodeTypeReturnExpr:
5858 case NodeTypeVariableDeclaration:
59 case NodeTypeTypeDecl:
5960 case NodeTypeErrorValueDecl:
6061 case NodeTypeNumberLiteral:
6162 case NodeTypeStringLiteral:
......@@ -83,6 +84,7 @@ static AstNode *first_executing_node(AstNode *node) {
8384 case NodeTypeSwitchProng:
8485 case NodeTypeArrayType:
8586 case NodeTypeErrorType:
87 case NodeTypeTypeLiteral:
8688 case NodeTypeContainerInitExpr:
8789 return node;
8890 }
......@@ -123,6 +125,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
123125 case TypeTableEntryIdErrorUnion:
124126 case TypeTableEntryIdPureError:
125127 case TypeTableEntryIdUndefLit:
128 case TypeTableEntryIdTypeDecl:
126129 // nothing to init
127130 break;
128131 case TypeTableEntryIdStruct:
......@@ -149,7 +152,7 @@ static int bits_needed_for_unsigned(uint64_t x) {
149152 }
150153}
151154
152static TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
155TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
153156 return get_int_type(g, false, bits_needed_for_unsigned(x));
154157}
155158
......@@ -165,12 +168,15 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
165168 buf_resize(&entry->name, 0);
166169 buf_appendf(&entry->name, "&%s%s", const_str, buf_ptr(&child_type->name));
167170
171 TypeTableEntry *canon_child_type = get_underlying_type(child_type);
172 assert(canon_child_type->id != TypeTableEntryIdInvalid);
173
168174 bool zero_bits;
169 if (child_type->size_in_bits == 0) {
170 if (child_type->id == TypeTableEntryIdStruct) {
171 zero_bits = child_type->data.structure.complete;
172 } else if (child_type->id == TypeTableEntryIdEnum) {
173 zero_bits = child_type->data.enumeration.complete;
175 if (canon_child_type->size_in_bits == 0) {
176 if (canon_child_type->id == TypeTableEntryIdStruct) {
177 zero_bits = canon_child_type->data.structure.complete;
178 } else if (canon_child_type->id == TypeTableEntryIdEnum) {
179 zero_bits = canon_child_type->data.enumeration.complete;
174180 } else {
175181 zero_bits = true;
176182 }
......@@ -196,7 +202,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
196202 }
197203}
198204
199static TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
205TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
200206 if (child_type->maybe_parent) {
201207 TypeTableEntry *entry = child_type->maybe_parent;
202208 return entry;
......@@ -317,8 +323,7 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
317323 }
318324}
319325
320static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size)
321{
326TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size) {
322327 auto existing_entry = child_type->arrays_by_size.maybe_get(array_size);
323328 if (existing_entry) {
324329 TypeTableEntry *entry = existing_entry->value;
......@@ -417,147 +422,109 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *c
417422 }
418423}
419424
420// If the node does not have a constant expression value with a metatype, generates an error
421// and returns invalid type. Otherwise, returns the type of the constant expression value.
422// Must be called after analyze_expression on the same node.
423static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
424 if (node->type == NodeTypeSymbol && node->data.symbol_expr.override_type_entry) {
425 return node->data.symbol_expr.override_type_entry;
426 }
427 Expr *expr = get_resolved_expr(node);
428 assert(expr->type_entry);
429 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
430 return g->builtin_types.entry_invalid;
431 } else if (expr->type_entry->id == TypeTableEntryIdMetaType) {
432 // OK
433 } else {
434 add_node_error(g, node, buf_sprintf("expected type, found expression"));
435 return g->builtin_types.entry_invalid;
436 }
425TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type) {
426 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdTypeDecl);
437427
438 ConstExprValue *const_val = &expr->const_val;
439 if (!const_val->ok) {
440 add_node_error(g, node, buf_sprintf("unable to resolve constant expression"));
441 return g->builtin_types.entry_invalid;
442 }
428 buf_init_from_str(&entry->name, name);
443429
444 return const_val->data.x_type;
445}
430 entry->type_ref = child_type->type_ref;
431 entry->type_ref = child_type->type_ref;
432 entry->di_type = child_type->di_type;
433 entry->size_in_bits = child_type->size_in_bits;
434 entry->align_in_bits = child_type->align_in_bits;
446435
447// Calls analyze_expression on node, and then resolve_type.
448static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
449 AstNode *node)
450{
451 AstNode **node_ptr = node->parent_field;
452 analyze_expression(g, import, context, nullptr, *node_ptr);
453 return resolve_type(g, *node_ptr);
454}
436 entry->data.type_decl.child_type = child_type;
455437
456static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
457 TypeTableEntry *expected_type, AstNode *node, bool is_naked)
458{
459 assert(node->type == NodeTypeFnProto);
460 AstNodeFnProto *fn_proto = &node->data.fn_proto;
438 if (child_type->id == TypeTableEntryIdTypeDecl) {
439 entry->data.type_decl.canonical_type = child_type->data.type_decl.canonical_type;
440 } else {
441 entry->data.type_decl.canonical_type = child_type;
442 }
461443
462 if (fn_proto->skip) {
463 return g->builtin_types.entry_invalid;
444 return entry;
445}
446
447// accepts ownership of fn_type_id memory
448TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
449 auto table_entry = g->fn_type_table.maybe_get(fn_type_id);
450 if (table_entry) {
451 return table_entry->value;
464452 }
465453
466454 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
467 fn_type->data.fn.is_extern = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport);
468 fn_type->data.fn.is_naked = is_naked;
469 fn_type->data.fn.calling_convention = fn_proto->is_extern ? LLVMCCallConv : LLVMFastCallConv;
455 fn_type->data.fn.fn_type_id = fn_type_id;
456 fn_type->data.fn.calling_convention = fn_type_id.is_extern ? LLVMCCallConv : LLVMFastCallConv;
470457
471 int src_param_count = node->data.fn_proto.params.length;
472458 fn_type->size_in_bits = g->pointer_size_bytes * 8;
473459 fn_type->align_in_bits = g->pointer_size_bytes * 8;
474 fn_type->data.fn.src_param_count = src_param_count;
475 fn_type->data.fn.param_types = allocate<TypeTableEntry*>(src_param_count);
476460
477 // first, analyze the parameters and return type in order they appear in
478 // source code in order for error messages to be in the best order.
461 // populate the name of the type
479462 buf_resize(&fn_type->name, 0);
480 const char *extern_str = fn_type->data.fn.is_extern ? "extern " : "";
481 const char *naked_str = fn_type->data.fn.is_naked ? "naked " : "";
463 const char *extern_str = fn_type_id.is_extern ? "extern " : "";
464 const char *naked_str = fn_type_id.is_naked ? "naked " : "";
482465 buf_appendf(&fn_type->name, "%s%sfn(", extern_str, naked_str);
483 for (int i = 0; i < src_param_count; i += 1) {
484 AstNode *child = node->data.fn_proto.params.at(i);
485 assert(child->type == NodeTypeParamDecl);
486 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,
487 child->data.param_decl.type);
488 fn_type->data.fn.param_types[i] = type_entry;
466 for (int i = 0; i < fn_type_id.param_count; i += 1) {
467 FnTypeParamInfo *param_info = &fn_type_id.param_info[i];
489468
469 TypeTableEntry *param_type = param_info->type;
490470 const char *comma = (i == 0) ? "" : ", ";
491 buf_appendf(&fn_type->name, "%s%s", comma, buf_ptr(&type_entry->name));
471 const char *noalias_str = param_info->is_noalias ? "noalias " : "";
472 buf_appendf(&fn_type->name, "%s%s%s", comma, noalias_str, buf_ptr(&param_type->name));
492473 }
493474
494 TypeTableEntry *return_type = analyze_type_expr(g, import, import->block_context,
495 node->data.fn_proto.return_type);
496 fn_type->data.fn.src_return_type = return_type;
497 if (return_type->id == TypeTableEntryIdInvalid) {
498 fn_proto->skip = true;
499 }
500 fn_type->data.fn.is_var_args = fn_proto->is_var_args;
501 if (fn_proto->is_var_args) {
502 const char *comma = (src_param_count == 0) ? "" : ", ";
475 if (fn_type_id.is_var_args) {
476 const char *comma = (fn_type_id.param_count == 0) ? "" : ", ";
503477 buf_appendf(&fn_type->name, "%s...", comma);
504478 }
505479 buf_appendf(&fn_type->name, ")");
506 if (return_type->id != TypeTableEntryIdVoid) {
507 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&return_type->name));
480 if (fn_type_id.return_type->id != TypeTableEntryIdVoid) {
481 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id.return_type->name));
508482 }
509483
510484
511485 // next, loop over the parameters again and compute debug information
512486 // and codegen information
513 bool first_arg_return = !fn_proto->skip && handle_is_ptr(return_type);
487 bool first_arg_return = handle_is_ptr(fn_type_id.return_type);
514488 // +1 for maybe making the first argument the return value
515 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + src_param_count);
489 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id.param_count);
516490 // +1 because 0 is the return type and +1 for maybe making first arg ret val
517 LLVMZigDIType **param_di_types = allocate<LLVMZigDIType*>(2 + src_param_count);
518 param_di_types[0] = return_type->di_type;
491 LLVMZigDIType **param_di_types = allocate<LLVMZigDIType*>(2 + fn_type_id.param_count);
492 param_di_types[0] = fn_type_id.return_type->di_type;
519493 int gen_param_index = 0;
520494 TypeTableEntry *gen_return_type;
521495 if (first_arg_return) {
522 TypeTableEntry *gen_type = get_pointer_to_type(g, return_type, false);
496 TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id.return_type, false);
523497 gen_param_types[gen_param_index] = gen_type->type_ref;
524498 gen_param_index += 1;
525499 // after the gen_param_index += 1 because 0 is the return type
526500 param_di_types[gen_param_index] = gen_type->di_type;
527501 gen_return_type = g->builtin_types.entry_void;
528 } else if (return_type->size_in_bits == 0) {
502 } else if (fn_type_id.return_type->size_in_bits == 0) {
529503 gen_return_type = g->builtin_types.entry_void;
530504 } else {
531 gen_return_type = return_type;
505 gen_return_type = fn_type_id.return_type;
532506 }
533507 fn_type->data.fn.gen_return_type = gen_return_type;
534 for (int i = 0; i < src_param_count; i += 1) {
535 AstNode *child = node->data.fn_proto.params.at(i);
536 assert(child->type == NodeTypeParamDecl);
537 TypeTableEntry *type_entry = fn_type->data.fn.param_types[i];
538
539 if (type_entry->id == TypeTableEntryIdUnreachable) {
540 add_node_error(g, child->data.param_decl.type,
541 buf_sprintf("parameter of type 'unreachable' not allowed"));
542 fn_proto->skip = true;
543 } else if (type_entry->id == TypeTableEntryIdInvalid) {
544 fn_proto->skip = true;
545 }
546508
547 child->data.param_decl.src_index = i;
548 child->data.param_decl.gen_index = -1;
509 fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id.param_count);
510 for (int i = 0; i < fn_type_id.param_count; i += 1) {
511 FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i];
512 TypeTableEntry *type_entry = src_param_info->type;
513 FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i];
549514
550 if (!fn_proto->skip && type_entry->size_in_bits > 0) {
515 gen_param_info->src_index = i;
516 gen_param_info->gen_index = -1;
551517
518 if (type_entry->size_in_bits > 0) {
552519 TypeTableEntry *gen_type;
553520 if (handle_is_ptr(type_entry)) {
554521 gen_type = get_pointer_to_type(g, type_entry, true);
555 child->data.param_decl.is_byval = true;
522 gen_param_info->is_byval = true;
556523 } else {
557524 gen_type = type_entry;
558525 }
559526 gen_param_types[gen_param_index] = gen_type->type_ref;
560 child->data.param_decl.gen_index = gen_param_index;
527 gen_param_info->gen_index = gen_param_index;
561528
562529 gen_param_index += 1;
563530
......@@ -568,24 +535,168 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
568535
569536 fn_type->data.fn.gen_param_count = gen_param_index;
570537
538 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
539 gen_param_types, gen_param_index, fn_type_id.is_var_args);
540 fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);
541 LLVMZigDIFile *di_file = nullptr; // TODO if we get a crash maybe this is the culprit
542 fn_type->di_type = LLVMZigCreateSubroutineType(g->dbuilder, di_file,
543 param_di_types, gen_param_index + 1, 0);
544
545 g->fn_type_table.put(fn_type_id, fn_type);
546
547 return fn_type;
548}
549
550static TypeTableEntryId container_to_type(ContainerKind kind) {
551 switch (kind) {
552 case ContainerKindStruct:
553 return TypeTableEntryIdStruct;
554 case ContainerKindEnum:
555 return TypeTableEntryIdEnum;
556 }
557 zig_unreachable();
558}
559
560TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,
561 ContainerKind kind, AstNode *decl_node, const char *name)
562{
563 TypeTableEntryId type_id = container_to_type(kind);
564 TypeTableEntry *entry = new_type_table_entry(type_id);
565
566 switch (kind) {
567 case ContainerKindStruct:
568 entry->data.structure.decl_node = decl_node;
569 break;
570 case ContainerKindEnum:
571 entry->data.enumeration.decl_node = decl_node;
572 break;
573 }
574
575 unsigned line = decl_node ? decl_node->line : 0;
576
577 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), name);
578 entry->di_type = LLVMZigCreateReplaceableCompositeType(g->dbuilder,
579 LLVMZigTag_DW_structure_type(), name,
580 LLVMZigFileToScope(import->di_file), import->di_file, line + 1);
581
582 buf_init_from_str(&entry->name, name);
583
584 return entry;
585}
586
587
588TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry) {
589 if (type_entry->id == TypeTableEntryIdTypeDecl) {
590 return type_entry->data.type_decl.canonical_type;
591 } else {
592 return type_entry;
593 }
594}
595
596// If the node does not have a constant expression value with a metatype, generates an error
597// and returns invalid type. Otherwise, returns the type of the constant expression value.
598// Must be called after analyze_expression on the same node.
599static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
600 if (node->type == NodeTypeSymbol && node->data.symbol_expr.override_type_entry) {
601 return node->data.symbol_expr.override_type_entry;
602 }
603 Expr *expr = get_resolved_expr(node);
604 assert(expr->type_entry);
605 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
606 return g->builtin_types.entry_invalid;
607 } else if (expr->type_entry->id == TypeTableEntryIdMetaType) {
608 // OK
609 } else {
610 add_node_error(g, node, buf_sprintf("expected type, found expression"));
611 return g->builtin_types.entry_invalid;
612 }
613
614 ConstExprValue *const_val = &expr->const_val;
615 if (!const_val->ok) {
616 add_node_error(g, node, buf_sprintf("unable to resolve constant expression"));
617 return g->builtin_types.entry_invalid;
618 }
619
620 return const_val->data.x_type;
621}
622
623// Calls analyze_expression on node, and then resolve_type.
624static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
625 AstNode *node)
626{
627 AstNode **node_ptr = node->parent_field;
628 analyze_expression(g, import, context, nullptr, *node_ptr);
629 return resolve_type(g, *node_ptr);
630}
631
632static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
633 TypeTableEntry *expected_type, AstNode *node, bool is_naked)
634{
635 assert(node->type == NodeTypeFnProto);
636 AstNodeFnProto *fn_proto = &node->data.fn_proto;
637
571638 if (fn_proto->skip) {
572639 return g->builtin_types.entry_invalid;
573640 }
574641
575 auto table_entry = import->fn_type_table.maybe_get(&fn_type->name);
576 if (table_entry) {
577 return table_entry->value;
578 } else {
579 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
580 gen_param_types, gen_param_index, fn_type->data.fn.is_var_args);
581 fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);
582 fn_type->di_type = LLVMZigCreateSubroutineType(g->dbuilder, import->di_file,
583 param_di_types, gen_param_index + 1, 0);
642 FnTypeId fn_type_id;
643 fn_type_id.is_extern = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport);
644 fn_type_id.is_naked = is_naked;
645 fn_type_id.param_count = node->data.fn_proto.params.length;
646 fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count);
647 fn_type_id.is_var_args = fn_proto->is_var_args;
648 fn_type_id.return_type = analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type);
649
650 if (fn_type_id.return_type->id == TypeTableEntryIdInvalid) {
651 fn_proto->skip = true;
652 }
584653
585 import->fn_type_table.put(&fn_type->name, fn_type);
654 for (int i = 0; i < fn_type_id.param_count; i += 1) {
655 AstNode *child = node->data.fn_proto.params.at(i);
656 assert(child->type == NodeTypeParamDecl);
657 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,
658 child->data.param_decl.type);
659 switch (type_entry->id) {
660 case TypeTableEntryIdInvalid:
661 fn_proto->skip = true;
662 break;
663 case TypeTableEntryIdNumLitFloat:
664 case TypeTableEntryIdNumLitInt:
665 case TypeTableEntryIdUndefLit:
666 case TypeTableEntryIdMetaType:
667 case TypeTableEntryIdUnreachable:
668 fn_proto->skip = true;
669 add_node_error(g, child->data.param_decl.type,
670 buf_sprintf("parameter of type '%s' not allowed'", buf_ptr(&type_entry->name)));
671 break;
672 case TypeTableEntryIdVoid:
673 case TypeTableEntryIdBool:
674 case TypeTableEntryIdInt:
675 case TypeTableEntryIdFloat:
676 case TypeTableEntryIdPointer:
677 case TypeTableEntryIdArray:
678 case TypeTableEntryIdStruct:
679 case TypeTableEntryIdMaybe:
680 case TypeTableEntryIdErrorUnion:
681 case TypeTableEntryIdPureError:
682 case TypeTableEntryIdEnum:
683 case TypeTableEntryIdFn:
684 case TypeTableEntryIdTypeDecl:
685 break;
686 }
687 if (type_entry->id == TypeTableEntryIdInvalid) {
688 fn_proto->skip = true;
689 }
690 FnTypeParamInfo *param_info = &fn_type_id.param_info[i];
691 param_info->type = type_entry;
692 param_info->is_noalias = child->data.param_decl.is_noalias;
693 }
586694
587 return fn_type;
695 if (fn_proto->skip) {
696 return g->builtin_types.entry_invalid;
588697 }
698
699 return get_fn_type(g, fn_type_id);
589700}
590701
591702
......@@ -640,14 +751,14 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
640751 if (fn_table_entry->is_inline) {
641752 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMAlwaysInlineAttribute);
642753 }
643 if (fn_type->data.fn.is_naked) {
754 if (fn_type->data.fn.fn_type_id.is_naked) {
644755 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNakedAttribute);
645756 }
646757
647758 LLVMSetLinkage(fn_table_entry->fn_value, fn_table_entry->internal_linkage ?
648759 LLVMInternalLinkage : LLVMExternalLinkage);
649760
650 if (fn_type->data.fn.src_return_type->id == TypeTableEntryIdUnreachable) {
761 if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdUnreachable) {
651762 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoReturnAttribute);
652763 }
653764 LLVMSetFunctionCallConv(fn_table_entry->fn_value, fn_type->data.fn.calling_convention);
......@@ -691,6 +802,7 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_
691802}
692803
693804static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type) {
805 // if you change this logic you likely must also change similar logic in parseh.cpp
694806 assert(enum_type->id == TypeTableEntryIdEnum);
695807
696808 AstNode *decl_node = enum_type->data.enumeration.decl_node;
......@@ -853,6 +965,8 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
853965}
854966
855967static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type) {
968 // if you change the logic of this function likely you must make a similar change in
969 // parseh.cpp
856970 assert(struct_type->id == TypeTableEntryIdStruct);
857971
858972 AstNode *decl_node = struct_type->data.structure.decl_node;
......@@ -1104,15 +1218,12 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
11041218
11051219 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
11061220 child_import->fn_table.init(32);
1107 child_import->fn_type_table.init(32);
11081221 child_import->c_import_node = node;
11091222
11101223 ZigList<ErrorMsg *> errors = {0};
11111224
11121225 int err;
1113 if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len,
1114 buf_ptr(g->libc_include_path), false, &g->next_node_index)))
1115 {
1226 if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {
11161227 zig_panic("unable to parse h file: %s\n", err_str(err));
11171228 }
11181229
......@@ -1175,6 +1286,27 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
11751286 VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context,
11761287 nullptr, node);
11771288 g->global_vars.append(var);
1289 break;
1290 }
1291 case NodeTypeTypeDecl:
1292 {
1293 AstNode *type_node = node->data.type_decl.child_type;
1294 Buf *decl_name = &node->data.type_decl.symbol;
1295
1296 TypeTableEntry *typedecl_type;
1297 if (node->data.type_decl.override_type) {
1298 typedecl_type = node->data.type_decl.override_type;
1299 } else {
1300 TypeTableEntry *child_type = analyze_type_expr(g, import, import->block_context, type_node);
1301 if (child_type->id == TypeTableEntryIdInvalid) {
1302 typedecl_type = child_type;
1303 } else {
1304 typedecl_type = get_typedecl_type(g, buf_ptr(decl_name), child_type);
1305 }
1306 }
1307
1308 import->block_context->type_table.put(decl_name, typedecl_type);
1309
11781310 break;
11791311 }
11801312 case NodeTypeErrorValueDecl:
......@@ -1224,6 +1356,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
12241356 case NodeTypeContainerInitExpr:
12251357 case NodeTypeArrayType:
12261358 case NodeTypeErrorType:
1359 case NodeTypeTypeLiteral:
12271360 zig_unreachable();
12281361 }
12291362
......@@ -1278,8 +1411,10 @@ static bool type_has_codegen_value(TypeTableEntryId id) {
12781411 case TypeTableEntryIdEnum:
12791412 case TypeTableEntryIdFn:
12801413 return true;
1414
1415 case TypeTableEntryIdTypeDecl:
1416 zig_unreachable();
12811417 }
1282 zig_unreachable();
12831418}
12841419
12851420static void add_global_const_expr(CodeGen *g, Expr *expr) {
......@@ -1376,25 +1511,30 @@ static bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTable
13761511 if (expected_type->id == TypeTableEntryIdFn &&
13771512 actual_type->id == TypeTableEntryIdFn)
13781513 {
1379 if (expected_type->data.fn.is_extern != actual_type->data.fn.is_extern) {
1514 if (expected_type->data.fn.fn_type_id.is_extern != actual_type->data.fn.fn_type_id.is_extern) {
13801515 return false;
13811516 }
1382 if (expected_type->data.fn.is_naked != actual_type->data.fn.is_naked) {
1517 if (expected_type->data.fn.fn_type_id.is_naked != actual_type->data.fn.fn_type_id.is_naked) {
13831518 return false;
13841519 }
1385 if (!types_match_const_cast_only(expected_type->data.fn.src_return_type,
1386 actual_type->data.fn.src_return_type))
1520 if (!types_match_const_cast_only(expected_type->data.fn.fn_type_id.return_type,
1521 actual_type->data.fn.fn_type_id.return_type))
13871522 {
13881523 return false;
13891524 }
1390 if (expected_type->data.fn.src_param_count != actual_type->data.fn.src_param_count) {
1525 if (expected_type->data.fn.fn_type_id.param_count != actual_type->data.fn.fn_type_id.param_count) {
13911526 return false;
13921527 }
1393 for (int i = 0; i < expected_type->data.fn.src_param_count; i += 1) {
1528 for (int i = 0; i < expected_type->data.fn.fn_type_id.param_count; i += 1) {
13941529 // note it's reversed for parameters
1395 if (types_match_const_cast_only(actual_type->data.fn.param_types[i],
1396 expected_type->data.fn.param_types[i]))
1397 {
1530 FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];
1531 FnTypeParamInfo *expected_param_info = &expected_type->data.fn.fn_type_id.param_info[i];
1532
1533 if (!types_match_const_cast_only(actual_param_info->type, expected_param_info->type)) {
1534 return false;
1535 }
1536
1537 if (expected_param_info->is_noalias != actual_param_info->is_noalias) {
13981538 return false;
13991539 }
14001540 }
......@@ -3610,6 +3750,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
36103750 case TypeTableEntryIdPureError:
36113751 case TypeTableEntryIdEnum:
36123752 case TypeTableEntryIdFn:
3753 case TypeTableEntryIdTypeDecl:
36133754 return resolve_expr_const_val_as_type(g, node, type_entry);
36143755 }
36153756 }
......@@ -3664,14 +3805,14 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
36643805 assert(node->type == NodeTypeFnCallExpr);
36653806
36663807 // count parameters
3667 int src_param_count = fn_type->data.fn.src_param_count;
3808 int src_param_count = fn_type->data.fn.fn_type_id.param_count;
36683809 int actual_param_count = node->data.fn_call_expr.params.length;
36693810
36703811 if (struct_type) {
36713812 actual_param_count += 1;
36723813 }
36733814
3674 if (fn_type->data.fn.is_var_args) {
3815 if (fn_type->data.fn.fn_type_id.is_var_args) {
36753816 if (actual_param_count < src_param_count) {
36763817 add_node_error(g, node,
36773818 buf_sprintf("expected at least %d arguments, got %d", src_param_count, actual_param_count));
......@@ -3689,12 +3830,12 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
36893830 TypeTableEntry *expected_param_type = nullptr;
36903831 int fn_proto_i = i + (struct_type ? 1 : 0);
36913832 if (fn_proto_i < src_param_count) {
3692 expected_param_type = fn_type->data.fn.param_types[fn_proto_i];
3833 expected_param_type = fn_type->data.fn.fn_type_id.param_info[fn_proto_i].type;
36933834 }
36943835 analyze_expression(g, import, context, expected_param_type, child);
36953836 }
36963837
3697 TypeTableEntry *return_type = fn_type->data.fn.src_return_type;
3838 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
36983839
36993840 if (return_type->id == TypeTableEntryIdInvalid) {
37003841 return return_type;
......@@ -4304,6 +4445,9 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
43044445 case NodeTypeErrorType:
43054446 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_pure_error);
43064447 break;
4448 case NodeTypeTypeLiteral:
4449 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_type);
4450 break;
43074451 case NodeTypeSwitchExpr:
43084452 return_type = analyze_switch_expr(g, import, context, expected_type, node);
43094453 break;
......@@ -4322,6 +4466,7 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
43224466 case NodeTypeStructField:
43234467 case NodeTypeStructValueField:
43244468 case NodeTypeErrorValueDecl:
4469 case NodeTypeTypeDecl:
43254470 zig_unreachable();
43264471 }
43274472 assert(return_type);
......@@ -4354,8 +4499,9 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
43544499
43554500 BlockContext *context = node->data.fn_def.block_context;
43564501
4502 FnTableEntry *fn_table_entry = fn_proto_node->data.fn_proto.fn_table_entry;
4503 TypeTableEntry *fn_type = fn_table_entry->type_entry;
43574504 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
4358 bool is_exported = (fn_proto->visib_mod == VisibModExport);
43594505 for (int i = 0; i < fn_proto->params.length; i += 1) {
43604506 AstNode *param_decl_node = fn_proto->params.at(i);
43614507 assert(param_decl_node->type == NodeTypeParamDecl);
......@@ -4369,9 +4515,9 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
43694515 buf_sprintf("noalias on non-pointer parameter"));
43704516 }
43714517
4372 if (is_exported && type->id == TypeTableEntryIdStruct) {
4518 if (fn_type->data.fn.fn_type_id.is_extern && type->id == TypeTableEntryIdStruct) {
43734519 add_node_error(g, param_decl_node,
4374 buf_sprintf("byvalue struct parameters not yet supported on exported functions"));
4520 buf_sprintf("byvalue struct parameters not yet supported on extern functions"));
43754521 }
43764522
43774523 if (buf_len(&param_decl->name) == 0) {
......@@ -4382,16 +4528,15 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
43824528 var->src_arg_index = i;
43834529 param_decl_node->data.param_decl.variable = var;
43844530
4385 var->gen_arg_index = param_decl_node->data.param_decl.gen_index;
4531 var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index;
43864532 }
43874533
4388 TypeTableEntry *expected_type = unwrapped_node_type(fn_proto->return_type);
4534 TypeTableEntry *expected_type = fn_type->data.fn.fn_type_id.return_type;
43894535 TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);
43904536
43914537 node->data.fn_def.implicit_return_type = block_return_type;
43924538
43934539 {
4394 FnTableEntry *fn_table_entry = fn_proto_node->data.fn_proto.fn_table_entry;
43954540 auto it = fn_table_entry->label_table.entry_iterator();
43964541 for (;;) {
43974542 auto *entry = it.next();
......@@ -4427,6 +4572,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
44274572 case NodeTypeVariableDeclaration:
44284573 case NodeTypeErrorValueDecl:
44294574 case NodeTypeFnProto:
4575 case NodeTypeTypeDecl:
44304576 // already took care of these
44314577 break;
44324578 case NodeTypeDirective:
......@@ -4466,6 +4612,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
44664612 case NodeTypeContainerInitExpr:
44674613 case NodeTypeArrayType:
44684614 case NodeTypeErrorType:
4615 case NodeTypeTypeLiteral:
44694616 zig_unreachable();
44704617 }
44714618}
......@@ -4485,10 +4632,14 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
44854632 case NodeTypeContinue:
44864633 case NodeTypeErrorValueDecl:
44874634 case NodeTypeErrorType:
4635 case NodeTypeTypeLiteral:
44884636 // no dependencies on other top level declarations
44894637 break;
44904638 case NodeTypeSymbol:
44914639 {
4640 if (node->data.symbol_expr.override_type_entry) {
4641 break;
4642 }
44924643 Buf *name = &node->data.symbol_expr.symbol;
44934644 auto table_entry = g->primitive_type_table.maybe_get(name);
44944645 if (!table_entry) {
......@@ -4627,6 +4778,9 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
46274778 case NodeTypeParamDecl:
46284779 collect_expr_decl_deps(g, import, node->data.param_decl.type, decl_node);
46294780 break;
4781 case NodeTypeTypeDecl:
4782 collect_expr_decl_deps(g, import, node->data.type_decl.child_type, decl_node);
4783 break;
46304784 case NodeTypeVariableDeclaration:
46314785 case NodeTypeRootExportDecl:
46324786 case NodeTypeFnDef:
......@@ -4642,16 +4796,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
46424796 }
46434797}
46444798
4645static TypeTableEntryId container_to_type(ContainerKind kind) {
4646 switch (kind) {
4647 case ContainerKindStruct:
4648 return TypeTableEntryIdStruct;
4649 case ContainerKindEnum:
4650 return TypeTableEntryIdEnum;
4651 }
4652 zig_unreachable();
4653}
4654
46554799static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) {
46564800 switch (node->type) {
46574801 case NodeTypeRoot:
......@@ -4669,28 +4813,16 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
46694813 }
46704814 if (table_entry) {
46714815 node->data.struct_decl.type_entry = table_entry->value;
4672 add_node_error(g, node,
4673 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
4816 add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name)));
46744817 } else {
4675 TypeTableEntryId type_id = container_to_type(node->data.struct_decl.kind);
4676 TypeTableEntry *entry = new_type_table_entry(type_id);
4677 switch (node->data.struct_decl.kind) {
4678 case ContainerKindStruct:
4679 entry->data.structure.decl_node = node;
4680 break;
4681 case ContainerKindEnum:
4682 entry->data.enumeration.decl_node = node;
4683 break;
4818 TypeTableEntry *entry;
4819 if (node->data.struct_decl.type_entry) {
4820 entry = node->data.struct_decl.type_entry;
4821 } else {
4822 entry = get_partial_container_type(g, import,
4823 node->data.struct_decl.kind, node, buf_ptr(name));
46844824 }
46854825
4686 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name));
4687 entry->di_type = LLVMZigCreateReplaceableCompositeType(g->dbuilder,
4688 LLVMZigTag_DW_structure_type(), buf_ptr(name),
4689 LLVMZigFileToScope(import->di_file), import->di_file, node->line + 1);
4690
4691 buf_init_from_buf(&entry->name, name);
4692 // put off adding the debug type until we do the full struct body
4693 // this type is incomplete until we do another pass
46944826 import->block_context->type_table.put(&entry->name, entry);
46954827 node->data.struct_decl.type_entry = entry;
46964828
......@@ -4761,6 +4893,23 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
47614893 }
47624894 break;
47634895 }
4896 case NodeTypeTypeDecl:
4897 {
4898 // determine which other top level declarations this variable declaration depends on.
4899 TopLevelDecl *decl_node = &node->data.type_decl.top_level_decl;
4900 decl_node->deps.init(1);
4901 collect_expr_decl_deps(g, import, node, decl_node);
4902
4903 Buf *name = &node->data.type_decl.symbol;
4904 decl_node->name = name;
4905 decl_node->import = import;
4906 if (decl_node->deps.size() > 0) {
4907 g->unresolved_top_level_decls.put(name, node);
4908 } else {
4909 resolve_top_level_decl(g, import, node);
4910 }
4911 break;
4912 }
47644913 case NodeTypeFnProto:
47654914 {
47664915 // if the name is missing, we immediately announce an error
......@@ -4848,6 +4997,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
48484997 case NodeTypeStructValueField:
48494998 case NodeTypeArrayType:
48504999 case NodeTypeErrorType:
5000 case NodeTypeTypeLiteral:
48515001 zig_unreachable();
48525002 }
48535003}
......@@ -5063,6 +5213,8 @@ Expr *get_resolved_expr(AstNode *node) {
50635213 return &node->data.array_type.resolved_expr;
50645214 case NodeTypeErrorType:
50655215 return &node->data.error_type.resolved_expr;
5216 case NodeTypeTypeLiteral:
5217 return &node->data.type_literal.resolved_expr;
50665218 case NodeTypeSwitchExpr:
50675219 return &node->data.switch_expr.resolved_expr;
50685220 case NodeTypeFnProto:
......@@ -5081,6 +5233,7 @@ Expr *get_resolved_expr(AstNode *node) {
50815233 case NodeTypeStructField:
50825234 case NodeTypeStructValueField:
50835235 case NodeTypeErrorValueDecl:
5236 case NodeTypeTypeDecl:
50845237 zig_unreachable();
50855238 }
50865239 zig_unreachable();
......@@ -5098,6 +5251,8 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
50985251 return &node->data.error_value_decl.top_level_decl;
50995252 case NodeTypeCImport:
51005253 return &node->data.c_import.top_level_decl;
5254 case NodeTypeTypeDecl:
5255 return &node->data.type_decl.top_level_decl;
51015256 case NodeTypeNumberLiteral:
51025257 case NodeTypeReturnExpr:
51035258 case NodeTypeBinOpExpr:
......@@ -5138,6 +5293,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
51385293 case NodeTypeStructValueField:
51395294 case NodeTypeArrayType:
51405295 case NodeTypeErrorType:
5296 case NodeTypeTypeLiteral:
51415297 zig_unreachable();
51425298 }
51435299 zig_unreachable();
......@@ -5178,6 +5334,14 @@ TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits) {
51785334 return *get_int_type_ptr(g, is_signed, size_in_bits);
51795335}
51805336
5337TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
5338 return &g->builtin_types.entry_c_int[c_int_type];
5339}
5340
5341TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type) {
5342 return *get_c_int_type_ptr(g, c_int_type);
5343}
5344
51815345bool handle_is_ptr(TypeTableEntry *type_entry) {
51825346 switch (type_entry->id) {
51835347 case TypeTableEntryIdInvalid:
......@@ -5204,6 +5368,8 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
52045368 return type_entry->data.enumeration.gen_field_count != 0;
52055369 case TypeTableEntryIdMaybe:
52065370 return type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer;
5371 case TypeTableEntryIdTypeDecl:
5372 return handle_is_ptr(type_entry->data.type_decl.canonical_type);
52075373 }
52085374 zig_unreachable();
52095375}
......@@ -5226,3 +5392,48 @@ void find_libc_path(CodeGen *g) {
52265392 }
52275393}
52285394
5395static uint32_t hash_ptr(void *ptr) {
5396 uint64_t x = (uint64_t)(uintptr_t)(ptr);
5397 uint32_t a = x >> 32;
5398 uint32_t b = x & 0xffffffff;
5399 return a ^ b;
5400}
5401
5402uint32_t fn_type_id_hash(FnTypeId id) {
5403 uint32_t result = 0;
5404 result += id.is_extern ? 3349388391 : 0;
5405 result += id.is_naked ? 608688877 : 0;
5406 result += id.is_var_args ? 1931444534 : 0;
5407 result += hash_ptr(id.return_type);
5408 result += id.param_count;
5409 for (int i = 0; i < id.param_count; i += 1) {
5410 FnTypeParamInfo *info = &id.param_info[i];
5411 result += info->is_noalias ? 892356923 : 0;
5412 result += hash_ptr(info->type);
5413 }
5414 return result;
5415}
5416
5417bool fn_type_id_eql(FnTypeId a, FnTypeId b) {
5418 if (a.is_extern != b.is_extern ||
5419 a.is_naked != b.is_naked ||
5420 a.return_type != b.return_type ||
5421 a.is_var_args != b.is_var_args ||
5422 a.param_count != b.param_count)
5423 {
5424 return false;
5425 }
5426 for (int i = 0; i < a.param_count; i += 1) {
5427 FnTypeParamInfo *a_param_info = &a.param_info[i];
5428 FnTypeParamInfo *b_param_info = &b.param_info[i];
5429
5430 if (a_param_info->type != b_param_info->type) {
5431 return false;
5432 }
5433
5434 if (a_param_info->is_noalias != b_param_info->is_noalias) {
5435 return false;
5436 }
5437 }
5438 return true;
5439}
src/analyze.hpp+11
......@@ -22,7 +22,18 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
2222bool is_node_void_expr(AstNode *node);
2323TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);
2424TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);
25TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
26TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
27TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type);
28TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id);
29TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);
30TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
31TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,
32 ContainerKind kind, AstNode *decl_node, const char *name);
33TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
2534bool handle_is_ptr(TypeTableEntry *type_entry);
2635void find_libc_path(CodeGen *g);
2736
37TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);
38
2839#endif
src/ast_render.cpp+44-3
......@@ -119,6 +119,8 @@ static const char *node_type_str(NodeType node_type) {
119119 return "ReturnExpr";
120120 case NodeTypeVariableDeclaration:
121121 return "VariableDeclaration";
122 case NodeTypeTypeDecl:
123 return "TypeDecl";
122124 case NodeTypeErrorValueDecl:
123125 return "ErrorValueDecl";
124126 case NodeTypeNumberLiteral:
......@@ -179,6 +181,8 @@ static const char *node_type_str(NodeType node_type) {
179181 return "ArrayType";
180182 case NodeTypeErrorType:
181183 return "ErrorType";
184 case NodeTypeTypeLiteral:
185 return "TypeLiteral";
182186 }
183187}
184188
......@@ -260,6 +264,13 @@ void ast_print(FILE *f, AstNode *node, int indent) {
260264 ast_print(f, node->data.variable_declaration.expr, indent + 2);
261265 break;
262266 }
267 case NodeTypeTypeDecl:
268 {
269 Buf *name_buf = &node->data.type_decl.symbol;
270 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
271 ast_print(f, node->data.type_decl.child_type, indent + 2);
272 break;
273 }
263274 case NodeTypeErrorValueDecl:
264275 {
265276 Buf *name_buf = &node->data.error_value_decl.name;
......@@ -478,6 +489,9 @@ void ast_print(FILE *f, AstNode *node, int indent) {
478489 case NodeTypeErrorType:
479490 fprintf(f, "%s\n", node_type_str(node->type));
480491 break;
492 case NodeTypeTypeLiteral:
493 fprintf(f, "%s\n", node_type_str(node->type));
494 break;
481495 }
482496}
483497
......@@ -494,7 +508,14 @@ static void print_indent(AstRender *ar) {
494508}
495509
496510static bool is_node_void(AstNode *node) {
497 return node->type == NodeTypeSymbol && buf_eql_str(&node->data.symbol_expr.symbol, "void");
511 if (node->type == NodeTypeSymbol) {
512 if (node->data.symbol_expr.override_type_entry) {
513 return node->data.symbol_expr.override_type_entry->id == TypeTableEntryIdVoid;
514 } else if (buf_eql_str(&node->data.symbol_expr.symbol, "void")) {
515 return true;
516 }
517 }
518 return false;
498519}
499520
500521static bool is_printable(uint8_t c) {
......@@ -515,6 +536,7 @@ static void render_node(AstRender *ar, AstNode *node) {
515536
516537 if (child->type == NodeTypeImport ||
517538 child->type == NodeTypeVariableDeclaration ||
539 child->type == NodeTypeTypeDecl ||
518540 child->type == NodeTypeErrorValueDecl ||
519541 child->type == NodeTypeFnProto)
520542 {
......@@ -588,6 +610,14 @@ static void render_node(AstRender *ar, AstNode *node) {
588610 }
589611 break;
590612 }
613 case NodeTypeTypeDecl:
614 {
615 const char *pub_str = visib_mod_string(node->data.type_decl.visib_mod);
616 const char *var_name = buf_ptr(&node->data.type_decl.symbol);
617 fprintf(ar->f, "%stype %s = ", pub_str, var_name);
618 render_node(ar, node->data.type_decl.child_type);
619 break;
620 }
591621 case NodeTypeErrorValueDecl:
592622 zig_panic("TODO");
593623 case NodeTypeBinOpExpr:
......@@ -617,7 +647,14 @@ static void render_node(AstRender *ar, AstNode *node) {
617647 break;
618648 }
619649 case NodeTypeSymbol:
620 fprintf(ar->f, "%s", buf_ptr(&node->data.symbol_expr.symbol));
650 {
651 TypeTableEntry *override_type = node->data.symbol_expr.override_type_entry;
652 if (override_type) {
653 fprintf(ar->f, "%s", buf_ptr(&override_type->name));
654 } else {
655 fprintf(ar->f, "%s", buf_ptr(&node->data.symbol_expr.symbol));
656 }
657 }
621658 break;
622659 case NodeTypePrefixOpExpr:
623660 {
......@@ -719,7 +756,11 @@ static void render_node(AstRender *ar, AstNode *node) {
719756 break;
720757 }
721758 case NodeTypeErrorType:
722 zig_panic("TODO");
759 fprintf(ar->f, "error");
760 break;
761 case NodeTypeTypeLiteral:
762 fprintf(ar->f, "type");
763 break;
723764 }
724765}
725766
src/codegen.cpp+62-23
......@@ -13,11 +13,13 @@
1313#include "error.hpp"
1414#include "analyze.hpp"
1515#include "errmsg.hpp"
16#include "parseh.hpp"
1617#include "ast_render.hpp"
1718
1819#include <stdio.h>
1920#include <errno.h>
2021
22
2123CodeGen *codegen_create(Buf *root_source_dir) {
2224 CodeGen *g = allocate<CodeGen>(1);
2325 g->link_table.init(32);
......@@ -25,6 +27,7 @@ CodeGen *codegen_create(Buf *root_source_dir) {
2527 g->builtin_fn_table.init(32);
2628 g->primitive_type_table.init(32);
2729 g->unresolved_top_level_decls.init(32);
30 g->fn_type_table.init(32);
2831 g->build_type = CodeGenBuildTypeDebug;
2932 g->root_source_dir = root_source_dir;
3033 g->next_error_index = 1;
......@@ -530,12 +533,12 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
530533 fn_type = get_expr_type(fn_ref_expr);
531534 }
532535
533 TypeTableEntry *src_return_type = fn_type->data.fn.src_return_type;
536 TypeTableEntry *src_return_type = fn_type->data.fn.fn_type_id.return_type;
534537
535538 int fn_call_param_count = node->data.fn_call_expr.params.length;
536539 bool first_arg_ret = handle_is_ptr(src_return_type);
537540 int actual_param_count = fn_call_param_count + (struct_type ? 1 : 0) + (first_arg_ret ? 1 : 0);
538 bool is_var_args = fn_type->data.fn.is_var_args;
541 bool is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
539542
540543 // don't really include void values
541544 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
......@@ -1460,7 +1463,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
14601463}
14611464
14621465static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value) {
1463 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.src_return_type;
1466 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
14641467 if (handle_is_ptr(return_type)) {
14651468 assert(g->cur_ret_ptr);
14661469 gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);
......@@ -1503,7 +1506,7 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
15031506 LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);
15041507
15051508 LLVMPositionBuilderAtEnd(g->builder, return_block);
1506 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.src_return_type;
1509 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
15071510 if (return_type->id == TypeTableEntryIdPureError) {
15081511 gen_return(g, node, err_val);
15091512 } else if (return_type->id == TypeTableEntryIdErrorUnion) {
......@@ -2296,6 +2299,9 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
22962299 case NodeTypeCharLiteral:
22972300 case NodeTypeNullLiteral:
22982301 case NodeTypeUndefinedLiteral:
2302 case NodeTypeErrorType:
2303 case NodeTypeTypeLiteral:
2304 case NodeTypeArrayType:
22992305 // caught by constant expression eval codegen
23002306 zig_unreachable();
23012307 case NodeTypeRoot:
......@@ -2310,11 +2316,10 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
23102316 case NodeTypeStructDecl:
23112317 case NodeTypeStructField:
23122318 case NodeTypeStructValueField:
2313 case NodeTypeArrayType:
2314 case NodeTypeErrorType:
23152319 case NodeTypeSwitchProng:
23162320 case NodeTypeSwitchRange:
23172321 case NodeTypeErrorValueDecl:
2322 case NodeTypeTypeDecl:
23182323 zig_unreachable();
23192324 }
23202325 zig_unreachable();
......@@ -2341,6 +2346,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
23412346 }
23422347
23432348 switch (type_entry->id) {
2349 case TypeTableEntryIdTypeDecl:
2350 return gen_const_val(g, type_entry->data.type_decl.canonical_type, const_val);
23442351 case TypeTableEntryIdInt:
23452352 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
23462353 case TypeTableEntryIdPureError:
......@@ -2557,7 +2564,9 @@ static void do_code_gen(CodeGen *g) {
25572564 assert(proto_node->type == NodeTypeFnProto);
25582565 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
25592566
2560 if (handle_is_ptr(fn_table_entry->type_entry->data.fn.src_return_type)) {
2567 TypeTableEntry *fn_type = fn_table_entry->type_entry;
2568
2569 if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type)) {
25612570 LLVMValueRef first_arg = LLVMGetParam(fn_table_entry->fn_value, 0);
25622571 LLVMAddAttribute(first_arg, LLVMStructRetAttribute);
25632572 }
......@@ -2567,7 +2576,9 @@ static void do_code_gen(CodeGen *g) {
25672576 AstNode *param_node = fn_proto->params.at(param_decl_i);
25682577 assert(param_node->type == NodeTypeParamDecl);
25692578
2570 int gen_index = param_node->data.param_decl.gen_index;
2579 FnGenParamInfo *info = &fn_type->data.fn.gen_param_info[param_decl_i];
2580 int gen_index = info->gen_index;
2581 bool is_byval = info->is_byval;
25712582
25722583 if (gen_index < 0) {
25732584 continue;
......@@ -2587,7 +2598,7 @@ static void do_code_gen(CodeGen *g) {
25872598 // when https://github.com/andrewrk/zig/issues/82 is fixed, add
25882599 // non null attribute here
25892600 }
2590 if (param_node->data.param_decl.is_byval) {
2601 if (is_byval) {
25912602 LLVMAddAttribute(argument_val, LLVMByValAttribute);
25922603 }
25932604 }
......@@ -2601,7 +2612,7 @@ static void do_code_gen(CodeGen *g) {
26012612 AstNode *fn_def_node = fn_table_entry->fn_def_node;
26022613 LLVMValueRef fn = fn_table_entry->fn_value;
26032614 g->cur_fn = fn_table_entry;
2604 if (handle_is_ptr(fn_table_entry->type_entry->data.fn.src_return_type)) {
2615 if (handle_is_ptr(fn_table_entry->type_entry->data.fn.fn_type_id.return_type)) {
26052616 g->cur_ret_ptr = LLVMGetParam(fn, 0);
26062617 } else {
26072618 g->cur_ret_ptr = nullptr;
......@@ -2685,7 +2696,9 @@ static void do_code_gen(CodeGen *g) {
26852696 AstNode *param_decl = fn_proto->params.at(param_i);
26862697 assert(param_decl->type == NodeTypeParamDecl);
26872698
2688 if (param_decl->data.param_decl.gen_index < 0) {
2699 FnGenParamInfo *info = &fn_table_entry->type_entry->data.fn.gen_param_info[param_i];
2700
2701 if (info->gen_index < 0) {
26892702 continue;
26902703 }
26912704
......@@ -2724,17 +2737,6 @@ static const int int_sizes_in_bits[] = {
27242737 64,
27252738};
27262739
2727enum CIntType {
2728 CIntTypeShort,
2729 CIntTypeUShort,
2730 CIntTypeInt,
2731 CIntTypeUInt,
2732 CIntTypeLong,
2733 CIntTypeULong,
2734 CIntTypeLongLong,
2735 CIntTypeULongLong,
2736};
2737
27382740struct CIntTypeInfo {
27392741 CIntType id;
27402742 const char *name;
......@@ -2840,6 +2842,8 @@ static void define_builtin_types(CodeGen *g) {
28402842 is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());
28412843 entry->data.integral.is_signed = is_signed;
28422844 g->primitive_type_table.put(&entry->name, entry);
2845
2846 get_c_int_type_ptr(g, info->id)[0] = entry;
28432847 }
28442848
28452849 {
......@@ -3093,6 +3097,42 @@ static void init(CodeGen *g, Buf *source_path) {
30933097
30943098}
30953099
3100void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
3101 find_libc_path(g);
3102 Buf *full_path = buf_alloc();
3103 os_path_join(src_dirname, src_basename, full_path);
3104
3105 ImportTableEntry *import = allocate<ImportTableEntry>(1);
3106 import->source_code = source_code;
3107 import->path = full_path;
3108 import->fn_table.init(32);
3109 g->root_import = import;
3110
3111 init(g, full_path);
3112
3113 import->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
3114
3115 ZigList<ErrorMsg *> errors = {0};
3116 int err = parse_h_buf(import, &errors, source_code, g, nullptr);
3117 if (err) {
3118 fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));
3119 exit(1);
3120 }
3121
3122 if (errors.length > 0) {
3123 for (int i = 0; i < errors.length; i += 1) {
3124 ErrorMsg *err_msg = errors.at(i);
3125 print_err_msg(err_msg, g->err_color);
3126 }
3127 exit(1);
3128 }
3129}
3130
3131void codegen_render_ast(CodeGen *g, FILE *f, int indent_size) {
3132 ast_render(stdout, g->root_import->root, 4);
3133}
3134
3135
30963136static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {
30973137 char *dot1 = strstr(buf_ptr(buf), ".");
30983138 if (!dot1)
......@@ -3156,7 +3196,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
31563196 import_entry->line_offsets = tokenization.line_offsets;
31573197 import_entry->path = full_path;
31583198 import_entry->fn_table.init(32);
3159 import_entry->fn_type_table.init(32);
31603199
31613200 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
31623201 &g->next_node_index);
src/codegen.hpp+5
......@@ -11,6 +11,8 @@
1111#include "parser.hpp"
1212#include "errmsg.hpp"
1313
14#include <stdio.h>
15
1416CodeGen *codegen_create(Buf *root_source_dir);
1517
1618void codegen_set_clang_argv(CodeGen *codegen, const char **args, int len);
......@@ -27,4 +29,7 @@ void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Bu
2729
2830void codegen_link(CodeGen *g, const char *out_file);
2931
32void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code);
33void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);
34
3035#endif
src/main.cpp+114-177
......@@ -10,8 +10,6 @@
1010#include "codegen.hpp"
1111#include "os.hpp"
1212#include "error.hpp"
13#include "parseh.hpp"
14#include "ast_render.hpp"
1513
1614#include <stdio.h>
1715
......@@ -38,40 +36,41 @@ static int usage(const char *arg0) {
3836 return EXIT_FAILURE;
3937}
4038
41static int version(const char *arg0, int argc, char **argv) {
42 printf("%s\n", ZIG_VERSION_STRING);
43 return EXIT_SUCCESS;
44}
45
46struct Build {
47 const char *in_file;
48 const char *out_file;
49 bool release;
50 bool strip;
51 bool is_static;
52 OutType out_type;
53 const char *out_name;
54 bool verbose;
55 ErrColor color;
56 const char *libc_path;
57 ZigList<const char *> clang_argv;
39enum Cmd {
40 CmdInvalid,
41 CmdBuild,
42 CmdVersion,
43 CmdParseH,
5844};
5945
60static int build(const char *arg0, int argc, char **argv) {
46int main(int argc, char **argv) {
47 char *arg0 = argv[0];
48 Cmd cmd = CmdInvalid;
49 const char *in_file = nullptr;
50 const char *out_file = nullptr;
51 bool release = false;
52 bool strip = false;
53 bool is_static = false;
54 OutType out_type = OutTypeUnknown;
55 const char *out_name = nullptr;
56 bool verbose = false;
57 ErrColor color = ErrColorAuto;
58 const char *libc_path = nullptr;
59 ZigList<const char *> clang_argv = {0};
6160 int err;
62 Build b = {0};
6361
64 for (int i = 0; i < argc; i += 1) {
62 for (int i = 1; i < argc; i += 1) {
6563 char *arg = argv[i];
64
6665 if (arg[0] == '-') {
6766 if (strcmp(arg, "--release") == 0) {
68 b.release = true;
67 release = true;
6968 } else if (strcmp(arg, "--strip") == 0) {
70 b.strip = true;
69 strip = true;
7170 } else if (strcmp(arg, "--static") == 0) {
72 b.is_static = true;
71 is_static = true;
7372 } else if (strcmp(arg, "--verbose") == 0) {
74 b.verbose = true;
73 verbose = true;
7574 } else if (i + 1 >= argc) {
7675 return usage(arg0);
7776 } else {
......@@ -79,190 +78,128 @@ static int build(const char *arg0, int argc, char **argv) {
7978 if (i >= argc) {
8079 return usage(arg0);
8180 } else if (strcmp(arg, "--output") == 0) {
82 b.out_file = argv[i];
81 out_file = argv[i];
8382 } else if (strcmp(arg, "--export") == 0) {
8483 if (strcmp(argv[i], "exe") == 0) {
85 b.out_type = OutTypeExe;
84 out_type = OutTypeExe;
8685 } else if (strcmp(argv[i], "lib") == 0) {
87 b.out_type = OutTypeLib;
86 out_type = OutTypeLib;
8887 } else if (strcmp(argv[i], "obj") == 0) {
89 b.out_type = OutTypeObj;
88 out_type = OutTypeObj;
9089 } else {
9190 return usage(arg0);
9291 }
9392 } else if (strcmp(arg, "--color") == 0) {
9493 if (strcmp(argv[i], "auto") == 0) {
95 b.color = ErrColorAuto;
94 color = ErrColorAuto;
9695 } else if (strcmp(argv[i], "on") == 0) {
97 b.color = ErrColorOn;
96 color = ErrColorOn;
9897 } else if (strcmp(argv[i], "off") == 0) {
99 b.color = ErrColorOff;
98 color = ErrColorOff;
10099 } else {
101100 return usage(arg0);
102101 }
103102 } else if (strcmp(arg, "--name") == 0) {
104 b.out_name = argv[i];
103 out_name = argv[i];
105104 } else if (strcmp(arg, "--libc-path") == 0) {
106 b.libc_path = argv[i];
105 libc_path = argv[i];
107106 } else if (strcmp(arg, "-isystem") == 0) {
108 b.clang_argv.append("-isystem");
109 b.clang_argv.append(argv[i]);
107 clang_argv.append("-isystem");
108 clang_argv.append(argv[i]);
110109 } else if (strcmp(arg, "-dirafter") == 0) {
111 b.clang_argv.append("-dirafter");
112 b.clang_argv.append(argv[i]);
110 clang_argv.append("-dirafter");
111 clang_argv.append(argv[i]);
113112 } else {
114113 return usage(arg0);
115114 }
116115 }
117 } else if (!b.in_file) {
118 b.in_file = arg;
119 } else {
120 return usage(arg0);
121 }
122 }
123
124 if (!b.in_file)
125 return usage(arg0);
126
127 Buf in_file_buf = BUF_INIT;
128 buf_init_from_str(&in_file_buf, b.in_file);
129
130 Buf root_source_dir = BUF_INIT;
131 Buf root_source_code = BUF_INIT;
132 Buf root_source_name = BUF_INIT;
133 if (buf_eql_str(&in_file_buf, "-")) {
134 os_get_cwd(&root_source_dir);
135 if ((err = os_fetch_file(stdin, &root_source_code))) {
136 fprintf(stderr, "unable to read stdin: %s\n", err_str(err));
137 return 1;
138 }
139 buf_init_from_str(&root_source_name, "");
140 } else {
141 os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
142 if ((err = os_fetch_file_path(buf_create_from_str(b.in_file), &root_source_code))) {
143 fprintf(stderr, "unable to open '%s': %s\n", b.in_file, err_str(err));
144 return 1;
145 }
146 }
147
148 CodeGen *g = codegen_create(&root_source_dir);
149 codegen_set_build_type(g, b.release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
150 codegen_set_clang_argv(g, b.clang_argv.items, b.clang_argv.length);
151 codegen_set_strip(g, b.strip);
152 codegen_set_is_static(g, b.is_static);
153 if (b.out_type != OutTypeUnknown)
154 codegen_set_out_type(g, b.out_type);
155 if (b.out_name)
156 codegen_set_out_name(g, buf_create_from_str(b.out_name));
157 if (b.libc_path)
158 codegen_set_libc_path(g, buf_create_from_str(b.libc_path));
159 codegen_set_verbose(g, b.verbose);
160 codegen_set_errmsg_color(g, b.color);
161 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
162 codegen_link(g, b.out_file);
163
164 return 0;
165}
166
167static int parseh(const char *arg0, int argc, char **argv) {
168 char *in_file = nullptr;
169 ZigList<const char *> clang_argv = {0};
170 ErrColor color = ErrColorAuto;
171 bool warnings_on = false;
172 for (int i = 0; i < argc; i += 1) {
173 char *arg = argv[i];
174 if (arg[0] == '-') {
175 if (arg[1] == 'I') {
176 clang_argv.append(arg);
177 } else if (strcmp(arg, "-isystem") == 0) {
178 if (i + 1 >= argc) {
179 return usage(arg0);
180 }
181 i += 1;
182 clang_argv.append("-isystem");
183 clang_argv.append(argv[i]);
184 } else if (strcmp(arg, "--color") == 0) {
185 if (i + 1 >= argc) {
186 return usage(arg0);
187 }
188 i += 1;
189 if (strcmp(argv[i], "auto") == 0) {
190 color = ErrColorAuto;
191 } else if (strcmp(argv[i], "on") == 0) {
192 color = ErrColorOn;
193 } else if (strcmp(argv[i], "off") == 0) {
194 color = ErrColorOff;
195 } else {
196 return usage(arg0);
197 }
198 } else if (strcmp(arg, "--c-import-warnings") == 0) {
199 warnings_on = true;
116 } else if (cmd == CmdInvalid) {
117 if (strcmp(arg, "build") == 0) {
118 cmd = CmdBuild;
119 } else if (strcmp(arg, "version") == 0) {
120 cmd = CmdVersion;
121 } else if (strcmp(arg, "parseh") == 0) {
122 cmd = CmdParseH;
200123 } else {
201 fprintf(stderr, "unrecognized argument: %s", arg);
124 fprintf(stderr, "Unrecognized command: %s\n", arg);
202125 return usage(arg0);
203126 }
204 } else if (!in_file) {
205 in_file = arg;
206127 } else {
207 return usage(arg0);
208 }
209 }
210 if (!in_file) {
211 fprintf(stderr, "missing target argument");
212 return usage(arg0);
213 }
214
215 clang_argv.append(in_file);
216
217 Buf *libc_include_path = buf_alloc();
218 os_path_join(buf_create_from_str(ZIG_LIBC_DIR), buf_create_from_str("include"), libc_include_path);
219 clang_argv.append("-isystem");
220 clang_argv.append(buf_ptr(libc_include_path));
221
222 ImportTableEntry import = {0};
223 ZigList<ErrorMsg *> errors = {0};
224 uint32_t next_node_index = 0;
225 int err = parse_h_file(&import, &errors, &clang_argv, warnings_on, &next_node_index);
226
227 if (err) {
228 fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));
229 return EXIT_FAILURE;
230 }
231
232 if (errors.length > 0) {
233 for (int i = 0; i < errors.length; i += 1) {
234 ErrorMsg *err_msg = errors.at(i);
235 print_err_msg(err_msg, color);
128 switch (cmd) {
129 case CmdBuild:
130 case CmdParseH:
131 if (!in_file) {
132 in_file = arg;
133 } else {
134 return usage(arg0);
135 }
136 break;
137 case CmdVersion:
138 return usage(arg0);
139 case CmdInvalid:
140 zig_unreachable();
141 }
236142 }
237 return EXIT_FAILURE;
238143 }
239144
240 ast_render(stdout, import.root, 4);
145 switch (cmd) {
146 case CmdBuild:
147 case CmdParseH:
148 {
149 if (!in_file)
150 return usage(arg0);
241151
242 return 0;
243}
152 Buf in_file_buf = BUF_INIT;
153 buf_init_from_str(&in_file_buf, in_file);
154
155 Buf root_source_dir = BUF_INIT;
156 Buf root_source_code = BUF_INIT;
157 Buf root_source_name = BUF_INIT;
158 if (buf_eql_str(&in_file_buf, "-")) {
159 os_get_cwd(&root_source_dir);
160 if ((err = os_fetch_file(stdin, &root_source_code))) {
161 fprintf(stderr, "unable to read stdin: %s\n", err_str(err));
162 return 1;
163 }
164 buf_init_from_str(&root_source_name, "");
165 } else {
166 os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
167 if ((err = os_fetch_file_path(buf_create_from_str(in_file), &root_source_code))) {
168 fprintf(stderr, "unable to open '%s': %s\n", in_file, err_str(err));
169 return 1;
170 }
171 }
244172
245int main(int argc, char **argv) {
246 char *arg0 = argv[0];
247 int (*cmd)(const char *, int, char **) = nullptr;
248 for (int i = 1; i < argc; i += 1) {
249 char *arg = argv[i];
250 if (arg[0] == '-' && arg[1] == '-') {
251 return usage(arg0);
252 } else {
253 if (strcmp(arg, "build") == 0) {
254 cmd = build;
255 } else if (strcmp(arg, "version") == 0) {
256 cmd = version;
257 } else if (strcmp(arg, "parseh") == 0) {
258 cmd = parseh;
173 CodeGen *g = codegen_create(&root_source_dir);
174 codegen_set_build_type(g, release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
175 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);
176 codegen_set_strip(g, strip);
177 codegen_set_is_static(g, is_static);
178 if (out_type != OutTypeUnknown)
179 codegen_set_out_type(g, out_type);
180 if (out_name)
181 codegen_set_out_name(g, buf_create_from_str(out_name));
182 if (libc_path)
183 codegen_set_libc_path(g, buf_create_from_str(libc_path));
184 codegen_set_verbose(g, verbose);
185 codegen_set_errmsg_color(g, color);
186
187 if (cmd == CmdBuild) {
188 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
189 codegen_link(g, out_file);
190 return EXIT_SUCCESS;
191 } else if (cmd == CmdParseH) {
192 codegen_parseh(g, &root_source_dir, &root_source_name, &root_source_code);
193 codegen_render_ast(g, stdout, 4);
194 return EXIT_SUCCESS;
259195 } else {
260 fprintf(stderr, "Unrecognized command: %s\n", arg);
261 return usage(arg0);
196 zig_unreachable();
262197 }
263 return cmd(arg0, argc - i - 1, &argv[i + 1]);
264198 }
199 case CmdVersion:
200 printf("%s\n", ZIG_VERSION_STRING);
201 return EXIT_SUCCESS;
202 case CmdInvalid:
203 return usage(arg0);
265204 }
266
267 return usage(arg0);
268205}
src/parseh.cpp+433-264
......@@ -12,6 +12,7 @@
1212#include "parser.hpp"
1313#include "all_types.hpp"
1414#include "tokenizer.hpp"
15#include "analyze.hpp"
1516
1617#include <clang/Frontend/ASTUnit.h>
1718#include <clang/Frontend/CompilerInstance.h>
......@@ -30,22 +31,27 @@ struct Context {
3031 ZigList<ErrorMsg *> *errors;
3132 bool warnings_on;
3233 VisibMod visib_mod;
33 bool have_c_void_decl_node;
34 TypeTableEntry *c_void_type;
3435 AstNode *root;
35 HashMap<Buf *, bool, buf_hash, buf_eql_buf> root_name_table;
36 HashMap<Buf *, bool, buf_hash, buf_eql_buf> struct_type_table;
37 HashMap<Buf *, bool, buf_hash, buf_eql_buf> enum_type_table;
36 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_type_table;
37 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_value_table;
38 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> struct_type_table;
39 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> enum_type_table;
3840 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;
3941 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
4042 SourceManager *source_manager;
4143 ZigList<AstNode *> aliases;
4244 ZigList<MacroSymbol> macro_symbols;
43 uint32_t *next_node_index;
45 AstNode *source_node;
46
47 CodeGen *codegen;
4448};
4549
46static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl);
47static AstNode *make_qual_type_node_with_table(Context *c, QualType qt, const Decl *decl,
48 HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table);
50static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl,
51 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table);
52
53static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl);
54
4955
5056__attribute__ ((format (printf, 3, 4)))
5157static void emit_warning(Context *c, const Decl *decl, const char *format, ...) {
......@@ -77,8 +83,8 @@ static AstNode *create_node(Context *c, NodeType type) {
7783 AstNode *node = allocate<AstNode>(1);
7884 node->type = type;
7985 node->owner = c->import;
80 node->create_index = *c->next_node_index;
81 *c->next_node_index += 1;
86 node->create_index = c->codegen->next_node_index;
87 c->codegen->next_node_index += 1;
8288 return node;
8389}
8490
......@@ -178,61 +184,51 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {
178184 return create_prefix_node(c, PrefixOpNegation, num_lit_node);
179185}
180186
181static AstNode *create_array_type_node(Context *c, AstNode *child_type_node, uint64_t size, bool is_const) {
182 AstNode *node = create_node(c, NodeTypeArrayType);
183 node->data.array_type.size = create_num_lit_unsigned(c, size);
184 node->data.array_type.child_type = child_type_node;
185 node->data.array_type.is_const = is_const;
187static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *child_type_node) {
188 AstNode *node = create_node(c, NodeTypeTypeDecl);
189 buf_init_from_str(&node->data.type_decl.symbol, name);
190 node->data.type_decl.visib_mod = c->visib_mod;
191 node->data.type_decl.directives = create_empty_directives(c);
192 node->data.type_decl.child_type = child_type_node;
186193
187194 normalize_parent_ptrs(node);
188195 return node;
189196}
190197
198static AstNode *make_type_node(Context *c, TypeTableEntry *type_entry) {
199 AstNode *node = create_node(c, NodeTypeSymbol);
200 node->data.symbol_expr.override_type_entry = type_entry;
201 return node;
202}
203
191204static const char *decl_name(const Decl *decl) {
192205 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
193206 return (const char *)named_decl->getName().bytes_begin();
194207}
195208
209static AstNode *add_typedef_node(Context *c, TypeTableEntry *type_decl) {
210 assert(type_decl);
196211
197static AstNode *add_typedef_node(Context *c, Buf *new_name, AstNode *target_node) {
198 if (!target_node) {
199 return nullptr;
200 }
201 AstNode *node = create_var_decl_node(c, buf_ptr(new_name), target_node);
212 AstNode *node = create_type_decl_node(c, buf_ptr(&type_decl->name),
213 make_type_node(c, type_decl->data.type_decl.child_type));
214 node->data.type_decl.override_type = type_decl;
202215
203 c->root_name_table.put(new_name, true);
216 c->global_type_table.put(&type_decl->name, type_decl);
204217 c->root->data.root.top_level_decls.append(node);
205218 return node;
206219}
207220
208static AstNode *convert_to_c_void(Context *c, AstNode *type_node) {
209 if (type_node->type == NodeTypeSymbol &&
210 buf_eql_str(&type_node->data.symbol_expr.symbol, "void"))
211 {
212 if (!c->have_c_void_decl_node) {
213 add_typedef_node(c, buf_create_from_str("c_void"), create_symbol_node(c, "u8"));
214 c->have_c_void_decl_node = true;
215 }
216 return create_symbol_node(c, "c_void");
217 } else {
218 return type_node;
221static TypeTableEntry *get_c_void_type(Context *c) {
222 if (!c->c_void_type) {
223 c->c_void_type = get_typedecl_type(c->codegen, "c_void", c->codegen->builtin_types.entry_u8);
224 add_typedef_node(c, c->c_void_type);
219225 }
220}
221
222static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) {
223 assert(type_node);
224 PrefixOp op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf;
225 AstNode *child_node = create_prefix_node(c, op, convert_to_c_void(c, type_node));
226 return create_prefix_node(c, PrefixOpMaybe, child_node);
227}
228226
229static bool type_is_int(AstNode *type_node) {
230 // TODO recurse through the type table
231 return true;
227 return c->c_void_type;
232228}
233229
234static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
235 HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table)
230static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const Decl *decl,
231 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table)
236232{
237233 switch (ty->getTypeClass()) {
238234 case Type::Builtin:
......@@ -240,35 +236,35 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
240236 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
241237 switch (builtin_ty->getKind()) {
242238 case BuiltinType::Void:
243 return create_symbol_node(c, "void");
239 return c->codegen->builtin_types.entry_void;
244240 case BuiltinType::Bool:
245 return create_symbol_node(c, "bool");
241 return c->codegen->builtin_types.entry_bool;
246242 case BuiltinType::Char_U:
247243 case BuiltinType::UChar:
248244 case BuiltinType::Char_S:
249 return create_symbol_node(c, "u8");
245 return c->codegen->builtin_types.entry_u8;
250246 case BuiltinType::SChar:
251 return create_symbol_node(c, "i8");
247 return c->codegen->builtin_types.entry_i8;
252248 case BuiltinType::UShort:
253 return create_symbol_node(c, "c_ushort");
249 return get_c_int_type(c->codegen, CIntTypeUShort);
254250 case BuiltinType::UInt:
255 return create_symbol_node(c, "c_uint");
251 return get_c_int_type(c->codegen, CIntTypeUInt);
256252 case BuiltinType::ULong:
257 return create_symbol_node(c, "c_ulong");
253 return get_c_int_type(c->codegen, CIntTypeULong);
258254 case BuiltinType::ULongLong:
259 return create_symbol_node(c, "c_ulonglong");
255 return get_c_int_type(c->codegen, CIntTypeULongLong);
260256 case BuiltinType::Short:
261 return create_symbol_node(c, "c_short");
257 return get_c_int_type(c->codegen, CIntTypeShort);
262258 case BuiltinType::Int:
263 return create_symbol_node(c, "c_int");
259 return get_c_int_type(c->codegen, CIntTypeInt);
264260 case BuiltinType::Long:
265 return create_symbol_node(c, "c_long");
261 return get_c_int_type(c->codegen, CIntTypeLong);
266262 case BuiltinType::LongLong:
267 return create_symbol_node(c, "c_longlong");
263 return get_c_int_type(c->codegen, CIntTypeLongLong);
268264 case BuiltinType::Float:
269 return create_symbol_node(c, "f32");
265 return c->codegen->builtin_types.entry_f32;
270266 case BuiltinType::Double:
271 return create_symbol_node(c, "f64");
267 return c->codegen->builtin_types.entry_f64;
272268 case BuiltinType::LongDouble:
273269 case BuiltinType::WChar_U:
274270 case BuiltinType::Char16:
......@@ -297,7 +293,7 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
297293 case BuiltinType::BuiltinFn:
298294 case BuiltinType::ARCUnbridgedCast:
299295 emit_warning(c, decl, "missed a builtin type");
300 return nullptr;
296 return c->codegen->builtin_types.entry_invalid;
301297 }
302298 break;
303299 }
......@@ -305,17 +301,26 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
305301 {
306302 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
307303 QualType child_qt = pointer_ty->getPointeeType();
308 AstNode *type_node = make_qual_type_node(c, child_qt, decl);
309 if (!type_node) {
310 return nullptr;
304 TypeTableEntry *child_type = resolve_qual_type(c, child_qt, decl);
305 if (get_underlying_type(child_type)->id == TypeTableEntryIdInvalid) {
306 emit_warning(c, decl, "pointer to unresolved type");
307 return c->codegen->builtin_types.entry_invalid;
311308 }
309
312310 if (child_qt.getTypePtr()->getTypeClass() == Type::Paren) {
313311 const ParenType *paren_type = static_cast<const ParenType *>(child_qt.getTypePtr());
314312 if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
315 return create_prefix_node(c, PrefixOpMaybe, type_node);
313 return get_maybe_type(c->codegen, child_type);
316314 }
317315 }
318 return pointer_to_type(c, type_node, child_qt.isConstQualified());
316 bool is_const = child_qt.isConstQualified();
317
318 if (child_type->id == TypeTableEntryIdVoid) {
319 child_type = get_c_void_type(c);
320 }
321
322 TypeTableEntry *non_null_pointer_type = get_pointer_to_type(c->codegen, child_type, is_const);
323 return get_maybe_type(c->codegen, non_null_pointer_type);
319324 }
320325 case Type::Typedef:
321326 {
......@@ -323,32 +328,28 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
323328 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
324329 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
325330 if (buf_eql_str(type_name, "uint8_t")) {
326 return create_symbol_node(c, "u8");
331 return c->codegen->builtin_types.entry_u8;
327332 } else if (buf_eql_str(type_name, "int8_t")) {
328 return create_symbol_node(c, "i8");
333 return c->codegen->builtin_types.entry_i8;
329334 } else if (buf_eql_str(type_name, "uint16_t")) {
330 return create_symbol_node(c, "u16");
335 return c->codegen->builtin_types.entry_u16;
331336 } else if (buf_eql_str(type_name, "int16_t")) {
332 return create_symbol_node(c, "i16");
337 return c->codegen->builtin_types.entry_i16;
333338 } else if (buf_eql_str(type_name, "uint32_t")) {
334 return create_symbol_node(c, "u32");
339 return c->codegen->builtin_types.entry_u32;
335340 } else if (buf_eql_str(type_name, "int32_t")) {
336 return create_symbol_node(c, "i32");
341 return c->codegen->builtin_types.entry_i32;
337342 } else if (buf_eql_str(type_name, "uint64_t")) {
338 return create_symbol_node(c, "u64");
343 return c->codegen->builtin_types.entry_u64;
339344 } else if (buf_eql_str(type_name, "int64_t")) {
340 return create_symbol_node(c, "i64");
345 return c->codegen->builtin_types.entry_i64;
341346 } else if (buf_eql_str(type_name, "intptr_t")) {
342 return create_symbol_node(c, "isize");
347 return c->codegen->builtin_types.entry_isize;
343348 } else if (buf_eql_str(type_name, "uintptr_t")) {
344 return create_symbol_node(c, "usize");
349 return c->codegen->builtin_types.entry_usize;
345350 } else {
346351 auto entry = type_table->maybe_get(type_name);
347 if (entry) {
348 return create_symbol_node(c, buf_ptr(type_name));
349 } else {
350 return nullptr;
351 }
352 return entry ? entry->value : c->codegen->builtin_types.entry_invalid;
352353 }
353354 }
354355 case Type::Elaborated:
......@@ -356,10 +357,10 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
356357 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
357358 switch (elaborated_ty->getKeyword()) {
358359 case ETK_Struct:
359 return make_qual_type_node_with_table(c, elaborated_ty->getNamedType(),
360 return resolve_qual_type_with_table(c, elaborated_ty->getNamedType(),
360361 decl, &c->struct_type_table);
361362 case ETK_Enum:
362 return make_qual_type_node_with_table(c, elaborated_ty->getNamedType(),
363 return resolve_qual_type_with_table(c, elaborated_ty->getNamedType(),
363364 decl, &c->enum_type_table);
364365 case ETK_Interface:
365366 case ETK_Union:
......@@ -367,35 +368,63 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
367368 case ETK_Typename:
368369 case ETK_None:
369370 emit_warning(c, decl, "unsupported elaborated type");
370 return nullptr;
371 return c->codegen->builtin_types.entry_invalid;
371372 }
372373 }
373374 case Type::FunctionProto:
374375 {
375376 const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);
376 AstNode *node = create_node(c, NodeTypeFnProto);
377 buf_resize(&node->data.fn_proto.name, 0);
378 node->data.fn_proto.is_extern = true;
379 node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
380 node->data.fn_proto.return_type = make_qual_type_node(c, fn_proto_ty->getReturnType(), decl);
381
382 if (!node->data.fn_proto.return_type) {
383 return nullptr;
377
378 switch (fn_proto_ty->getCallConv()) {
379 case CC_C: // __attribute__((cdecl))
380 break;
381 case CC_X86StdCall: // __attribute__((stdcall))
382 case CC_X86FastCall: // __attribute__((fastcall))
383 case CC_X86ThisCall: // __attribute__((thiscall))
384 case CC_X86VectorCall: // __attribute__((vectorcall))
385 case CC_X86Pascal: // __attribute__((pascal))
386 case CC_X86_64Win64: // __attribute__((ms_abi))
387 case CC_X86_64SysV: // __attribute__((sysv_abi))
388 case CC_AAPCS: // __attribute__((pcs("aapcs")))
389 case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
390 case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
391 case CC_SpirFunction: // default for OpenCL functions on SPIR target
392 case CC_SpirKernel: // inferred for OpenCL kernels on SPIR target
393 emit_warning(c, decl, "function type has non C calling convention");
394 return c->codegen->builtin_types.entry_invalid;
395 }
396
397 FnTypeId fn_type_id;
398 fn_type_id.is_naked = false;
399 fn_type_id.is_extern = true;
400 fn_type_id.is_var_args = fn_proto_ty->isVariadic();
401 fn_type_id.param_count = fn_proto_ty->getNumParams();
402
403
404 if (fn_proto_ty->getNoReturnAttr()) {
405 fn_type_id.return_type = c->codegen->builtin_types.entry_unreachable;
406 } else {
407 fn_type_id.return_type = resolve_qual_type(c, fn_proto_ty->getReturnType(), decl);
408 if (fn_type_id.return_type->id == TypeTableEntryIdInvalid) {
409 return c->codegen->builtin_types.entry_invalid;
410 }
384411 }
385412
386 int arg_count = fn_proto_ty->getNumParams();
387 for (int i = 0; i < arg_count; i += 1) {
413 fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count);
414 for (int i = 0; i < fn_type_id.param_count; i += 1) {
388415 QualType qt = fn_proto_ty->getParamType(i);
389 bool is_noalias = qt.isRestrictQualified();
390 AstNode *type_node = make_qual_type_node(c, qt, decl);
391 if (!type_node) {
392 return nullptr;
416 TypeTableEntry *param_type = resolve_qual_type(c, qt, decl);
417
418 if (param_type->id == TypeTableEntryIdInvalid) {
419 return c->codegen->builtin_types.entry_invalid;
393420 }
394 node->data.fn_proto.params.append(create_param_decl_node(c, "", type_node, is_noalias));
421
422 FnTypeParamInfo *param_info = &fn_type_id.param_info[i];
423 param_info->type = param_type;
424 param_info->is_noalias = qt.isRestrictQualified();
395425 }
396426
397 normalize_parent_ptrs(node);
398 return node;
427 return get_fn_type(c->codegen, fn_type_id);
399428 }
400429 case Type::Record:
401430 {
......@@ -403,20 +432,15 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
403432 Buf *record_name = buf_create_from_str(decl_name(record_ty->getDecl()));
404433 if (buf_len(record_name) == 0) {
405434 emit_warning(c, decl, "unhandled anonymous struct");
406 return nullptr;
407 } else if (type_table->maybe_get(record_name)) {
408 const char *prefix_str;
409 if (type_table == &c->enum_type_table) {
410 prefix_str = "enum_";
411 } else if (type_table == &c->struct_type_table) {
412 prefix_str = "struct_";
413 } else {
414 prefix_str = "";
415 }
416 return create_symbol_node(c, buf_ptr(buf_sprintf("%s%s", prefix_str, buf_ptr(record_name))));
417 } else {
418 return nullptr;
435 return c->codegen->builtin_types.entry_invalid;
419436 }
437
438 auto entry = type_table->maybe_get(record_name);
439 if (!entry) {
440 return c->codegen->builtin_types.entry_invalid;
441 }
442
443 return entry->value;
420444 }
421445 case Type::Enum:
422446 {
......@@ -424,32 +448,32 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
424448 Buf *record_name = buf_create_from_str(decl_name(enum_ty->getDecl()));
425449 if (buf_len(record_name) == 0) {
426450 emit_warning(c, decl, "unhandled anonymous enum");
427 return nullptr;
428 } else if (type_table->maybe_get(record_name)) {
429 const char *prefix_str;
430 if (type_table == &c->enum_type_table) {
431 prefix_str = "enum_";
432 } else if (type_table == &c->struct_type_table) {
433 prefix_str = "struct_";
434 } else {
435 prefix_str = "";
436 }
437 return create_symbol_node(c, buf_ptr(buf_sprintf("%s%s", prefix_str, buf_ptr(record_name))));
438 } else {
439 return nullptr;
451 return c->codegen->builtin_types.entry_invalid;
452 }
453
454 auto entry = type_table->maybe_get(record_name);
455 if (!entry) {
456 return c->codegen->builtin_types.entry_invalid;
440457 }
458
459 return entry->value;
441460 }
442461 case Type::ConstantArray:
443462 {
444463 const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);
445 AstNode *child_type_node = make_qual_type_node(c, const_arr_ty->getElementType(), decl);
464 TypeTableEntry *child_type = resolve_qual_type(c, const_arr_ty->getElementType(), decl);
446465 uint64_t size = const_arr_ty->getSize().getLimitedValue();
447 return create_array_type_node(c, child_type_node, size, false);
466 return get_array_type(c->codegen, child_type, size);
448467 }
449468 case Type::Paren:
450469 {
451470 const ParenType *paren_ty = static_cast<const ParenType *>(ty);
452 return make_qual_type_node(c, paren_ty->getInnerType(), decl);
471 return resolve_qual_type(c, paren_ty->getInnerType(), decl);
472 }
473 case Type::Decayed:
474 {
475 const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty);
476 return resolve_qual_type(c, decayed_ty->getOriginalType(), decl);
453477 }
454478 case Type::BlockPointer:
455479 case Type::LValueReference:
......@@ -464,7 +488,6 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
464488 case Type::FunctionNoProto:
465489 case Type::UnresolvedUsing:
466490 case Type::Adjusted:
467 case Type::Decayed:
468491 case Type::TypeOfExpr:
469492 case Type::TypeOf:
470493 case Type::Decltype:
......@@ -485,68 +508,68 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
485508 case Type::ObjCObjectPointer:
486509 case Type::Atomic:
487510 emit_warning(c, decl, "missed a '%s' type", ty->getTypeClassName());
488 return nullptr;
511 return c->codegen->builtin_types.entry_invalid;
489512 }
490513}
491514
492static AstNode *make_qual_type_node_with_table(Context *c, QualType qt, const Decl *decl,
493 HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table)
515static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl,
516 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table)
494517{
495 return make_type_node(c, qt.getTypePtr(), decl, type_table);
518 return resolve_type_with_table(c, qt.getTypePtr(), decl, type_table);
496519}
497520
498static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl) {
499 return make_qual_type_node_with_table(c, qt, decl, &c->root_name_table);
521static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl) {
522 return resolve_qual_type_with_table(c, qt, decl, &c->global_type_table);
500523}
501524
502525static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
503 AstNode *node = create_node(c, NodeTypeFnProto);
504 buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl));
526 Buf fn_name = BUF_INIT;
527 buf_init_from_str(&fn_name, decl_name(fn_decl));
505528
506 auto fn_entry = c->fn_table.maybe_get(&node->data.fn_proto.name);
507 if (fn_entry) {
529 if (c->fn_table.maybe_get(&fn_name)) {
508530 // we already saw this function
509531 return;
510532 }
511533
512 node->data.fn_proto.is_extern = true;
534 TypeTableEntry *fn_type = resolve_qual_type(c, fn_decl->getType(), fn_decl);
535
536 if (fn_type->id == TypeTableEntryIdInvalid) {
537 emit_warning(c, fn_decl, "ignoring function '%s' - unable to resolve type", buf_ptr(&fn_name));
538 return;
539 }
540 assert(fn_type->id == TypeTableEntryIdFn);
541
542
543 AstNode *node = create_node(c, NodeTypeFnProto);
544 buf_init_from_buf(&node->data.fn_proto.name, &fn_name);
545
546 node->data.fn_proto.is_extern = fn_type->data.fn.fn_type_id.is_extern;
513547 node->data.fn_proto.visib_mod = c->visib_mod;
514548 node->data.fn_proto.directives = create_empty_directives(c);
515 node->data.fn_proto.is_var_args = fn_decl->isVariadic();
549 node->data.fn_proto.is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
550 node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type);
551
552 assert(!fn_type->data.fn.fn_type_id.is_naked);
516553
517 int arg_count = fn_decl->getNumParams();
554 int arg_count = fn_type->data.fn.fn_type_id.param_count;
555 Buf name_buf = BUF_INIT;
518556 for (int i = 0; i < arg_count; i += 1) {
557 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[i];
558 AstNode *type_node = make_type_node(c, param_info->type);
519559 const ParmVarDecl *param = fn_decl->getParamDecl(i);
520560 const char *name = decl_name(param);
521561 if (strlen(name) == 0) {
522 name = buf_ptr(buf_sprintf("arg%d", i));
562 buf_resize(&name_buf, 0);
563 buf_appendf(&name_buf, "arg%d", i);
564 name = buf_ptr(&name_buf);
523565 }
524 QualType qt = param->getOriginalType();
525 bool is_noalias = qt.isRestrictQualified();
526 AstNode *type_node = make_qual_type_node(c, qt, fn_decl);
527 if (!type_node) {
528 emit_warning(c, param, "skipping function %s, unresolved param type\n", name);
529 return;
530 }
531
532 node->data.fn_proto.params.append(create_param_decl_node(c, name, type_node, is_noalias));
533 }
534566
535 if (fn_decl->isNoReturn()) {
536 node->data.fn_proto.return_type = create_symbol_node(c, "unreachable");
537 } else {
538 node->data.fn_proto.return_type = make_qual_type_node(c, fn_decl->getReturnType(), fn_decl);
539 }
540
541 if (!node->data.fn_proto.return_type) {
542 emit_warning(c, fn_decl, "skipping function %s, unresolved return type\n",
543 buf_ptr(&node->data.fn_proto.name));
544 return;
567 node->data.fn_proto.params.append(create_param_decl_node(c, name, type_node, param_info->is_noalias));
545568 }
546569
547570 normalize_parent_ptrs(node);
548571
549 c->fn_table.put(&node->data.fn_proto.name, true);
572 c->fn_table.put(buf_create_from_buf(&fn_name), true);
550573 c->root->data.root.top_level_decls.append(node);
551574}
552575
......@@ -573,7 +596,9 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)
573596 // use the name of this typedef
574597 // TODO
575598
576 add_typedef_node(c, type_name, make_qual_type_node(c, child_qt, typedef_decl));
599 TypeTableEntry *child_type = resolve_qual_type(c, child_qt, typedef_decl);
600 TypeTableEntry *decl_type = get_typedecl_type(c->codegen, buf_ptr(type_name), child_type);
601 add_typedef_node(c, decl_type);
577602}
578603
579604static void add_alias(Context *c, const char *new_name, const char *target_name) {
......@@ -582,7 +607,14 @@ static void add_alias(Context *c, const char *new_name, const char *target_name)
582607}
583608
584609static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
585 Buf *bare_name = buf_create_from_str(decl_name(enum_decl));
610 const char *raw_name = decl_name(enum_decl);
611 // we have no interest in top level anonymous enums since they're
612 // not exposing anything.
613 if (raw_name[0] == 0) {
614 return;
615 }
616
617 Buf *bare_name = buf_create_from_str(raw_name);
586618 Buf *full_type_name = buf_sprintf("enum_%s", buf_ptr(bare_name));
587619
588620 if (c->enum_type_table.maybe_get(bare_name)) {
......@@ -590,97 +622,145 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
590622 return;
591623 }
592624
593 // eagerly put the name in the table, but we need to remember to remove it if it fails
594 // boy it would be nice to have defer here wouldn't it
595 c->enum_type_table.put(bare_name, true);
596
597625 const EnumDecl *enum_def = enum_decl->getDefinition();
598626
599627 if (!enum_def) {
628 TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(full_type_name),
629 c->codegen->builtin_types.entry_u8);
630 c->enum_type_table.put(bare_name, typedecl_type);
631
600632 // this is a type that we can point to but that's it, same as `struct Foo;`.
601 add_typedef_node(c, full_type_name, create_symbol_node(c, "u8"));
633 add_typedef_node(c, typedecl_type);
602634 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
603635 return;
604636 }
605637
606 AstNode *node = create_node(c, NodeTypeStructDecl);
607 buf_init_from_buf(&node->data.struct_decl.name, full_type_name);
608
609 node->data.struct_decl.kind = ContainerKindEnum;
610 node->data.struct_decl.visib_mod = VisibModExport;
611 node->data.struct_decl.directives = create_empty_directives(c);
612
613
614 ZigList<AstNode *> var_decls = {0};
615 int i = 0;
638 // count and validate
639 uint32_t field_count = 0;
616640 for (auto it = enum_def->enumerator_begin(),
617641 it_end = enum_def->enumerator_end();
618 it != it_end; ++it, i += 1)
642 it != it_end; ++it, field_count += 1)
619643 {
620644 const EnumConstantDecl *enum_const = *it;
621645 if (enum_const->getInitExpr()) {
622 c->enum_type_table.remove(bare_name);
623646 emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(bare_name));
624647 return;
625648 }
626 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
649 }
650
651 TypeTableEntry *enum_type = get_partial_container_type(c->codegen, c->import,
652 ContainerKindEnum, c->source_node, buf_ptr(full_type_name));
653
654 enum_type->data.enumeration.gen_field_count = 0;
655 enum_type->data.enumeration.complete = true;
627656
628 Buf field_name = BUF_INIT;
657 TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(c->codegen, field_count);
658 enum_type->align_in_bits = tag_type_entry->size_in_bits;
659 enum_type->size_in_bits = tag_type_entry->size_in_bits;
660 enum_type->data.enumeration.tag_type = tag_type_entry;
629661
662 c->enum_type_table.put(bare_name, enum_type);
663 // make an alias without the "enum_" prefix. this will get emitted at the
664 // end if it doesn't conflict with anything else
665 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
666
667 enum_type->data.enumeration.field_count = field_count;
668 enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
669 LLVMZigDIEnumerator **di_enumerators = allocate<LLVMZigDIEnumerator*>(field_count);
670
671 ZigList<AstNode *> var_decls = {0};
672 uint32_t i = 0;
673 for (auto it = enum_def->enumerator_begin(),
674 it_end = enum_def->enumerator_end();
675 it != it_end; ++it, i += 1)
676 {
677 const EnumConstantDecl *enum_const = *it;
678
679 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
680 Buf *field_name;
630681 if (buf_starts_with_buf(enum_val_name, bare_name)) {
631682 Buf *slice = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
632683 if (valid_symbol_starter(buf_ptr(slice)[0])) {
633 buf_init_from_buf(&field_name, slice);
684 field_name = slice;
634685 } else {
635 buf_resize(&field_name, 0);
636 buf_appendf(&field_name, "_%s", buf_ptr(slice));
686 field_name = buf_sprintf("_%s", buf_ptr(slice));
637687 }
638688 } else {
639 buf_init_from_buf(&field_name, enum_val_name);
689 field_name = enum_val_name;
640690 }
641691
642 AstNode *field_node = create_struct_field_node(c, buf_ptr(&field_name), create_symbol_node(c, "void"));
643 node->data.struct_decl.fields.append(field_node);
692 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
693 type_enum_field->name = field_name;
694 type_enum_field->type_entry = c->codegen->builtin_types.entry_void;
695 type_enum_field->value = i;
696
697 di_enumerators[i] = LLVMZigCreateDebugEnumerator(c->codegen->dbuilder, buf_ptr(type_enum_field->name), i);
698
644699
645700 // in C each enum value is in the global namespace. so we put them there too.
646 AstNode *field_access_node = create_field_access_node(c, buf_ptr(full_type_name), buf_ptr(&field_name));
701 // at this point we can rely on the enum emitting successfully
702 AstNode *field_access_node = create_field_access_node(c, buf_ptr(full_type_name), buf_ptr(field_name));
647703 AstNode *var_node = create_var_decl_node(c, buf_ptr(enum_val_name), field_access_node);
648704 var_decls.append(var_node);
649 c->root_name_table.put(enum_val_name, true);
705 c->global_value_table.put(enum_val_name, enum_type);
650706 }
651707
652 normalize_parent_ptrs(node);
653 c->root->data.root.top_level_decls.append(node);
708 // create llvm type for root struct
709 enum_type->type_ref = tag_type_entry->type_ref;
710
711 // create debug type for tag
712 unsigned line = c->source_node ? (c->source_node->line + 1) : 0;
713 LLVMZigDIType *tag_di_type = LLVMZigCreateDebugEnumerationType(c->codegen->dbuilder,
714 LLVMZigFileToScope(c->import->di_file), buf_ptr(bare_name),
715 c->import->di_file, line,
716 tag_type_entry->size_in_bits, tag_type_entry->align_in_bits, di_enumerators, field_count,
717 tag_type_entry->di_type, "");
718
719 LLVMZigReplaceTemporary(c->codegen->dbuilder, enum_type->di_type, tag_di_type);
720 enum_type->di_type = tag_di_type;
721
722 //////////
723
724 // now create top level decl for the type
725 AstNode *enum_node = create_node(c, NodeTypeStructDecl);
726 buf_init_from_buf(&enum_node->data.struct_decl.name, full_type_name);
727 enum_node->data.struct_decl.kind = ContainerKindEnum;
728 enum_node->data.struct_decl.visib_mod = VisibModExport;
729 enum_node->data.struct_decl.directives = create_empty_directives(c);
730 enum_node->data.struct_decl.type_entry = enum_type;
731
732 for (uint32_t i = 0; i < field_count; i += 1) {
733 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
734 AstNode *type_node = make_type_node(c, type_enum_field->type_entry);
735 AstNode *field_node = create_struct_field_node(c, buf_ptr(type_enum_field->name), type_node);
736 enum_node->data.struct_decl.fields.append(field_node);
737 }
738
739 normalize_parent_ptrs(enum_node);
740 c->root->data.root.top_level_decls.append(enum_node);
654741
655742 for (int i = 0; i < var_decls.length; i += 1) {
656743 AstNode *var_node = var_decls.at(i);
657744 c->root->data.root.top_level_decls.append(var_node);
658745 }
659746
660 // make an alias without the "enum_" prefix. this will get emitted at the
661 // end if it doesn't conflict with anything else
662 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
663747}
664748
665749static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
666750 const char *raw_name = decl_name(record_decl);
667751
752 // we have no interest in top level anonymous structs since they're
753 // not exposing anything.
668754 if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) {
669755 return;
670756 }
671757
672 Buf *bare_name = buf_create_from_str(raw_name);
673
674758 if (!record_decl->isStruct()) {
675 emit_warning(c, record_decl, "skipping record %s, not a struct", buf_ptr(bare_name));
676 return;
677 }
678
679 if (buf_len(bare_name) == 0) {
680 emit_warning(c, record_decl, "skipping anonymous struct");
759 emit_warning(c, record_decl, "skipping record %s, not a struct", raw_name);
681760 return;
682761 }
683762
763 Buf *bare_name = buf_create_from_str(raw_name);
684764 Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name));
685765
686766 if (c->struct_type_table.maybe_get(bare_name)) {
......@@ -688,55 +768,127 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
688768 return;
689769 }
690770
691 // eagerly put the name in the table, but we need to remember to remove it if it fails
692 // boy it would be nice to have defer here wouldn't it
693 c->struct_type_table.put(bare_name, true);
694
695
696771 RecordDecl *record_def = record_decl->getDefinition();
697772 if (!record_def) {
773 TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(full_type_name),
774 c->codegen->builtin_types.entry_u8);
775 c->struct_type_table.put(bare_name, typedecl_type);
776
698777 // this is a type that we can point to but that's it, such as `struct Foo;`.
699 add_typedef_node(c, full_type_name, create_symbol_node(c, "u8"));
778 add_typedef_node(c, typedecl_type);
700779 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
701780 return;
702781 }
703782
704 AstNode *node = create_node(c, NodeTypeStructDecl);
705 buf_init_from_buf(&node->data.struct_decl.name, full_type_name);
783 TypeTableEntry *struct_type = get_partial_container_type(c->codegen, c->import,
784 ContainerKindStruct, c->source_node, buf_ptr(full_type_name));
706785
707 node->data.struct_decl.kind = ContainerKindStruct;
708 node->data.struct_decl.visib_mod = VisibModExport;
709 node->data.struct_decl.directives = create_empty_directives(c);
786 c->struct_type_table.put(bare_name, struct_type);
787 // make an alias without the "struct_" prefix. this will get emitted at the
788 // end if it doesn't conflict with anything else
789 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
710790
791 // count fields and validate
792 uint32_t field_count = 0;
711793 for (auto it = record_def->field_begin(),
712794 it_end = record_def->field_end();
713 it != it_end; ++it)
795 it != it_end; ++it, field_count += 1)
714796 {
715797 const FieldDecl *field_decl = *it;
716798
717799 if (field_decl->isBitField()) {
718 c->struct_type_table.remove(bare_name);
719800 emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(bare_name));
720801 return;
721802 }
803 }
804
805 struct_type->data.structure.src_field_count = field_count;
806 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
807
808 // we possibly allocate too much here since gen_field_count can be lower than field_count.
809 // the only problem is potential wasted space though.
810 LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count);
811 LLVMZigDIType **di_element_types = allocate<LLVMZigDIType*>(field_count);
812
813 uint64_t total_size_in_bits = 0;
814 uint64_t first_field_align_in_bits = 0;
815 uint64_t offset_in_bits = 0;
816
817 uint32_t i = 0;
818 unsigned line = c->source_node ? c->source_node->line : 0;
819 for (auto it = record_def->field_begin(),
820 it_end = record_def->field_end();
821 it != it_end; ++it, i += 1)
822 {
823 const FieldDecl *field_decl = *it;
824
825 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
826 type_struct_field->name = buf_create_from_str(decl_name(field_decl));
827 type_struct_field->src_index = i;
828 type_struct_field->gen_index = i;
829 type_struct_field->type_entry = resolve_qual_type(c, field_decl->getType(), field_decl);
722830
723 AstNode *type_node = make_qual_type_node(c, field_decl->getType(), field_decl);
724 if (!type_node) {
725 c->struct_type_table.remove(bare_name);
726 emit_warning(c, field_decl, "skipping struct %s - unhandled type\n", buf_ptr(bare_name));
831 if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) {
832 emit_warning(c, field_decl, "skipping struct %s - unresolved type\n", buf_ptr(bare_name));
727833 return;
728834 }
729835
730 AstNode *field_node = create_struct_field_node(c, decl_name(field_decl), type_node);
731 node->data.struct_decl.fields.append(field_node);
836 di_element_types[i] = LLVMZigCreateDebugMemberType(c->codegen->dbuilder,
837 LLVMZigTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),
838 c->import->di_file, line + 1,
839 type_struct_field->type_entry->size_in_bits,
840 type_struct_field->type_entry->align_in_bits,
841 offset_in_bits, 0, type_struct_field->type_entry->di_type);
842
843 element_types[i] = type_struct_field->type_entry->type_ref;
844 assert(di_element_types[i]);
845 assert(element_types[i]);
846
847 total_size_in_bits += type_struct_field->type_entry->size_in_bits;
848 if (first_field_align_in_bits == 0) {
849 first_field_align_in_bits = type_struct_field->type_entry->align_in_bits;
850 }
851 offset_in_bits += type_struct_field->type_entry->size_in_bits;
852
732853 }
854 struct_type->data.structure.embedded_in_current = false;
733855
734 normalize_parent_ptrs(node);
735 c->root->data.root.top_level_decls.append(node);
856 struct_type->data.structure.gen_field_count = field_count;
857 struct_type->data.structure.complete = true;
736858
737 // make an alias without the "struct_" prefix. this will get emitted at the
738 // end if it doesn't conflict with anything else
739 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
859 LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false);
860
861 struct_type->align_in_bits = first_field_align_in_bits;
862 struct_type->size_in_bits = total_size_in_bits;
863
864 LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(c->codegen->dbuilder,
865 LLVMZigFileToScope(c->import->di_file),
866 buf_ptr(full_type_name),
867 c->import->di_file, line + 1, struct_type->size_in_bits, struct_type->align_in_bits, 0,
868 nullptr, di_element_types, field_count, 0, nullptr, "");
869
870 LLVMZigReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type);
871 struct_type->di_type = replacement_di_type;
872
873 //////
874
875 // now create a top level decl node for the type
876 AstNode *struct_node = create_node(c, NodeTypeStructDecl);
877 buf_init_from_buf(&struct_node->data.struct_decl.name, full_type_name);
878 struct_node->data.struct_decl.kind = ContainerKindStruct;
879 struct_node->data.struct_decl.visib_mod = VisibModExport;
880 struct_node->data.struct_decl.directives = create_empty_directives(c);
881 struct_node->data.struct_decl.type_entry = struct_type;
882
883 for (uint32_t i = 0; i < field_count; i += 1) {
884 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
885 AstNode *type_node = make_type_node(c, type_struct_field->type_entry);
886 AstNode *field_node = create_struct_field_node(c, buf_ptr(type_struct_field->name), type_node);
887 struct_node->data.struct_decl.fields.append(field_node);
888 }
889
890 normalize_parent_ptrs(struct_node);
891 c->root->data.root.top_level_decls.append(struct_node);
740892}
741893
742894static void visit_var_decl(Context *c, const VarDecl *var_decl) {
......@@ -754,8 +906,8 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
754906 }
755907
756908 QualType qt = var_decl->getType();
757 AstNode *type_node = make_qual_type_node(c, qt, var_decl);
758 if (!type_node) {
909 TypeTableEntry *var_type = resolve_qual_type(c, qt, var_decl);
910 if (var_type->id == TypeTableEntryIdInvalid) {
759911 emit_warning(c, var_decl, "ignoring variable '%s' - unresolved type\n", buf_ptr(name));
760912 return;
761913 }
......@@ -778,7 +930,8 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
778930 switch (ap_value->getKind()) {
779931 case APValue::Int:
780932 {
781 if (!type_is_int(type_node)) {
933 TypeTableEntry *canon_type = get_underlying_type(var_type);
934 if (canon_type->id != TypeTableEntryIdInt) {
782935 emit_warning(c, var_decl,
783936 "ignoring variable '%s' - int initializer for non int type\n", buf_ptr(name));
784937 return;
......@@ -819,17 +972,19 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
819972 return;
820973 }
821974
975 AstNode *type_node = make_type_node(c, var_type);
822976 AstNode *var_node = create_typed_var_decl_node(c, true, buf_ptr(name), type_node, init_node);
823977 c->root->data.root.top_level_decls.append(var_node);
824 c->root_name_table.put(name, true);
978 c->global_value_table.put(name, var_type);
825979 return;
826980 }
827981
828982 if (is_extern) {
983 AstNode *type_node = make_type_node(c, var_type);
829984 AstNode *var_node = create_typed_var_decl_node(c, is_const, buf_ptr(name), type_node, nullptr);
830985 var_node->data.variable_declaration.is_extern = true;
831986 c->root->data.root.top_level_decls.append(var_node);
832 c->root_name_table.put(name, true);
987 c->global_value_table.put(name, var_type);
833988 return;
834989 }
835990
......@@ -864,7 +1019,10 @@ static bool decl_visitor(void *context, const Decl *decl) {
8641019}
8651020
8661021static bool name_exists(Context *c, Buf *name) {
867 if (c->root_name_table.maybe_get(name)) {
1022 if (c->global_type_table.maybe_get(name)) {
1023 return true;
1024 }
1025 if (c->global_value_table.maybe_get(name)) {
8681026 return true;
8691027 }
8701028 if (c->fn_table.maybe_get(name)) {
......@@ -1001,6 +1159,11 @@ static void process_macro(Context *c, Buf *name, Buf *value) {
10011159
10021160 // maybe it's a symbol
10031161 if (is_simple_symbol(value)) {
1162 // if it equals itself, ignore. for example, from stdio.h:
1163 // #define stdin stdin
1164 if (buf_eql_buf(name, value)) {
1165 return;
1166 }
10041167 c->macro_symbols.append({name, value});
10051168 }
10061169}
......@@ -1054,46 +1217,43 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
10541217}
10551218
10561219int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
1057 const char **args, int args_len, const char *libc_include_path, bool warnings_on,
1058 uint32_t *next_node_index)
1220 CodeGen *codegen, AstNode *source_node)
10591221{
10601222 int err;
10611223 Buf tmp_file_path = BUF_INIT;
10621224 if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) {
10631225 return err;
10641226 }
1065 ZigList<const char *> clang_argv = {0};
1066 clang_argv.append(buf_ptr(&tmp_file_path));
1067
1068 clang_argv.append("-isystem");
1069 clang_argv.append(libc_include_path);
1070
1071 for (int i = 0; i < args_len; i += 1) {
1072 clang_argv.append(args[i]);
1073 }
10741227
1075 err = parse_h_file(import, errors, &clang_argv, warnings_on, next_node_index);
1228 err = parse_h_file(import, errors, buf_ptr(&tmp_file_path), codegen, source_node);
10761229
10771230 os_delete_file(&tmp_file_path);
10781231
10791232 return err;
10801233}
10811234
1082int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
1083 ZigList<const char *> *clang_argv, bool warnings_on, uint32_t *next_node_index)
1235int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
1236 CodeGen *codegen, AstNode *source_node)
10841237{
10851238 Context context = {0};
10861239 Context *c = &context;
1087 c->warnings_on = warnings_on;
1240 c->warnings_on = codegen->verbose;
10881241 c->import = import;
10891242 c->errors = errors;
10901243 c->visib_mod = VisibModPub;
1091 c->root_name_table.init(8);
1244 c->global_type_table.init(8);
1245 c->global_value_table.init(8);
10921246 c->enum_type_table.init(8);
10931247 c->struct_type_table.init(8);
10941248 c->fn_table.init(8);
10951249 c->macro_table.init(8);
1096 c->next_node_index = next_node_index;
1250 c->codegen = codegen;
1251 c->source_node = source_node;
1252
1253 ZigList<const char *> clang_argv = {0};
1254
1255 clang_argv.append("-x");
1256 clang_argv.append("c");
10971257
10981258 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");
10991259 if (ZIG_PARSEH_CFLAGS) {
......@@ -1103,28 +1263,37 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
11031263 while (space) {
11041264 if (space - start > 0) {
11051265 buf_init_from_mem(&tmp_buf, start, space - start);
1106 clang_argv->append(buf_ptr(buf_create_from_buf(&tmp_buf)));
1266 clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
11071267 }
11081268 start = space + 1;
11091269 space = strstr(start, " ");
11101270 }
11111271 buf_init_from_str(&tmp_buf, start);
1112 clang_argv->append(buf_ptr(buf_create_from_buf(&tmp_buf)));
1272 clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
11131273 }
11141274
1115 clang_argv->append("-isystem");
1116 clang_argv->append(ZIG_HEADERS_DIR);
1275 clang_argv.append("-isystem");
1276 clang_argv.append(ZIG_HEADERS_DIR);
1277
1278 clang_argv.append("-isystem");
1279 clang_argv.append(buf_ptr(codegen->libc_include_path));
1280
1281 for (int i = 0; i < codegen->clang_argv_len; i += 1) {
1282 clang_argv.append(codegen->clang_argv[i]);
1283 }
11171284
11181285 // we don't need spell checking and it slows things down
1119 clang_argv->append("-fno-spell-checking");
1286 clang_argv.append("-fno-spell-checking");
11201287
11211288 // this gives us access to preprocessing entities, presumably at
11221289 // the cost of performance
1123 clang_argv->append("-Xclang");
1124 clang_argv->append("-detailed-preprocessing-record");
1290 clang_argv.append("-Xclang");
1291 clang_argv.append("-detailed-preprocessing-record");
1292
1293 clang_argv.append(target_file);
11251294
1126 // to make the end argument work
1127 clang_argv->append(nullptr);
1295 // to make the [start...end] argument work
1296 clang_argv.append(nullptr);
11281297
11291298 IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
11301299
......@@ -1138,7 +1307,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
11381307 const char *resources_path = ZIG_HEADERS_DIR;
11391308 std::unique_ptr<ASTUnit> err_unit;
11401309 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(
1141 &clang_argv->at(0), &clang_argv->last(),
1310 &clang_argv.at(0), &clang_argv.last(),
11421311 pch_container_ops, diags, resources_path,
11431312 only_local_decls, capture_diagnostics, None, true, false, TU_Complete,
11441313 false, false, allow_pch_with_compiler_errors, skip_function_bodies,
src/parseh.hpp+5-5
......@@ -11,10 +11,10 @@
1111
1212#include "all_types.hpp"
1313
14int parse_h_file(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs,
15 ZigList<const char *> *clang_argv, bool warnings_on, uint32_t *next_node_index);
16int parse_h_buf(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs,
17 Buf *source, const char **args, int args_len, const char *libc_include_path,
18 bool warnings_on, uint32_t *next_node_index);
14int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
15 CodeGen *codegen, AstNode *source_node);
16
17int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
18 CodeGen *codegen, AstNode *source_node);
1919
2020#endif
src/parser.cpp+49-2
......@@ -908,7 +908,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mand
908908
909909/*
910910PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." "Symbol")
911KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined" | "error"
911KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type"
912912*/
913913static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
914914 Token *token = &pc->tokens->at(*token_index);
......@@ -954,6 +954,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
954954 AstNode *node = ast_create_node(pc, NodeTypeUndefinedLiteral, token);
955955 *token_index += 1;
956956 return node;
957 } else if (token->id == TokenIdKeywordType) {
958 AstNode *node = ast_create_node(pc, NodeTypeTypeLiteral, token);
959 *token_index += 1;
960 return node;
957961 } else if (token->id == TokenIdKeywordError) {
958962 AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
959963 *token_index += 1;
......@@ -2470,7 +2474,34 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index,
24702474}
24712475
24722476/*
2473TopLevelDecl : many(Directive) option(FnVisibleMod) (FnDef | ExternFnProto | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl | CImportDecl)
2477TypeDecl = "type" "Symbol" "=" TypeExpr ";"
2478*/
2479static AstNode *ast_parse_type_decl(ParseContext *pc, int *token_index,
2480 ZigList<AstNode*> *directives, VisibMod visib_mod)
2481{
2482 Token *first_token = &pc->tokens->at(*token_index);
2483
2484 if (first_token->id != TokenIdKeywordType) {
2485 return nullptr;
2486 }
2487 *token_index += 1;
2488
2489 Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
2490 ast_eat_token(pc, token_index, TokenIdEq);
2491
2492 AstNode *node = ast_create_node(pc, NodeTypeTypeDecl, first_token);
2493 ast_buf_from_token(pc, name_tok, &node->data.type_decl.symbol);
2494 node->data.type_decl.child_type = ast_parse_prefix_op_expr(pc, token_index, true);
2495
2496 node->data.type_decl.visib_mod = visib_mod;
2497 node->data.type_decl.directives = directives;
2498
2499 normalize_parent_ptrs(node);
2500 return node;
2501}
2502
2503/*
2504TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl | TypeDecl)
24742505*/
24752506static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
24762507 for (;;) {
......@@ -2545,6 +2576,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
25452576 continue;
25462577 }
25472578
2579 AstNode *type_decl_node = ast_parse_type_decl(pc, token_index, directives, visib_mod);
2580 if (type_decl_node) {
2581 top_level_decls->append(type_decl_node);
2582 continue;
2583 }
2584
25482585 if (directives->length > 0) {
25492586 ast_error(pc, directive_token, "invalid directive");
25502587 }
......@@ -2631,9 +2668,16 @@ void normalize_parent_ptrs(AstNode *node) {
26312668 set_field(&node->data.return_expr.expr);
26322669 break;
26332670 case NodeTypeVariableDeclaration:
2671 if (node->data.variable_declaration.directives) {
2672 set_list_fields(node->data.variable_declaration.directives);
2673 }
26342674 set_field(&node->data.variable_declaration.type);
26352675 set_field(&node->data.variable_declaration.expr);
26362676 break;
2677 case NodeTypeTypeDecl:
2678 set_list_fields(node->data.type_decl.directives);
2679 set_field(&node->data.type_decl.child_type);
2680 break;
26372681 case NodeTypeErrorValueDecl:
26382682 // none
26392683 break;
......@@ -2772,5 +2816,8 @@ void normalize_parent_ptrs(AstNode *node) {
27722816 case NodeTypeErrorType:
27732817 // none
27742818 break;
2819 case NodeTypeTypeLiteral:
2820 // none
2821 break;
27752822 }
27762823}
src/tokenizer.cpp+4-1
......@@ -101,7 +101,7 @@ const char * zig_keywords[] = {
101101 "true", "false", "null", "fn", "return", "var", "const", "extern",
102102 "pub", "export", "import", "c_import", "if", "else", "goto", "asm",
103103 "volatile", "struct", "enum", "while", "for", "continue", "break",
104 "null", "noalias", "switch", "undefined", "error"
104 "null", "noalias", "switch", "undefined", "error", "type"
105105};
106106
107107bool is_zig_keyword(Buf *buf) {
......@@ -271,6 +271,8 @@ static void end_token(Tokenize *t) {
271271 t->cur_tok->id = TokenIdKeywordUndefined;
272272 } else if (mem_eql_str(token_mem, token_len, "error")) {
273273 t->cur_tok->id = TokenIdKeywordError;
274 } else if (mem_eql_str(token_mem, token_len, "type")) {
275 t->cur_tok->id = TokenIdKeywordType;
274276 }
275277
276278 t->cur_tok = nullptr;
......@@ -1084,6 +1086,7 @@ const char * token_name(TokenId id) {
10841086 case TokenIdKeywordSwitch: return "switch";
10851087 case TokenIdKeywordUndefined: return "undefined";
10861088 case TokenIdKeywordError: return "error";
1089 case TokenIdKeywordType: return "type";
10871090 case TokenIdLParen: return "(";
10881091 case TokenIdRParen: return ")";
10891092 case TokenIdComma: return ",";
src/tokenizer.hpp+1
......@@ -40,6 +40,7 @@ enum TokenId {
4040 TokenIdKeywordSwitch,
4141 TokenIdKeywordUndefined,
4242 TokenIdKeywordError,
43 TokenIdKeywordType,
4344 TokenIdLParen,
4445 TokenIdRParen,
4546 TokenIdComma,
test/run_tests.cpp+5-5
......@@ -115,7 +115,7 @@ static TestCase *add_parseh_case(const char *case_name, const char *source, int
115115
116116 test_case->compiler_args.append("parseh");
117117 test_case->compiler_args.append(tmp_h_path);
118 test_case->compiler_args.append("--c-import-warnings");
118 test_case->compiler_args.append("--verbose");
119119
120120 test_cases.append(test_case);
121121
......@@ -1689,7 +1689,7 @@ var a : i32 = 2;
16891689 add_compile_fail_case("byvalue struct on exported functions", R"SOURCE(
16901690struct A { x : i32, }
16911691export fn f(a : A) {}
1692 )SOURCE", 1, ".tmp_source.zig:3:13: error: byvalue struct parameters not yet supported on exported functions");
1692 )SOURCE", 1, ".tmp_source.zig:3:13: error: byvalue struct parameters not yet supported on extern functions");
16931693
16941694 add_compile_fail_case("duplicate field in struct value expression", R"SOURCE(
16951695struct A {
......@@ -1929,7 +1929,7 @@ pub const Foo1 = enum_Foo._1;)OUTPUT",
19291929
19301930 add_parseh_case("restrict -> noalias", R"SOURCE(
19311931void foo(void *restrict bar, void *restrict);
1932 )SOURCE", 1, R"OUTPUT(pub const c_void = u8;
1932 )SOURCE", 1, R"OUTPUT(pub type c_void = u8;
19331933pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT");
19341934
19351935 add_parseh_case("simple struct", R"SOURCE(
......@@ -1977,14 +1977,14 @@ struct Foo {
19771977 void (*derp)(struct Foo *foo);
19781978};
19791979 )SOURCE", 2, R"OUTPUT(export struct struct_Foo {
1980 derp: ?extern fn (?&struct_Foo),
1980 derp: ?extern fn(?&struct_Foo),
19811981})OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
19821982
19831983
19841984 add_parseh_case("struct prototype used in func", R"SOURCE(
19851985struct Foo;
19861986struct Foo *some_func(struct Foo *foo, int x);
1987 )SOURCE", 2, R"OUTPUT(pub const struct_Foo = u8;
1987 )SOURCE", 2, R"OUTPUT(pub type struct_Foo = u8;
19881988pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",
19891989 R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
19901990