authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-05-06 16:44:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-05-06 16:45:04-07:00
log9db45ac36230c80c68af7b66827b6c73fc96c147
tree5311f0444151c2eb586538245a543b8acd4d572b
parent100802cdc0a898b948d30b464ac2348be1928080

add shl_with_overflow builtin function

See #46

5 files changed, 42 insertions(+), 0 deletions(-)

src/all_types.hpp+1
...@@ -1104,6 +1104,7 @@ enum BuiltinFnId {...@@ -1104,6 +1104,7 @@ enum BuiltinFnId {
1104 BuiltinFnIdAddWithOverflow,1104 BuiltinFnIdAddWithOverflow,
1105 BuiltinFnIdSubWithOverflow,1105 BuiltinFnIdSubWithOverflow,
1106 BuiltinFnIdMulWithOverflow,1106 BuiltinFnIdMulWithOverflow,
1107 BuiltinFnIdShlWithOverflow,
1107 BuiltinFnIdCInclude,1108 BuiltinFnIdCInclude,
1108 BuiltinFnIdCDefine,1109 BuiltinFnIdCDefine,
1109 BuiltinFnIdCUndef,1110 BuiltinFnIdCUndef,
src/analyze.cpp+1
...@@ -4546,6 +4546,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -4546,6 +4546,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
4546 case BuiltinFnIdAddWithOverflow:4546 case BuiltinFnIdAddWithOverflow:
4547 case BuiltinFnIdSubWithOverflow:4547 case BuiltinFnIdSubWithOverflow:
4548 case BuiltinFnIdMulWithOverflow:4548 case BuiltinFnIdMulWithOverflow:
4549 case BuiltinFnIdShlWithOverflow:
4549 {4550 {
4550 AstNode *type_node = node->data.fn_call_expr.params.at(0);4551 AstNode *type_node = node->data.fn_call_expr.params.at(0);
4551 TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);4552 TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
src/codegen.cpp+31
...@@ -459,6 +459,34 @@ static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) {...@@ -459,6 +459,34 @@ static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) {
459 return nullptr;459 return nullptr;
460}460}
461461
462static 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
462static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {490static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
463 assert(node->type == NodeTypeFnCallExpr);491 assert(node->type == NodeTypeFnCallExpr);
464 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;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,6 +555,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
527555
528 return overflow_bit;556 return overflow_bit;
529 }557 }
558 case BuiltinFnIdShlWithOverflow:
559 return gen_shl_with_overflow(g, node);
530 case BuiltinFnIdMemcpy:560 case BuiltinFnIdMemcpy:
531 {561 {
532 int fn_call_param_count = node->data.fn_call_expr.params.length;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,6 +4387,7 @@ static void define_builtin_fns(CodeGen *g) {
4357 create_builtin_fn_with_arg_count(g, BuiltinFnIdAddWithOverflow, "add_with_overflow", 4);4387 create_builtin_fn_with_arg_count(g, BuiltinFnIdAddWithOverflow, "add_with_overflow", 4);
4358 create_builtin_fn_with_arg_count(g, BuiltinFnIdSubWithOverflow, "sub_with_overflow", 4);4388 create_builtin_fn_with_arg_count(g, BuiltinFnIdSubWithOverflow, "sub_with_overflow", 4);
4359 create_builtin_fn_with_arg_count(g, BuiltinFnIdMulWithOverflow, "mul_with_overflow", 4);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 create_builtin_fn_with_arg_count(g, BuiltinFnIdCInclude, "c_include", 1);4391 create_builtin_fn_with_arg_count(g, BuiltinFnIdCInclude, "c_include", 1);
4361 create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2);4392 create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2);
4362 create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "c_undef", 1);4393 create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "c_undef", 1);
src/eval.cpp+1
...@@ -707,6 +707,7 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_...@@ -707,6 +707,7 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_
707 case BuiltinFnIdErrName:707 case BuiltinFnIdErrName:
708 case BuiltinFnIdEmbedFile:708 case BuiltinFnIdEmbedFile:
709 case BuiltinFnIdCmpExchange:709 case BuiltinFnIdCmpExchange:
710 case BuiltinFnIdShlWithOverflow:
710 zig_panic("TODO");711 zig_panic("TODO");
711 case BuiltinFnIdBreakpoint:712 case BuiltinFnIdBreakpoint:
712 case BuiltinFnIdInvalid:713 case BuiltinFnIdInvalid:
test/self_hosted.zig+8
...@@ -1522,3 +1522,11 @@ fn test_shl_wrapping_noeval(x: u16w) {...@@ -1522,3 +1522,11 @@ fn test_shl_wrapping_noeval(x: u16w) {
1522 x_u16 <<= 1;1522 x_u16 <<= 1;
1523 assert(x_u16 == 65534);1523 assert(x_u16 == 65534);
1524}1524}
1525
1526#attribute("test")
1527fn shl_with_overflow() {
1528 var result: u16 = undefined;
1529 assert(@shl_with_overflow(u16, 0b0010111111111111, 3, &result));
1530 assert(!@shl_with_overflow(u16, 0b0010111111111111, 2, &result));
1531 assert(result == 0b1011111111111100);
1532}