@@ -8252,12 +8252,16 @@ Builtin_call_expression::Builtin_call_expression(Gogo* gogo,
8252
8252
this->code_ = BUILTIN_REAL;
8253
8253
else if (name == "recover")
8254
8254
this->code_ = BUILTIN_RECOVER;
8255
+ else if (name == "Add")
8256
+ this->code_ = BUILTIN_ADD;
8255
8257
else if (name == "Alignof")
8256
8258
this->code_ = BUILTIN_ALIGNOF;
8257
8259
else if (name == "Offsetof")
8258
8260
this->code_ = BUILTIN_OFFSETOF;
8259
8261
else if (name == "Sizeof")
8260
8262
this->code_ = BUILTIN_SIZEOF;
8263
+ else if (name == "Slice")
8264
+ this->code_ = BUILTIN_SLICE;
8261
8265
else
8262
8266
go_unreachable();
8263
8267
}
@@ -8694,6 +8698,119 @@ Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function,
8694
8698
8695
8699
return Runtime::make_call(code, loc, 3, e1, e2, e3);
8696
8700
}
8701
+
8702
+ case BUILTIN_ADD:
8703
+ {
8704
+ Expression* ptr = this->args()->front();
8705
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
8706
+ ptr = Expression::make_cast(uintptr_type, ptr, loc);
8707
+ Expression* len = this->args()->back();
8708
+ len = Expression::make_cast(uintptr_type, len, loc);
8709
+ Expression* add = Expression::make_binary(OPERATOR_PLUS, ptr, len,
8710
+ loc);
8711
+ return Expression::make_cast(this->args()->front()->type(), add, loc);
8712
+ }
8713
+
8714
+ case BUILTIN_SLICE:
8715
+ {
8716
+ Expression* ptr = this->args()->front();
8717
+ Temporary_statement* ptr_temp = NULL;
8718
+ if (!ptr->is_multi_eval_safe())
8719
+ {
8720
+ ptr_temp = Statement::make_temporary(NULL, ptr, loc);
8721
+ inserter->insert(ptr_temp);
8722
+ ptr = Expression::make_temporary_reference(ptr_temp, loc);
8723
+ }
8724
+
8725
+ Expression* len = this->args()->back();
8726
+ Temporary_statement* len_temp = NULL;
8727
+ if (!len->is_multi_eval_safe())
8728
+ {
8729
+ len_temp = Statement::make_temporary(NULL, len, loc);
8730
+ inserter->insert(len_temp);
8731
+ len = Expression::make_temporary_reference(len_temp, loc);
8732
+ }
8733
+
8734
+ bool fits_in_int;
8735
+ Numeric_constant nc;
8736
+ if (this->args()->back()->numeric_constant_value(&nc))
8737
+ {
8738
+ // We gave an error for constants that don't fit in int in
8739
+ // check_types.
8740
+ fits_in_int = true;
8741
+ }
8742
+ else
8743
+ {
8744
+ Integer_type* itype = this->args()->back()->type()->integer_type();
8745
+ go_assert(itype != NULL);
8746
+ int ebits = itype->bits();
8747
+ int intbits =
8748
+ Type::lookup_integer_type("int")->integer_type()->bits();
8749
+
8750
+ // We can treat ebits == intbits as small even for an
8751
+ // unsigned integer type, because we will convert the
8752
+ // value to int and then reject it in the runtime if it is
8753
+ // negative.
8754
+
8755
+ fits_in_int = ebits <= intbits;
8756
+ }
8757
+
8758
+ Runtime::Function code = (fits_in_int
8759
+ ? Runtime::UNSAFESLICE
8760
+ : Runtime::UNSAFESLICE64);
8761
+ Expression* td =
8762
+ Expression::make_type_descriptor(ptr->type()->points_to(), loc);
8763
+ Expression* check = Runtime::make_call(code, loc, 3,
8764
+ td, ptr, len);
8765
+
8766
+ if (ptr_temp == NULL)
8767
+ ptr = ptr->copy();
8768
+ else
8769
+ ptr = Expression::make_temporary_reference(ptr_temp, loc);
8770
+ Expression* nil = Expression::make_nil(loc);
8771
+ nil = Expression::make_cast(ptr->type(), nil, loc);
8772
+ Expression* is_nil = Expression::make_binary(OPERATOR_EQEQ, ptr, nil,
8773
+ loc);
8774
+
8775
+ if (len_temp == NULL)
8776
+ len = len->copy();
8777
+ else
8778
+ len = Expression::make_temporary_reference(len_temp, loc);
8779
+ Expression* zero = Expression::make_integer_ul(0, len->type(), loc);
8780
+ Expression* is_zero = Expression::make_binary(OPERATOR_EQEQ, len, zero,
8781
+ loc);
8782
+
8783
+ Expression* cond = Expression::make_binary(OPERATOR_ANDAND, is_nil,
8784
+ is_zero, loc);
8785
+
8786
+ Type* slice_type = Type::make_array_type(ptr->type()->points_to(),
8787
+ NULL);
8788
+ nil = Expression::make_nil(loc);
8789
+ Expression* nil_slice = Expression::make_cast(slice_type, nil, loc);
8790
+
8791
+ if (ptr_temp == NULL)
8792
+ ptr = ptr->copy();
8793
+ else
8794
+ ptr = Expression::make_temporary_reference(ptr_temp, loc);
8795
+
8796
+ if (len_temp == NULL)
8797
+ len = len->copy();
8798
+ else
8799
+ len = Expression::make_temporary_reference(len_temp, loc);
8800
+
8801
+ Expression* cap;
8802
+ if (len_temp == NULL)
8803
+ cap = len->copy();
8804
+ else
8805
+ cap = Expression::make_temporary_reference(len_temp, loc);
8806
+
8807
+ Expression* slice = Expression::make_slice_value(slice_type, ptr,
8808
+ len, cap, loc);
8809
+
8810
+ slice = Expression::make_conditional(cond, nil_slice, slice, loc);
8811
+
8812
+ return Expression::make_compound(check, slice, loc);
8813
+ }
8697
8814
}
8698
8815
8699
8816
return this;
@@ -9781,9 +9898,11 @@ Builtin_call_expression::do_discarding_value()
9781
9898
case BUILTIN_MAKE:
9782
9899
case BUILTIN_NEW:
9783
9900
case BUILTIN_REAL:
9901
+ case BUILTIN_ADD:
9784
9902
case BUILTIN_ALIGNOF:
9785
9903
case BUILTIN_OFFSETOF:
9786
9904
case BUILTIN_SIZEOF:
9905
+ case BUILTIN_SLICE:
9787
9906
this->unused_value_error();
9788
9907
return false;
9789
9908
@@ -9890,6 +10009,18 @@ Builtin_call_expression::do_type()
9890
10009
t = Type::make_error_type();
9891
10010
return t;
9892
10011
}
10012
+
10013
+ case BUILTIN_ADD:
10014
+ return Type::make_pointer_type(Type::make_void_type());
10015
+
10016
+ case BUILTIN_SLICE:
10017
+ const Expression_list* args = this->args();
10018
+ if (args == NULL || args->size() != 2)
10019
+ return Type::make_error_type();
10020
+ Type* pt = args->front()->type()->points_to();
10021
+ if (pt == NULL)
10022
+ return Type::make_error_type();
10023
+ return Type::make_array_type(pt, NULL);
9893
10024
}
9894
10025
}
9895
10026
@@ -9954,6 +10085,28 @@ Builtin_call_expression::do_determine_type(const Type_context* context)
9954
10085
is_print = false;
9955
10086
break;
9956
10087
10088
+ case BUILTIN_ADD:
10089
+ case BUILTIN_SLICE:
10090
+ // Both unsafe.Add and unsafe.Slice take two arguments, and the
10091
+ // second arguments defaults to "int".
10092
+ if (args != NULL && args->size() == 2)
10093
+ {
10094
+ if (this->code_ == BUILTIN_SLICE)
10095
+ args->front()->determine_type_no_context();
10096
+ else
10097
+ {
10098
+ Type* pointer = Type::make_pointer_type(Type::make_void_type());
10099
+ Type_context subcontext(pointer, false);
10100
+ args->front()->determine_type(&subcontext);
10101
+ }
10102
+ Type* int_type = Type::lookup_integer_type("int");
10103
+ Type_context subcontext(int_type, false);
10104
+ args->back()->determine_type(&subcontext);
10105
+ return;
10106
+ }
10107
+ is_print = false;
10108
+ break;
10109
+
9957
10110
default:
9958
10111
is_print = false;
9959
10112
break;
@@ -10353,6 +10506,78 @@ Builtin_call_expression::do_check_types(Gogo*)
10353
10506
}
10354
10507
break;
10355
10508
10509
+ case BUILTIN_ADD:
10510
+ case BUILTIN_SLICE:
10511
+ {
10512
+ Numeric_constant nc;
10513
+ unsigned long v;
10514
+ const Expression_list* args = this->args();
10515
+ if (args == NULL || args->size() < 2)
10516
+ this->report_error(_("not enough arguments"));
10517
+ else if (args->size() > 2)
10518
+ this->report_error(_("too many arguments"));
10519
+ else if (args->front()->is_error_expression()
10520
+ || args->front()->type()->is_error()
10521
+ || args->back()->is_error_expression()
10522
+ || args->back()->type()->is_error())
10523
+ this->set_is_error();
10524
+ else if (args->back()->type()->integer_type() == NULL
10525
+ && (!args->back()->type()->is_abstract()
10526
+ || !args->back()->numeric_constant_value(&nc)
10527
+ || (nc.to_unsigned_long(&v)
10528
+ == Numeric_constant::NC_UL_NOTINT)))
10529
+ {
10530
+ if (this->code_ == BUILTIN_ADD)
10531
+ go_error_at(args->back()->location(), "non-integer offset");
10532
+ else
10533
+ go_error_at(args->back()->location(), "non-integer size");
10534
+ }
10535
+ else if (this->code_ == BUILTIN_ADD)
10536
+ {
10537
+ Type* pointer_type =
10538
+ Type::make_pointer_type(Type::make_void_type());
10539
+ std::string reason;
10540
+ if (!Type::are_assignable(pointer_type, args->front()->type(),
10541
+ &reason))
10542
+ {
10543
+ if (reason.empty())
10544
+ go_error_at(args->front()->location(),
10545
+ "argument 1 has incompatible type");
10546
+ else
10547
+ go_error_at(args->front()->location(),
10548
+ "argument 1 has incompatible type (%s)",
10549
+ reason.c_str());
10550
+ this->set_is_error();
10551
+ }
10552
+ }
10553
+ else
10554
+ {
10555
+ if (args->front()->type()->points_to() == NULL)
10556
+ {
10557
+ go_error_at(args->front()->location(),
10558
+ "argument 1 must be a pointer");
10559
+ this->set_is_error();
10560
+ }
10561
+
10562
+ unsigned int int_bits =
10563
+ Type::lookup_integer_type("int")->integer_type()->bits();
10564
+
10565
+ mpz_t ival;
10566
+ if (args->back()->numeric_constant_value(&nc) && nc.to_int(&ival))
10567
+ {
10568
+ if (mpz_sgn(ival) < 0
10569
+ || mpz_sizeinbase(ival, 2) >= int_bits)
10570
+ {
10571
+ go_error_at(args->back()->location(),
10572
+ "slice length out of range");
10573
+ this->set_is_error();
10574
+ }
10575
+ mpz_clear(ival);
10576
+ }
10577
+ }
10578
+ }
10579
+ break;
10580
+
10356
10581
default:
10357
10582
go_unreachable();
10358
10583
}
@@ -10397,6 +10622,8 @@ Builtin_call_expression::do_get_backend(Translate_context* context)
10397
10622
case BUILTIN_INVALID:
10398
10623
case BUILTIN_NEW:
10399
10624
case BUILTIN_MAKE:
10625
+ case BUILTIN_ADD:
10626
+ case BUILTIN_SLICE:
10400
10627
go_unreachable();
10401
10628
10402
10629
case BUILTIN_LEN:
0 commit comments