async function fulfills promise atomically

master
Andrew Kelley 2018-02-28 21:48:20 -05:00
parent 807a5e94e9
commit c622766156
2 changed files with 33 additions and 8 deletions

View File

@ -4132,8 +4132,9 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,
IrInstructionAtomicRmw *instruction)
{
bool is_signed;
if (instruction->operand->value.type->id == TypeTableEntryIdInt) {
is_signed = instruction->operand->value.type->data.integral.is_signed;
TypeTableEntry *operand_type = instruction->operand->value.type;
if (operand_type->id == TypeTableEntryIdInt) {
is_signed = operand_type->data.integral.is_signed;
} else {
is_signed = false;
}
@ -4141,7 +4142,17 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,
LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering);
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
return LLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, false);
if (get_codegen_ptr_type(operand_type) == nullptr) {
return LLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, false);
}
// it's a pointer but we need to treat it as an int
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
LLVMPointerType(g->builtin_types.entry_usize->type_ref, 0), "");
LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_usize->type_ref, "");
LLVMValueRef uncasted_result = LLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering, false);
return LLVMBuildIntToPtr(g->builder, uncasted_result, operand_type->type_ref, "");
}
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {

View File

@ -2727,7 +2727,13 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
ir_build_store_ptr(irb, scope, node, result_ptr, return_value);
}
IrInstruction *maybe_await_handle = ir_build_load_ptr(irb, scope, node, irb->exec->coro_awaiter_field_ptr);
IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node,
get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
// TODO replace replacement_value with @intToPtr(?promise, 0x1) when it doesn't crash zig
IrInstruction *replacement_value = irb->exec->coro_handle;
IrInstruction *maybe_await_handle = ir_build_atomic_rmw(irb, scope, node,
promise_type_val, irb->exec->coro_awaiter_field_ptr, nullptr, replacement_value, nullptr,
AtomicRmwOp_xchg, AtomicOrderSeqCst);
IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_await_handle);
IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false);
return ir_build_cond_br(irb, scope, node, is_non_null, irb->exec->coro_normal_final, irb->exec->coro_early_final,
@ -17433,8 +17439,12 @@ static TypeTableEntry *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstr
return ira->codegen->builtin_types.entry_invalid;
AtomicRmwOp op;
if (!ir_resolve_atomic_rmw_op(ira, instruction->op->other, &op)) {
return ira->codegen->builtin_types.entry_invalid;
if (instruction->op == nullptr) {
op = instruction->resolved_op;
} else {
if (!ir_resolve_atomic_rmw_op(ira, instruction->op->other, &op)) {
return ira->codegen->builtin_types.entry_invalid;
}
}
IrInstruction *operand = instruction->operand->other;
@ -17446,8 +17456,12 @@ static TypeTableEntry *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstr
return ira->codegen->builtin_types.entry_invalid;
AtomicOrder ordering;
if (!ir_resolve_atomic_order(ira, instruction->ordering->other, &ordering))
return ira->codegen->builtin_types.entry_invalid;
if (instruction->ordering == nullptr) {
ordering = instruction->resolved_ordering;
} else {
if (!ir_resolve_atomic_order(ira, instruction->ordering->other, &ordering))
return ira->codegen->builtin_types.entry_invalid;
}
if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
{