aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-08-04 15:19:03 -0400
committerAndrew Kelley <superjoe30@gmail.com>2018-08-04 15:19:03 -0400
commitb48948d6e805cdee7f33243098af9a862c152df1 (patch)
tree8b1b4b37670f7444e8fe12748a8db99ac7498cce /src
parentf804310d9f953c9d78a4271ba8d75133341840e6 (diff)
parent9bd8b01650f9cf21e601117951711b21aa5fd216 (diff)
downloadzig-b48948d6e805cdee7f33243098af9a862c152df1.tar.gz
zig-b48948d6e805cdee7f33243098af9a862c152df1.zip
Merge branch 'master' into llvm7
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp8
-rw-r--r--src/ast_render.cpp3
-rw-r--r--src/codegen.cpp24
-rw-r--r--src/ir.cpp78
-rw-r--r--src/ir_print.cpp7
-rw-r--r--src/parser.cpp25
6 files changed, 111 insertions, 34 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 0d9e2e1bf4..e930b84e6d 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -899,7 +899,6 @@ struct AstNodeAwaitExpr {
struct AstNodeSuspend {
AstNode *block;
- AstNode *promise_symbol;
};
struct AstNodePromiseType {
@@ -1358,6 +1357,7 @@ enum BuiltinFnId {
BuiltinFnIdBreakpoint,
BuiltinFnIdReturnAddress,
BuiltinFnIdFrameAddress,
+ BuiltinFnIdHandle,
BuiltinFnIdEmbedFile,
BuiltinFnIdCmpxchgWeak,
BuiltinFnIdCmpxchgStrong,
@@ -1714,6 +1714,7 @@ struct CodeGen {
LLVMValueRef coro_save_fn_val;
LLVMValueRef coro_promise_fn_val;
LLVMValueRef coro_alloc_helper_fn_val;
+ LLVMValueRef coro_frame_fn_val;
LLVMValueRef merge_err_ret_traces_fn_val;
LLVMValueRef add_error_return_trace_addr_fn_val;
LLVMValueRef stacksave_fn_val;
@@ -2074,6 +2075,7 @@ enum IrInstructionId {
IrInstructionIdBreakpoint,
IrInstructionIdReturnAddress,
IrInstructionIdFrameAddress,
+ IrInstructionIdHandle,
IrInstructionIdAlignOf,
IrInstructionIdOverflowOp,
IrInstructionIdTestErr,
@@ -2791,6 +2793,10 @@ struct IrInstructionFrameAddress {
IrInstruction base;
};
+struct IrInstructionHandle {
+ IrInstruction base;
+};
+
enum IrOverflowOp {
IrOverflowOpAdd,
IrOverflowOpSub,
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 2ace00885d..984b4230b1 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -1112,9 +1112,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
{
fprintf(ar->f, "suspend");
if (node->data.suspend.block != nullptr) {
- fprintf(ar->f, " |");
- render_node_grouped(ar, node->data.suspend.promise_symbol);
- fprintf(ar->f, "| ");
render_node_grouped(ar, node->data.suspend.block);
}
break;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index c288af4273..c9c80ede6d 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4057,6 +4057,26 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable
return LLVMBuildCall(g->builder, get_frame_address_fn_val(g), &zero, 1, "");
}
+static LLVMValueRef get_handle_fn_val(CodeGen *g) {
+ if (g->coro_frame_fn_val)
+ return g->coro_frame_fn_val;
+
+ LLVMTypeRef fn_type = LLVMFunctionType( LLVMPointerType(LLVMInt8Type(), 0)
+ , nullptr, 0, false);
+ Buf *name = buf_sprintf("llvm.coro.frame");
+ g->coro_frame_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
+ assert(LLVMGetIntrinsicID(g->coro_frame_fn_val));
+
+ return g->coro_frame_fn_val;
+}
+
+static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable,
+ IrInstructionHandle *instruction)
+{
+ LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_promise->type_ref);
+ return LLVMBuildCall(g->builder, get_handle_fn_val(g), &zero, 0, "");
+}
+
static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {
TypeTableEntry *int_type = instruction->result_ptr_type;
assert(int_type->id == TypeTableEntryIdInt);
@@ -4821,6 +4841,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_return_address(g, executable, (IrInstructionReturnAddress *)instruction);
case IrInstructionIdFrameAddress:
return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction);
+ case IrInstructionIdHandle:
+ return ir_render_handle(g, executable, (IrInstructionHandle *)instruction);
case IrInstructionIdOverflowOp:
return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
case IrInstructionIdTestErr:
@@ -5916,6 +5938,7 @@ static void do_code_gen(CodeGen *g) {
ir_render(g, fn_table_entry);
}
+
assert(!g->errors.length);
if (buf_len(&g->global_asm) != 0) {
@@ -6255,6 +6278,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdBreakpoint, "breakpoint", 0);
create_builtin_fn(g, BuiltinFnIdReturnAddress, "returnAddress", 0);
create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);
+ create_builtin_fn(g, BuiltinFnIdHandle, "handle", 0);
create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3);
create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3);
create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1);
diff --git a/src/ir.cpp b/src/ir.cpp
index 699baa152e..3e423487aa 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -580,6 +580,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *)
return IrInstructionIdFrameAddress;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionHandle *) {
+ return IrInstructionIdHandle;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {
return IrInstructionIdAlignOf;
}
@@ -2240,6 +2244,17 @@ static IrInstruction *ir_build_frame_address_from(IrBuilder *irb, IrInstruction
return new_instruction;
}
+static IrInstruction *ir_build_handle(IrBuilder *irb, Scope *scope, AstNode *source_node) {
+ IrInstructionHandle *instruction = ir_build_instruction<IrInstructionHandle>(irb, scope, source_node);
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_handle_from(IrBuilder *irb, IrInstruction *old_instruction) {
+ IrInstruction *new_instruction = ir_build_handle(irb, old_instruction->scope, old_instruction->source_node);
+ ir_link_new_instruction(new_instruction, old_instruction);
+ return new_instruction;
+}
+
static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2,
IrInstruction *result_ptr, TypeTableEntry *result_ptr_type)
@@ -3317,7 +3332,15 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco
static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *name,
bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime)
{
- VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name, src_is_const, gen_is_const, is_shadowable, is_comptime);
+ bool is_underscored = name ? buf_eql_str(name, "_") : false;
+ VariableTableEntry *var = create_local_var( irb->codegen
+ , node
+ , scope
+ , (is_underscored ? nullptr : name)
+ , src_is_const
+ , gen_is_const
+ , (is_underscored ? true : is_shadowable)
+ , is_comptime );
if (is_comptime != nullptr || gen_is_const) {
var->mem_slot_index = exec_next_mem_slot(irb->exec);
var->owner_exec = irb->exec;
@@ -3843,6 +3866,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return irb->codegen->invalid_instruction;
}
+ bool is_async = exec_is_async(irb->exec);
+
switch (builtin_fn->id) {
case BuiltinFnIdInvalid:
zig_unreachable();
@@ -4475,6 +4500,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval);
case BuiltinFnIdFrameAddress:
return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval);
+ case BuiltinFnIdHandle:
+ if (!irb->exec->fn_entry) {
+ add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition"));
+ return irb->codegen->invalid_instruction;
+ }
+ if (!is_async) {
+ add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function"));
+ return irb->codegen->invalid_instruction;
+ }
+ return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval);
case BuiltinFnIdAlignOf:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -5159,6 +5194,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;
+ if (buf_eql_str(variable_declaration->symbol, "_")) {
+ add_node_error(irb->codegen, node, buf_sprintf("`_` is not a declarable symbol"));
+ return irb->codegen->invalid_instruction;
+ }
+
IrInstruction *type_instruction;
if (variable_declaration->type != nullptr) {
type_instruction = ir_gen_node(irb, variable_declaration->type, scope);
@@ -5171,6 +5211,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
bool is_shadowable = false;
bool is_const = variable_declaration->is_const;
bool is_extern = variable_declaration->is_extern;
+
IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
@@ -7069,19 +7110,8 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
if (node->data.suspend.block == nullptr) {
suspend_code = ir_build_coro_suspend(irb, parent_scope, node, nullptr, const_bool_false);
} else {
- assert(node->data.suspend.promise_symbol != nullptr);
- assert(node->data.suspend.promise_symbol->type == NodeTypeSymbol);
- Buf *promise_symbol_name = node->data.suspend.promise_symbol->data.symbol_expr.symbol;
Scope *child_scope;
- if (!buf_eql_str(promise_symbol_name, "_")) {
- VariableTableEntry *promise_var = ir_create_var(irb, node, parent_scope, promise_symbol_name,
- true, true, false, const_bool_false);
- ir_build_var_decl(irb, parent_scope, node, promise_var, nullptr, nullptr, irb->exec->coro_handle);
- child_scope = promise_var->child_scope;
- } else {
- child_scope = parent_scope;
- }
- ScopeSuspend *suspend_scope = create_suspend_scope(node, child_scope);
+ ScopeSuspend *suspend_scope = create_suspend_scope(node, parent_scope);
suspend_scope->resume_block = resume_block;
child_scope = &suspend_scope->base;
IrInstruction *save_token = ir_build_coro_save(irb, child_scope, node, irb->exec->coro_handle);
@@ -9598,6 +9628,9 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
case ConstValSpecialStatic:
return &value->value;
case ConstValSpecialRuntime:
+ if (!type_has_bits(value->value.type)) {
+ return &value->value;
+ }
ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression"));
return nullptr;
case ConstValSpecialUndef:
@@ -16099,8 +16132,14 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir
if (casted_field_value == ira->codegen->invalid_instruction)
return ira->codegen->builtin_types.entry_invalid;
+ type_ensure_zero_bits_known(ira->codegen, casted_field_value->value.type);
+ if (type_is_invalid(casted_field_value->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);
- if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {
+ if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
+ !type_has_bits(casted_field_value->value.type))
+ {
ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
if (!field_val)
return ira->codegen->builtin_types.entry_invalid;
@@ -19007,6 +19046,14 @@ static TypeTableEntry *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIn
return u8_ptr_const;
}
+static TypeTableEntry *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) {
+ ir_build_handle_from(&ira->new_irb, &instruction->base);
+
+ FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
+ assert(fn_entry != nullptr);
+ return get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type);
+}
+
static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
IrInstruction *type_value = instruction->type_value->other;
if (type_is_invalid(type_value->value.type))
@@ -20982,6 +21029,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction);
case IrInstructionIdFrameAddress:
return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction);
+ case IrInstructionIdHandle:
+ return ir_analyze_instruction_handle(ira, (IrInstructionHandle *)instruction);
case IrInstructionIdAlignOf:
return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
case IrInstructionIdOverflowOp:
@@ -21274,6 +21323,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdAlignOf:
case IrInstructionIdReturnAddress:
case IrInstructionIdFrameAddress:
+ case IrInstructionIdHandle:
case IrInstructionIdTestErr:
case IrInstructionIdUnwrapErrCode:
case IrInstructionIdOptionalWrap:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 127afa94a5..77c7ef47b6 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -791,6 +791,10 @@ static void ir_print_frame_address(IrPrint *irp, IrInstructionFrameAddress *inst
fprintf(irp->f, "@frameAddress()");
}
+static void ir_print_handle(IrPrint *irp, IrInstructionHandle *instruction) {
+ fprintf(irp->f, "@handle()");
+}
+
static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) {
fprintf(irp->f, "@returnAddress()");
}
@@ -1556,6 +1560,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdFrameAddress:
ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction);
break;
+ case IrInstructionIdHandle:
+ ir_print_handle(irp, (IrInstructionHandle *)instruction);
+ break;
case IrInstructionIdAlignOf:
ir_print_align_of(irp, (IrInstructionAlignOf *)instruction);
break;
diff --git a/src/parser.cpp b/src/parser.cpp
index a93d8de830..453ab7ce2c 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -648,12 +648,11 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, size_t *token_index, bool m
}
/*
-SuspendExpression(body) = "suspend" option(("|" Symbol "|" body))
+SuspendExpression(body) = "suspend" option( body )
*/
static AstNode *ast_parse_suspend_block(ParseContext *pc, size_t *token_index, bool mandatory) {
- size_t orig_token_index = *token_index;
-
Token *suspend_token = &pc->tokens->at(*token_index);
+
if (suspend_token->id == TokenIdKeywordSuspend) {
*token_index += 1;
} else if (mandatory) {
@@ -663,23 +662,18 @@ static AstNode *ast_parse_suspend_block(ParseContext *pc, size_t *token_index, b
return nullptr;
}
- Token *bar_token = &pc->tokens->at(*token_index);
- if (bar_token->id == TokenIdBinOr) {
- *token_index += 1;
+ Token *lbrace = &pc->tokens->at(*token_index);
+ if (lbrace->id == TokenIdLBrace) {
+ AstNode *node = ast_create_node(pc, NodeTypeSuspend, suspend_token);
+ node->data.suspend.block = ast_parse_block(pc, token_index, true);
+ return node;
} else if (mandatory) {
- ast_expect_token(pc, suspend_token, TokenIdBinOr);
+ ast_expect_token(pc, lbrace, TokenIdLBrace);
zig_unreachable();
} else {
- *token_index = orig_token_index;
+ *token_index -= 1;
return nullptr;
}
-
- AstNode *node = ast_create_node(pc, NodeTypeSuspend, suspend_token);
- node->data.suspend.promise_symbol = ast_parse_symbol(pc, token_index);
- ast_eat_token(pc, token_index, TokenIdBinOr);
- node->data.suspend.block = ast_parse_block(pc, token_index, true);
-
- return node;
}
/*
@@ -3134,7 +3128,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.await_expr.expr, visit, context);
break;
case NodeTypeSuspend:
- visit_field(&node->data.suspend.promise_symbol, visit, context);
visit_field(&node->data.suspend.block, visit, context);
break;
}