diff options
| author | Vexu <git@vexu.eu> | 2020-03-11 16:46:12 +0200 |
|---|---|---|
| committer | Vexu <git@vexu.eu> | 2020-03-11 16:48:18 +0200 |
| commit | 9262f065f50db3ea72454b6c1b9b66fd911aa6ba (patch) | |
| tree | 79ccf2cc6b2f06fd87545ebc252c8403bd82357c /src/codegen.cpp | |
| parent | ec906a97712b329694e8f2e1a35b50b75d052642 (diff) | |
| download | zig-9262f065f50db3ea72454b6c1b9b66fd911aa6ba.tar.gz zig-9262f065f50db3ea72454b6c1b9b66fd911aa6ba.zip | |
Move abi size checking to codegen
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 66cf919d88..55713c1b88 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5219,18 +5219,48 @@ static enum ZigLLVM_AtomicRMWBinOp to_ZigLLVMAtomicRMWBinOp(AtomicRmwOp op, bool zig_unreachable(); } +static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) { + // If the operand type of an atomic operation is not a power of two sized + // we need to widen it before using it and then truncate the result. + + ir_assert(instruction->value->type->id == ZigTypeIdPointer, instruction); + ZigType *operand_type = instruction->value->type->data.pointer.child_type; + if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) { + if (operand_type->id == ZigTypeIdEnum) { + operand_type = operand_type->data.enumeration.tag_int_type; + } + auto bit_count = operand_type->data.integral.bit_count; + bool is_signed = operand_type->data.integral.is_signed; + + ir_assert(bit_count != 0, instruction); + if (bit_count == 1 || !is_power_of_2(bit_count)) { + return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8)); + } else { + return nullptr; + } + } else if (operand_type->id == ZigTypeIdFloat) { + return nullptr; + } else if (operand_type->id == ZigTypeIdBool) { + return g->builtin_types.entry_u8->llvm_type; + } else { + ir_assert(get_codegen_ptr_type_bail(g, operand_type) != nullptr, instruction); + return nullptr; + } +} + static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, IrInstGenCmpxchg *instruction) { LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value); ZigType *operand_type = instruction->new_value->value->type; - if (instruction->actual_type != nullptr) { + LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr); + if (actual_abi_type != nullptr) { // operand needs widening and truncating ptr_val = LLVMBuildBitCast(g->builder, ptr_val, - LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), ""); - cmp_val = LLVMBuildZExt(g->builder, cmp_val, get_llvm_type(g, instruction->actual_type), ""); - new_val = LLVMBuildZExt(g->builder, new_val, get_llvm_type(g, instruction->actual_type), ""); + LLVMPointerType(actual_abi_type, 0), ""); + cmp_val = LLVMBuildZExt(g->builder, cmp_val, actual_abi_type, ""); + new_val = LLVMBuildZExt(g->builder, new_val, actual_abi_type, ""); } LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order); @@ -5245,7 +5275,7 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I if (!handle_is_ptr(g, optional_type)) { LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); - if (instruction->actual_type != nullptr) { + if (actual_abi_type != nullptr) { payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), ""); } LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); @@ -5262,7 +5292,7 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I ir_assert(type_has_bits(g, child_type), &instruction->base); LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); - if (instruction->actual_type != nullptr) { + if (actual_abi_type != nullptr) { payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), ""); } LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); @@ -5842,11 +5872,12 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); LLVMValueRef operand = ir_llvm_value(g, instruction->operand); - if (instruction->actual_type != nullptr) { + LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr); + if (actual_abi_type != nullptr) { // operand needs widening and truncating LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr, - LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), ""); - LLVMValueRef casted_operand = LLVMBuildZExt(g->builder, operand, get_llvm_type(g, instruction->actual_type), ""); + LLVMPointerType(actual_abi_type, 0), ""); + LLVMValueRef casted_operand = LLVMBuildZExt(g->builder, operand, actual_abi_type, ""); LLVMValueRef uncasted_result = ZigLLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering, g->is_single_threaded); return LLVMBuildTrunc(g->builder, uncasted_result, get_llvm_type(g, operand_type), ""); @@ -5872,10 +5903,11 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executabl LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); ZigType *operand_type = instruction->ptr->value->type->data.pointer.child_type; - if (instruction->actual_type != nullptr) { + LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr); + if (actual_abi_type != nullptr) { // operand needs widening and truncating ptr = LLVMBuildBitCast(g->builder, ptr, - LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), ""); + LLVMPointerType(actual_abi_type, 0), ""); LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, ""); LLVMSetOrdering(load_inst, ordering); return LLVMBuildTrunc(g->builder, load_inst, get_llvm_type(g, operand_type), ""); @@ -5892,11 +5924,12 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); LLVMValueRef value = ir_llvm_value(g, instruction->value); - if (instruction->actual_type != nullptr) { + LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr); + if (actual_abi_type != nullptr) { // operand needs widening ptr = LLVMBuildBitCast(g->builder, ptr, - LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), ""); - value = LLVMBuildZExt(g->builder, value, get_llvm_type(g, instruction->actual_type), ""); + LLVMPointerType(actual_abi_type, 0), ""); + value = LLVMBuildZExt(g->builder, value, actual_abi_type, ""); } LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type); LLVMSetOrdering(store_inst, ordering); |
