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 @@...@@ -5,15 +5,17 @@
5```5```
6Root = many(TopLevelDecl) "EOF"6Root = 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
10CImportDecl = "c_import" Block10CImportDecl = "c_import" Block
1111
12TypeDecl = "type" "Symbol" "=" TypeExpr ";"
13
12ErrorValueDecl = "error" "Symbol" ";"14ErrorValueDecl = "error" "Symbol" ";"
1315
14GlobalVarDecl = VariableDeclaration ";"16GlobalVarDecl = VariableDeclaration ";"
1517
16VariableDeclaration = ("var" | "const") "Symbol" option(":" PrefixOpExpression) "=" Expression18VariableDeclaration = ("var" | "const") "Symbol" option(":" TypeExpr) "=" Expression
1719
18ContainerDecl = ("struct" | "enum") "Symbol" "{" many(StructMember) "}"20ContainerDecl = ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
1921
...@@ -27,7 +29,7 @@ RootExportDecl = "export" "Symbol" "String" ";"...@@ -27,7 +29,7 @@ RootExportDecl = "export" "Symbol" "String" ";"
2729
28ExternDecl = "extern" (FnProto | VariableDeclaration) ";"30ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
2931
30FnProto = "fn" option("Symbol") ParamDeclList option("->" PrefixOpExpression)32FnProto = "fn" option("Symbol") ParamDeclList option("->" TypeExpr)
3133
32Directive = "#" "Symbol" "(" "String" ")"34Directive = "#" "Symbol" "(" "String" ")"
3335
...@@ -37,7 +39,7 @@ FnDef = FnProto Block...@@ -37,7 +39,7 @@ FnDef = FnProto Block
3739
38ParamDeclList = "(" list(ParamDecl, ",") ")"40ParamDeclList = "(" list(ParamDecl, ",") ")"
3941
40ParamDecl = option("noalias") option("Symbol" ":") PrefixOpExpression | "..."42ParamDecl = option("noalias") option("Symbol" ":") TypeExpr | "..."
4143
42Block = "{" list(option(Statement), ";") "}"44Block = "{" list(option(Statement), ";") "}"
4345
...@@ -47,6 +49,8 @@ Label = "Symbol" ":"...@@ -47,6 +49,8 @@ Label = "Symbol" ":"
4749
48Expression = BlockExpression | NonBlockExpression50Expression = BlockExpression | NonBlockExpression
4951
52TypeExpr = PrefixOpExpression
53
50NonBlockExpression = ReturnExpression | AssignmentExpression54NonBlockExpression = ReturnExpression | AssignmentExpression
5155
52AsmExpression = "asm" option("volatile") "(" "String" option(AsmOutput) ")"56AsmExpression = "asm" option("volatile") "(" "String" option(AsmOutput) ")"
...@@ -55,7 +59,7 @@ AsmOutput = ":" list(AsmOutputItem, ",") option(AsmInput)...@@ -55,7 +59,7 @@ AsmOutput = ":" list(AsmOutputItem, ",") option(AsmInput)
5559
56AsmInput = ":" list(AsmInputItem, ",") option(AsmClobbers)60AsmInput = ":" list(AsmInputItem, ",") option(AsmClobbers)
5761
58AsmOutputItem = "[" "Symbol" "]" "String" "(" ("Symbol" | "->" PrefixOpExpression) ")"62AsmOutputItem = "[" "Symbol" "]" "String" "(" ("Symbol" | "->" TypeExpr) ")"
5963
60AsmInputItem = "[" "Symbol" "]" "String" "(" Expression ")"64AsmInputItem = "[" "Symbol" "]" "String" "(" Expression ")"
6165
...@@ -91,7 +95,7 @@ IfExpression = IfVarExpression | IfBoolExpression...@@ -91,7 +95,7 @@ IfExpression = IfVarExpression | IfBoolExpression
9195
92IfBoolExpression = "if" "(" Expression ")" Expression option(Else)96IfBoolExpression = "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
96Else = "else" Expression100Else = "else" Expression
97101
...@@ -117,7 +121,7 @@ AdditionOperator = "+" | "-" | "++"...@@ -117,7 +121,7 @@ AdditionOperator = "+" | "-" | "++"
117121
118MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression122MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
119123
120CurlySuffixExpression = PrefixOpExpression option(ContainerInitExpression)124CurlySuffixExpression = TypeExpr option(ContainerInitExpression)
121125
122MultiplyOperator = "*" | "/" | "%"126MultiplyOperator = "*" | "/" | "%"
123127
...@@ -143,13 +147,13 @@ PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%"...@@ -143,13 +147,13 @@ PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%"
143147
144PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol")148PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol")
145149
146ArrayType = "[" option(Expression) "]" option("const") PrefixOpExpression150ArrayType = "[" option(Expression) "]" option("const") TypeExpr
147151
148GotoExpression = "goto" "Symbol"152GotoExpression = "goto" "Symbol"
149153
150GroupedExpression = "(" Expression ")"154GroupedExpression = "(" Expression ")"
151155
152KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error"156KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type"
153```157```
154158
155## Operator Precedence159## Operator Precedence
src/all_types.hpp+69-17
...@@ -124,6 +124,7 @@ enum NodeType {...@@ -124,6 +124,7 @@ enum NodeType {
124 NodeTypeDirective,124 NodeTypeDirective,
125 NodeTypeReturnExpr,125 NodeTypeReturnExpr,
126 NodeTypeVariableDeclaration,126 NodeTypeVariableDeclaration,
127 NodeTypeTypeDecl,
127 NodeTypeErrorValueDecl,128 NodeTypeErrorValueDecl,
128 NodeTypeBinOpExpr,129 NodeTypeBinOpExpr,
129 NodeTypeUnwrapErrorExpr,130 NodeTypeUnwrapErrorExpr,
...@@ -159,6 +160,7 @@ enum NodeType {...@@ -159,6 +160,7 @@ enum NodeType {
159 NodeTypeStructValueField,160 NodeTypeStructValueField,
160 NodeTypeArrayType,161 NodeTypeArrayType,
161 NodeTypeErrorType,162 NodeTypeErrorType,
163 NodeTypeTypeLiteral,
162};164};
163165
164struct AstNodeRoot {166struct AstNodeRoot {
...@@ -212,9 +214,6 @@ struct AstNodeParamDecl {...@@ -212,9 +214,6 @@ struct AstNodeParamDecl {
212214
213 // populated by semantic analyzer215 // populated by semantic analyzer
214 VariableTableEntry *variable;216 VariableTableEntry *variable;
215 bool is_byval;
216 int src_index;
217 int gen_index;
218};217};
219218
220struct AstNodeBlock {219struct AstNodeBlock {
...@@ -256,6 +255,19 @@ struct AstNodeVariableDeclaration {...@@ -256,6 +255,19 @@ struct AstNodeVariableDeclaration {
256 VariableTableEntry *variable;255 VariableTableEntry *variable;
257};256};
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
259struct AstNodeErrorValueDecl {271struct AstNodeErrorValueDecl {
260 Buf name;272 Buf name;
261 VisibMod visib_mod;273 VisibMod visib_mod;
...@@ -684,6 +696,11 @@ struct AstNodeErrorType {...@@ -684,6 +696,11 @@ struct AstNodeErrorType {
684 Expr resolved_expr;696 Expr resolved_expr;
685};697};
686698
699struct AstNodeTypeLiteral {
700 // populated by semantic analyzer
701 Expr resolved_expr;
702};
703
687struct AstNode {704struct AstNode {
688 enum NodeType type;705 enum NodeType type;
689 int line;706 int line;
...@@ -704,6 +721,7 @@ struct AstNode {...@@ -704,6 +721,7 @@ struct AstNode {
704 AstNodeBlock block;721 AstNodeBlock block;
705 AstNodeReturnExpr return_expr;722 AstNodeReturnExpr return_expr;
706 AstNodeVariableDeclaration variable_declaration;723 AstNodeVariableDeclaration variable_declaration;
724 AstNodeTypeDecl type_decl;
707 AstNodeErrorValueDecl error_value_decl;725 AstNodeErrorValueDecl error_value_decl;
708 AstNodeBinOpExpr bin_op_expr;726 AstNodeBinOpExpr bin_op_expr;
709 AstNodeUnwrapErrorExpr unwrap_err_expr;727 AstNodeUnwrapErrorExpr unwrap_err_expr;
...@@ -740,6 +758,7 @@ struct AstNode {...@@ -740,6 +758,7 @@ struct AstNode {
740 AstNodeContinueExpr continue_expr;758 AstNodeContinueExpr continue_expr;
741 AstNodeArrayType array_type;759 AstNodeArrayType array_type;
742 AstNodeErrorType error_type;760 AstNodeErrorType error_type;
761 AstNodeTypeLiteral type_literal;
743 } data;762 } data;
744};763};
745764
...@@ -755,6 +774,24 @@ struct AsmToken {...@@ -755,6 +774,24 @@ struct AsmToken {
755 int end;774 int end;
756};775};
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
758struct TypeTableEntryPointer {795struct TypeTableEntryPointer {
759 TypeTableEntry *child_type;796 TypeTableEntry *child_type;
760 bool is_const;797 bool is_const;
...@@ -820,17 +857,25 @@ struct TypeTableEntryEnum {...@@ -820,17 +857,25 @@ struct TypeTableEntryEnum {
820 bool complete;857 bool complete;
821};858};
822859
860struct FnGenParamInfo {
861 int src_index;
862 int gen_index;
863 bool is_byval;
864};
865
823struct TypeTableEntryFn {866struct TypeTableEntryFn {
824 TypeTableEntry *src_return_type;867 FnTypeId fn_type_id;
825 TypeTableEntry *gen_return_type;868 TypeTableEntry *gen_return_type;
826 TypeTableEntry **param_types;
827 int src_param_count;
828 LLVMTypeRef raw_type_ref;
829 bool is_var_args;
830 int gen_param_count;869 int gen_param_count;
870 FnGenParamInfo *gen_param_info;
871
872 LLVMTypeRef raw_type_ref;
831 LLVMCallConv calling_convention;873 LLVMCallConv calling_convention;
832 bool is_extern;874};
833 bool is_naked;875
876struct TypeTableEntryTypeDecl {
877 TypeTableEntry *child_type;
878 TypeTableEntry *canonical_type;
834};879};
835880
836enum TypeTableEntryId {881enum TypeTableEntryId {
...@@ -852,6 +897,7 @@ enum TypeTableEntryId {...@@ -852,6 +897,7 @@ enum TypeTableEntryId {
852 TypeTableEntryIdPureError,897 TypeTableEntryIdPureError,
853 TypeTableEntryIdEnum,898 TypeTableEntryIdEnum,
854 TypeTableEntryIdFn,899 TypeTableEntryIdFn,
900 TypeTableEntryIdTypeDecl,
855};901};
856902
857struct TypeTableEntry {903struct TypeTableEntry {
...@@ -873,6 +919,7 @@ struct TypeTableEntry {...@@ -873,6 +919,7 @@ struct TypeTableEntry {
873 TypeTableEntryError error;919 TypeTableEntryError error;
874 TypeTableEntryEnum enumeration;920 TypeTableEntryEnum enumeration;
875 TypeTableEntryFn fn;921 TypeTableEntryFn fn;
922 TypeTableEntryTypeDecl type_decl;
876 } data;923 } data;
877924
878 // use these fields to make sure we don't duplicate type table entries for the same type925 // use these fields to make sure we don't duplicate type table entries for the same type
...@@ -900,7 +947,6 @@ struct ImportTableEntry {...@@ -900,7 +947,6 @@ struct ImportTableEntry {
900947
901 // reminder: hash tables must be initialized before use948 // reminder: hash tables must be initialized before use
902 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;949 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
903 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> fn_type_table;
904};950};
905951
906struct LabelTableEntry {952struct LabelTableEntry {
...@@ -969,12 +1015,14 @@ struct CodeGen {...@@ -969,12 +1015,14 @@ struct CodeGen {
969 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;1015 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
970 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;1016 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
971 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls;1017 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
973 uint32_t next_unresolved_index;1020 uint32_t next_unresolved_index;
9741021
975 struct {1022 struct {
976 TypeTableEntry *entry_bool;1023 TypeTableEntry *entry_bool;
977 TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64]1024 TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64]
1025 TypeTableEntry *entry_c_int[8];
978 TypeTableEntry *entry_u8;1026 TypeTableEntry *entry_u8;
979 TypeTableEntry *entry_u16;1027 TypeTableEntry *entry_u16;
980 TypeTableEntry *entry_u32;1028 TypeTableEntry *entry_u32;
...@@ -1082,12 +1130,16 @@ struct BlockContext {...@@ -1082,12 +1130,16 @@ struct BlockContext {
1082 Buf *c_import_buf;1130 Buf *c_import_buf;
1083};1131};
10841132
1085struct ParseH {1133enum CIntType {
1086 ZigList<ErrorMsg*> errors;1134 CIntTypeShort,
1087 ZigList<AstNode *> fn_list;1135 CIntTypeUShort,
1088 ZigList<AstNode *> struct_list;1136 CIntTypeInt,
1089 ZigList<AstNode *> var_list;1137 CIntTypeUInt,
1090 ZigList<AstNode *> incomplete_struct_list;1138 CIntTypeLong,
1139 CIntTypeULong,
1140 CIntTypeLongLong,
1141 CIntTypeULongLong,
1091};1142};
10921143
1144
1093#endif1145#endif
src/analyze.cpp+377-166
...@@ -56,6 +56,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -56,6 +56,7 @@ static AstNode *first_executing_node(AstNode *node) {
56 case NodeTypeDirective:56 case NodeTypeDirective:
57 case NodeTypeReturnExpr:57 case NodeTypeReturnExpr:
58 case NodeTypeVariableDeclaration:58 case NodeTypeVariableDeclaration:
59 case NodeTypeTypeDecl:
59 case NodeTypeErrorValueDecl:60 case NodeTypeErrorValueDecl:
60 case NodeTypeNumberLiteral:61 case NodeTypeNumberLiteral:
61 case NodeTypeStringLiteral:62 case NodeTypeStringLiteral:
...@@ -83,6 +84,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -83,6 +84,7 @@ static AstNode *first_executing_node(AstNode *node) {
83 case NodeTypeSwitchProng:84 case NodeTypeSwitchProng:
84 case NodeTypeArrayType:85 case NodeTypeArrayType:
85 case NodeTypeErrorType:86 case NodeTypeErrorType:
87 case NodeTypeTypeLiteral:
86 case NodeTypeContainerInitExpr:88 case NodeTypeContainerInitExpr:
87 return node;89 return node;
88 }90 }
...@@ -123,6 +125,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {...@@ -123,6 +125,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
123 case TypeTableEntryIdErrorUnion:125 case TypeTableEntryIdErrorUnion:
124 case TypeTableEntryIdPureError:126 case TypeTableEntryIdPureError:
125 case TypeTableEntryIdUndefLit:127 case TypeTableEntryIdUndefLit:
128 case TypeTableEntryIdTypeDecl:
126 // nothing to init129 // nothing to init
127 break;130 break;
128 case TypeTableEntryIdStruct:131 case TypeTableEntryIdStruct:
...@@ -149,7 +152,7 @@ static int bits_needed_for_unsigned(uint64_t x) {...@@ -149,7 +152,7 @@ static int bits_needed_for_unsigned(uint64_t x) {
149 }152 }
150}153}
151154
152static TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {155TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
153 return get_int_type(g, false, bits_needed_for_unsigned(x));156 return get_int_type(g, false, bits_needed_for_unsigned(x));
154}157}
155158
...@@ -165,12 +168,15 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool...@@ -165,12 +168,15 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
165 buf_resize(&entry->name, 0);168 buf_resize(&entry->name, 0);
166 buf_appendf(&entry->name, "&%s%s", const_str, buf_ptr(&child_type->name));169 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
168 bool zero_bits;174 bool zero_bits;
169 if (child_type->size_in_bits == 0) {175 if (canon_child_type->size_in_bits == 0) {
170 if (child_type->id == TypeTableEntryIdStruct) {176 if (canon_child_type->id == TypeTableEntryIdStruct) {
171 zero_bits = child_type->data.structure.complete;177 zero_bits = canon_child_type->data.structure.complete;
172 } else if (child_type->id == TypeTableEntryIdEnum) {178 } else if (canon_child_type->id == TypeTableEntryIdEnum) {
173 zero_bits = child_type->data.enumeration.complete;179 zero_bits = canon_child_type->data.enumeration.complete;
174 } else {180 } else {
175 zero_bits = true;181 zero_bits = true;
176 }182 }
...@@ -196,7 +202,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool...@@ -196,7 +202,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
196 }202 }
197}203}
198204
199static TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {205TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
200 if (child_type->maybe_parent) {206 if (child_type->maybe_parent) {
201 TypeTableEntry *entry = child_type->maybe_parent;207 TypeTableEntry *entry = child_type->maybe_parent;
202 return entry;208 return entry;
...@@ -317,8 +323,7 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {...@@ -317,8 +323,7 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
317 }323 }
318}324}
319325
320static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size)326TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size) {
321{
322 auto existing_entry = child_type->arrays_by_size.maybe_get(array_size);327 auto existing_entry = child_type->arrays_by_size.maybe_get(array_size);
323 if (existing_entry) {328 if (existing_entry) {
324 TypeTableEntry *entry = existing_entry->value;329 TypeTableEntry *entry = existing_entry->value;
...@@ -417,147 +422,109 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *c...@@ -417,147 +422,109 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *c
417 }422 }
418}423}
419424
420// If the node does not have a constant expression value with a metatype, generates an error425TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type) {
421// and returns invalid type. Otherwise, returns the type of the constant expression value.426 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdTypeDecl);
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 }
437427
438 ConstExprValue *const_val = &expr->const_val;428 buf_init_from_str(&entry->name, name);
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 }
443429
444 return const_val->data.x_type;430 entry->type_ref = child_type->type_ref;
445}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.436 entry->data.type_decl.child_type = child_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}
455437
456static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,438 if (child_type->id == TypeTableEntryIdTypeDecl) {
457 TypeTableEntry *expected_type, AstNode *node, bool is_naked)439 entry->data.type_decl.canonical_type = child_type->data.type_decl.canonical_type;
458{440 } else {
459 assert(node->type == NodeTypeFnProto);441 entry->data.type_decl.canonical_type = child_type;
460 AstNodeFnProto *fn_proto = &node->data.fn_proto;442 }
461443
462 if (fn_proto->skip) {444 return entry;
463 return g->builtin_types.entry_invalid;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;
464 }452 }
465453
466 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);454 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
467 fn_type->data.fn.is_extern = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport);455 fn_type->data.fn.fn_type_id = fn_type_id;
468 fn_type->data.fn.is_naked = is_naked;456 fn_type->data.fn.calling_convention = fn_type_id.is_extern ? LLVMCCallConv : LLVMFastCallConv;
469 fn_type->data.fn.calling_convention = fn_proto->is_extern ? LLVMCCallConv : LLVMFastCallConv;
470457
471 int src_param_count = node->data.fn_proto.params.length;
472 fn_type->size_in_bits = g->pointer_size_bytes * 8;458 fn_type->size_in_bits = g->pointer_size_bytes * 8;
473 fn_type->align_in_bits = g->pointer_size_bytes * 8;459 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 in461 // populate the name of the type
478 // source code in order for error messages to be in the best order.
479 buf_resize(&fn_type->name, 0);462 buf_resize(&fn_type->name, 0);
480 const char *extern_str = fn_type->data.fn.is_extern ? "extern " : "";463 const char *extern_str = fn_type_id.is_extern ? "extern " : "";
481 const char *naked_str = fn_type->data.fn.is_naked ? "naked " : "";464 const char *naked_str = fn_type_id.is_naked ? "naked " : "";
482 buf_appendf(&fn_type->name, "%s%sfn(", extern_str, naked_str);465 buf_appendf(&fn_type->name, "%s%sfn(", extern_str, naked_str);
483 for (int i = 0; i < src_param_count; i += 1) {466 for (int i = 0; i < fn_type_id.param_count; i += 1) {
484 AstNode *child = node->data.fn_proto.params.at(i);467 FnTypeParamInfo *param_info = &fn_type_id.param_info[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;
489468
469 TypeTableEntry *param_type = param_info->type;
490 const char *comma = (i == 0) ? "" : ", ";470 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));
492 }473 }
493474
494 TypeTableEntry *return_type = analyze_type_expr(g, import, import->block_context,475 if (fn_type_id.is_var_args) {
495 node->data.fn_proto.return_type);476 const char *comma = (fn_type_id.param_count == 0) ? "" : ", ";
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) ? "" : ", ";
503 buf_appendf(&fn_type->name, "%s...", comma);477 buf_appendf(&fn_type->name, "%s...", comma);
504 }478 }
505 buf_appendf(&fn_type->name, ")");479 buf_appendf(&fn_type->name, ")");
506 if (return_type->id != TypeTableEntryIdVoid) {480 if (fn_type_id.return_type->id != TypeTableEntryIdVoid) {
507 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&return_type->name));481 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id.return_type->name));
508 }482 }
509483
510484
511 // next, loop over the parameters again and compute debug information485 // next, loop over the parameters again and compute debug information
512 // and codegen information486 // 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);
514 // +1 for maybe making the first argument the return value488 // +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);
516 // +1 because 0 is the return type and +1 for maybe making first arg ret val490 // +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);491 LLVMZigDIType **param_di_types = allocate<LLVMZigDIType*>(2 + fn_type_id.param_count);
518 param_di_types[0] = return_type->di_type;492 param_di_types[0] = fn_type_id.return_type->di_type;
519 int gen_param_index = 0;493 int gen_param_index = 0;
520 TypeTableEntry *gen_return_type;494 TypeTableEntry *gen_return_type;
521 if (first_arg_return) {495 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);
523 gen_param_types[gen_param_index] = gen_type->type_ref;497 gen_param_types[gen_param_index] = gen_type->type_ref;
524 gen_param_index += 1;498 gen_param_index += 1;
525 // after the gen_param_index += 1 because 0 is the return type499 // after the gen_param_index += 1 because 0 is the return type
526 param_di_types[gen_param_index] = gen_type->di_type;500 param_di_types[gen_param_index] = gen_type->di_type;
527 gen_return_type = g->builtin_types.entry_void;501 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) {
529 gen_return_type = g->builtin_types.entry_void;503 gen_return_type = g->builtin_types.entry_void;
530 } else {504 } else {
531 gen_return_type = return_type;505 gen_return_type = fn_type_id.return_type;
532 }506 }
533 fn_type->data.fn.gen_return_type = gen_return_type;507 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;509 fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id.param_count);
548 child->data.param_decl.gen_index = -1;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) {
552 TypeTableEntry *gen_type;519 TypeTableEntry *gen_type;
553 if (handle_is_ptr(type_entry)) {520 if (handle_is_ptr(type_entry)) {
554 gen_type = get_pointer_to_type(g, type_entry, true);521 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;
556 } else {523 } else {
557 gen_type = type_entry;524 gen_type = type_entry;
558 }525 }
559 gen_param_types[gen_param_index] = gen_type->type_ref;526 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
562 gen_param_index += 1;529 gen_param_index += 1;
563530
...@@ -568,24 +535,168 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor...@@ -568,24 +535,168 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
568535
569 fn_type->data.fn.gen_param_count = gen_param_index;536 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
571 if (fn_proto->skip) {638 if (fn_proto->skip) {
572 return g->builtin_types.entry_invalid;639 return g->builtin_types.entry_invalid;
573 }640 }
574641
575 auto table_entry = import->fn_type_table.maybe_get(&fn_type->name);642 FnTypeId fn_type_id;
576 if (table_entry) {643 fn_type_id.is_extern = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport);
577 return table_entry->value;644 fn_type_id.is_naked = is_naked;
578 } else {645 fn_type_id.param_count = node->data.fn_proto.params.length;
579 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,646 fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count);
580 gen_param_types, gen_param_index, fn_type->data.fn.is_var_args);647 fn_type_id.is_var_args = fn_proto->is_var_args;
581 fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);648 fn_type_id.return_type = analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type);
582 fn_type->di_type = LLVMZigCreateSubroutineType(g->dbuilder, import->di_file,649
583 param_di_types, gen_param_index + 1, 0);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;
588 }697 }
698
699 return get_fn_type(g, fn_type_id);
589}700}
590701
591702
...@@ -640,14 +751,14 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -640,14 +751,14 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
640 if (fn_table_entry->is_inline) {751 if (fn_table_entry->is_inline) {
641 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMAlwaysInlineAttribute);752 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMAlwaysInlineAttribute);
642 }753 }
643 if (fn_type->data.fn.is_naked) {754 if (fn_type->data.fn.fn_type_id.is_naked) {
644 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNakedAttribute);755 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNakedAttribute);
645 }756 }
646757
647 LLVMSetLinkage(fn_table_entry->fn_value, fn_table_entry->internal_linkage ?758 LLVMSetLinkage(fn_table_entry->fn_value, fn_table_entry->internal_linkage ?
648 LLVMInternalLinkage : LLVMExternalLinkage);759 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) {
651 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoReturnAttribute);762 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoReturnAttribute);
652 }763 }
653 LLVMSetFunctionCallConv(fn_table_entry->fn_value, fn_type->data.fn.calling_convention);764 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_...@@ -691,6 +802,7 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_
691}802}
692803
693static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type) {804static 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
694 assert(enum_type->id == TypeTableEntryIdEnum);806 assert(enum_type->id == TypeTableEntryIdEnum);
695807
696 AstNode *decl_node = enum_type->data.enumeration.decl_node;808 AstNode *decl_node = enum_type->data.enumeration.decl_node;
...@@ -853,6 +965,8 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt...@@ -853,6 +965,8 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
853}965}
854966
855static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type) {967static 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
856 assert(struct_type->id == TypeTableEntryIdStruct);970 assert(struct_type->id == TypeTableEntryIdStruct);
857971
858 AstNode *decl_node = struct_type->data.structure.decl_node;972 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...@@ -1104,15 +1218,12 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
11041218
1105 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);1219 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
1106 child_import->fn_table.init(32);1220 child_import->fn_table.init(32);
1107 child_import->fn_type_table.init(32);
1108 child_import->c_import_node = node;1221 child_import->c_import_node = node;
11091222
1110 ZigList<ErrorMsg *> errors = {0};1223 ZigList<ErrorMsg *> errors = {0};
11111224
1112 int err;1225 int err;
1113 if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len,1226 if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {
1114 buf_ptr(g->libc_include_path), false, &g->next_node_index)))
1115 {
1116 zig_panic("unable to parse h file: %s\n", err_str(err));1227 zig_panic("unable to parse h file: %s\n", err_str(err));
1117 }1228 }
11181229
...@@ -1175,6 +1286,27 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1175,6 +1286,27 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1175 VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context,1286 VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context,
1176 nullptr, node);1287 nullptr, node);
1177 g->global_vars.append(var);1288 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
1178 break;1310 break;
1179 }1311 }
1180 case NodeTypeErrorValueDecl:1312 case NodeTypeErrorValueDecl:
...@@ -1224,6 +1356,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1224,6 +1356,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1224 case NodeTypeContainerInitExpr:1356 case NodeTypeContainerInitExpr:
1225 case NodeTypeArrayType:1357 case NodeTypeArrayType:
1226 case NodeTypeErrorType:1358 case NodeTypeErrorType:
1359 case NodeTypeTypeLiteral:
1227 zig_unreachable();1360 zig_unreachable();
1228 }1361 }
12291362
...@@ -1278,8 +1411,10 @@ static bool type_has_codegen_value(TypeTableEntryId id) {...@@ -1278,8 +1411,10 @@ static bool type_has_codegen_value(TypeTableEntryId id) {
1278 case TypeTableEntryIdEnum:1411 case TypeTableEntryIdEnum:
1279 case TypeTableEntryIdFn:1412 case TypeTableEntryIdFn:
1280 return true;1413 return true;
1414
1415 case TypeTableEntryIdTypeDecl:
1416 zig_unreachable();
1281 }1417 }
1282 zig_unreachable();
1283}1418}
12841419
1285static void add_global_const_expr(CodeGen *g, Expr *expr) {1420static void add_global_const_expr(CodeGen *g, Expr *expr) {
...@@ -1376,25 +1511,30 @@ static bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTable...@@ -1376,25 +1511,30 @@ static bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTable
1376 if (expected_type->id == TypeTableEntryIdFn &&1511 if (expected_type->id == TypeTableEntryIdFn &&
1377 actual_type->id == TypeTableEntryIdFn)1512 actual_type->id == TypeTableEntryIdFn)
1378 {1513 {
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) {
1380 return false;1515 return false;
1381 }1516 }
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) {
1383 return false;1518 return false;
1384 }1519 }
1385 if (!types_match_const_cast_only(expected_type->data.fn.src_return_type,1520 if (!types_match_const_cast_only(expected_type->data.fn.fn_type_id.return_type,
1386 actual_type->data.fn.src_return_type))1521 actual_type->data.fn.fn_type_id.return_type))
1387 {1522 {
1388 return false;1523 return false;
1389 }1524 }
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) {
1391 return false;1526 return false;
1392 }1527 }
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) {
1394 // note it's reversed for parameters1529 // note it's reversed for parameters
1395 if (types_match_const_cast_only(actual_type->data.fn.param_types[i],1530 FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];
1396 expected_type->data.fn.param_types[i]))1531 FnTypeParamInfo *expected_param_info = &expected_type->data.fn.fn_type_id.param_info[i];
1397 {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) {
1398 return false;1538 return false;
1399 }1539 }
1400 }1540 }
...@@ -3610,6 +3750,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -3610,6 +3750,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
3610 case TypeTableEntryIdPureError:3750 case TypeTableEntryIdPureError:
3611 case TypeTableEntryIdEnum:3751 case TypeTableEntryIdEnum:
3612 case TypeTableEntryIdFn:3752 case TypeTableEntryIdFn:
3753 case TypeTableEntryIdTypeDecl:
3613 return resolve_expr_const_val_as_type(g, node, type_entry);3754 return resolve_expr_const_val_as_type(g, node, type_entry);
3614 }3755 }
3615 }3756 }
...@@ -3664,14 +3805,14 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,...@@ -3664,14 +3805,14 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
3664 assert(node->type == NodeTypeFnCallExpr);3805 assert(node->type == NodeTypeFnCallExpr);
36653806
3666 // count parameters3807 // 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;
3668 int actual_param_count = node->data.fn_call_expr.params.length;3809 int actual_param_count = node->data.fn_call_expr.params.length;
36693810
3670 if (struct_type) {3811 if (struct_type) {
3671 actual_param_count += 1;3812 actual_param_count += 1;
3672 }3813 }
36733814
3674 if (fn_type->data.fn.is_var_args) {3815 if (fn_type->data.fn.fn_type_id.is_var_args) {
3675 if (actual_param_count < src_param_count) {3816 if (actual_param_count < src_param_count) {
3676 add_node_error(g, node,3817 add_node_error(g, node,
3677 buf_sprintf("expected at least %d arguments, got %d", src_param_count, actual_param_count));3818 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,...@@ -3689,12 +3830,12 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
3689 TypeTableEntry *expected_param_type = nullptr;3830 TypeTableEntry *expected_param_type = nullptr;
3690 int fn_proto_i = i + (struct_type ? 1 : 0);3831 int fn_proto_i = i + (struct_type ? 1 : 0);
3691 if (fn_proto_i < src_param_count) {3832 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;
3693 }3834 }
3694 analyze_expression(g, import, context, expected_param_type, child);3835 analyze_expression(g, import, context, expected_param_type, child);
3695 }3836 }
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
3699 if (return_type->id == TypeTableEntryIdInvalid) {3840 if (return_type->id == TypeTableEntryIdInvalid) {
3700 return return_type;3841 return return_type;
...@@ -4304,6 +4445,9 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -4304,6 +4445,9 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
4304 case NodeTypeErrorType:4445 case NodeTypeErrorType:
4305 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_pure_error);4446 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_pure_error);
4306 break;4447 break;
4448 case NodeTypeTypeLiteral:
4449 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_type);
4450 break;
4307 case NodeTypeSwitchExpr:4451 case NodeTypeSwitchExpr:
4308 return_type = analyze_switch_expr(g, import, context, expected_type, node);4452 return_type = analyze_switch_expr(g, import, context, expected_type, node);
4309 break;4453 break;
...@@ -4322,6 +4466,7 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -4322,6 +4466,7 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
4322 case NodeTypeStructField:4466 case NodeTypeStructField:
4323 case NodeTypeStructValueField:4467 case NodeTypeStructValueField:
4324 case NodeTypeErrorValueDecl:4468 case NodeTypeErrorValueDecl:
4469 case NodeTypeTypeDecl:
4325 zig_unreachable();4470 zig_unreachable();
4326 }4471 }
4327 assert(return_type);4472 assert(return_type);
...@@ -4354,8 +4499,9 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo...@@ -4354,8 +4499,9 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
43544499
4355 BlockContext *context = node->data.fn_def.block_context;4500 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;
4357 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;4504 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
4358 bool is_exported = (fn_proto->visib_mod == VisibModExport);
4359 for (int i = 0; i < fn_proto->params.length; i += 1) {4505 for (int i = 0; i < fn_proto->params.length; i += 1) {
4360 AstNode *param_decl_node = fn_proto->params.at(i);4506 AstNode *param_decl_node = fn_proto->params.at(i);
4361 assert(param_decl_node->type == NodeTypeParamDecl);4507 assert(param_decl_node->type == NodeTypeParamDecl);
...@@ -4369,9 +4515,9 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo...@@ -4369,9 +4515,9 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
4369 buf_sprintf("noalias on non-pointer parameter"));4515 buf_sprintf("noalias on non-pointer parameter"));
4370 }4516 }
43714517
4372 if (is_exported && type->id == TypeTableEntryIdStruct) {4518 if (fn_type->data.fn.fn_type_id.is_extern && type->id == TypeTableEntryIdStruct) {
4373 add_node_error(g, param_decl_node,4519 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"));
4375 }4521 }
43764522
4377 if (buf_len(&param_decl->name) == 0) {4523 if (buf_len(&param_decl->name) == 0) {
...@@ -4382,16 +4528,15 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo...@@ -4382,16 +4528,15 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
4382 var->src_arg_index = i;4528 var->src_arg_index = i;
4383 param_decl_node->data.param_decl.variable = var;4529 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;
4386 }4532 }
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;
4389 TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);4535 TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);
43904536
4391 node->data.fn_def.implicit_return_type = block_return_type;4537 node->data.fn_def.implicit_return_type = block_return_type;
43924538
4393 {4539 {
4394 FnTableEntry *fn_table_entry = fn_proto_node->data.fn_proto.fn_table_entry;
4395 auto it = fn_table_entry->label_table.entry_iterator();4540 auto it = fn_table_entry->label_table.entry_iterator();
4396 for (;;) {4541 for (;;) {
4397 auto *entry = it.next();4542 auto *entry = it.next();
...@@ -4427,6 +4572,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4427,6 +4572,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
4427 case NodeTypeVariableDeclaration:4572 case NodeTypeVariableDeclaration:
4428 case NodeTypeErrorValueDecl:4573 case NodeTypeErrorValueDecl:
4429 case NodeTypeFnProto:4574 case NodeTypeFnProto:
4575 case NodeTypeTypeDecl:
4430 // already took care of these4576 // already took care of these
4431 break;4577 break;
4432 case NodeTypeDirective:4578 case NodeTypeDirective:
...@@ -4466,6 +4612,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4466,6 +4612,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
4466 case NodeTypeContainerInitExpr:4612 case NodeTypeContainerInitExpr:
4467 case NodeTypeArrayType:4613 case NodeTypeArrayType:
4468 case NodeTypeErrorType:4614 case NodeTypeErrorType:
4615 case NodeTypeTypeLiteral:
4469 zig_unreachable();4616 zig_unreachable();
4470 }4617 }
4471}4618}
...@@ -4485,10 +4632,14 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4485,10 +4632,14 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
4485 case NodeTypeContinue:4632 case NodeTypeContinue:
4486 case NodeTypeErrorValueDecl:4633 case NodeTypeErrorValueDecl:
4487 case NodeTypeErrorType:4634 case NodeTypeErrorType:
4635 case NodeTypeTypeLiteral:
4488 // no dependencies on other top level declarations4636 // no dependencies on other top level declarations
4489 break;4637 break;
4490 case NodeTypeSymbol:4638 case NodeTypeSymbol:
4491 {4639 {
4640 if (node->data.symbol_expr.override_type_entry) {
4641 break;
4642 }
4492 Buf *name = &node->data.symbol_expr.symbol;4643 Buf *name = &node->data.symbol_expr.symbol;
4493 auto table_entry = g->primitive_type_table.maybe_get(name);4644 auto table_entry = g->primitive_type_table.maybe_get(name);
4494 if (!table_entry) {4645 if (!table_entry) {
...@@ -4627,6 +4778,9 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4627,6 +4778,9 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
4627 case NodeTypeParamDecl:4778 case NodeTypeParamDecl:
4628 collect_expr_decl_deps(g, import, node->data.param_decl.type, decl_node);4779 collect_expr_decl_deps(g, import, node->data.param_decl.type, decl_node);
4629 break;4780 break;
4781 case NodeTypeTypeDecl:
4782 collect_expr_decl_deps(g, import, node->data.type_decl.child_type, decl_node);
4783 break;
4630 case NodeTypeVariableDeclaration:4784 case NodeTypeVariableDeclaration:
4631 case NodeTypeRootExportDecl:4785 case NodeTypeRootExportDecl:
4632 case NodeTypeFnDef:4786 case NodeTypeFnDef:
...@@ -4642,16 +4796,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4642,16 +4796,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
4642 }4796 }
4643}4797}
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
4655static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) {4799static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) {
4656 switch (node->type) {4800 switch (node->type) {
4657 case NodeTypeRoot:4801 case NodeTypeRoot:
...@@ -4669,28 +4813,16 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -4669,28 +4813,16 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
4669 }4813 }
4670 if (table_entry) {4814 if (table_entry) {
4671 node->data.struct_decl.type_entry = table_entry->value;4815 node->data.struct_decl.type_entry = table_entry->value;
4672 add_node_error(g, node,4816 add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name)));
4673 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
4674 } else {4817 } else {
4675 TypeTableEntryId type_id = container_to_type(node->data.struct_decl.kind);4818 TypeTableEntry *entry;
4676 TypeTableEntry *entry = new_type_table_entry(type_id);4819 if (node->data.struct_decl.type_entry) {
4677 switch (node->data.struct_decl.kind) {4820 entry = node->data.struct_decl.type_entry;
4678 case ContainerKindStruct:4821 } else {
4679 entry->data.structure.decl_node = node;4822 entry = get_partial_container_type(g, import,
4680 break;4823 node->data.struct_decl.kind, node, buf_ptr(name));
4681 case ContainerKindEnum:
4682 entry->data.enumeration.decl_node = node;
4683 break;
4684 }4824 }
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
4694 import->block_context->type_table.put(&entry->name, entry);4826 import->block_context->type_table.put(&entry->name, entry);
4695 node->data.struct_decl.type_entry = entry;4827 node->data.struct_decl.type_entry = entry;
46964828
...@@ -4761,6 +4893,23 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -4761,6 +4893,23 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
4761 }4893 }
4762 break;4894 break;
4763 }4895 }
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 }
4764 case NodeTypeFnProto:4913 case NodeTypeFnProto:
4765 {4914 {
4766 // if the name is missing, we immediately announce an error4915 // 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...@@ -4848,6 +4997,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
4848 case NodeTypeStructValueField:4997 case NodeTypeStructValueField:
4849 case NodeTypeArrayType:4998 case NodeTypeArrayType:
4850 case NodeTypeErrorType:4999 case NodeTypeErrorType:
5000 case NodeTypeTypeLiteral:
4851 zig_unreachable();5001 zig_unreachable();
4852 }5002 }
4853}5003}
...@@ -5063,6 +5213,8 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -5063,6 +5213,8 @@ Expr *get_resolved_expr(AstNode *node) {
5063 return &node->data.array_type.resolved_expr;5213 return &node->data.array_type.resolved_expr;
5064 case NodeTypeErrorType:5214 case NodeTypeErrorType:
5065 return &node->data.error_type.resolved_expr;5215 return &node->data.error_type.resolved_expr;
5216 case NodeTypeTypeLiteral:
5217 return &node->data.type_literal.resolved_expr;
5066 case NodeTypeSwitchExpr:5218 case NodeTypeSwitchExpr:
5067 return &node->data.switch_expr.resolved_expr;5219 return &node->data.switch_expr.resolved_expr;
5068 case NodeTypeFnProto:5220 case NodeTypeFnProto:
...@@ -5081,6 +5233,7 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -5081,6 +5233,7 @@ Expr *get_resolved_expr(AstNode *node) {
5081 case NodeTypeStructField:5233 case NodeTypeStructField:
5082 case NodeTypeStructValueField:5234 case NodeTypeStructValueField:
5083 case NodeTypeErrorValueDecl:5235 case NodeTypeErrorValueDecl:
5236 case NodeTypeTypeDecl:
5084 zig_unreachable();5237 zig_unreachable();
5085 }5238 }
5086 zig_unreachable();5239 zig_unreachable();
...@@ -5098,6 +5251,8 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -5098,6 +5251,8 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
5098 return &node->data.error_value_decl.top_level_decl;5251 return &node->data.error_value_decl.top_level_decl;
5099 case NodeTypeCImport:5252 case NodeTypeCImport:
5100 return &node->data.c_import.top_level_decl;5253 return &node->data.c_import.top_level_decl;
5254 case NodeTypeTypeDecl:
5255 return &node->data.type_decl.top_level_decl;
5101 case NodeTypeNumberLiteral:5256 case NodeTypeNumberLiteral:
5102 case NodeTypeReturnExpr:5257 case NodeTypeReturnExpr:
5103 case NodeTypeBinOpExpr:5258 case NodeTypeBinOpExpr:
...@@ -5138,6 +5293,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -5138,6 +5293,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
5138 case NodeTypeStructValueField:5293 case NodeTypeStructValueField:
5139 case NodeTypeArrayType:5294 case NodeTypeArrayType:
5140 case NodeTypeErrorType:5295 case NodeTypeErrorType:
5296 case NodeTypeTypeLiteral:
5141 zig_unreachable();5297 zig_unreachable();
5142 }5298 }
5143 zig_unreachable();5299 zig_unreachable();
...@@ -5178,6 +5334,14 @@ TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits) {...@@ -5178,6 +5334,14 @@ TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits) {
5178 return *get_int_type_ptr(g, is_signed, size_in_bits);5334 return *get_int_type_ptr(g, is_signed, size_in_bits);
5179}5335}
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
5181bool handle_is_ptr(TypeTableEntry *type_entry) {5345bool handle_is_ptr(TypeTableEntry *type_entry) {
5182 switch (type_entry->id) {5346 switch (type_entry->id) {
5183 case TypeTableEntryIdInvalid:5347 case TypeTableEntryIdInvalid:
...@@ -5204,6 +5368,8 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {...@@ -5204,6 +5368,8 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
5204 return type_entry->data.enumeration.gen_field_count != 0;5368 return type_entry->data.enumeration.gen_field_count != 0;
5205 case TypeTableEntryIdMaybe:5369 case TypeTableEntryIdMaybe:
5206 return type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer;5370 return type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer;
5371 case TypeTableEntryIdTypeDecl:
5372 return handle_is_ptr(type_entry->data.type_decl.canonical_type);
5207 }5373 }
5208 zig_unreachable();5374 zig_unreachable();
5209}5375}
...@@ -5226,3 +5392,48 @@ void find_libc_path(CodeGen *g) {...@@ -5226,3 +5392,48 @@ void find_libc_path(CodeGen *g) {
5226 }5392 }
5227}5393}
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);...@@ -22,7 +22,18 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
22bool is_node_void_expr(AstNode *node);22bool is_node_void_expr(AstNode *node);
23TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);23TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);
24TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);24TypeTableEntry *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);
25bool handle_is_ptr(TypeTableEntry *type_entry);34bool handle_is_ptr(TypeTableEntry *type_entry);
26void find_libc_path(CodeGen *g);35void find_libc_path(CodeGen *g);
2736
37TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);
38
28#endif39#endif
src/ast_render.cpp+44-3
...@@ -119,6 +119,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -119,6 +119,8 @@ static const char *node_type_str(NodeType node_type) {
119 return "ReturnExpr";119 return "ReturnExpr";
120 case NodeTypeVariableDeclaration:120 case NodeTypeVariableDeclaration:
121 return "VariableDeclaration";121 return "VariableDeclaration";
122 case NodeTypeTypeDecl:
123 return "TypeDecl";
122 case NodeTypeErrorValueDecl:124 case NodeTypeErrorValueDecl:
123 return "ErrorValueDecl";125 return "ErrorValueDecl";
124 case NodeTypeNumberLiteral:126 case NodeTypeNumberLiteral:
...@@ -179,6 +181,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -179,6 +181,8 @@ static const char *node_type_str(NodeType node_type) {
179 return "ArrayType";181 return "ArrayType";
180 case NodeTypeErrorType:182 case NodeTypeErrorType:
181 return "ErrorType";183 return "ErrorType";
184 case NodeTypeTypeLiteral:
185 return "TypeLiteral";
182 }186 }
183}187}
184188
...@@ -260,6 +264,13 @@ void ast_print(FILE *f, AstNode *node, int indent) {...@@ -260,6 +264,13 @@ void ast_print(FILE *f, AstNode *node, int indent) {
260 ast_print(f, node->data.variable_declaration.expr, indent + 2);264 ast_print(f, node->data.variable_declaration.expr, indent + 2);
261 break;265 break;
262 }266 }
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 }
263 case NodeTypeErrorValueDecl:274 case NodeTypeErrorValueDecl:
264 {275 {
265 Buf *name_buf = &node->data.error_value_decl.name;276 Buf *name_buf = &node->data.error_value_decl.name;
...@@ -478,6 +489,9 @@ void ast_print(FILE *f, AstNode *node, int indent) {...@@ -478,6 +489,9 @@ void ast_print(FILE *f, AstNode *node, int indent) {
478 case NodeTypeErrorType:489 case NodeTypeErrorType:
479 fprintf(f, "%s\n", node_type_str(node->type));490 fprintf(f, "%s\n", node_type_str(node->type));
480 break;491 break;
492 case NodeTypeTypeLiteral:
493 fprintf(f, "%s\n", node_type_str(node->type));
494 break;
481 }495 }
482}496}
483497
...@@ -494,7 +508,14 @@ static void print_indent(AstRender *ar) {...@@ -494,7 +508,14 @@ static void print_indent(AstRender *ar) {
494}508}
495509
496static bool is_node_void(AstNode *node) {510static 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;
498}519}
499520
500static bool is_printable(uint8_t c) {521static bool is_printable(uint8_t c) {
...@@ -515,6 +536,7 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -515,6 +536,7 @@ static void render_node(AstRender *ar, AstNode *node) {
515536
516 if (child->type == NodeTypeImport ||537 if (child->type == NodeTypeImport ||
517 child->type == NodeTypeVariableDeclaration ||538 child->type == NodeTypeVariableDeclaration ||
539 child->type == NodeTypeTypeDecl ||
518 child->type == NodeTypeErrorValueDecl ||540 child->type == NodeTypeErrorValueDecl ||
519 child->type == NodeTypeFnProto)541 child->type == NodeTypeFnProto)
520 {542 {
...@@ -588,6 +610,14 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -588,6 +610,14 @@ static void render_node(AstRender *ar, AstNode *node) {
588 }610 }
589 break;611 break;
590 }612 }
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 }
591 case NodeTypeErrorValueDecl:621 case NodeTypeErrorValueDecl:
592 zig_panic("TODO");622 zig_panic("TODO");
593 case NodeTypeBinOpExpr:623 case NodeTypeBinOpExpr:
...@@ -617,7 +647,14 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -617,7 +647,14 @@ static void render_node(AstRender *ar, AstNode *node) {
617 break;647 break;
618 }648 }
619 case NodeTypeSymbol:649 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 }
621 break;658 break;
622 case NodeTypePrefixOpExpr:659 case NodeTypePrefixOpExpr:
623 {660 {
...@@ -719,7 +756,11 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -719,7 +756,11 @@ static void render_node(AstRender *ar, AstNode *node) {
719 break;756 break;
720 }757 }
721 case NodeTypeErrorType:758 case NodeTypeErrorType:
722 zig_panic("TODO");759 fprintf(ar->f, "error");
760 break;
761 case NodeTypeTypeLiteral:
762 fprintf(ar->f, "type");
763 break;
723 }764 }
724}765}
725766
src/codegen.cpp+62-23
...@@ -13,11 +13,13 @@...@@ -13,11 +13,13 @@
13#include "error.hpp"13#include "error.hpp"
14#include "analyze.hpp"14#include "analyze.hpp"
15#include "errmsg.hpp"15#include "errmsg.hpp"
16#include "parseh.hpp"
16#include "ast_render.hpp"17#include "ast_render.hpp"
1718
18#include <stdio.h>19#include <stdio.h>
19#include <errno.h>20#include <errno.h>
2021
22
21CodeGen *codegen_create(Buf *root_source_dir) {23CodeGen *codegen_create(Buf *root_source_dir) {
22 CodeGen *g = allocate<CodeGen>(1);24 CodeGen *g = allocate<CodeGen>(1);
23 g->link_table.init(32);25 g->link_table.init(32);
...@@ -25,6 +27,7 @@ CodeGen *codegen_create(Buf *root_source_dir) {...@@ -25,6 +27,7 @@ CodeGen *codegen_create(Buf *root_source_dir) {
25 g->builtin_fn_table.init(32);27 g->builtin_fn_table.init(32);
26 g->primitive_type_table.init(32);28 g->primitive_type_table.init(32);
27 g->unresolved_top_level_decls.init(32);29 g->unresolved_top_level_decls.init(32);
30 g->fn_type_table.init(32);
28 g->build_type = CodeGenBuildTypeDebug;31 g->build_type = CodeGenBuildTypeDebug;
29 g->root_source_dir = root_source_dir;32 g->root_source_dir = root_source_dir;
30 g->next_error_index = 1;33 g->next_error_index = 1;
...@@ -530,12 +533,12 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -530,12 +533,12 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
530 fn_type = get_expr_type(fn_ref_expr);533 fn_type = get_expr_type(fn_ref_expr);
531 }534 }
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
535 int fn_call_param_count = node->data.fn_call_expr.params.length;538 int fn_call_param_count = node->data.fn_call_expr.params.length;
536 bool first_arg_ret = handle_is_ptr(src_return_type);539 bool first_arg_ret = handle_is_ptr(src_return_type);
537 int actual_param_count = fn_call_param_count + (struct_type ? 1 : 0) + (first_arg_ret ? 1 : 0);540 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
540 // don't really include void values543 // don't really include void values
541 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);544 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
...@@ -1460,7 +1463,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {...@@ -1460,7 +1463,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
1460}1463}
14611464
1462static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value) {1465static 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;
1464 if (handle_is_ptr(return_type)) {1467 if (handle_is_ptr(return_type)) {
1465 assert(g->cur_ret_ptr);1468 assert(g->cur_ret_ptr);
1466 gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);1469 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) {...@@ -1503,7 +1506,7 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
1503 LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);1506 LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);
15041507
1505 LLVMPositionBuilderAtEnd(g->builder, return_block);1508 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;
1507 if (return_type->id == TypeTableEntryIdPureError) {1510 if (return_type->id == TypeTableEntryIdPureError) {
1508 gen_return(g, node, err_val);1511 gen_return(g, node, err_val);
1509 } else if (return_type->id == TypeTableEntryIdErrorUnion) {1512 } else if (return_type->id == TypeTableEntryIdErrorUnion) {
...@@ -2296,6 +2299,9 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -2296,6 +2299,9 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2296 case NodeTypeCharLiteral:2299 case NodeTypeCharLiteral:
2297 case NodeTypeNullLiteral:2300 case NodeTypeNullLiteral:
2298 case NodeTypeUndefinedLiteral:2301 case NodeTypeUndefinedLiteral:
2302 case NodeTypeErrorType:
2303 case NodeTypeTypeLiteral:
2304 case NodeTypeArrayType:
2299 // caught by constant expression eval codegen2305 // caught by constant expression eval codegen
2300 zig_unreachable();2306 zig_unreachable();
2301 case NodeTypeRoot:2307 case NodeTypeRoot:
...@@ -2310,11 +2316,10 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -2310,11 +2316,10 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2310 case NodeTypeStructDecl:2316 case NodeTypeStructDecl:
2311 case NodeTypeStructField:2317 case NodeTypeStructField:
2312 case NodeTypeStructValueField:2318 case NodeTypeStructValueField:
2313 case NodeTypeArrayType:
2314 case NodeTypeErrorType:
2315 case NodeTypeSwitchProng:2319 case NodeTypeSwitchProng:
2316 case NodeTypeSwitchRange:2320 case NodeTypeSwitchRange:
2317 case NodeTypeErrorValueDecl:2321 case NodeTypeErrorValueDecl:
2322 case NodeTypeTypeDecl:
2318 zig_unreachable();2323 zig_unreachable();
2319 }2324 }
2320 zig_unreachable();2325 zig_unreachable();
...@@ -2341,6 +2346,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2341,6 +2346,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2341 }2346 }
23422347
2343 switch (type_entry->id) {2348 switch (type_entry->id) {
2349 case TypeTableEntryIdTypeDecl:
2350 return gen_const_val(g, type_entry->data.type_decl.canonical_type, const_val);
2344 case TypeTableEntryIdInt:2351 case TypeTableEntryIdInt:
2345 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);2352 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
2346 case TypeTableEntryIdPureError:2353 case TypeTableEntryIdPureError:
...@@ -2557,7 +2564,9 @@ static void do_code_gen(CodeGen *g) {...@@ -2557,7 +2564,9 @@ static void do_code_gen(CodeGen *g) {
2557 assert(proto_node->type == NodeTypeFnProto);2564 assert(proto_node->type == NodeTypeFnProto);
2558 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;2565 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)) {
2561 LLVMValueRef first_arg = LLVMGetParam(fn_table_entry->fn_value, 0);2570 LLVMValueRef first_arg = LLVMGetParam(fn_table_entry->fn_value, 0);
2562 LLVMAddAttribute(first_arg, LLVMStructRetAttribute);2571 LLVMAddAttribute(first_arg, LLVMStructRetAttribute);
2563 }2572 }
...@@ -2567,7 +2576,9 @@ static void do_code_gen(CodeGen *g) {...@@ -2567,7 +2576,9 @@ static void do_code_gen(CodeGen *g) {
2567 AstNode *param_node = fn_proto->params.at(param_decl_i);2576 AstNode *param_node = fn_proto->params.at(param_decl_i);
2568 assert(param_node->type == NodeTypeParamDecl);2577 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
2572 if (gen_index < 0) {2583 if (gen_index < 0) {
2573 continue;2584 continue;
...@@ -2587,7 +2598,7 @@ static void do_code_gen(CodeGen *g) {...@@ -2587,7 +2598,7 @@ static void do_code_gen(CodeGen *g) {
2587 // when https://github.com/andrewrk/zig/issues/82 is fixed, add2598 // when https://github.com/andrewrk/zig/issues/82 is fixed, add
2588 // non null attribute here2599 // non null attribute here
2589 }2600 }
2590 if (param_node->data.param_decl.is_byval) {2601 if (is_byval) {
2591 LLVMAddAttribute(argument_val, LLVMByValAttribute);2602 LLVMAddAttribute(argument_val, LLVMByValAttribute);
2592 }2603 }
2593 }2604 }
...@@ -2601,7 +2612,7 @@ static void do_code_gen(CodeGen *g) {...@@ -2601,7 +2612,7 @@ static void do_code_gen(CodeGen *g) {
2601 AstNode *fn_def_node = fn_table_entry->fn_def_node;2612 AstNode *fn_def_node = fn_table_entry->fn_def_node;
2602 LLVMValueRef fn = fn_table_entry->fn_value;2613 LLVMValueRef fn = fn_table_entry->fn_value;
2603 g->cur_fn = fn_table_entry;2614 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)) {
2605 g->cur_ret_ptr = LLVMGetParam(fn, 0);2616 g->cur_ret_ptr = LLVMGetParam(fn, 0);
2606 } else {2617 } else {
2607 g->cur_ret_ptr = nullptr;2618 g->cur_ret_ptr = nullptr;
...@@ -2685,7 +2696,9 @@ static void do_code_gen(CodeGen *g) {...@@ -2685,7 +2696,9 @@ static void do_code_gen(CodeGen *g) {
2685 AstNode *param_decl = fn_proto->params.at(param_i);2696 AstNode *param_decl = fn_proto->params.at(param_i);
2686 assert(param_decl->type == NodeTypeParamDecl);2697 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) {
2689 continue;2702 continue;
2690 }2703 }
26912704
...@@ -2724,17 +2737,6 @@ static const int int_sizes_in_bits[] = {...@@ -2724,17 +2737,6 @@ static const int int_sizes_in_bits[] = {
2724 64,2737 64,
2725};2738};
27262739
2727enum CIntType {
2728 CIntTypeShort,
2729 CIntTypeUShort,
2730 CIntTypeInt,
2731 CIntTypeUInt,
2732 CIntTypeLong,
2733 CIntTypeULong,
2734 CIntTypeLongLong,
2735 CIntTypeULongLong,
2736};
2737
2738struct CIntTypeInfo {2740struct CIntTypeInfo {
2739 CIntType id;2741 CIntType id;
2740 const char *name;2742 const char *name;
...@@ -2840,6 +2842,8 @@ static void define_builtin_types(CodeGen *g) {...@@ -2840,6 +2842,8 @@ static void define_builtin_types(CodeGen *g) {
2840 is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());2842 is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());
2841 entry->data.integral.is_signed = is_signed;2843 entry->data.integral.is_signed = is_signed;
2842 g->primitive_type_table.put(&entry->name, entry);2844 g->primitive_type_table.put(&entry->name, entry);
2845
2846 get_c_int_type_ptr(g, info->id)[0] = entry;
2843 }2847 }
28442848
2845 {2849 {
...@@ -3093,6 +3097,42 @@ static void init(CodeGen *g, Buf *source_path) {...@@ -3093,6 +3097,42 @@ static void init(CodeGen *g, Buf *source_path) {
30933097
3094}3098}
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
3096static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {3136static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {
3097 char *dot1 = strstr(buf_ptr(buf), ".");3137 char *dot1 = strstr(buf_ptr(buf), ".");
3098 if (!dot1)3138 if (!dot1)
...@@ -3156,7 +3196,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,...@@ -3156,7 +3196,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
3156 import_entry->line_offsets = tokenization.line_offsets;3196 import_entry->line_offsets = tokenization.line_offsets;
3157 import_entry->path = full_path;3197 import_entry->path = full_path;
3158 import_entry->fn_table.init(32);3198 import_entry->fn_table.init(32);
3159 import_entry->fn_type_table.init(32);
31603199
3161 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,3200 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
3162 &g->next_node_index);3201 &g->next_node_index);
src/codegen.hpp+5
...@@ -11,6 +11,8 @@...@@ -11,6 +11,8 @@
11#include "parser.hpp"11#include "parser.hpp"
12#include "errmsg.hpp"12#include "errmsg.hpp"
1313
14#include <stdio.h>
15
14CodeGen *codegen_create(Buf *root_source_dir);16CodeGen *codegen_create(Buf *root_source_dir);
1517
16void codegen_set_clang_argv(CodeGen *codegen, const char **args, int len);18void 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...@@ -27,4 +29,7 @@ void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Bu
2729
28void codegen_link(CodeGen *g, const char *out_file);30void 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
30#endif35#endif
src/main.cpp+114-177
...@@ -10,8 +10,6 @@...@@ -10,8 +10,6 @@
10#include "codegen.hpp"10#include "codegen.hpp"
11#include "os.hpp"11#include "os.hpp"
12#include "error.hpp"12#include "error.hpp"
13#include "parseh.hpp"
14#include "ast_render.hpp"
1513
16#include <stdio.h>14#include <stdio.h>
1715
...@@ -38,40 +36,41 @@ static int usage(const char *arg0) {...@@ -38,40 +36,41 @@ static int usage(const char *arg0) {
38 return EXIT_FAILURE;36 return EXIT_FAILURE;
39}37}
4038
41static int version(const char *arg0, int argc, char **argv) {39enum Cmd {
42 printf("%s\n", ZIG_VERSION_STRING);40 CmdInvalid,
43 return EXIT_SUCCESS;41 CmdBuild,
44}42 CmdVersion,
4543 CmdParseH,
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;
58};44};
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};
61 int err;60 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) {
65 char *arg = argv[i];63 char *arg = argv[i];
64
66 if (arg[0] == '-') {65 if (arg[0] == '-') {
67 if (strcmp(arg, "--release") == 0) {66 if (strcmp(arg, "--release") == 0) {
68 b.release = true;67 release = true;
69 } else if (strcmp(arg, "--strip") == 0) {68 } else if (strcmp(arg, "--strip") == 0) {
70 b.strip = true;69 strip = true;
71 } else if (strcmp(arg, "--static") == 0) {70 } else if (strcmp(arg, "--static") == 0) {
72 b.is_static = true;71 is_static = true;
73 } else if (strcmp(arg, "--verbose") == 0) {72 } else if (strcmp(arg, "--verbose") == 0) {
74 b.verbose = true;73 verbose = true;
75 } else if (i + 1 >= argc) {74 } else if (i + 1 >= argc) {
76 return usage(arg0);75 return usage(arg0);
77 } else {76 } else {
...@@ -79,190 +78,128 @@ static int build(const char *arg0, int argc, char **argv) {...@@ -79,190 +78,128 @@ static int build(const char *arg0, int argc, char **argv) {
79 if (i >= argc) {78 if (i >= argc) {
80 return usage(arg0);79 return usage(arg0);
81 } else if (strcmp(arg, "--output") == 0) {80 } else if (strcmp(arg, "--output") == 0) {
82 b.out_file = argv[i];81 out_file = argv[i];
83 } else if (strcmp(arg, "--export") == 0) {82 } else if (strcmp(arg, "--export") == 0) {
84 if (strcmp(argv[i], "exe") == 0) {83 if (strcmp(argv[i], "exe") == 0) {
85 b.out_type = OutTypeExe;84 out_type = OutTypeExe;
86 } else if (strcmp(argv[i], "lib") == 0) {85 } else if (strcmp(argv[i], "lib") == 0) {
87 b.out_type = OutTypeLib;86 out_type = OutTypeLib;
88 } else if (strcmp(argv[i], "obj") == 0) {87 } else if (strcmp(argv[i], "obj") == 0) {
89 b.out_type = OutTypeObj;88 out_type = OutTypeObj;
90 } else {89 } else {
91 return usage(arg0);90 return usage(arg0);
92 }91 }
93 } else if (strcmp(arg, "--color") == 0) {92 } else if (strcmp(arg, "--color") == 0) {
94 if (strcmp(argv[i], "auto") == 0) {93 if (strcmp(argv[i], "auto") == 0) {
95 b.color = ErrColorAuto;94 color = ErrColorAuto;
96 } else if (strcmp(argv[i], "on") == 0) {95 } else if (strcmp(argv[i], "on") == 0) {
97 b.color = ErrColorOn;96 color = ErrColorOn;
98 } else if (strcmp(argv[i], "off") == 0) {97 } else if (strcmp(argv[i], "off") == 0) {
99 b.color = ErrColorOff;98 color = ErrColorOff;
100 } else {99 } else {
101 return usage(arg0);100 return usage(arg0);
102 }101 }
103 } else if (strcmp(arg, "--name") == 0) {102 } else if (strcmp(arg, "--name") == 0) {
104 b.out_name = argv[i];103 out_name = argv[i];
105 } else if (strcmp(arg, "--libc-path") == 0) {104 } else if (strcmp(arg, "--libc-path") == 0) {
106 b.libc_path = argv[i];105 libc_path = argv[i];
107 } else if (strcmp(arg, "-isystem") == 0) {106 } else if (strcmp(arg, "-isystem") == 0) {
108 b.clang_argv.append("-isystem");107 clang_argv.append("-isystem");
109 b.clang_argv.append(argv[i]);108 clang_argv.append(argv[i]);
110 } else if (strcmp(arg, "-dirafter") == 0) {109 } else if (strcmp(arg, "-dirafter") == 0) {
111 b.clang_argv.append("-dirafter");110 clang_argv.append("-dirafter");
112 b.clang_argv.append(argv[i]);111 clang_argv.append(argv[i]);
113 } else {112 } else {
114 return usage(arg0);113 return usage(arg0);
115 }114 }
116 }115 }
117 } else if (!b.in_file) {116 } else if (cmd == CmdInvalid) {
118 b.in_file = arg;117 if (strcmp(arg, "build") == 0) {
119 } else {118 cmd = CmdBuild;
120 return usage(arg0);119 } else if (strcmp(arg, "version") == 0) {
121 }120 cmd = CmdVersion;
122 }121 } else if (strcmp(arg, "parseh") == 0) {
123122 cmd = CmdParseH;
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;
200 } else {123 } else {
201 fprintf(stderr, "unrecognized argument: %s", arg);124 fprintf(stderr, "Unrecognized command: %s\n", arg);
202 return usage(arg0);125 return usage(arg0);
203 }126 }
204 } else if (!in_file) {
205 in_file = arg;
206 } else {127 } else {
207 return usage(arg0);128 switch (cmd) {
208 }129 case CmdBuild:
209 }130 case CmdParseH:
210 if (!in_file) {131 if (!in_file) {
211 fprintf(stderr, "missing target argument");132 in_file = arg;
212 return usage(arg0);133 } else {
213 }134 return usage(arg0);
214135 }
215 clang_argv.append(in_file);136 break;
216137 case CmdVersion:
217 Buf *libc_include_path = buf_alloc();138 return usage(arg0);
218 os_path_join(buf_create_from_str(ZIG_LIBC_DIR), buf_create_from_str("include"), libc_include_path);139 case CmdInvalid:
219 clang_argv.append("-isystem");140 zig_unreachable();
220 clang_argv.append(buf_ptr(libc_include_path));141 }
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);
236 }142 }
237 return EXIT_FAILURE;
238 }143 }
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;152 Buf in_file_buf = BUF_INIT;
243}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) {173 CodeGen *g = codegen_create(&root_source_dir);
246 char *arg0 = argv[0];174 codegen_set_build_type(g, release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
247 int (*cmd)(const char *, int, char **) = nullptr;175 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);
248 for (int i = 1; i < argc; i += 1) {176 codegen_set_strip(g, strip);
249 char *arg = argv[i];177 codegen_set_is_static(g, is_static);
250 if (arg[0] == '-' && arg[1] == '-') {178 if (out_type != OutTypeUnknown)
251 return usage(arg0);179 codegen_set_out_type(g, out_type);
252 } else {180 if (out_name)
253 if (strcmp(arg, "build") == 0) {181 codegen_set_out_name(g, buf_create_from_str(out_name));
254 cmd = build;182 if (libc_path)
255 } else if (strcmp(arg, "version") == 0) {183 codegen_set_libc_path(g, buf_create_from_str(libc_path));
256 cmd = version;184 codegen_set_verbose(g, verbose);
257 } else if (strcmp(arg, "parseh") == 0) {185 codegen_set_errmsg_color(g, color);
258 cmd = parseh;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;
259 } else {195 } else {
260 fprintf(stderr, "Unrecognized command: %s\n", arg);196 zig_unreachable();
261 return usage(arg0);
262 }197 }
263 return cmd(arg0, argc - i - 1, &argv[i + 1]);
264 }198 }
199 case CmdVersion:
200 printf("%s\n", ZIG_VERSION_STRING);
201 return EXIT_SUCCESS;
202 case CmdInvalid:
203 return usage(arg0);
265 }204 }
266
267 return usage(arg0);
268}205}
src/parseh.cpp+433-264
...@@ -12,6 +12,7 @@...@@ -12,6 +12,7 @@
12#include "parser.hpp"12#include "parser.hpp"
13#include "all_types.hpp"13#include "all_types.hpp"
14#include "tokenizer.hpp"14#include "tokenizer.hpp"
15#include "analyze.hpp"
1516
16#include <clang/Frontend/ASTUnit.h>17#include <clang/Frontend/ASTUnit.h>
17#include <clang/Frontend/CompilerInstance.h>18#include <clang/Frontend/CompilerInstance.h>
...@@ -30,22 +31,27 @@ struct Context {...@@ -30,22 +31,27 @@ struct Context {
30 ZigList<ErrorMsg *> *errors;31 ZigList<ErrorMsg *> *errors;
31 bool warnings_on;32 bool warnings_on;
32 VisibMod visib_mod;33 VisibMod visib_mod;
33 bool have_c_void_decl_node;34 TypeTableEntry *c_void_type;
34 AstNode *root;35 AstNode *root;
35 HashMap<Buf *, bool, buf_hash, buf_eql_buf> root_name_table;36 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_type_table;
36 HashMap<Buf *, bool, buf_hash, buf_eql_buf> struct_type_table;37 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_value_table;
37 HashMap<Buf *, bool, buf_hash, buf_eql_buf> enum_type_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;
38 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;40 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;
39 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;41 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
40 SourceManager *source_manager;42 SourceManager *source_manager;
41 ZigList<AstNode *> aliases;43 ZigList<AstNode *> aliases;
42 ZigList<MacroSymbol> macro_symbols;44 ZigList<MacroSymbol> macro_symbols;
43 uint32_t *next_node_index;45 AstNode *source_node;
46
47 CodeGen *codegen;
44};48};
4549
46static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl);50static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl,
47static AstNode *make_qual_type_node_with_table(Context *c, QualType qt, const Decl *decl,51 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table);
48 HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table);52
53static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl);
54
4955
50__attribute__ ((format (printf, 3, 4)))56__attribute__ ((format (printf, 3, 4)))
51static void emit_warning(Context *c, const Decl *decl, const char *format, ...) {57static void emit_warning(Context *c, const Decl *decl, const char *format, ...) {
...@@ -77,8 +83,8 @@ static AstNode *create_node(Context *c, NodeType type) {...@@ -77,8 +83,8 @@ static AstNode *create_node(Context *c, NodeType type) {
77 AstNode *node = allocate<AstNode>(1);83 AstNode *node = allocate<AstNode>(1);
78 node->type = type;84 node->type = type;
79 node->owner = c->import;85 node->owner = c->import;
80 node->create_index = *c->next_node_index;86 node->create_index = c->codegen->next_node_index;
81 *c->next_node_index += 1;87 c->codegen->next_node_index += 1;
82 return node;88 return node;
83}89}
8490
...@@ -178,61 +184,51 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {...@@ -178,61 +184,51 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {
178 return create_prefix_node(c, PrefixOpNegation, num_lit_node);184 return create_prefix_node(c, PrefixOpNegation, num_lit_node);
179}185}
180186
181static AstNode *create_array_type_node(Context *c, AstNode *child_type_node, uint64_t size, bool is_const) {187static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *child_type_node) {
182 AstNode *node = create_node(c, NodeTypeArrayType);188 AstNode *node = create_node(c, NodeTypeTypeDecl);
183 node->data.array_type.size = create_num_lit_unsigned(c, size);189 buf_init_from_str(&node->data.type_decl.symbol, name);
184 node->data.array_type.child_type = child_type_node;190 node->data.type_decl.visib_mod = c->visib_mod;
185 node->data.array_type.is_const = is_const;191 node->data.type_decl.directives = create_empty_directives(c);
192 node->data.type_decl.child_type = child_type_node;
186193
187 normalize_parent_ptrs(node);194 normalize_parent_ptrs(node);
188 return node;195 return node;
189}196}
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
191static const char *decl_name(const Decl *decl) {204static const char *decl_name(const Decl *decl) {
192 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);205 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
193 return (const char *)named_decl->getName().bytes_begin();206 return (const char *)named_decl->getName().bytes_begin();
194}207}
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) {212 AstNode *node = create_type_decl_node(c, buf_ptr(&type_decl->name),
198 if (!target_node) {213 make_type_node(c, type_decl->data.type_decl.child_type));
199 return nullptr;214 node->data.type_decl.override_type = type_decl;
200 }
201 AstNode *node = create_var_decl_node(c, buf_ptr(new_name), target_node);
202215
203 c->root_name_table.put(new_name, true);216 c->global_type_table.put(&type_decl->name, type_decl);
204 c->root->data.root.top_level_decls.append(node);217 c->root->data.root.top_level_decls.append(node);
205 return node;218 return node;
206}219}
207220
208static AstNode *convert_to_c_void(Context *c, AstNode *type_node) {221static TypeTableEntry *get_c_void_type(Context *c) {
209 if (type_node->type == NodeTypeSymbol &&222 if (!c->c_void_type) {
210 buf_eql_str(&type_node->data.symbol_expr.symbol, "void"))223 c->c_void_type = get_typedecl_type(c->codegen, "c_void", c->codegen->builtin_types.entry_u8);
211 {224 add_typedef_node(c, c->c_void_type);
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;
219 }225 }
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) {227 return c->c_void_type;
230 // TODO recurse through the type table
231 return true;
232}228}
233229
234static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,230static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const Decl *decl,
235 HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table)231 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table)
236{232{
237 switch (ty->getTypeClass()) {233 switch (ty->getTypeClass()) {
238 case Type::Builtin:234 case Type::Builtin:
...@@ -240,35 +236,35 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -240,35 +236,35 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
240 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);236 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
241 switch (builtin_ty->getKind()) {237 switch (builtin_ty->getKind()) {
242 case BuiltinType::Void:238 case BuiltinType::Void:
243 return create_symbol_node(c, "void");239 return c->codegen->builtin_types.entry_void;
244 case BuiltinType::Bool:240 case BuiltinType::Bool:
245 return create_symbol_node(c, "bool");241 return c->codegen->builtin_types.entry_bool;
246 case BuiltinType::Char_U:242 case BuiltinType::Char_U:
247 case BuiltinType::UChar:243 case BuiltinType::UChar:
248 case BuiltinType::Char_S:244 case BuiltinType::Char_S:
249 return create_symbol_node(c, "u8");245 return c->codegen->builtin_types.entry_u8;
250 case BuiltinType::SChar:246 case BuiltinType::SChar:
251 return create_symbol_node(c, "i8");247 return c->codegen->builtin_types.entry_i8;
252 case BuiltinType::UShort:248 case BuiltinType::UShort:
253 return create_symbol_node(c, "c_ushort");249 return get_c_int_type(c->codegen, CIntTypeUShort);
254 case BuiltinType::UInt:250 case BuiltinType::UInt:
255 return create_symbol_node(c, "c_uint");251 return get_c_int_type(c->codegen, CIntTypeUInt);
256 case BuiltinType::ULong:252 case BuiltinType::ULong:
257 return create_symbol_node(c, "c_ulong");253 return get_c_int_type(c->codegen, CIntTypeULong);
258 case BuiltinType::ULongLong:254 case BuiltinType::ULongLong:
259 return create_symbol_node(c, "c_ulonglong");255 return get_c_int_type(c->codegen, CIntTypeULongLong);
260 case BuiltinType::Short:256 case BuiltinType::Short:
261 return create_symbol_node(c, "c_short");257 return get_c_int_type(c->codegen, CIntTypeShort);
262 case BuiltinType::Int:258 case BuiltinType::Int:
263 return create_symbol_node(c, "c_int");259 return get_c_int_type(c->codegen, CIntTypeInt);
264 case BuiltinType::Long:260 case BuiltinType::Long:
265 return create_symbol_node(c, "c_long");261 return get_c_int_type(c->codegen, CIntTypeLong);
266 case BuiltinType::LongLong:262 case BuiltinType::LongLong:
267 return create_symbol_node(c, "c_longlong");263 return get_c_int_type(c->codegen, CIntTypeLongLong);
268 case BuiltinType::Float:264 case BuiltinType::Float:
269 return create_symbol_node(c, "f32");265 return c->codegen->builtin_types.entry_f32;
270 case BuiltinType::Double:266 case BuiltinType::Double:
271 return create_symbol_node(c, "f64");267 return c->codegen->builtin_types.entry_f64;
272 case BuiltinType::LongDouble:268 case BuiltinType::LongDouble:
273 case BuiltinType::WChar_U:269 case BuiltinType::WChar_U:
274 case BuiltinType::Char16:270 case BuiltinType::Char16:
...@@ -297,7 +293,7 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -297,7 +293,7 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
297 case BuiltinType::BuiltinFn:293 case BuiltinType::BuiltinFn:
298 case BuiltinType::ARCUnbridgedCast:294 case BuiltinType::ARCUnbridgedCast:
299 emit_warning(c, decl, "missed a builtin type");295 emit_warning(c, decl, "missed a builtin type");
300 return nullptr;296 return c->codegen->builtin_types.entry_invalid;
301 }297 }
302 break;298 break;
303 }299 }
...@@ -305,17 +301,26 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -305,17 +301,26 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
305 {301 {
306 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);302 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
307 QualType child_qt = pointer_ty->getPointeeType();303 QualType child_qt = pointer_ty->getPointeeType();
308 AstNode *type_node = make_qual_type_node(c, child_qt, decl);304 TypeTableEntry *child_type = resolve_qual_type(c, child_qt, decl);
309 if (!type_node) {305 if (get_underlying_type(child_type)->id == TypeTableEntryIdInvalid) {
310 return nullptr;306 emit_warning(c, decl, "pointer to unresolved type");
307 return c->codegen->builtin_types.entry_invalid;
311 }308 }
309
312 if (child_qt.getTypePtr()->getTypeClass() == Type::Paren) {310 if (child_qt.getTypePtr()->getTypeClass() == Type::Paren) {
313 const ParenType *paren_type = static_cast<const ParenType *>(child_qt.getTypePtr());311 const ParenType *paren_type = static_cast<const ParenType *>(child_qt.getTypePtr());
314 if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {312 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);
316 }314 }
317 }315 }
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);
319 }324 }
320 case Type::Typedef:325 case Type::Typedef:
321 {326 {
...@@ -323,32 +328,28 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -323,32 +328,28 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
323 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();328 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
324 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));329 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
325 if (buf_eql_str(type_name, "uint8_t")) {330 if (buf_eql_str(type_name, "uint8_t")) {
326 return create_symbol_node(c, "u8");331 return c->codegen->builtin_types.entry_u8;
327 } else if (buf_eql_str(type_name, "int8_t")) {332 } else if (buf_eql_str(type_name, "int8_t")) {
328 return create_symbol_node(c, "i8");333 return c->codegen->builtin_types.entry_i8;
329 } else if (buf_eql_str(type_name, "uint16_t")) {334 } else if (buf_eql_str(type_name, "uint16_t")) {
330 return create_symbol_node(c, "u16");335 return c->codegen->builtin_types.entry_u16;
331 } else if (buf_eql_str(type_name, "int16_t")) {336 } else if (buf_eql_str(type_name, "int16_t")) {
332 return create_symbol_node(c, "i16");337 return c->codegen->builtin_types.entry_i16;
333 } else if (buf_eql_str(type_name, "uint32_t")) {338 } else if (buf_eql_str(type_name, "uint32_t")) {
334 return create_symbol_node(c, "u32");339 return c->codegen->builtin_types.entry_u32;
335 } else if (buf_eql_str(type_name, "int32_t")) {340 } else if (buf_eql_str(type_name, "int32_t")) {
336 return create_symbol_node(c, "i32");341 return c->codegen->builtin_types.entry_i32;
337 } else if (buf_eql_str(type_name, "uint64_t")) {342 } else if (buf_eql_str(type_name, "uint64_t")) {
338 return create_symbol_node(c, "u64");343 return c->codegen->builtin_types.entry_u64;
339 } else if (buf_eql_str(type_name, "int64_t")) {344 } else if (buf_eql_str(type_name, "int64_t")) {
340 return create_symbol_node(c, "i64");345 return c->codegen->builtin_types.entry_i64;
341 } else if (buf_eql_str(type_name, "intptr_t")) {346 } else if (buf_eql_str(type_name, "intptr_t")) {
342 return create_symbol_node(c, "isize");347 return c->codegen->builtin_types.entry_isize;
343 } else if (buf_eql_str(type_name, "uintptr_t")) {348 } else if (buf_eql_str(type_name, "uintptr_t")) {
344 return create_symbol_node(c, "usize");349 return c->codegen->builtin_types.entry_usize;
345 } else {350 } else {
346 auto entry = type_table->maybe_get(type_name);351 auto entry = type_table->maybe_get(type_name);
347 if (entry) {352 return entry ? entry->value : c->codegen->builtin_types.entry_invalid;
348 return create_symbol_node(c, buf_ptr(type_name));
349 } else {
350 return nullptr;
351 }
352 }353 }
353 }354 }
354 case Type::Elaborated:355 case Type::Elaborated:
...@@ -356,10 +357,10 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -356,10 +357,10 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
356 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);357 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
357 switch (elaborated_ty->getKeyword()) {358 switch (elaborated_ty->getKeyword()) {
358 case ETK_Struct:359 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(),
360 decl, &c->struct_type_table);361 decl, &c->struct_type_table);
361 case ETK_Enum:362 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(),
363 decl, &c->enum_type_table);364 decl, &c->enum_type_table);
364 case ETK_Interface:365 case ETK_Interface:
365 case ETK_Union:366 case ETK_Union:
...@@ -367,35 +368,63 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -367,35 +368,63 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
367 case ETK_Typename:368 case ETK_Typename:
368 case ETK_None:369 case ETK_None:
369 emit_warning(c, decl, "unsupported elaborated type");370 emit_warning(c, decl, "unsupported elaborated type");
370 return nullptr;371 return c->codegen->builtin_types.entry_invalid;
371 }372 }
372 }373 }
373 case Type::FunctionProto:374 case Type::FunctionProto:
374 {375 {
375 const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);376 const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);
376 AstNode *node = create_node(c, NodeTypeFnProto);377
377 buf_resize(&node->data.fn_proto.name, 0);378 switch (fn_proto_ty->getCallConv()) {
378 node->data.fn_proto.is_extern = true;379 case CC_C: // __attribute__((cdecl))
379 node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();380 break;
380 node->data.fn_proto.return_type = make_qual_type_node(c, fn_proto_ty->getReturnType(), decl);381 case CC_X86StdCall: // __attribute__((stdcall))
381382 case CC_X86FastCall: // __attribute__((fastcall))
382 if (!node->data.fn_proto.return_type) {383 case CC_X86ThisCall: // __attribute__((thiscall))
383 return nullptr;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 }
384 }411 }
385412
386 int arg_count = fn_proto_ty->getNumParams();413 fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count);
387 for (int i = 0; i < arg_count; i += 1) {414 for (int i = 0; i < fn_type_id.param_count; i += 1) {
388 QualType qt = fn_proto_ty->getParamType(i);415 QualType qt = fn_proto_ty->getParamType(i);
389 bool is_noalias = qt.isRestrictQualified();416 TypeTableEntry *param_type = resolve_qual_type(c, qt, decl);
390 AstNode *type_node = make_qual_type_node(c, qt, decl);417
391 if (!type_node) {418 if (param_type->id == TypeTableEntryIdInvalid) {
392 return nullptr;419 return c->codegen->builtin_types.entry_invalid;
393 }420 }
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();
395 }425 }
396426
397 normalize_parent_ptrs(node);427 return get_fn_type(c->codegen, fn_type_id);
398 return node;
399 }428 }
400 case Type::Record:429 case Type::Record:
401 {430 {
...@@ -403,20 +432,15 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -403,20 +432,15 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
403 Buf *record_name = buf_create_from_str(decl_name(record_ty->getDecl()));432 Buf *record_name = buf_create_from_str(decl_name(record_ty->getDecl()));
404 if (buf_len(record_name) == 0) {433 if (buf_len(record_name) == 0) {
405 emit_warning(c, decl, "unhandled anonymous struct");434 emit_warning(c, decl, "unhandled anonymous struct");
406 return nullptr;435 return c->codegen->builtin_types.entry_invalid;
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;
419 }436 }
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;
420 }444 }
421 case Type::Enum:445 case Type::Enum:
422 {446 {
...@@ -424,32 +448,32 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -424,32 +448,32 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
424 Buf *record_name = buf_create_from_str(decl_name(enum_ty->getDecl()));448 Buf *record_name = buf_create_from_str(decl_name(enum_ty->getDecl()));
425 if (buf_len(record_name) == 0) {449 if (buf_len(record_name) == 0) {
426 emit_warning(c, decl, "unhandled anonymous enum");450 emit_warning(c, decl, "unhandled anonymous enum");
427 return nullptr;451 return c->codegen->builtin_types.entry_invalid;
428 } else if (type_table->maybe_get(record_name)) {452 }
429 const char *prefix_str;453
430 if (type_table == &c->enum_type_table) {454 auto entry = type_table->maybe_get(record_name);
431 prefix_str = "enum_";455 if (!entry) {
432 } else if (type_table == &c->struct_type_table) {456 return c->codegen->builtin_types.entry_invalid;
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;
440 }457 }
458
459 return entry->value;
441 }460 }
442 case Type::ConstantArray:461 case Type::ConstantArray:
443 {462 {
444 const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);463 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);
446 uint64_t size = const_arr_ty->getSize().getLimitedValue();465 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);
448 }467 }
449 case Type::Paren:468 case Type::Paren:
450 {469 {
451 const ParenType *paren_ty = static_cast<const ParenType *>(ty);470 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);
453 }477 }
454 case Type::BlockPointer:478 case Type::BlockPointer:
455 case Type::LValueReference:479 case Type::LValueReference:
...@@ -464,7 +488,6 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -464,7 +488,6 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
464 case Type::FunctionNoProto:488 case Type::FunctionNoProto:
465 case Type::UnresolvedUsing:489 case Type::UnresolvedUsing:
466 case Type::Adjusted:490 case Type::Adjusted:
467 case Type::Decayed:
468 case Type::TypeOfExpr:491 case Type::TypeOfExpr:
469 case Type::TypeOf:492 case Type::TypeOf:
470 case Type::Decltype:493 case Type::Decltype:
...@@ -485,68 +508,68 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,...@@ -485,68 +508,68 @@ static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl,
485 case Type::ObjCObjectPointer:508 case Type::ObjCObjectPointer:
486 case Type::Atomic:509 case Type::Atomic:
487 emit_warning(c, decl, "missed a '%s' type", ty->getTypeClassName());510 emit_warning(c, decl, "missed a '%s' type", ty->getTypeClassName());
488 return nullptr;511 return c->codegen->builtin_types.entry_invalid;
489 }512 }
490}513}
491514
492static AstNode *make_qual_type_node_with_table(Context *c, QualType qt, const Decl *decl,515static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl,
493 HashMap<Buf *, bool, buf_hash, buf_eql_buf> *type_table)516 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table)
494{517{
495 return make_type_node(c, qt.getTypePtr(), decl, type_table);518 return resolve_type_with_table(c, qt.getTypePtr(), decl, type_table);
496}519}
497520
498static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl) {521static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl) {
499 return make_qual_type_node_with_table(c, qt, decl, &c->root_name_table);522 return resolve_qual_type_with_table(c, qt, decl, &c->global_type_table);
500}523}
501524
502static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {525static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
503 AstNode *node = create_node(c, NodeTypeFnProto);526 Buf fn_name = BUF_INIT;
504 buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl));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);529 if (c->fn_table.maybe_get(&fn_name)) {
507 if (fn_entry) {
508 // we already saw this function530 // we already saw this function
509 return;531 return;
510 }532 }
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;
513 node->data.fn_proto.visib_mod = c->visib_mod;547 node->data.fn_proto.visib_mod = c->visib_mod;
514 node->data.fn_proto.directives = create_empty_directives(c);548 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;
518 for (int i = 0; i < arg_count; i += 1) {556 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);
519 const ParmVarDecl *param = fn_decl->getParamDecl(i);559 const ParmVarDecl *param = fn_decl->getParamDecl(i);
520 const char *name = decl_name(param);560 const char *name = decl_name(param);
521 if (strlen(name) == 0) {561 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);
523 }565 }
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()) {567 node->data.fn_proto.params.append(create_param_decl_node(c, name, type_node, param_info->is_noalias));
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;
545 }568 }
546569
547 normalize_parent_ptrs(node);570 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);
550 c->root->data.root.top_level_decls.append(node);573 c->root->data.root.top_level_decls.append(node);
551}574}
552575
...@@ -573,7 +596,9 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)...@@ -573,7 +596,9 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)
573 // use the name of this typedef596 // use the name of this typedef
574 // TODO597 // 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);
577}602}
578603
579static void add_alias(Context *c, const char *new_name, const char *target_name) {604static 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)...@@ -582,7 +607,14 @@ static void add_alias(Context *c, const char *new_name, const char *target_name)
582}607}
583608
584static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {609static 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);
586 Buf *full_type_name = buf_sprintf("enum_%s", buf_ptr(bare_name));618 Buf *full_type_name = buf_sprintf("enum_%s", buf_ptr(bare_name));
587619
588 if (c->enum_type_table.maybe_get(bare_name)) {620 if (c->enum_type_table.maybe_get(bare_name)) {
...@@ -590,97 +622,145 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -590,97 +622,145 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
590 return;622 return;
591 }623 }
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
597 const EnumDecl *enum_def = enum_decl->getDefinition();625 const EnumDecl *enum_def = enum_decl->getDefinition();
598626
599 if (!enum_def) {627 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
600 // this is a type that we can point to but that's it, same as `struct Foo;`.632 // 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);
602 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));634 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
603 return;635 return;
604 }636 }
605637
606 AstNode *node = create_node(c, NodeTypeStructDecl);638 // count and validate
607 buf_init_from_buf(&node->data.struct_decl.name, full_type_name);639 uint32_t field_count = 0;
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;
616 for (auto it = enum_def->enumerator_begin(),640 for (auto it = enum_def->enumerator_begin(),
617 it_end = enum_def->enumerator_end();641 it_end = enum_def->enumerator_end();
618 it != it_end; ++it, i += 1)642 it != it_end; ++it, field_count += 1)
619 {643 {
620 const EnumConstantDecl *enum_const = *it;644 const EnumConstantDecl *enum_const = *it;
621 if (enum_const->getInitExpr()) {645 if (enum_const->getInitExpr()) {
622 c->enum_type_table.remove(bare_name);
623 emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(bare_name));646 emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(bare_name));
624 return;647 return;
625 }648 }
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;
630 if (buf_starts_with_buf(enum_val_name, bare_name)) {681 if (buf_starts_with_buf(enum_val_name, bare_name)) {
631 Buf *slice = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));682 Buf *slice = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
632 if (valid_symbol_starter(buf_ptr(slice)[0])) {683 if (valid_symbol_starter(buf_ptr(slice)[0])) {
633 buf_init_from_buf(&field_name, slice);684 field_name = slice;
634 } else {685 } else {
635 buf_resize(&field_name, 0);686 field_name = buf_sprintf("_%s", buf_ptr(slice));
636 buf_appendf(&field_name, "_%s", buf_ptr(slice));
637 }687 }
638 } else {688 } else {
639 buf_init_from_buf(&field_name, enum_val_name);689 field_name = enum_val_name;
640 }690 }
641691
642 AstNode *field_node = create_struct_field_node(c, buf_ptr(&field_name), create_symbol_node(c, "void"));692 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
643 node->data.struct_decl.fields.append(field_node);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
645 // in C each enum value is in the global namespace. so we put them there too.700 // 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));
647 AstNode *var_node = create_var_decl_node(c, buf_ptr(enum_val_name), field_access_node);703 AstNode *var_node = create_var_decl_node(c, buf_ptr(enum_val_name), field_access_node);
648 var_decls.append(var_node);704 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);
650 }706 }
651707
652 normalize_parent_ptrs(node);708 // create llvm type for root struct
653 c->root->data.root.top_level_decls.append(node);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
655 for (int i = 0; i < var_decls.length; i += 1) {742 for (int i = 0; i < var_decls.length; i += 1) {
656 AstNode *var_node = var_decls.at(i);743 AstNode *var_node = var_decls.at(i);
657 c->root->data.root.top_level_decls.append(var_node);744 c->root->data.root.top_level_decls.append(var_node);
658 }745 }
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));
663}747}
664748
665static void visit_record_decl(Context *c, const RecordDecl *record_decl) {749static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
666 const char *raw_name = decl_name(record_decl);750 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.
668 if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) {754 if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) {
669 return;755 return;
670 }756 }
671757
672 Buf *bare_name = buf_create_from_str(raw_name);
673
674 if (!record_decl->isStruct()) {758 if (!record_decl->isStruct()) {
675 emit_warning(c, record_decl, "skipping record %s, not a struct", buf_ptr(bare_name));759 emit_warning(c, record_decl, "skipping record %s, not a struct", raw_name);
676 return;
677 }
678
679 if (buf_len(bare_name) == 0) {
680 emit_warning(c, record_decl, "skipping anonymous struct");
681 return;760 return;
682 }761 }
683762
763 Buf *bare_name = buf_create_from_str(raw_name);
684 Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name));764 Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name));
685765
686 if (c->struct_type_table.maybe_get(bare_name)) {766 if (c->struct_type_table.maybe_get(bare_name)) {
...@@ -688,55 +768,127 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -688,55 +768,127 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
688 return;768 return;
689 }769 }
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
696 RecordDecl *record_def = record_decl->getDefinition();771 RecordDecl *record_def = record_decl->getDefinition();
697 if (!record_def) {772 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
698 // this is a type that we can point to but that's it, such as `struct Foo;`.777 // 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);
700 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));779 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));
701 return;780 return;
702 }781 }
703782
704 AstNode *node = create_node(c, NodeTypeStructDecl);783 TypeTableEntry *struct_type = get_partial_container_type(c->codegen, c->import,
705 buf_init_from_buf(&node->data.struct_decl.name, full_type_name);784 ContainerKindStruct, c->source_node, buf_ptr(full_type_name));
706785
707 node->data.struct_decl.kind = ContainerKindStruct;786 c->struct_type_table.put(bare_name, struct_type);
708 node->data.struct_decl.visib_mod = VisibModExport;787 // make an alias without the "struct_" prefix. this will get emitted at the
709 node->data.struct_decl.directives = create_empty_directives(c);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;
711 for (auto it = record_def->field_begin(),793 for (auto it = record_def->field_begin(),
712 it_end = record_def->field_end();794 it_end = record_def->field_end();
713 it != it_end; ++it)795 it != it_end; ++it, field_count += 1)
714 {796 {
715 const FieldDecl *field_decl = *it;797 const FieldDecl *field_decl = *it;
716798
717 if (field_decl->isBitField()) {799 if (field_decl->isBitField()) {
718 c->struct_type_table.remove(bare_name);
719 emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(bare_name));800 emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(bare_name));
720 return;801 return;
721 }802 }
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);831 if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) {
724 if (!type_node) {832 emit_warning(c, field_decl, "skipping struct %s - unresolved type\n", buf_ptr(bare_name));
725 c->struct_type_table.remove(bare_name);
726 emit_warning(c, field_decl, "skipping struct %s - unhandled type\n", buf_ptr(bare_name));
727 return;833 return;
728 }834 }
729835
730 AstNode *field_node = create_struct_field_node(c, decl_name(field_decl), type_node);836 di_element_types[i] = LLVMZigCreateDebugMemberType(c->codegen->dbuilder,
731 node->data.struct_decl.fields.append(field_node);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
732 }853 }
854 struct_type->data.structure.embedded_in_current = false;
733855
734 normalize_parent_ptrs(node);856 struct_type->data.structure.gen_field_count = field_count;
735 c->root->data.root.top_level_decls.append(node);857 struct_type->data.structure.complete = true;
736858
737 // make an alias without the "struct_" prefix. this will get emitted at the859 LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false);
738 // end if it doesn't conflict with anything else860
739 add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name));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);
740}892}
741893
742static void visit_var_decl(Context *c, const VarDecl *var_decl) {894static 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) {...@@ -754,8 +906,8 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
754 }906 }
755907
756 QualType qt = var_decl->getType();908 QualType qt = var_decl->getType();
757 AstNode *type_node = make_qual_type_node(c, qt, var_decl);909 TypeTableEntry *var_type = resolve_qual_type(c, qt, var_decl);
758 if (!type_node) {910 if (var_type->id == TypeTableEntryIdInvalid) {
759 emit_warning(c, var_decl, "ignoring variable '%s' - unresolved type\n", buf_ptr(name));911 emit_warning(c, var_decl, "ignoring variable '%s' - unresolved type\n", buf_ptr(name));
760 return;912 return;
761 }913 }
...@@ -778,7 +930,8 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {...@@ -778,7 +930,8 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
778 switch (ap_value->getKind()) {930 switch (ap_value->getKind()) {
779 case APValue::Int:931 case APValue::Int:
780 {932 {
781 if (!type_is_int(type_node)) {933 TypeTableEntry *canon_type = get_underlying_type(var_type);
934 if (canon_type->id != TypeTableEntryIdInt) {
782 emit_warning(c, var_decl,935 emit_warning(c, var_decl,
783 "ignoring variable '%s' - int initializer for non int type\n", buf_ptr(name));936 "ignoring variable '%s' - int initializer for non int type\n", buf_ptr(name));
784 return;937 return;
...@@ -819,17 +972,19 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {...@@ -819,17 +972,19 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
819 return;972 return;
820 }973 }
821974
975 AstNode *type_node = make_type_node(c, var_type);
822 AstNode *var_node = create_typed_var_decl_node(c, true, buf_ptr(name), type_node, init_node);976 AstNode *var_node = create_typed_var_decl_node(c, true, buf_ptr(name), type_node, init_node);
823 c->root->data.root.top_level_decls.append(var_node);977 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);
825 return;979 return;
826 }980 }
827981
828 if (is_extern) {982 if (is_extern) {
983 AstNode *type_node = make_type_node(c, var_type);
829 AstNode *var_node = create_typed_var_decl_node(c, is_const, buf_ptr(name), type_node, nullptr);984 AstNode *var_node = create_typed_var_decl_node(c, is_const, buf_ptr(name), type_node, nullptr);
830 var_node->data.variable_declaration.is_extern = true;985 var_node->data.variable_declaration.is_extern = true;
831 c->root->data.root.top_level_decls.append(var_node);986 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);
833 return;988 return;
834 }989 }
835990
...@@ -864,7 +1019,10 @@ static bool decl_visitor(void *context, const Decl *decl) {...@@ -864,7 +1019,10 @@ static bool decl_visitor(void *context, const Decl *decl) {
864}1019}
8651020
866static bool name_exists(Context *c, Buf *name) {1021static 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)) {
868 return true;1026 return true;
869 }1027 }
870 if (c->fn_table.maybe_get(name)) {1028 if (c->fn_table.maybe_get(name)) {
...@@ -1001,6 +1159,11 @@ static void process_macro(Context *c, Buf *name, Buf *value) {...@@ -1001,6 +1159,11 @@ static void process_macro(Context *c, Buf *name, Buf *value) {
10011159
1002 // maybe it's a symbol1160 // maybe it's a symbol
1003 if (is_simple_symbol(value)) {1161 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 }
1004 c->macro_symbols.append({name, value});1167 c->macro_symbols.append({name, value});
1005 }1168 }
1006}1169}
...@@ -1054,46 +1217,43 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {...@@ -1054,46 +1217,43 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
1054}1217}
10551218
1056int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,1219int 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,1220 CodeGen *codegen, AstNode *source_node)
1058 uint32_t *next_node_index)
1059{1221{
1060 int err;1222 int err;
1061 Buf tmp_file_path = BUF_INIT;1223 Buf tmp_file_path = BUF_INIT;
1062 if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) {1224 if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) {
1063 return err;1225 return err;
1064 }1226 }
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
1077 os_delete_file(&tmp_file_path);1230 os_delete_file(&tmp_file_path);
10781231
1079 return err;1232 return err;
1080}1233}
10811234
1082int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,1235int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
1083 ZigList<const char *> *clang_argv, bool warnings_on, uint32_t *next_node_index)1236 CodeGen *codegen, AstNode *source_node)
1084{1237{
1085 Context context = {0};1238 Context context = {0};
1086 Context *c = &context;1239 Context *c = &context;
1087 c->warnings_on = warnings_on;1240 c->warnings_on = codegen->verbose;
1088 c->import = import;1241 c->import = import;
1089 c->errors = errors;1242 c->errors = errors;
1090 c->visib_mod = VisibModPub;1243 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);
1092 c->enum_type_table.init(8);1246 c->enum_type_table.init(8);
1093 c->struct_type_table.init(8);1247 c->struct_type_table.init(8);
1094 c->fn_table.init(8);1248 c->fn_table.init(8);
1095 c->macro_table.init(8);1249 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
1098 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");1258 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");
1099 if (ZIG_PARSEH_CFLAGS) {1259 if (ZIG_PARSEH_CFLAGS) {
...@@ -1103,28 +1263,37 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,...@@ -1103,28 +1263,37 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
1103 while (space) {1263 while (space) {
1104 if (space - start > 0) {1264 if (space - start > 0) {
1105 buf_init_from_mem(&tmp_buf, start, space - start);1265 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)));
1107 }1267 }
1108 start = space + 1;1268 start = space + 1;
1109 space = strstr(start, " ");1269 space = strstr(start, " ");
1110 }1270 }
1111 buf_init_from_str(&tmp_buf, start);1271 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)));
1113 }1273 }
11141274
1115 clang_argv->append("-isystem");1275 clang_argv.append("-isystem");
1116 clang_argv->append(ZIG_HEADERS_DIR);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
1118 // we don't need spell checking and it slows things down1285 // 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
1121 // this gives us access to preprocessing entities, presumably at1288 // this gives us access to preprocessing entities, presumably at
1122 // the cost of performance1289 // the cost of performance
1123 clang_argv->append("-Xclang");1290 clang_argv.append("-Xclang");
1124 clang_argv->append("-detailed-preprocessing-record");1291 clang_argv.append("-detailed-preprocessing-record");
1292
1293 clang_argv.append(target_file);
11251294
1126 // to make the end argument work1295 // to make the [start...end] argument work
1127 clang_argv->append(nullptr);1296 clang_argv.append(nullptr);
11281297
1129 IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));1298 IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
11301299
...@@ -1138,7 +1307,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,...@@ -1138,7 +1307,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
1138 const char *resources_path = ZIG_HEADERS_DIR;1307 const char *resources_path = ZIG_HEADERS_DIR;
1139 std::unique_ptr<ASTUnit> err_unit;1308 std::unique_ptr<ASTUnit> err_unit;
1140 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(1309 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(
1141 &clang_argv->at(0), &clang_argv->last(),1310 &clang_argv.at(0), &clang_argv.last(),
1142 pch_container_ops, diags, resources_path,1311 pch_container_ops, diags, resources_path,
1143 only_local_decls, capture_diagnostics, None, true, false, TU_Complete,1312 only_local_decls, capture_diagnostics, None, true, false, TU_Complete,
1144 false, false, allow_pch_with_compiler_errors, skip_function_bodies,1313 false, false, allow_pch_with_compiler_errors, skip_function_bodies,
src/parseh.hpp+5-5
...@@ -11,10 +11,10 @@...@@ -11,10 +11,10 @@
1111
12#include "all_types.hpp"12#include "all_types.hpp"
1313
14int parse_h_file(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs,14int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
15 ZigList<const char *> *clang_argv, bool warnings_on, uint32_t *next_node_index);15 CodeGen *codegen, AstNode *source_node);
16int parse_h_buf(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs,16
17 Buf *source, const char **args, int args_len, const char *libc_include_path,17int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
18 bool warnings_on, uint32_t *next_node_index);18 CodeGen *codegen, AstNode *source_node);
1919
20#endif20#endif
src/parser.cpp+49-2
...@@ -908,7 +908,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mand...@@ -908,7 +908,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mand
908908
909/*909/*
910PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." "Symbol")910PrimaryExpression = "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"
912*/912*/
913static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {913static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
914 Token *token = &pc->tokens->at(*token_index);914 Token *token = &pc->tokens->at(*token_index);
...@@ -954,6 +954,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -954,6 +954,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
954 AstNode *node = ast_create_node(pc, NodeTypeUndefinedLiteral, token);954 AstNode *node = ast_create_node(pc, NodeTypeUndefinedLiteral, token);
955 *token_index += 1;955 *token_index += 1;
956 return node;956 return node;
957 } else if (token->id == TokenIdKeywordType) {
958 AstNode *node = ast_create_node(pc, NodeTypeTypeLiteral, token);
959 *token_index += 1;
960 return node;
957 } else if (token->id == TokenIdKeywordError) {961 } else if (token->id == TokenIdKeywordError) {
958 AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);962 AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
959 *token_index += 1;963 *token_index += 1;
...@@ -2470,7 +2474,34 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index,...@@ -2470,7 +2474,34 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index,
2470}2474}
24712475
2472/*2476/*
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)
2474*/2505*/
2475static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {2506static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
2476 for (;;) {2507 for (;;) {
...@@ -2545,6 +2576,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis...@@ -2545,6 +2576,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
2545 continue;2576 continue;
2546 }2577 }
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
2548 if (directives->length > 0) {2585 if (directives->length > 0) {
2549 ast_error(pc, directive_token, "invalid directive");2586 ast_error(pc, directive_token, "invalid directive");
2550 }2587 }
...@@ -2631,9 +2668,16 @@ void normalize_parent_ptrs(AstNode *node) {...@@ -2631,9 +2668,16 @@ void normalize_parent_ptrs(AstNode *node) {
2631 set_field(&node->data.return_expr.expr);2668 set_field(&node->data.return_expr.expr);
2632 break;2669 break;
2633 case NodeTypeVariableDeclaration:2670 case NodeTypeVariableDeclaration:
2671 if (node->data.variable_declaration.directives) {
2672 set_list_fields(node->data.variable_declaration.directives);
2673 }
2634 set_field(&node->data.variable_declaration.type);2674 set_field(&node->data.variable_declaration.type);
2635 set_field(&node->data.variable_declaration.expr);2675 set_field(&node->data.variable_declaration.expr);
2636 break;2676 break;
2677 case NodeTypeTypeDecl:
2678 set_list_fields(node->data.type_decl.directives);
2679 set_field(&node->data.type_decl.child_type);
2680 break;
2637 case NodeTypeErrorValueDecl:2681 case NodeTypeErrorValueDecl:
2638 // none2682 // none
2639 break;2683 break;
...@@ -2772,5 +2816,8 @@ void normalize_parent_ptrs(AstNode *node) {...@@ -2772,5 +2816,8 @@ void normalize_parent_ptrs(AstNode *node) {
2772 case NodeTypeErrorType:2816 case NodeTypeErrorType:
2773 // none2817 // none
2774 break;2818 break;
2819 case NodeTypeTypeLiteral:
2820 // none
2821 break;
2775 }2822 }
2776}2823}
src/tokenizer.cpp+4-1
...@@ -101,7 +101,7 @@ const char * zig_keywords[] = {...@@ -101,7 +101,7 @@ const char * zig_keywords[] = {
101 "true", "false", "null", "fn", "return", "var", "const", "extern",101 "true", "false", "null", "fn", "return", "var", "const", "extern",
102 "pub", "export", "import", "c_import", "if", "else", "goto", "asm",102 "pub", "export", "import", "c_import", "if", "else", "goto", "asm",
103 "volatile", "struct", "enum", "while", "for", "continue", "break",103 "volatile", "struct", "enum", "while", "for", "continue", "break",
104 "null", "noalias", "switch", "undefined", "error"104 "null", "noalias", "switch", "undefined", "error", "type"
105};105};
106106
107bool is_zig_keyword(Buf *buf) {107bool is_zig_keyword(Buf *buf) {
...@@ -271,6 +271,8 @@ static void end_token(Tokenize *t) {...@@ -271,6 +271,8 @@ static void end_token(Tokenize *t) {
271 t->cur_tok->id = TokenIdKeywordUndefined;271 t->cur_tok->id = TokenIdKeywordUndefined;
272 } else if (mem_eql_str(token_mem, token_len, "error")) {272 } else if (mem_eql_str(token_mem, token_len, "error")) {
273 t->cur_tok->id = TokenIdKeywordError;273 t->cur_tok->id = TokenIdKeywordError;
274 } else if (mem_eql_str(token_mem, token_len, "type")) {
275 t->cur_tok->id = TokenIdKeywordType;
274 }276 }
275277
276 t->cur_tok = nullptr;278 t->cur_tok = nullptr;
...@@ -1084,6 +1086,7 @@ const char * token_name(TokenId id) {...@@ -1084,6 +1086,7 @@ const char * token_name(TokenId id) {
1084 case TokenIdKeywordSwitch: return "switch";1086 case TokenIdKeywordSwitch: return "switch";
1085 case TokenIdKeywordUndefined: return "undefined";1087 case TokenIdKeywordUndefined: return "undefined";
1086 case TokenIdKeywordError: return "error";1088 case TokenIdKeywordError: return "error";
1089 case TokenIdKeywordType: return "type";
1087 case TokenIdLParen: return "(";1090 case TokenIdLParen: return "(";
1088 case TokenIdRParen: return ")";1091 case TokenIdRParen: return ")";
1089 case TokenIdComma: return ",";1092 case TokenIdComma: return ",";
src/tokenizer.hpp+1
...@@ -40,6 +40,7 @@ enum TokenId {...@@ -40,6 +40,7 @@ enum TokenId {
40 TokenIdKeywordSwitch,40 TokenIdKeywordSwitch,
41 TokenIdKeywordUndefined,41 TokenIdKeywordUndefined,
42 TokenIdKeywordError,42 TokenIdKeywordError,
43 TokenIdKeywordType,
43 TokenIdLParen,44 TokenIdLParen,
44 TokenIdRParen,45 TokenIdRParen,
45 TokenIdComma,46 TokenIdComma,
test/run_tests.cpp+5-5
...@@ -115,7 +115,7 @@ static TestCase *add_parseh_case(const char *case_name, const char *source, int...@@ -115,7 +115,7 @@ static TestCase *add_parseh_case(const char *case_name, const char *source, int
115115
116 test_case->compiler_args.append("parseh");116 test_case->compiler_args.append("parseh");
117 test_case->compiler_args.append(tmp_h_path);117 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
120 test_cases.append(test_case);120 test_cases.append(test_case);
121121
...@@ -1689,7 +1689,7 @@ var a : i32 = 2;...@@ -1689,7 +1689,7 @@ var a : i32 = 2;
1689 add_compile_fail_case("byvalue struct on exported functions", R"SOURCE(1689 add_compile_fail_case("byvalue struct on exported functions", R"SOURCE(
1690struct A { x : i32, }1690struct A { x : i32, }
1691export fn f(a : A) {}1691export 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
1694 add_compile_fail_case("duplicate field in struct value expression", R"SOURCE(1694 add_compile_fail_case("duplicate field in struct value expression", R"SOURCE(
1695struct A {1695struct A {
...@@ -1929,7 +1929,7 @@ pub const Foo1 = enum_Foo._1;)OUTPUT",...@@ -1929,7 +1929,7 @@ pub const Foo1 = enum_Foo._1;)OUTPUT",
19291929
1930 add_parseh_case("restrict -> noalias", R"SOURCE(1930 add_parseh_case("restrict -> noalias", R"SOURCE(
1931void foo(void *restrict bar, void *restrict);1931void 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;
1933pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT");1933pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT");
19341934
1935 add_parseh_case("simple struct", R"SOURCE(1935 add_parseh_case("simple struct", R"SOURCE(
...@@ -1977,14 +1977,14 @@ struct Foo {...@@ -1977,14 +1977,14 @@ struct Foo {
1977 void (*derp)(struct Foo *foo);1977 void (*derp)(struct Foo *foo);
1978};1978};
1979 )SOURCE", 2, R"OUTPUT(export struct struct_Foo {1979 )SOURCE", 2, R"OUTPUT(export struct struct_Foo {
1980 derp: ?extern fn (?&struct_Foo),1980 derp: ?extern fn(?&struct_Foo),
1981})OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");1981})OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
19821982
19831983
1984 add_parseh_case("struct prototype used in func", R"SOURCE(1984 add_parseh_case("struct prototype used in func", R"SOURCE(
1985struct Foo;1985struct Foo;
1986struct Foo *some_func(struct Foo *foo, int x);1986struct 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;
1988pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",1988pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",
1989 R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");1989 R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
19901990