From c6227661568a9e8cad9d28bd7a11cb76c4f9c1c1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 28 Feb 2018 21:48:20 -0500 Subject: [PATCH] async function fulfills promise atomically --- src/codegen.cpp | 17 ++++++++++++++--- src/ir.cpp | 24 +++++++++++++++++++----- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 89dc23f428..315699b826 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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) { diff --git a/src/ir.cpp b/src/ir.cpp index dcca05ad02..dc845bdaf7 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -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) {