| author | |
| committer | |
| log | 0c24ed8a818dddc1c77a41c07815b036a94279ca |
| tree | 7df54df324e797d2fd06cf12dc7d377a528cec41 |
| parent | b7dd88ad68aab5b6bc8321431d1a53b343b2dd37 |
10 files changed, 48 insertions(+), 48 deletions(-)
doc/langref.md+2-2| ... | ... | @@ -68,11 +68,11 @@ CompilerFnExpr : token(NumberSign) token(Symbol) token(LParen) Expression token( |
| 68 | 68 | |
| 69 | 69 | CompilerFnType : token(NumberSign) token(Symbol) token(LParen) Type token(RParen) |
| 70 | 70 | |
| 71 | PointerType : token(Ampersand) option(token(Const)) option(token(Restrict)) Type | |
| 71 | PointerType : token(Ampersand) option(token(Const)) option(token(NoAlias)) Type | |
| 72 | 72 | |
| 73 | 73 | MaybeType : token(Question) Type |
| 74 | 74 | |
| 75 | ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) option(token(Restrict)) Type | |
| 75 | ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) option(token(NoAlias)) Type | |
| 76 | 76 | |
| 77 | 77 | Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace) |
| 78 | 78 |
doc/vim/syntax/zig.vim+1-1| ... | ... | @@ -8,7 +8,7 @@ if exists("b:current_syntax") |
| 8 | 8 | endif |
| 9 | 9 | |
| 10 | 10 | syn keyword zigOperator as |
| 11 | syn keyword zigStorage const var extern volatile export pub restrict | |
| 11 | syn keyword zigStorage const var extern volatile export pub noalias | |
| 12 | 12 | syn keyword zigStructure struct enum type |
| 13 | 13 | syn keyword zigStatement goto break return continue asm |
| 14 | 14 | syn keyword zigConditional if else match |
src/analyze.cpp+20-20| ... | ... | @@ -135,8 +135,8 @@ static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x) |
| 135 | 135 | return g->num_lit_types[get_number_literal_kind_unsigned(x)]; |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_restrict) { | |
| 139 | TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)][(is_restrict ? 1 : 0)]; | |
| 138 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias) { | |
| 139 | TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)][(is_noalias ? 1 : 0)]; | |
| 140 | 140 | if (*parent_pointer) { |
| 141 | 141 | return *parent_pointer; |
| 142 | 142 | } else { |
| ... | ... | @@ -151,7 +151,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool |
| 151 | 151 | entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name)); |
| 152 | 152 | entry->data.pointer.child_type = child_type; |
| 153 | 153 | entry->data.pointer.is_const = is_const; |
| 154 | entry->data.pointer.is_restrict = is_restrict; | |
| 154 | entry->data.pointer.is_noalias = is_noalias; | |
| 155 | 155 | |
| 156 | 156 | *parent_pointer = entry; |
| 157 | 157 | return entry; |
| ... | ... | @@ -240,9 +240,9 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | 242 | static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry *import, |
| 243 | TypeTableEntry *child_type, bool is_const, bool is_restrict) | |
| 243 | TypeTableEntry *child_type, bool is_const, bool is_noalias) | |
| 244 | 244 | { |
| 245 | TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)][(is_restrict ? 1 : 0)]; | |
| 245 | TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)][(is_noalias ? 1 : 0)]; | |
| 246 | 246 | if (*parent_pointer) { |
| 247 | 247 | return *parent_pointer; |
| 248 | 248 | } else { |
| ... | ... | @@ -252,7 +252,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry |
| 252 | 252 | buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name)); |
| 253 | 253 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name)); |
| 254 | 254 | |
| 255 | TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const, is_restrict); | |
| 255 | TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const, is_noalias); | |
| 256 | 256 | |
| 257 | 257 | unsigned element_count = 2; |
| 258 | 258 | LLVMTypeRef element_types[] = { |
| ... | ... | @@ -428,7 +428,7 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, |
| 428 | 428 | } |
| 429 | 429 | |
| 430 | 430 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, |
| 431 | BlockContext *context, bool restrict_allowed) | |
| 431 | BlockContext *context, bool noalias_allowed) | |
| 432 | 432 | { |
| 433 | 433 | assert(node->type == NodeTypeType); |
| 434 | 434 | alloc_codegen_node(node); |
| ... | ... | @@ -449,13 +449,13 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 449 | 449 | } |
| 450 | 450 | case AstNodeTypeTypePointer: |
| 451 | 451 | { |
| 452 | bool use_restrict = false; | |
| 453 | if (node->data.type.is_restrict) { | |
| 454 | if (!restrict_allowed) { | |
| 452 | bool use_noalias = false; | |
| 453 | if (node->data.type.is_noalias) { | |
| 454 | if (!noalias_allowed) { | |
| 455 | 455 | add_node_error(g, node, |
| 456 | buf_create_from_str("invalid restrict qualifier")); | |
| 456 | buf_create_from_str("invalid noalias qualifier")); | |
| 457 | 457 | } else { |
| 458 | use_restrict = true; | |
| 458 | use_noalias = true; | |
| 459 | 459 | } |
| 460 | 460 | } |
| 461 | 461 | |
| ... | ... | @@ -471,7 +471,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 471 | 471 | type_node->entry = child_type; |
| 472 | 472 | return child_type; |
| 473 | 473 | } else { |
| 474 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const, use_restrict); | |
| 474 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const, use_noalias); | |
| 475 | 475 | return type_node->entry; |
| 476 | 476 | } |
| 477 | 477 | } |
| ... | ... | @@ -479,13 +479,13 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 479 | 479 | { |
| 480 | 480 | AstNode *size_node = node->data.type.array_size; |
| 481 | 481 | |
| 482 | bool use_restrict = false; | |
| 483 | if (node->data.type.is_restrict) { | |
| 484 | if (!restrict_allowed || size_node) { | |
| 482 | bool use_noalias = false; | |
| 483 | if (node->data.type.is_noalias) { | |
| 484 | if (!noalias_allowed || size_node) { | |
| 485 | 485 | add_node_error(g, node, |
| 486 | buf_create_from_str("invalid restrict qualifier")); | |
| 486 | buf_create_from_str("invalid noalias qualifier")); | |
| 487 | 487 | } else { |
| 488 | use_restrict = true; | |
| 488 | use_noalias = true; | |
| 489 | 489 | } |
| 490 | 490 | } |
| 491 | 491 | |
| ... | ... | @@ -524,7 +524,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 524 | 524 | return type_node->entry; |
| 525 | 525 | } else { |
| 526 | 526 | type_node->entry = get_unknown_size_array_type(g, import, child_type, |
| 527 | node->data.type.is_const, use_restrict); | |
| 527 | node->data.type.is_const, use_noalias); | |
| 528 | 528 | return type_node->entry; |
| 529 | 529 | } |
| 530 | 530 | |
| ... | ... | @@ -1221,7 +1221,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1221 | 1221 | return expected_type; |
| 1222 | 1222 | } |
| 1223 | 1223 | |
| 1224 | // implicit non-const to const and ignore restrict | |
| 1224 | // implicit non-const to const and ignore noalias | |
| 1225 | 1225 | if (expected_type->id == TypeTableEntryIdPointer && |
| 1226 | 1226 | actual_type->id == TypeTableEntryIdPointer && |
| 1227 | 1227 | (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const)) |
src/analyze.hpp+4-4| ... | ... | @@ -23,7 +23,7 @@ struct StructValExprNode; |
| 23 | 23 | struct TypeTableEntryPointer { |
| 24 | 24 | TypeTableEntry *child_type; |
| 25 | 25 | bool is_const; |
| 26 | bool is_restrict; | |
| 26 | bool is_noalias; | |
| 27 | 27 | }; |
| 28 | 28 | |
| 29 | 29 | struct TypeTableEntryInt { |
| ... | ... | @@ -98,8 +98,8 @@ struct TypeTableEntry { |
| 98 | 98 | } data; |
| 99 | 99 | |
| 100 | 100 | // use these fields to make sure we don't duplicate type table entries for the same type |
| 101 | TypeTableEntry *pointer_parent[2][2]; // 0 - const. 1 - restrict | |
| 102 | TypeTableEntry *unknown_size_array_parent[2][2]; // 0 - const. 1 - restrict | |
| 101 | TypeTableEntry *pointer_parent[2][2]; // 0 - const. 1 - noalias | |
| 102 | TypeTableEntry *unknown_size_array_parent[2][2]; // 0 - const. 1 - noalias | |
| 103 | 103 | HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size; |
| 104 | 104 | TypeTableEntry *maybe_parent; |
| 105 | 105 | |
| ... | ... | @@ -391,7 +391,7 @@ void semantic_analyze(CodeGen *g); |
| 391 | 391 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 392 | 392 | void alloc_codegen_node(AstNode *node); |
| 393 | 393 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); |
| 394 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_restrict); | |
| 394 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias); | |
| 395 | 395 | VariableTableEntry *find_variable(BlockContext *context, Buf *name); |
| 396 | 396 | BlockContext *new_block_context(AstNode *node, BlockContext *parent); |
| 397 | 397 |
src/codegen.cpp+1-1| ... | ... | @@ -1840,7 +1840,7 @@ static void do_code_gen(CodeGen *g) { |
| 1840 | 1840 | TypeTableEntry *param_type = fn_proto_type_from_type_node(g, type_node); |
| 1841 | 1841 | LLVMValueRef argument_val = LLVMGetParam(fn, gen_param_index); |
| 1842 | 1842 | if (param_type->id == TypeTableEntryIdPointer && |
| 1843 | param_type->data.pointer.is_restrict) | |
| 1843 | param_type->data.pointer.is_noalias) | |
| 1844 | 1844 | { |
| 1845 | 1845 | LLVMAddAttribute(argument_val, LLVMNoAliasAttribute); |
| 1846 | 1846 | } else if (param_type->id == TypeTableEntryIdPointer && |
src/parser.cpp+14-14| ... | ... | @@ -225,8 +225,8 @@ void ast_print(AstNode *node, int indent) { |
| 225 | 225 | case AstNodeTypeTypePointer: |
| 226 | 226 | { |
| 227 | 227 | const char *const_or_mut_str = node->data.type.is_const ? "const " : ""; |
| 228 | const char *restrict_or_not_str = node->data.type.is_restrict ? "restrict " : ""; | |
| 229 | fprintf(stderr, "%s%s PointerType\n", const_or_mut_str, restrict_or_not_str); | |
| 228 | const char *noalias_or_not_str = node->data.type.is_noalias ? "noalias " : ""; | |
| 229 | fprintf(stderr, "%s%s PointerType\n", const_or_mut_str, noalias_or_not_str); | |
| 230 | 230 | |
| 231 | 231 | ast_print(node->data.type.child_type, indent + 2); |
| 232 | 232 | break; |
| ... | ... | @@ -234,8 +234,8 @@ void ast_print(AstNode *node, int indent) { |
| 234 | 234 | case AstNodeTypeTypeArray: |
| 235 | 235 | { |
| 236 | 236 | const char *const_or_mut_str = node->data.type.is_const ? "const " : ""; |
| 237 | const char *restrict_or_not_str = node->data.type.is_restrict ? "restrict " : ""; | |
| 238 | fprintf(stderr, "%s%s ArrayType\n", const_or_mut_str, restrict_or_not_str); | |
| 237 | const char *noalias_or_not_str = node->data.type.is_noalias ? "noalias " : ""; | |
| 238 | fprintf(stderr, "%s%s ArrayType\n", const_or_mut_str, noalias_or_not_str); | |
| 239 | 239 | if (node->data.type.array_size) |
| 240 | 240 | ast_print(node->data.type.array_size, indent + 2); |
| 241 | 241 | ast_print(node->data.type.child_type, indent + 2); |
| ... | ... | @@ -1024,12 +1024,12 @@ static void ast_parse_type_assume_amp(ParseContext *pc, int *token_index, AstNod |
| 1024 | 1024 | node->data.type.is_const = true; |
| 1025 | 1025 | *token_index += 1; |
| 1026 | 1026 | first_type_token = &pc->tokens->at(*token_index); |
| 1027 | if (first_type_token->id == TokenIdKeywordRestrict) { | |
| 1028 | node->data.type.is_restrict = true; | |
| 1027 | if (first_type_token->id == TokenIdKeywordNoAlias) { | |
| 1028 | node->data.type.is_noalias = true; | |
| 1029 | 1029 | *token_index += 1; |
| 1030 | 1030 | } |
| 1031 | } else if (first_type_token->id == TokenIdKeywordRestrict) { | |
| 1032 | node->data.type.is_restrict = true; | |
| 1031 | } else if (first_type_token->id == TokenIdKeywordNoAlias) { | |
| 1032 | node->data.type.is_noalias = true; | |
| 1033 | 1033 | *token_index += 1; |
| 1034 | 1034 | } |
| 1035 | 1035 | |
| ... | ... | @@ -1088,8 +1088,8 @@ static AstNode *ast_parse_compiler_fn_call(ParseContext *pc, int *token_index, b |
| 1088 | 1088 | |
| 1089 | 1089 | /* |
| 1090 | 1090 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompilerFnExpr |
| 1091 | PointerType : token(Ampersand) option(token(Const)) option(token(Restrict)) Type | |
| 1092 | ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) option(token(Restrict)) Type | |
| 1091 | PointerType : token(Ampersand) option(token(Const)) option(token(NoAlias)) Type | |
| 1092 | ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) option(token(NoAlias)) Type | |
| 1093 | 1093 | */ |
| 1094 | 1094 | static AstNode *ast_parse_type(ParseContext *pc, int *token_index) { |
| 1095 | 1095 | Token *token = &pc->tokens->at(*token_index); |
| ... | ... | @@ -1140,13 +1140,13 @@ static AstNode *ast_parse_type(ParseContext *pc, int *token_index) { |
| 1140 | 1140 | node->data.type.is_const = true; |
| 1141 | 1141 | |
| 1142 | 1142 | Token *next_tok = &pc->tokens->at(*token_index); |
| 1143 | if (next_tok->id == TokenIdKeywordRestrict) { | |
| 1143 | if (next_tok->id == TokenIdKeywordNoAlias) { | |
| 1144 | 1144 | *token_index += 1; |
| 1145 | node->data.type.is_restrict = true; | |
| 1145 | node->data.type.is_noalias = true; | |
| 1146 | 1146 | } |
| 1147 | } else if (const_tok->id == TokenIdKeywordRestrict) { | |
| 1147 | } else if (const_tok->id == TokenIdKeywordNoAlias) { | |
| 1148 | 1148 | *token_index += 1; |
| 1149 | node->data.type.is_restrict = true; | |
| 1149 | node->data.type.is_noalias = true; | |
| 1150 | 1150 | } |
| 1151 | 1151 | |
| 1152 | 1152 | node->data.type.child_type = ast_parse_type(pc, token_index); |
src/parser.hpp+1-1| ... | ... | @@ -110,7 +110,7 @@ struct AstNodeType { |
| 110 | 110 | AstNode *child_type; |
| 111 | 111 | AstNode *array_size; // can be null |
| 112 | 112 | bool is_const; |
| 113 | bool is_restrict; | |
| 113 | bool is_noalias; | |
| 114 | 114 | AstNode *compiler_expr; |
| 115 | 115 | }; |
| 116 | 116 |
src/tokenizer.cpp+3-3| ... | ... | @@ -243,8 +243,8 @@ static void end_token(Tokenize *t) { |
| 243 | 243 | t->cur_tok->id = TokenIdKeywordBreak; |
| 244 | 244 | } else if (mem_eql_str(token_mem, token_len, "null")) { |
| 245 | 245 | t->cur_tok->id = TokenIdKeywordNull; |
| 246 | } else if (mem_eql_str(token_mem, token_len, "restrict")) { | |
| 247 | t->cur_tok->id = TokenIdKeywordRestrict; | |
| 246 | } else if (mem_eql_str(token_mem, token_len, "noalias")) { | |
| 247 | t->cur_tok->id = TokenIdKeywordNoAlias; | |
| 248 | 248 | } |
| 249 | 249 | |
| 250 | 250 | t->cur_tok = nullptr; |
| ... | ... | @@ -1025,7 +1025,7 @@ static const char * token_name(Token *token) { |
| 1025 | 1025 | case TokenIdKeywordContinue: return "Continue"; |
| 1026 | 1026 | case TokenIdKeywordBreak: return "Break"; |
| 1027 | 1027 | case TokenIdKeywordNull: return "Null"; |
| 1028 | case TokenIdKeywordRestrict: return "Restrict"; | |
| 1028 | case TokenIdKeywordNoAlias: return "NoAlias"; | |
| 1029 | 1029 | case TokenIdLParen: return "LParen"; |
| 1030 | 1030 | case TokenIdRParen: return "RParen"; |
| 1031 | 1031 | case TokenIdComma: return "Comma"; |
src/tokenizer.hpp+1-1| ... | ... | @@ -36,7 +36,7 @@ enum TokenId { |
| 36 | 36 | TokenIdKeywordContinue, |
| 37 | 37 | TokenIdKeywordBreak, |
| 38 | 38 | TokenIdKeywordNull, |
| 39 | TokenIdKeywordRestrict, | |
| 39 | TokenIdKeywordNoAlias, | |
| 40 | 40 | TokenIdLParen, |
| 41 | 41 | TokenIdRParen, |
| 42 | 42 | TokenIdComma, |
std/builtin.zig+1-1| ... | ... | @@ -10,7 +10,7 @@ export fn memset(dest: &u8, c: u8, n: usize) -> &u8 { |
| 10 | 10 | return dest; |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | export fn memcpy(dest: &restrict u8, src: &const restrict u8, n: usize) -> &u8 { | |
| 13 | export fn memcpy(dest: &noalias u8, src: &const noalias u8, n: usize) -> &u8 { | |
| 14 | 14 | var index : #typeof(n) = 0; |
| 15 | 15 | while (index != n) { |
| 16 | 16 | dest[index] = src[index]; |