diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2016-12-07 00:22:14 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-12-07 00:22:14 -0500 |
| commit | c0b2fe4d6cf3f8c6aa07899863861d506f588ef5 (patch) | |
| tree | d48eb21337f5da54b535bbc6be22290a3e3bd00a /src | |
| parent | 7d9fa01ed54e99368f7351dbf1193e4f79ddf806 (diff) | |
| download | zig-c0b2fe4d6cf3f8c6aa07899863861d506f588ef5.tar.gz zig-c0b2fe4d6cf3f8c6aa07899863861d506f588ef5.zip | |
IR: add error for assigning runtime value to inline var
Diffstat (limited to 'src')
| -rw-r--r-- | src/all_types.hpp | 18 | ||||
| -rw-r--r-- | src/ir.cpp | 54 | ||||
| -rw-r--r-- | src/parser.cpp | 32 |
3 files changed, 72 insertions, 32 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index bc4ce33ece..c64a6c3eeb 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -78,15 +78,23 @@ struct ConstArrayValue { size_t size; }; +enum ConstPtrSpecial { + ConstPtrSpecialNone, + // This helps us preserve the null byte when performing compile-time + // concatenation on C strings. + ConstPtrSpecialCStr, + // This means that the pointer points to inline memory, so attempting + // to write a non-compile-time known value is an error + ConstPtrSpecialInline, +}; + struct ConstPtrValue { ConstExprValue *base_ptr; // If index is SIZE_MAX, then base_ptr points directly to child type. // Otherwise base_ptr points to an array const val and index is offset // in object units from base_ptr into the block of memory pointed to size_t index; - // This flag helps us preserve the null byte when performing compile-time - // concatenation on C strings. - bool is_c_str; + ConstPtrSpecial special; }; struct ConstErrValue { @@ -472,7 +480,7 @@ struct AstNodeIfBoolExpr { AstNode *condition; AstNode *then_block; AstNode *else_node; // null, block node, or other if expr node - bool is_inline; // TODO parse inline if + bool is_inline; }; struct AstNodeIfVarExpr { @@ -480,7 +488,7 @@ struct AstNodeIfVarExpr { AstNode *then_block; AstNode *else_node; // null, block node, or other if expr node bool var_is_ptr; - bool is_inline; // TODO parse inline ?if? + bool is_inline; }; struct AstNodeWhileExpr { diff --git a/src/ir.cpp b/src/ir.cpp index 2642eec4f9..9d8dbba475 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -540,7 +540,7 @@ static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, Ast ptr_val->special = ConstValSpecialStatic; ptr_val->data.x_ptr.base_ptr = array_val; ptr_val->data.x_ptr.index = 0; - ptr_val->data.x_ptr.is_c_str = true; + ptr_val->data.x_ptr.special = ConstPtrSpecialCStr; return &const_instruction->base; } @@ -3352,13 +3352,15 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio } static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction, - ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var) + ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var, + ConstPtrSpecial special) { TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, true); ConstExprValue *const_val = ir_build_const_from(ira, instruction, depends_on_compile_var || pointee->depends_on_compile_var); const_val->data.x_ptr.base_ptr = pointee; const_val->data.x_ptr.index = SIZE_MAX; + const_val->data.x_ptr.special = special; return ptr_type; } @@ -3791,7 +3793,7 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst ConstExprValue *val = ir_resolve_const(ira, value); if (!val) return ira->codegen->builtin_types.entry_invalid; - return ir_analyze_const_ptr(ira, source_instruction, val, value->type_entry, false); + return ir_analyze_const_ptr(ira, source_instruction, val, value->type_entry, false, ConstPtrSpecialNone); } TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, value->type_entry, true); @@ -4338,10 +4340,17 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc var->type = result_type; assert(var->type); - if (var->mem_slot_index != SIZE_MAX) { - assert(var->mem_slot_index < ira->exec_context.mem_slot_count); - ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; - *mem_slot = casted_init_value->static_value; + if (casted_init_value->static_value.special == ConstValSpecialStatic) { + if (var->mem_slot_index != SIZE_MAX) { + assert(var->mem_slot_index < ira->exec_context.mem_slot_count); + ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; + *mem_slot = casted_init_value->static_value; + } + } else if (var->is_inline) { + ir_add_error(ira, &decl_var_instruction->base, + buf_sprintf("cannot store runtime value in compile time variable")); + var->type = ira->codegen->builtin_types.entry_invalid; + return ira->codegen->builtin_types.entry_invalid; } ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, casted_init_value); @@ -5192,7 +5201,8 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc } if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { - return ir_analyze_const_ptr(ira, instruction, mem_slot, var->type, false); + ConstPtrSpecial ptr_special = var->is_inline ? ConstPtrSpecialInline : ConstPtrSpecialNone; + return ir_analyze_const_ptr(ira, instruction, mem_slot, var->type, false, ptr_special); } else { ir_build_var_ptr_from(&ira->new_irb, instruction, var); return get_pointer_to_type(ira->codegen, var->type, false); @@ -5407,7 +5417,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source const_val->special = ConstValSpecialStatic; const_val->data.x_fn = fn_entry; - return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry, depends_on_compile_var); + return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry, depends_on_compile_var, ConstPtrSpecialNone); } case TldIdContainer: { @@ -5420,7 +5430,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source const_val->special = ConstValSpecialStatic; const_val->data.x_type = tld_container->type_entry; - return ir_analyze_const_ptr(ira, source_instruction, const_val, tld_container->type_entry, depends_on_compile_var); + return ir_analyze_const_ptr(ira, source_instruction, const_val, tld_container->type_entry, depends_on_compile_var, ConstPtrSpecialNone); } case TldIdTypeDef: { @@ -5433,7 +5443,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source const_val->special = ConstValSpecialStatic; const_val->data.x_type = tld_typedef->type_entry; - return ir_analyze_const_ptr(ira, source_instruction, const_val, tld_typedef->type_entry, depends_on_compile_var); + return ir_analyze_const_ptr(ira, source_instruction, const_val, tld_typedef->type_entry, depends_on_compile_var, ConstPtrSpecialNone); } } zig_unreachable(); @@ -5461,7 +5471,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru bignum_init_unsigned(&len_val->data.x_bignum, container_type->data.array.len); TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; - return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, usize, false); + return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, usize, false, ConstPtrSpecialNone); } else { add_node_error(ira->codegen, source_node, buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), @@ -5570,13 +5580,19 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru if (casted_value == ira->codegen->invalid_instruction) return ira->codegen->builtin_types.entry_invalid; - if (ptr->static_value.special != ConstValSpecialRuntime && - casted_value->static_value.special != ConstValSpecialRuntime) - { - ConstExprValue *dest_val = const_ptr_pointee(&ptr->static_value); - if (dest_val->special != ConstValSpecialRuntime) { - *dest_val = casted_value->static_value; - return ir_analyze_void(ira, &store_ptr_instruction->base); + if (ptr->static_value.special != ConstValSpecialRuntime) { + bool is_inline = (ptr->static_value.data.x_ptr.special == ConstPtrSpecialInline); + if (casted_value->static_value.special != ConstValSpecialRuntime) { + ConstExprValue *dest_val = const_ptr_pointee(&ptr->static_value); + if (dest_val->special != ConstValSpecialRuntime) { + *dest_val = casted_value->static_value; + return ir_analyze_void(ira, &store_ptr_instruction->base); + } + } + if (is_inline) { + ir_add_error(ira, &store_ptr_instruction->base, + buf_sprintf("cannot store runtime value in compile time variable")); + return ira->codegen->builtin_types.entry_invalid; } } diff --git a/src/parser.cpp b/src/parser.cpp index 9e34bc55ab..2f4824ad39 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1306,25 +1306,40 @@ static AstNode *ast_parse_else(ParseContext *pc, size_t *token_index, bool manda /* IfExpression : IfVarExpression | IfBoolExpression -IfBoolExpression : token(If) token(LParen) Expression token(RParen) Expression option(Else) -IfVarExpression = "if" "(" ("const" | "var") option("*") "Symbol" option(":" TypeExpr) "?=" Expression ")" Expression Option(Else) +IfBoolExpression = option("inline") "if" "(" Expression ")" Expression option(Else) +IfVarExpression = option("inline") "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else) */ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory) { - Token *if_tok = &pc->tokens->at(*token_index); - if (if_tok->id != TokenIdKeywordIf) { - if (mandatory) { + Token *first_token = &pc->tokens->at(*token_index); + Token *if_tok; + + bool is_inline; + if (first_token->id == TokenIdKeywordInline) { + if_tok = &pc->tokens->at(*token_index + 1); + if (if_tok->id == TokenIdKeywordIf) { + is_inline = true; + *token_index += 2; + } else if (mandatory) { ast_expect_token(pc, if_tok, TokenIdKeywordIf); } else { return nullptr; } + } else if (first_token->id == TokenIdKeywordIf) { + if_tok = first_token; + is_inline = false; + *token_index += 1; + } else if (mandatory) { + ast_expect_token(pc, first_token, TokenIdKeywordIf); + } else { + return nullptr; } - *token_index += 1; ast_eat_token(pc, token_index, TokenIdLParen); Token *token = &pc->tokens->at(*token_index); if (token->id == TokenIdKeywordConst || token->id == TokenIdKeywordVar) { AstNode *node = ast_create_node(pc, NodeTypeIfVarExpr, if_tok); + node->data.if_var_expr.is_inline = is_inline; node->data.if_var_expr.var_decl.is_const = (token->id == TokenIdKeywordConst); *token_index += 1; @@ -1362,6 +1377,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma return node; } else { AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_tok); + node->data.if_bool_expr.is_inline = is_inline; node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true); ast_eat_token(pc, token_index, TokenIdRParen); node->data.if_bool_expr.then_block = ast_parse_expression(pc, token_index, true); @@ -1561,12 +1577,12 @@ static AstNode *ast_parse_while_expr(ParseContext *pc, size_t *token_index, bool bool is_inline; if (first_token->id == TokenIdKeywordInline) { - is_inline = true; while_token = &pc->tokens->at(*token_index + 1); if (while_token->id == TokenIdKeywordWhile) { + is_inline = true; *token_index += 2; } else if (mandatory) { - ast_expect_token(pc, first_token, TokenIdKeywordWhile); + ast_expect_token(pc, while_token, TokenIdKeywordWhile); } else { return nullptr; } |
