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 {
11041104 BuiltinFnIdAddWithOverflow,
11051105 BuiltinFnIdSubWithOverflow,
11061106 BuiltinFnIdMulWithOverflow,
1107 BuiltinFnIdShlWithOverflow,
11071108 BuiltinFnIdCInclude,
11081109 BuiltinFnIdCDefine,
11091110 BuiltinFnIdCUndef,
src/analyze.cpp+1
......@@ -4546,6 +4546,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
45464546 case BuiltinFnIdAddWithOverflow:
45474547 case BuiltinFnIdSubWithOverflow:
45484548 case BuiltinFnIdMulWithOverflow:
4549 case BuiltinFnIdShlWithOverflow:
45494550 {
45504551 AstNode *type_node = node->data.fn_call_expr.params.at(0);
45514552 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) {
459459 return nullptr;
460460}
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
462490static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
463491 assert(node->type == NodeTypeFnCallExpr);
464492 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) {
527555
528556 return overflow_bit;
529557 }
558 case BuiltinFnIdShlWithOverflow:
559 return gen_shl_with_overflow(g, node);
530560 case BuiltinFnIdMemcpy:
531561 {
532562 int fn_call_param_count = node->data.fn_call_expr.params.length;
......@@ -4357,6 +4387,7 @@ static void define_builtin_fns(CodeGen *g) {
43574387 create_builtin_fn_with_arg_count(g, BuiltinFnIdAddWithOverflow, "add_with_overflow", 4);
43584388 create_builtin_fn_with_arg_count(g, BuiltinFnIdSubWithOverflow, "sub_with_overflow", 4);
43594389 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);
43604391 create_builtin_fn_with_arg_count(g, BuiltinFnIdCInclude, "c_include", 1);
43614392 create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2);
43624393 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_
707707 case BuiltinFnIdErrName:
708708 case BuiltinFnIdEmbedFile:
709709 case BuiltinFnIdCmpExchange:
710 case BuiltinFnIdShlWithOverflow:
710711 zig_panic("TODO");
711712 case BuiltinFnIdBreakpoint:
712713 case BuiltinFnIdInvalid:
test/self_hosted.zig+8
......@@ -1522,3 +1522,11 @@ fn test_shl_wrapping_noeval(x: u16w) {
15221522 x_u16 <<= 1;
15231523 assert(x_u16 == 65534);
15241524}
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}