| ... | ... | @@ -440,7 +440,7 @@ static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) { |
| 440 | 440 | LLVMAtomicOrdering failure_order = to_LLVMAtomicOrdering((AtomicOrder)failure_order_val->data.x_enum.tag); |
| 441 | 441 | |
| 442 | 442 | LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val, |
| 443 | | success_order, failure_order, ""); |
| 443 | success_order, failure_order); |
| 444 | 444 | |
| 445 | 445 | return LLVMBuildExtractValue(g->builder, result_val, 1, ""); |
| 446 | 446 | } |
| ... | ... | @@ -1309,6 +1309,36 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddS |
| 1309 | 1309 | return result; |
| 1310 | 1310 | } |
| 1311 | 1311 | |
| 1312 | static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry, |
| 1313 | LLVMValueRef val1, LLVMValueRef val2) |
| 1314 | { |
| 1315 | // for unsigned left shifting, we do the wrapping shift, then logically shift |
| 1316 | // right the same number of bits |
| 1317 | // if the values don't match, we have an overflow |
| 1318 | // for signed left shifting we do the same except arithmetic shift right |
| 1319 | |
| 1320 | assert(type_entry->id == TypeTableEntryIdInt); |
| 1321 | |
| 1322 | LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, ""); |
| 1323 | LLVMValueRef orig_val; |
| 1324 | if (type_entry->data.integral.is_signed) { |
| 1325 | orig_val = LLVMBuildAShr(g->builder, result, val2, ""); |
| 1326 | } else { |
| 1327 | orig_val = LLVMBuildLShr(g->builder, result, val2, ""); |
| 1328 | } |
| 1329 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, orig_val, ""); |
| 1330 | |
| 1331 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk"); |
| 1332 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail"); |
| 1333 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 1334 | |
| 1335 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 1336 | gen_debug_safety_crash(g); |
| 1337 | |
| 1338 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1339 | return result; |
| 1340 | } |
| 1341 | |
| 1312 | 1342 | static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1313 | 1343 | assert(node->type == NodeTypePrefixOpExpr); |
| 1314 | 1344 | assert(node->data.prefix_op_expr.primary_expr); |
| ... | ... | @@ -1484,7 +1514,16 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1484 | 1514 | case BinOpTypeBitShiftLeft: |
| 1485 | 1515 | case BinOpTypeAssignBitShiftLeft: |
| 1486 | 1516 | set_debug_source_node(g, source_node); |
| 1487 | | return LLVMBuildShl(g->builder, val1, val2, ""); |
| 1517 | assert(op1_type->id == TypeTableEntryIdInt); |
| 1518 | if (op1_type->data.integral.is_wrapping) { |
| 1519 | return LLVMBuildShl(g->builder, val1, val2, ""); |
| 1520 | } else if (want_debug_safety(g, source_node)) { |
| 1521 | return gen_overflow_shl_op(g, op1_type, val1, val2); |
| 1522 | } else if (op1_type->data.integral.is_signed) { |
| 1523 | return ZigLLVMBuildNSWShl(g->builder, val1, val2, ""); |
| 1524 | } else { |
| 1525 | return ZigLLVMBuildNUWShl(g->builder, val1, val2, ""); |
| 1526 | } |
| 1488 | 1527 | case BinOpTypeBitShiftRight: |
| 1489 | 1528 | case BinOpTypeAssignBitShiftRight: |
| 1490 | 1529 | assert(op1_type->id == TypeTableEntryIdInt); |