| ... | ... | @@ -459,6 +459,34 @@ static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) { |
| 459 | 459 | return nullptr; |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) { |
| 463 | assert(node->type == NodeTypeFnCallExpr); |
| 464 | |
| 465 | int fn_call_param_count = node->data.fn_call_expr.params.length; |
| 466 | assert(fn_call_param_count == 4); |
| 467 | |
| 468 | TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0)); |
| 469 | assert(int_type->id == TypeTableEntryIdInt); |
| 470 | |
| 471 | LLVMValueRef val1 = gen_expr(g, node->data.fn_call_expr.params.at(1)); |
| 472 | LLVMValueRef val2 = gen_expr(g, node->data.fn_call_expr.params.at(2)); |
| 473 | LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3)); |
| 474 | |
| 475 | set_debug_source_node(g, node); |
| 476 | LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, ""); |
| 477 | LLVMValueRef orig_val; |
| 478 | if (int_type->data.integral.is_signed) { |
| 479 | orig_val = LLVMBuildAShr(g->builder, result, val2, ""); |
| 480 | } else { |
| 481 | orig_val = LLVMBuildLShr(g->builder, result, val2, ""); |
| 482 | } |
| 483 | LLVMValueRef overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, val1, orig_val, ""); |
| 484 | |
| 485 | LLVMBuildStore(g->builder, result, ptr_result); |
| 486 | |
| 487 | return overflow_bit; |
| 488 | } |
| 489 | |
| 462 | 490 | static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 463 | 491 | assert(node->type == NodeTypeFnCallExpr); |
| 464 | 492 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; |
| ... | ... | @@ -527,6 +555,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 527 | 555 | |
| 528 | 556 | return overflow_bit; |
| 529 | 557 | } |
| 558 | case BuiltinFnIdShlWithOverflow: |
| 559 | return gen_shl_with_overflow(g, node); |
| 530 | 560 | case BuiltinFnIdMemcpy: |
| 531 | 561 | { |
| 532 | 562 | int fn_call_param_count = node->data.fn_call_expr.params.length; |
| ... | ... | @@ -4357,6 +4387,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 4357 | 4387 | create_builtin_fn_with_arg_count(g, BuiltinFnIdAddWithOverflow, "add_with_overflow", 4); |
| 4358 | 4388 | create_builtin_fn_with_arg_count(g, BuiltinFnIdSubWithOverflow, "sub_with_overflow", 4); |
| 4359 | 4389 | create_builtin_fn_with_arg_count(g, BuiltinFnIdMulWithOverflow, "mul_with_overflow", 4); |
| 4390 | create_builtin_fn_with_arg_count(g, BuiltinFnIdShlWithOverflow, "shl_with_overflow", 4); |
| 4360 | 4391 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCInclude, "c_include", 1); |
| 4361 | 4392 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2); |
| 4362 | 4393 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "c_undef", 1); |