Mercurial > hg > CbC > CbC_gcc
comparison gcc/go/gofrontend/expressions.cc @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
129 { | 129 { |
130 Type_context context; | 130 Type_context context; |
131 this->do_determine_type(&context); | 131 this->do_determine_type(&context); |
132 } | 132 } |
133 | 133 |
134 // Return true if two expressions refer to the same variable or struct | |
135 // field. This can only be true when there are no side effects. | |
136 | |
137 bool | |
138 Expression::is_same_variable(Expression* a, Expression* b) | |
139 { | |
140 if (a->classification() != b->classification()) | |
141 return false; | |
142 | |
143 Var_expression* av = a->var_expression(); | |
144 if (av != NULL) | |
145 return av->named_object() == b->var_expression()->named_object(); | |
146 | |
147 Field_reference_expression* af = a->field_reference_expression(); | |
148 if (af != NULL) | |
149 { | |
150 Field_reference_expression* bf = b->field_reference_expression(); | |
151 return (af->field_index() == bf->field_index() | |
152 && Expression::is_same_variable(af->expr(), bf->expr())); | |
153 } | |
154 | |
155 Unary_expression* au = a->unary_expression(); | |
156 if (au != NULL) | |
157 { | |
158 Unary_expression* bu = b->unary_expression(); | |
159 return (au->op() == OPERATOR_MULT | |
160 && bu->op() == OPERATOR_MULT | |
161 && Expression::is_same_variable(au->operand(), | |
162 bu->operand())); | |
163 } | |
164 | |
165 return false; | |
166 } | |
167 | |
134 // Return an expression handling any conversions which must be done during | 168 // Return an expression handling any conversions which must be done during |
135 // assignment. | 169 // assignment. |
136 | 170 |
137 Expression* | 171 Expression* |
138 Expression::convert_for_assignment(Gogo*, Type* lhs_type, | 172 Expression::convert_for_assignment(Gogo*, Type* lhs_type, |
142 if (lhs_type->is_error() | 176 if (lhs_type->is_error() |
143 || rhs_type->is_error() | 177 || rhs_type->is_error() |
144 || rhs->is_error_expression()) | 178 || rhs->is_error_expression()) |
145 return Expression::make_error(location); | 179 return Expression::make_error(location); |
146 | 180 |
147 bool are_identical = Type::are_identical(lhs_type, rhs_type, false, NULL); | 181 bool are_identical = Type::are_identical(lhs_type, rhs_type, |
182 (Type::COMPARE_ERRORS | |
183 | Type::COMPARE_TAGS), | |
184 NULL); | |
148 if (!are_identical && lhs_type->interface_type() != NULL) | 185 if (!are_identical && lhs_type->interface_type() != NULL) |
149 { | 186 { |
150 if (rhs_type->interface_type() == NULL) | 187 if (rhs_type->interface_type() == NULL) |
151 return Expression::convert_type_to_interface(lhs_type, rhs, location); | 188 return Expression::convert_type_to_interface(lhs_type, rhs, location); |
152 else | 189 else |
288 | 325 |
289 Expression* mtable = | 326 Expression* mtable = |
290 Expression::make_interface_info(rhs, INTERFACE_INFO_METHODS, location); | 327 Expression::make_interface_info(rhs, INTERFACE_INFO_METHODS, location); |
291 | 328 |
292 Expression* descriptor = | 329 Expression* descriptor = |
293 Expression::make_unary(OPERATOR_MULT, mtable, location); | 330 Expression::make_dereference(mtable, NIL_CHECK_NOT_NEEDED, location); |
294 descriptor = Expression::make_field_reference(descriptor, 0, location); | 331 descriptor = Expression::make_field_reference(descriptor, 0, location); |
295 Expression* nil = Expression::make_nil(location); | 332 Expression* nil = Expression::make_nil(location); |
296 | 333 |
297 Expression* eq = | 334 Expression* eq = |
298 Expression::make_binary(OPERATOR_EQEQ, mtable, nil, location); | 335 Expression::make_binary(OPERATOR_EQEQ, mtable, nil, location); |
305 Expression* | 342 Expression* |
306 Expression::convert_interface_to_interface(Type *lhs_type, Expression* rhs, | 343 Expression::convert_interface_to_interface(Type *lhs_type, Expression* rhs, |
307 bool for_type_guard, | 344 bool for_type_guard, |
308 Location location) | 345 Location location) |
309 { | 346 { |
310 if (Type::are_identical(lhs_type, rhs->type(), false, NULL)) | 347 if (Type::are_identical(lhs_type, rhs->type(), |
348 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, | |
349 NULL)) | |
311 return rhs; | 350 return rhs; |
312 | 351 |
313 Interface_type* lhs_interface_type = lhs_type->interface_type(); | 352 Interface_type* lhs_interface_type = lhs_type->interface_type(); |
314 bool lhs_is_empty = lhs_interface_type->is_empty(); | 353 bool lhs_is_empty = lhs_interface_type->is_empty(); |
315 | 354 |
391 // Otherwise it points to the value. | 430 // Otherwise it points to the value. |
392 if (lhs_type->points_to() == NULL) | 431 if (lhs_type->points_to() == NULL) |
393 { | 432 { |
394 obj = Expression::make_unsafe_cast(Type::make_pointer_type(lhs_type), obj, | 433 obj = Expression::make_unsafe_cast(Type::make_pointer_type(lhs_type), obj, |
395 location); | 434 location); |
396 obj = Expression::make_unary(OPERATOR_MULT, obj, location); | 435 obj = Expression::make_dereference(obj, NIL_CHECK_NOT_NEEDED, |
436 location); | |
397 } | 437 } |
398 return Expression::make_compound(check_iface, obj, location); | 438 return Expression::make_compound(check_iface, obj, location); |
399 } | 439 } |
400 | 440 |
401 // Convert an expression to its backend representation. This is implemented by | 441 // Convert an expression to its backend representation. This is implemented by |
769 } | 809 } |
770 else | 810 else |
771 go_unreachable(); | 811 go_unreachable(); |
772 | 812 |
773 Bexpression* ret = | 813 Bexpression* ret = |
774 context->backend()->var_expression(bvar, this->in_lvalue_pos_, loc); | 814 context->backend()->var_expression(bvar, loc); |
775 if (is_in_heap) | 815 if (is_in_heap) |
776 ret = context->backend()->indirect_expression(btype, ret, true, loc); | 816 ret = context->backend()->indirect_expression(btype, ret, true, loc); |
777 return ret; | 817 return ret; |
778 } | 818 } |
779 | 819 |
780 // Ast dump for variable expression. | 820 // Ast dump for variable expression. |
781 | 821 |
782 void | 822 void |
783 Var_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const | 823 Var_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const |
784 { | 824 { |
785 ast_dump_context->ostream() << this->variable_->name() ; | 825 ast_dump_context->ostream() << this->variable_->message_name() ; |
786 } | 826 } |
787 | 827 |
788 // Make a reference to a variable in an expression. | 828 // Make a reference to a variable in an expression. |
789 | 829 |
790 Expression* | 830 Expression* |
856 // Ast dump for enclosed variable expression. | 896 // Ast dump for enclosed variable expression. |
857 | 897 |
858 void | 898 void |
859 Enclosed_var_expression::do_dump_expression(Ast_dump_context* adc) const | 899 Enclosed_var_expression::do_dump_expression(Ast_dump_context* adc) const |
860 { | 900 { |
861 adc->ostream() << this->variable_->name(); | 901 adc->ostream() << this->variable_->message_name(); |
862 } | 902 } |
863 | 903 |
864 // Make a reference to a variable within an enclosing function. | 904 // Make a reference to a variable within an enclosing function. |
865 | 905 |
866 Expression* | 906 Expression* |
896 Bexpression* | 936 Bexpression* |
897 Temporary_reference_expression::do_get_backend(Translate_context* context) | 937 Temporary_reference_expression::do_get_backend(Translate_context* context) |
898 { | 938 { |
899 Gogo* gogo = context->gogo(); | 939 Gogo* gogo = context->gogo(); |
900 Bvariable* bvar = this->statement_->get_backend_variable(context); | 940 Bvariable* bvar = this->statement_->get_backend_variable(context); |
901 Varexpr_context ve_ctxt = (this->is_lvalue_ ? VE_lvalue : VE_rvalue); | 941 Bexpression* ret = gogo->backend()->var_expression(bvar, this->location()); |
902 | |
903 Bexpression* ret = gogo->backend()->var_expression(bvar, ve_ctxt, | |
904 this->location()); | |
905 | 942 |
906 // The backend can't always represent the same set of recursive types | 943 // The backend can't always represent the same set of recursive types |
907 // that the Go frontend can. In some cases this means that a | 944 // that the Go frontend can. In some cases this means that a |
908 // temporary variable won't have the right backend type. Correct | 945 // temporary variable won't have the right backend type. Correct |
909 // that here by adding a type cast. We need to use base() to push | 946 // that here by adding a type cast. We need to use base() to push |
970 Set_and_use_temporary_expression::do_get_backend(Translate_context* context) | 1007 Set_and_use_temporary_expression::do_get_backend(Translate_context* context) |
971 { | 1008 { |
972 Location loc = this->location(); | 1009 Location loc = this->location(); |
973 Gogo* gogo = context->gogo(); | 1010 Gogo* gogo = context->gogo(); |
974 Bvariable* bvar = this->statement_->get_backend_variable(context); | 1011 Bvariable* bvar = this->statement_->get_backend_variable(context); |
975 Bexpression* lvar_ref = gogo->backend()->var_expression(bvar, VE_lvalue, loc); | 1012 Bexpression* lvar_ref = gogo->backend()->var_expression(bvar, loc); |
976 | 1013 |
977 Named_object* fn = context->function(); | 1014 Named_object* fn = context->function(); |
978 go_assert(fn != NULL); | 1015 go_assert(fn != NULL); |
979 Bfunction* bfn = fn->func_value()->get_or_make_decl(gogo, fn); | 1016 Bfunction* bfn = fn->func_value()->get_or_make_decl(gogo, fn); |
980 Bexpression* bexpr = this->expr_->get_backend(context); | 1017 Bexpression* bexpr = this->expr_->get_backend(context); |
981 Bstatement* set = gogo->backend()->assignment_statement(bfn, lvar_ref, | 1018 Bstatement* set = gogo->backend()->assignment_statement(bfn, lvar_ref, |
982 bexpr, loc); | 1019 bexpr, loc); |
983 Bexpression* var_ref = gogo->backend()->var_expression(bvar, VE_rvalue, loc); | 1020 Bexpression* var_ref = gogo->backend()->var_expression(bvar, loc); |
984 Bexpression* ret = gogo->backend()->compound_expression(set, var_ref, loc); | 1021 Bexpression* ret = gogo->backend()->compound_expression(set, var_ref, loc); |
985 return ret; | 1022 return ret; |
986 } | 1023 } |
987 | 1024 |
988 // Dump. | 1025 // Dump. |
1082 Bstatement* decl; | 1119 Bstatement* decl; |
1083 this->bvar_ = | 1120 this->bvar_ = |
1084 gogo->backend()->temporary_variable(fn_ctx, context->bblock(), bt, NULL, | 1121 gogo->backend()->temporary_variable(fn_ctx, context->bblock(), bt, NULL, |
1085 false, loc, &decl); | 1122 false, loc, &decl); |
1086 Bexpression* var_ref = | 1123 Bexpression* var_ref = |
1087 gogo->backend()->var_expression(this->bvar_, VE_lvalue, loc); | 1124 gogo->backend()->var_expression(this->bvar_, loc); |
1088 var_ref = gogo->backend()->compound_expression(decl, var_ref, loc); | 1125 var_ref = gogo->backend()->compound_expression(decl, var_ref, loc); |
1089 return var_ref; | 1126 return var_ref; |
1090 } | 1127 } |
1091 return gogo->backend()->var_expression(this->bvar_, VE_lvalue, loc); | 1128 return gogo->backend()->var_expression(this->bvar_, loc); |
1092 } | 1129 } |
1093 | 1130 |
1094 // Ast dump for sink expression. | 1131 // Ast dump for sink expression. |
1095 | 1132 |
1096 void | 1133 void |
1300 Func_descriptor_expression::do_get_backend(Translate_context* context) | 1337 Func_descriptor_expression::do_get_backend(Translate_context* context) |
1301 { | 1338 { |
1302 Named_object* no = this->fn_; | 1339 Named_object* no = this->fn_; |
1303 Location loc = no->location(); | 1340 Location loc = no->location(); |
1304 if (this->dvar_ != NULL) | 1341 if (this->dvar_ != NULL) |
1305 return context->backend()->var_expression(this->dvar_, VE_rvalue, loc); | 1342 return context->backend()->var_expression(this->dvar_, loc); |
1306 | 1343 |
1307 Gogo* gogo = context->gogo(); | 1344 Gogo* gogo = context->gogo(); |
1308 std::string var_name(gogo->function_descriptor_name(no)); | 1345 std::string var_name(gogo->function_descriptor_name(no)); |
1309 bool is_descriptor = false; | 1346 bool is_descriptor = false; |
1310 if (no->is_function_declaration() | 1347 if (no->is_function_declaration() |
1311 && !no->func_declaration_value()->asm_name().empty() | 1348 && !no->func_declaration_value()->asm_name().empty() |
1312 && Linemap::is_predeclared_location(no->location())) | 1349 && Linemap::is_predeclared_location(no->location())) |
1313 is_descriptor = true; | 1350 is_descriptor = true; |
1314 | 1351 |
1352 // The runtime package implements some functions defined in the | |
1353 // syscall package. Let the syscall package define the descriptor | |
1354 // in this case. | |
1355 if (gogo->compiling_runtime() | |
1356 && gogo->package_name() == "runtime" | |
1357 && no->is_function() | |
1358 && !no->func_value()->asm_name().empty() | |
1359 && no->func_value()->asm_name().compare(0, 8, "syscall.") == 0) | |
1360 is_descriptor = true; | |
1361 | |
1315 Btype* btype = this->type()->get_backend(gogo); | 1362 Btype* btype = this->type()->get_backend(gogo); |
1316 | 1363 |
1317 Bvariable* bvar; | 1364 Bvariable* bvar; |
1318 std::string asm_name(go_selectively_encode_id(var_name)); | 1365 std::string asm_name(go_selectively_encode_id(var_name)); |
1319 if (no->package() != NULL || is_descriptor) | 1366 if (no->package() != NULL || is_descriptor) |
1320 bvar = context->backend()->immutable_struct_reference(var_name, asm_name, | 1367 bvar = context->backend()->immutable_struct_reference(var_name, asm_name, |
1321 btype, loc); | 1368 btype, loc); |
1322 else | 1369 else |
1323 { | 1370 { |
1324 Location bloc = Linemap::predeclared_location(); | 1371 Location bloc = Linemap::predeclared_location(); |
1372 | |
1373 // The runtime package has hash/equality functions that are | |
1374 // referenced by type descriptors outside of the runtime, so the | |
1375 // function descriptors must be visible even though they are not | |
1376 // exported. | |
1377 bool is_exported_runtime = false; | |
1378 if (gogo->compiling_runtime() | |
1379 && gogo->package_name() == "runtime" | |
1380 && (no->name().find("hash") != std::string::npos | |
1381 || no->name().find("equal") != std::string::npos)) | |
1382 is_exported_runtime = true; | |
1383 | |
1325 bool is_hidden = ((no->is_function() | 1384 bool is_hidden = ((no->is_function() |
1326 && no->func_value()->enclosing() != NULL) | 1385 && no->func_value()->enclosing() != NULL) |
1386 || (Gogo::is_hidden_name(no->name()) | |
1387 && !is_exported_runtime) | |
1327 || Gogo::is_thunk(no)); | 1388 || Gogo::is_thunk(no)); |
1389 | |
1328 bvar = context->backend()->immutable_struct(var_name, asm_name, | 1390 bvar = context->backend()->immutable_struct(var_name, asm_name, |
1329 is_hidden, false, | 1391 is_hidden, false, |
1330 btype, bloc); | 1392 btype, bloc); |
1331 Expression_list* vals = new Expression_list(); | 1393 Expression_list* vals = new Expression_list(); |
1332 vals->push_back(Expression::make_func_code_reference(this->fn_, bloc)); | 1394 vals->push_back(Expression::make_func_code_reference(this->fn_, bloc)); |
1338 context->backend()->immutable_struct_set_init(bvar, var_name, is_hidden, | 1400 context->backend()->immutable_struct_set_init(bvar, var_name, is_hidden, |
1339 false, btype, bloc, binit); | 1401 false, btype, bloc, binit); |
1340 } | 1402 } |
1341 | 1403 |
1342 this->dvar_ = bvar; | 1404 this->dvar_ = bvar; |
1343 return gogo->backend()->var_expression(bvar, VE_rvalue, loc); | 1405 return gogo->backend()->var_expression(bvar, loc); |
1344 } | 1406 } |
1345 | 1407 |
1346 // Print a function descriptor expression. | 1408 // Print a function descriptor expression. |
1347 | 1409 |
1348 void | 1410 void |
1918 | 1980 |
1919 Expression* | 1981 Expression* |
1920 do_copy() | 1982 do_copy() |
1921 { | 1983 { |
1922 if (this->is_character_constant_) | 1984 if (this->is_character_constant_) |
1923 return Expression::make_character(&this->val_, this->type_, | 1985 return Expression::make_character(&this->val_, |
1986 (this->type_ == NULL | |
1987 ? NULL | |
1988 : this->type_->copy_expressions()), | |
1924 this->location()); | 1989 this->location()); |
1925 else | 1990 else |
1926 return Expression::make_integer_z(&this->val_, this->type_, | 1991 return Expression::make_integer_z(&this->val_, |
1992 (this->type_ == NULL | |
1993 ? NULL | |
1994 : this->type_->copy_expressions()), | |
1927 this->location()); | 1995 this->location()); |
1928 } | 1996 } |
1929 | 1997 |
1930 void | 1998 void |
1931 do_export(Export*) const; | 1999 do_export(Export*) const; |
2313 void | 2381 void |
2314 do_check_types(Gogo*); | 2382 do_check_types(Gogo*); |
2315 | 2383 |
2316 Expression* | 2384 Expression* |
2317 do_copy() | 2385 do_copy() |
2318 { return Expression::make_float(&this->val_, this->type_, | 2386 { return Expression::make_float(&this->val_, |
2387 (this->type_ == NULL | |
2388 ? NULL | |
2389 : this->type_->copy_expressions()), | |
2319 this->location()); } | 2390 this->location()); } |
2320 | 2391 |
2321 Bexpression* | 2392 Bexpression* |
2322 do_get_backend(Translate_context*); | 2393 do_get_backend(Translate_context*); |
2323 | 2394 |
2504 do_check_types(Gogo*); | 2575 do_check_types(Gogo*); |
2505 | 2576 |
2506 Expression* | 2577 Expression* |
2507 do_copy() | 2578 do_copy() |
2508 { | 2579 { |
2509 return Expression::make_complex(&this->val_, this->type_, | 2580 return Expression::make_complex(&this->val_, |
2581 (this->type_ == NULL | |
2582 ? NULL | |
2583 : this->type_->copy_expressions()), | |
2510 this->location()); | 2584 this->location()); |
2511 } | 2585 } |
2512 | 2586 |
2513 Bexpression* | 2587 Bexpression* |
2514 do_get_backend(Translate_context*); | 2588 do_get_backend(Translate_context*); |
2837 | 2911 |
2838 Named_constant* nc = this->constant_->const_value(); | 2912 Named_constant* nc = this->constant_->const_value(); |
2839 | 2913 |
2840 if (this->seen_ || nc->lowering()) | 2914 if (this->seen_ || nc->lowering()) |
2841 { | 2915 { |
2842 this->report_error(_("constant refers to itself")); | 2916 if (nc->type() == NULL || !nc->type()->is_error_type()) |
2917 { | |
2918 Location loc = this->location(); | |
2919 if (!this->seen_) | |
2920 loc = nc->location(); | |
2921 go_error_at(loc, "constant refers to itself"); | |
2922 } | |
2923 this->set_is_error(); | |
2843 this->type_ = Type::make_error_type(); | 2924 this->type_ = Type::make_error_type(); |
2925 nc->set_type(this->type_); | |
2844 return this->type_; | 2926 return this->type_; |
2845 } | 2927 } |
2846 | 2928 |
2847 this->seen_ = true; | 2929 this->seen_ = true; |
2848 | 2930 |
2857 // During parsing, a named constant may have a NULL type, but we | 2939 // During parsing, a named constant may have a NULL type, but we |
2858 // must not return a NULL type here. | 2940 // must not return a NULL type here. |
2859 ret = nc->expr()->type(); | 2941 ret = nc->expr()->type(); |
2860 | 2942 |
2861 this->seen_ = false; | 2943 this->seen_ = false; |
2944 | |
2945 if (ret->is_error_type()) | |
2946 nc->set_type(ret); | |
2862 | 2947 |
2863 return ret; | 2948 return ret; |
2864 } | 2949 } |
2865 | 2950 |
2866 // Set the type of the const reference. | 2951 // Set the type of the const reference. |
3307 return false; | 3392 return false; |
3308 | 3393 |
3309 if (!this->expr_->is_static_initializer()) | 3394 if (!this->expr_->is_static_initializer()) |
3310 return false; | 3395 return false; |
3311 | 3396 |
3312 if (Type::are_identical(type, expr_type, false, NULL)) | 3397 if (Type::are_identical(type, expr_type, |
3398 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, | |
3399 NULL)) | |
3313 return true; | 3400 return true; |
3314 | 3401 |
3315 if (type->is_string_type() && expr_type->is_string_type()) | 3402 if (type->is_string_type() && expr_type->is_string_type()) |
3316 return true; | 3403 return true; |
3317 | 3404 |
3399 | 3486 |
3400 go_error_at(this->location(), "%s", reason.c_str()); | 3487 go_error_at(this->location(), "%s", reason.c_str()); |
3401 this->set_is_error(); | 3488 this->set_is_error(); |
3402 } | 3489 } |
3403 | 3490 |
3491 // Copy. | |
3492 | |
3493 Expression* | |
3494 Type_conversion_expression::do_copy() | |
3495 { | |
3496 return new Type_conversion_expression(this->type_->copy_expressions(), | |
3497 this->expr_->copy(), | |
3498 this->location()); | |
3499 } | |
3500 | |
3404 // Get the backend representation for a type conversion. | 3501 // Get the backend representation for a type conversion. |
3405 | 3502 |
3406 Bexpression* | 3503 Bexpression* |
3407 Type_conversion_expression::do_get_backend(Translate_context* context) | 3504 Type_conversion_expression::do_get_backend(Translate_context* context) |
3408 { | 3505 { |
3411 | 3508 |
3412 Gogo* gogo = context->gogo(); | 3509 Gogo* gogo = context->gogo(); |
3413 Btype* btype = type->get_backend(gogo); | 3510 Btype* btype = type->get_backend(gogo); |
3414 Location loc = this->location(); | 3511 Location loc = this->location(); |
3415 | 3512 |
3416 if (Type::are_identical(type, expr_type, false, NULL)) | 3513 if (Type::are_identical(type, expr_type, |
3514 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, | |
3515 NULL)) | |
3417 { | 3516 { |
3418 Bexpression* bexpr = this->expr_->get_backend(context); | 3517 Bexpression* bexpr = this->expr_->get_backend(context); |
3419 return gogo->backend()->convert_expression(btype, bexpr, loc); | 3518 return gogo->backend()->convert_expression(btype, bexpr, loc); |
3420 } | 3519 } |
3421 else if (type->interface_type() != NULL | 3520 else if (type->interface_type() != NULL |
3598 || expr_type->is_boolean_type() | 3697 || expr_type->is_boolean_type() |
3599 || expr_type->points_to() != NULL)) | 3698 || expr_type->points_to() != NULL)) |
3600 return true; | 3699 return true; |
3601 | 3700 |
3602 return false; | 3701 return false; |
3702 } | |
3703 | |
3704 // Copy. | |
3705 | |
3706 Expression* | |
3707 Unsafe_type_conversion_expression::do_copy() | |
3708 { | |
3709 return new Unsafe_type_conversion_expression(this->type_->copy_expressions(), | |
3710 this->expr_->copy(), | |
3711 this->location()); | |
3603 } | 3712 } |
3604 | 3713 |
3605 // Convert to backend representation. | 3714 // Convert to backend representation. |
3606 | 3715 |
3607 Bexpression* | 3716 Bexpression* |
3700 | 3809 |
3701 // Call the address_taken method of the operand if needed. This is | 3810 // Call the address_taken method of the operand if needed. This is |
3702 // called after escape analysis but before inserting write barriers. | 3811 // called after escape analysis but before inserting write barriers. |
3703 | 3812 |
3704 void | 3813 void |
3705 Unary_expression::check_operand_address_taken(Gogo* gogo) | 3814 Unary_expression::check_operand_address_taken(Gogo*) |
3706 { | 3815 { |
3707 if (this->op_ != OPERATOR_AND) | 3816 if (this->op_ != OPERATOR_AND) |
3708 return; | 3817 return; |
3709 | 3818 |
3710 // If this->escapes_ is false at this point, then it was set to | 3819 // If this->escapes_ is false at this point, then it was set to |
3712 // does not escape. If this->escapes_ is true, we may be able to | 3821 // does not escape. If this->escapes_ is true, we may be able to |
3713 // set it to false if taking the address of a variable that does not | 3822 // set it to false if taking the address of a variable that does not |
3714 // escape. | 3823 // escape. |
3715 Node* n = Node::make_node(this); | 3824 Node* n = Node::make_node(this); |
3716 if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE)) | 3825 if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE)) |
3717 this->escapes_ = false; | |
3718 | |
3719 // When compiling the runtime, the address operator does not cause | |
3720 // local variables to escape. When escape analysis becomes the | |
3721 // default, this should be changed to make it an error if we have an | |
3722 // address operator that escapes. | |
3723 if (gogo->compiling_runtime() && gogo->package_name() == "runtime") | |
3724 this->escapes_ = false; | 3826 this->escapes_ = false; |
3725 | 3827 |
3726 Named_object* var = NULL; | 3828 Named_object* var = NULL; |
3727 if (this->expr_->var_expression() != NULL) | 3829 if (this->expr_->var_expression() != NULL) |
3728 var = this->expr_->var_expression()->named_object(); | 3830 var = this->expr_->var_expression()->named_object(); |
3843 Location location = this->location(); | 3945 Location location = this->location(); |
3844 if (this->op_ == OPERATOR_MULT | 3946 if (this->op_ == OPERATOR_MULT |
3845 && !this->expr_->is_variable()) | 3947 && !this->expr_->is_variable()) |
3846 { | 3948 { |
3847 go_assert(this->expr_->type()->points_to() != NULL); | 3949 go_assert(this->expr_->type()->points_to() != NULL); |
3848 Type* ptype = this->expr_->type()->points_to(); | 3950 switch (this->requires_nil_check(gogo)) |
3849 if (!ptype->is_void_type()) | |
3850 { | 3951 { |
3851 int64_t s; | 3952 case NIL_CHECK_ERROR_ENCOUNTERED: |
3852 bool ok = ptype->backend_type_size(gogo, &s); | |
3853 if (!ok) | |
3854 { | 3953 { |
3855 go_assert(saw_errors()); | 3954 go_assert(saw_errors()); |
3856 return Expression::make_error(this->location()); | 3955 return Expression::make_error(this->location()); |
3857 } | 3956 } |
3858 if (s >= 4096 || this->issue_nil_check_) | 3957 case NIL_CHECK_NOT_NEEDED: |
3859 { | 3958 break; |
3860 Temporary_statement* temp = | 3959 case NIL_CHECK_NEEDED: |
3861 Statement::make_temporary(NULL, this->expr_, location); | 3960 this->create_temp_ = true; |
3862 inserter->insert(temp); | 3961 break; |
3863 this->expr_ = | 3962 case NIL_CHECK_DEFAULT: |
3864 Expression::make_temporary_reference(temp, location); | 3963 go_unreachable(); |
3865 } | |
3866 } | 3964 } |
3867 } | 3965 } |
3868 | 3966 |
3869 if (this->create_temp_ && !this->expr_->is_variable()) | 3967 if (this->create_temp_ && !this->expr_->is_variable()) |
3870 { | 3968 { |
3959 // used when building a type descriptor. | 4057 // used when building a type descriptor. |
3960 if (expr->string_expression() != NULL) | 4058 if (expr->string_expression() != NULL) |
3961 return true; | 4059 return true; |
3962 | 4060 |
3963 return false; | 4061 return false; |
4062 } | |
4063 | |
4064 // Return whether this dereference expression requires an explicit nil | |
4065 // check. If we are dereferencing the pointer to a large struct | |
4066 // (greater than the specified size threshold), we need to check for | |
4067 // nil. We don't bother to check for small structs because we expect | |
4068 // the system to crash on a nil pointer dereference. However, if we | |
4069 // know the address of this expression is being taken, we must always | |
4070 // check for nil. | |
4071 Unary_expression::Nil_check_classification | |
4072 Unary_expression::requires_nil_check(Gogo* gogo) | |
4073 { | |
4074 go_assert(this->op_ == OPERATOR_MULT); | |
4075 go_assert(this->expr_->type()->points_to() != NULL); | |
4076 | |
4077 if (this->issue_nil_check_ == NIL_CHECK_NEEDED) | |
4078 return NIL_CHECK_NEEDED; | |
4079 else if (this->issue_nil_check_ == NIL_CHECK_NOT_NEEDED) | |
4080 return NIL_CHECK_NOT_NEEDED; | |
4081 | |
4082 Type* ptype = this->expr_->type()->points_to(); | |
4083 int64_t type_size = -1; | |
4084 if (!ptype->is_void_type()) | |
4085 { | |
4086 bool ok = ptype->backend_type_size(gogo, &type_size); | |
4087 if (!ok) | |
4088 return NIL_CHECK_ERROR_ENCOUNTERED; | |
4089 } | |
4090 | |
4091 int64_t size_cutoff = gogo->nil_check_size_threshold(); | |
4092 if (size_cutoff == -1 || (type_size != -1 && type_size >= size_cutoff)) | |
4093 this->issue_nil_check_ = NIL_CHECK_NEEDED; | |
4094 else | |
4095 this->issue_nil_check_ = NIL_CHECK_NOT_NEEDED; | |
4096 return this->issue_nil_check_; | |
3964 } | 4097 } |
3965 | 4098 |
3966 // Apply unary opcode OP to UNC, setting NC. Return true if this | 4099 // Apply unary opcode OP to UNC, setting NC. Return true if this |
3967 // could be done, false if not. On overflow, issues an error and sets | 4100 // could be done, false if not. On overflow, issues an error and sets |
3968 // *ISSUED_ERROR. | 4101 // *ISSUED_ERROR. |
4284 if (sut != NULL) | 4417 if (sut != NULL) |
4285 { | 4418 { |
4286 Temporary_statement* temp = sut->temporary(); | 4419 Temporary_statement* temp = sut->temporary(); |
4287 Bvariable* bvar = temp->get_backend_variable(context); | 4420 Bvariable* bvar = temp->get_backend_variable(context); |
4288 Bexpression* bvar_expr = | 4421 Bexpression* bvar_expr = |
4289 gogo->backend()->var_expression(bvar, VE_lvalue, loc); | 4422 gogo->backend()->var_expression(bvar, loc); |
4290 Bexpression* bval = sut->expression()->get_backend(context); | 4423 Bexpression* bval = sut->expression()->get_backend(context); |
4291 | 4424 |
4292 Named_object* fn = context->function(); | 4425 Named_object* fn = context->function(); |
4293 go_assert(fn != NULL); | 4426 go_assert(fn != NULL); |
4294 Bfunction* bfn = | 4427 Bfunction* bfn = |
4361 | 4494 |
4362 // If we are not copying the value to the heap, we will only | 4495 // If we are not copying the value to the heap, we will only |
4363 // initialize the value once, so we can use this directly | 4496 // initialize the value once, so we can use this directly |
4364 // rather than copying it. In that case we can't make it | 4497 // rather than copying it. In that case we can't make it |
4365 // read-only, because the program is permitted to change it. | 4498 // read-only, because the program is permitted to change it. |
4366 copy_to_heap = context->function() != NULL; | 4499 copy_to_heap = (context->function() != NULL |
4500 || context->is_const()); | |
4367 } | 4501 } |
4368 std::string asm_name(go_selectively_encode_id(var_name)); | 4502 std::string asm_name(go_selectively_encode_id(var_name)); |
4369 Bvariable* implicit = | 4503 Bvariable* implicit = |
4370 gogo->backend()->implicit_variable(var_name, asm_name, | 4504 gogo->backend()->implicit_variable(var_name, asm_name, |
4371 btype, true, copy_to_heap, | 4505 btype, true, copy_to_heap, |
4372 false, 0); | 4506 false, 0); |
4373 gogo->backend()->implicit_variable_set_init(implicit, var_name, btype, | 4507 gogo->backend()->implicit_variable_set_init(implicit, var_name, btype, |
4374 true, copy_to_heap, false, | 4508 true, copy_to_heap, false, |
4375 bexpr); | 4509 bexpr); |
4376 bexpr = gogo->backend()->var_expression(implicit, VE_rvalue, loc); | 4510 bexpr = gogo->backend()->var_expression(implicit, loc); |
4377 | 4511 |
4378 // If we are not copying a slice initializer to the heap, | 4512 // If we are not copying a slice initializer to the heap, |
4379 // then it can be changed by the program, so if it can | 4513 // then it can be changed by the program, so if it can |
4380 // contain pointers we must register it as a GC root. | 4514 // contain pointers we must register it as a GC root. |
4381 if (this->is_slice_init_ | 4515 if (this->is_slice_init_ |
4382 && !copy_to_heap | 4516 && !copy_to_heap |
4383 && this->expr_->type()->has_pointer()) | 4517 && this->expr_->type()->has_pointer()) |
4384 { | 4518 { |
4385 Bexpression* root = | 4519 Bexpression* root = |
4386 gogo->backend()->var_expression(implicit, VE_rvalue, loc); | 4520 gogo->backend()->var_expression(implicit, loc); |
4387 root = gogo->backend()->address_expression(root, loc); | 4521 root = gogo->backend()->address_expression(root, loc); |
4388 Type* type = Type::make_pointer_type(this->expr_->type()); | 4522 Type* type = Type::make_pointer_type(this->expr_->type()); |
4389 gogo->add_gc_root(Expression::make_backend(root, type, loc)); | 4523 gogo->add_gc_root(Expression::make_backend(root, type, loc)); |
4390 } | 4524 } |
4391 } | 4525 } |
4398 Bvariable* decl = | 4532 Bvariable* decl = |
4399 gogo->backend()->immutable_struct(var_name, asm_name, | 4533 gogo->backend()->immutable_struct(var_name, asm_name, |
4400 true, false, btype, loc); | 4534 true, false, btype, loc); |
4401 gogo->backend()->immutable_struct_set_init(decl, var_name, true, | 4535 gogo->backend()->immutable_struct_set_init(decl, var_name, true, |
4402 false, btype, loc, bexpr); | 4536 false, btype, loc, bexpr); |
4403 bexpr = gogo->backend()->var_expression(decl, VE_rvalue, loc); | 4537 bexpr = gogo->backend()->var_expression(decl, loc); |
4404 } | 4538 } |
4405 | 4539 |
4406 go_assert(!this->create_temp_ || this->expr_->is_variable()); | 4540 go_assert(!this->create_temp_ || this->expr_->is_variable()); |
4407 ret = gogo->backend()->address_expression(bexpr, loc); | 4541 ret = gogo->backend()->address_expression(bexpr, loc); |
4408 break; | 4542 break; |
4409 | 4543 |
4410 case OPERATOR_MULT: | 4544 case OPERATOR_MULT: |
4411 { | 4545 { |
4412 go_assert(this->expr_->type()->points_to() != NULL); | 4546 go_assert(this->expr_->type()->points_to() != NULL); |
4413 | 4547 |
4414 // If we are dereferencing the pointer to a large struct, we | 4548 bool known_valid = false; |
4415 // need to check for nil. We don't bother to check for small | |
4416 // structs because we expect the system to crash on a nil | |
4417 // pointer dereference. However, if we know the address of this | |
4418 // expression is being taken, we must always check for nil. | |
4419 | |
4420 Type* ptype = this->expr_->type()->points_to(); | 4549 Type* ptype = this->expr_->type()->points_to(); |
4421 Btype* pbtype = ptype->get_backend(gogo); | 4550 Btype* pbtype = ptype->get_backend(gogo); |
4422 if (!ptype->is_void_type()) | 4551 switch (this->requires_nil_check(gogo)) |
4423 { | 4552 { |
4424 int64_t s; | 4553 case NIL_CHECK_NOT_NEEDED: |
4425 bool ok = ptype->backend_type_size(gogo, &s); | 4554 break; |
4426 if (!ok) | 4555 case NIL_CHECK_ERROR_ENCOUNTERED: |
4427 { | 4556 { |
4428 go_assert(saw_errors()); | 4557 go_assert(saw_errors()); |
4429 return gogo->backend()->error_expression(); | 4558 return gogo->backend()->error_expression(); |
4430 } | 4559 } |
4431 if (s >= 4096 || this->issue_nil_check_) | 4560 case NIL_CHECK_NEEDED: |
4432 { | 4561 { |
4433 go_assert(this->expr_->is_variable()); | 4562 go_assert(this->expr_->is_variable()); |
4563 | |
4564 // If we're nil-checking the result of a set-and-use-temporary | |
4565 // expression, then pick out the target temp and use that | |
4566 // for the final result of the conditional. | |
4567 Bexpression* tbexpr = bexpr; | |
4568 Bexpression* ubexpr = bexpr; | |
4569 Set_and_use_temporary_expression* sut = | |
4570 this->expr_->set_and_use_temporary_expression(); | |
4571 if (sut != NULL) { | |
4572 Temporary_statement* temp = sut->temporary(); | |
4573 Bvariable* bvar = temp->get_backend_variable(context); | |
4574 ubexpr = gogo->backend()->var_expression(bvar, loc); | |
4575 } | |
4434 Bexpression* nil = | 4576 Bexpression* nil = |
4435 Expression::make_nil(loc)->get_backend(context); | 4577 Expression::make_nil(loc)->get_backend(context); |
4436 Bexpression* compare = | 4578 Bexpression* compare = |
4437 gogo->backend()->binary_expression(OPERATOR_EQEQ, bexpr, | 4579 gogo->backend()->binary_expression(OPERATOR_EQEQ, tbexpr, |
4438 nil, loc); | 4580 nil, loc); |
4439 Bexpression* crash = | 4581 Bexpression* crash = |
4440 gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, | 4582 gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, |
4441 loc)->get_backend(context); | 4583 loc)->get_backend(context); |
4442 Bfunction* bfn = context->function()->func_value()->get_decl(); | 4584 Bfunction* bfn = context->function()->func_value()->get_decl(); |
4443 bexpr = gogo->backend()->conditional_expression(bfn, btype, | 4585 bexpr = gogo->backend()->conditional_expression(bfn, btype, |
4444 compare, | 4586 compare, |
4445 crash, bexpr, | 4587 crash, ubexpr, |
4446 loc); | 4588 loc); |
4447 | 4589 known_valid = true; |
4448 } | 4590 break; |
4449 } | 4591 } |
4450 ret = gogo->backend()->indirect_expression(pbtype, bexpr, false, loc); | 4592 case NIL_CHECK_DEFAULT: |
4593 go_unreachable(); | |
4594 } | |
4595 ret = gogo->backend()->indirect_expression(pbtype, bexpr, | |
4596 known_valid, loc); | |
4451 } | 4597 } |
4452 break; | 4598 break; |
4453 | 4599 |
4454 default: | 4600 default: |
4455 go_unreachable(); | 4601 go_unreachable(); |
4528 | 4674 |
4529 Expression* | 4675 Expression* |
4530 Expression::make_unary(Operator op, Expression* expr, Location location) | 4676 Expression::make_unary(Operator op, Expression* expr, Location location) |
4531 { | 4677 { |
4532 return new Unary_expression(op, expr, location); | 4678 return new Unary_expression(op, expr, location); |
4679 } | |
4680 | |
4681 Expression* | |
4682 Expression::make_dereference(Expression* ptr, | |
4683 Nil_check_classification docheck, | |
4684 Location location) | |
4685 { | |
4686 Expression* deref = Expression::make_unary(OPERATOR_MULT, ptr, location); | |
4687 if (docheck == NIL_CHECK_NEEDED) | |
4688 deref->unary_expression()->set_requires_nil_check(true); | |
4689 else if (docheck == NIL_CHECK_NOT_NEEDED) | |
4690 deref->unary_expression()->set_requires_nil_check(false); | |
4691 return deref; | |
4533 } | 4692 } |
4534 | 4693 |
4535 // If this is an indirection through a pointer, return the expression | 4694 // If this is an indirection through a pointer, return the expression |
4536 // being pointed through. Otherwise return this. | 4695 // being pointed through. Otherwise return this. |
4537 | 4696 |
5281 { | 5440 { |
5282 Struct_type* st = this->left_->type()->struct_type(); | 5441 Struct_type* st = this->left_->type()->struct_type(); |
5283 Struct_type* st2 = this->right_->type()->struct_type(); | 5442 Struct_type* st2 = this->right_->type()->struct_type(); |
5284 if (st2 == NULL) | 5443 if (st2 == NULL) |
5285 return this; | 5444 return this; |
5286 if (st != st2 && !Type::are_identical(st, st2, false, NULL)) | 5445 if (st != st2 |
5446 && !Type::are_identical(st, st2, | |
5447 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, | |
5448 NULL)) | |
5287 return this; | 5449 return this; |
5288 if (!Type::are_compatible_for_comparison(true, this->left_->type(), | 5450 if (!Type::are_compatible_for_comparison(true, this->left_->type(), |
5289 this->right_->type(), NULL)) | 5451 this->right_->type(), NULL)) |
5290 return this; | 5452 return this; |
5291 | 5453 |
5360 { | 5522 { |
5361 Array_type* at = this->left_->type()->array_type(); | 5523 Array_type* at = this->left_->type()->array_type(); |
5362 Array_type* at2 = this->right_->type()->array_type(); | 5524 Array_type* at2 = this->right_->type()->array_type(); |
5363 if (at2 == NULL) | 5525 if (at2 == NULL) |
5364 return this; | 5526 return this; |
5365 if (at != at2 && !Type::are_identical(at, at2, false, NULL)) | 5527 if (at != at2 |
5528 && !Type::are_identical(at, at2, | |
5529 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, | |
5530 NULL)) | |
5366 return this; | 5531 return this; |
5367 if (!Type::are_compatible_for_comparison(true, this->left_->type(), | 5532 if (!Type::are_compatible_for_comparison(true, this->left_->type(), |
5368 this->right_->type(), NULL)) | 5533 this->right_->type(), NULL)) |
5369 return this; | 5534 return this; |
5370 | 5535 |
6750 Type* rtype = fntype->receiver()->type()->deref(); | 6915 Type* rtype = fntype->receiver()->type()->deref(); |
6751 Type* etype = (this->expr_type_ != NULL | 6916 Type* etype = (this->expr_type_ != NULL |
6752 ? this->expr_type_ | 6917 ? this->expr_type_ |
6753 : this->expr_->type()); | 6918 : this->expr_->type()); |
6754 etype = etype->deref(); | 6919 etype = etype->deref(); |
6755 if (!Type::are_identical(rtype, etype, true, NULL)) | 6920 if (!Type::are_identical(rtype, etype, Type::COMPARE_TAGS, NULL)) |
6756 this->report_error(_("method type does not match object type")); | 6921 this->report_error(_("method type does not match object type")); |
6757 } | 6922 } |
6758 | 6923 |
6759 // If a bound method expression is not simply called, then it is | 6924 // If a bound method expression is not simply called, then it is |
6760 // represented as a closure. The closure will hold a single variable, | 6925 // represented as a closure. The closure will hold a single variable, |
6796 else | 6961 else |
6797 orig_fntype = NULL; | 6962 orig_fntype = NULL; |
6798 | 6963 |
6799 if (orig_fntype == NULL || !orig_fntype->is_method()) | 6964 if (orig_fntype == NULL || !orig_fntype->is_method()) |
6800 { | 6965 { |
6801 ins.first->second = Named_object::make_erroneous_name(Gogo::thunk_name()); | 6966 ins.first->second = |
6967 Named_object::make_erroneous_name(gogo->thunk_name()); | |
6802 return ins.first->second; | 6968 return ins.first->second; |
6803 } | 6969 } |
6804 | 6970 |
6805 Struct_field_list* sfl = new Struct_field_list(); | 6971 Struct_field_list* sfl = new Struct_field_list(); |
6806 // The type here is wrong--it should be the C function type. But it | 6972 // The type here is wrong--it should be the C function type. But it |
6807 // doesn't really matter. | 6973 // doesn't really matter. |
6808 Type* vt = Type::make_pointer_type(Type::make_void_type()); | 6974 Type* vt = Type::make_pointer_type(Type::make_void_type()); |
6809 sfl->push_back(Struct_field(Typed_identifier("fn.0", vt, loc))); | 6975 sfl->push_back(Struct_field(Typed_identifier("fn", vt, loc))); |
6810 sfl->push_back(Struct_field(Typed_identifier("val.1", | 6976 sfl->push_back(Struct_field(Typed_identifier("val", |
6811 orig_fntype->receiver()->type(), | 6977 orig_fntype->receiver()->type(), |
6812 loc))); | 6978 loc))); |
6813 Struct_type* st = Type::make_struct_type(sfl, loc); | 6979 Struct_type* st = Type::make_struct_type(sfl, loc); |
6814 st->set_is_struct_incomparable(); | 6980 st->set_is_struct_incomparable(); |
6815 Type* closure_type = Type::make_pointer_type(st); | 6981 Type* closure_type = Type::make_pointer_type(st); |
6816 | 6982 |
6817 Function_type* new_fntype = orig_fntype->copy_with_names(); | 6983 Function_type* new_fntype = orig_fntype->copy_with_names(); |
6818 | 6984 |
6819 std::string thunk_name = Gogo::thunk_name(); | 6985 std::string thunk_name = gogo->thunk_name(); |
6820 Named_object* new_no = gogo->start_function(thunk_name, new_fntype, | 6986 Named_object* new_no = gogo->start_function(thunk_name, new_fntype, |
6821 false, loc); | 6987 false, loc); |
6822 | 6988 |
6823 Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc); | 6989 Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc); |
6824 cvar->set_is_used(); | 6990 cvar->set_is_used(); |
6830 gogo->start_block(loc); | 6996 gogo->start_block(loc); |
6831 | 6997 |
6832 // Field 0 of the closure is the function code pointer, field 1 is | 6998 // Field 0 of the closure is the function code pointer, field 1 is |
6833 // the value on which to invoke the method. | 6999 // the value on which to invoke the method. |
6834 Expression* arg = Expression::make_var_reference(cp, loc); | 7000 Expression* arg = Expression::make_var_reference(cp, loc); |
6835 arg = Expression::make_unary(OPERATOR_MULT, arg, loc); | 7001 arg = Expression::make_dereference(arg, NIL_CHECK_NOT_NEEDED, loc); |
6836 arg = Expression::make_field_reference(arg, 1, loc); | 7002 arg = Expression::make_field_reference(arg, 1, loc); |
6837 | 7003 |
6838 Expression* bme = Expression::make_bound_method(arg, method, fn, loc); | 7004 Expression* bme = Expression::make_bound_method(arg, method, fn, loc); |
6839 | 7005 |
6840 const Typed_identifier_list* orig_params = orig_fntype->parameters(); | 7006 const Typed_identifier_list* orig_params = orig_fntype->parameters(); |
6894 go_assert((*ref)->type()->points_to() != NULL); | 7060 go_assert((*ref)->type()->points_to() != NULL); |
6895 Expression* n = Expression::make_binary(OPERATOR_EQEQ, *ref, | 7061 Expression* n = Expression::make_binary(OPERATOR_EQEQ, *ref, |
6896 Expression::make_nil(loc), | 7062 Expression::make_nil(loc), |
6897 loc); | 7063 loc); |
6898 cond = Expression::make_binary(OPERATOR_OROR, cond, n, loc); | 7064 cond = Expression::make_binary(OPERATOR_OROR, cond, n, loc); |
6899 *ref = Expression::make_unary(OPERATOR_MULT, *ref, loc); | 7065 *ref = Expression::make_dereference(*ref, Expression::NIL_CHECK_DEFAULT, |
7066 loc); | |
6900 go_assert((*ref)->type()->struct_type() == stype); | 7067 go_assert((*ref)->type()->struct_type() == stype); |
6901 } | 7068 } |
6902 *ref = Expression::make_field_reference(*ref, field_indexes->field_index, | 7069 *ref = Expression::make_field_reference(*ref, field_indexes->field_index, |
6903 loc); | 7070 loc); |
6904 return cond; | 7071 return cond; |
6949 go_unreachable(); | 7116 go_unreachable(); |
6950 | 7117 |
6951 Expression* val = expr; | 7118 Expression* val = expr; |
6952 if (fntype->receiver()->type()->points_to() == NULL | 7119 if (fntype->receiver()->type()->points_to() == NULL |
6953 && val->type()->points_to() != NULL) | 7120 && val->type()->points_to() != NULL) |
6954 val = Expression::make_unary(OPERATOR_MULT, val, loc); | 7121 val = Expression::make_dereference(val, NIL_CHECK_DEFAULT, loc); |
6955 | 7122 |
6956 // Note that we are ignoring this->expr_type_ here. The thunk will | 7123 // Note that we are ignoring this->expr_type_ here. The thunk will |
6957 // expect a closure whose second field has type this->expr_type_ (if | 7124 // expect a closure whose second field has type this->expr_type_ (if |
6958 // that is not NULL). We are going to pass it a closure whose | 7125 // that is not NULL). We are going to pass it a closure whose |
6959 // second field has type this->expr_->type(). Since | 7126 // second field has type this->expr_->type(). Since |
6960 // this->expr_type_ is only not-NULL for pointer types, we can get | 7127 // this->expr_type_ is only not-NULL for pointer types, we can get |
6961 // away with this. | 7128 // away with this. |
6962 | 7129 |
6963 Struct_field_list* fields = new Struct_field_list(); | 7130 Struct_field_list* fields = new Struct_field_list(); |
6964 fields->push_back(Struct_field(Typed_identifier("fn.0", | 7131 fields->push_back(Struct_field(Typed_identifier("fn", |
6965 thunk->func_value()->type(), | 7132 thunk->func_value()->type(), |
6966 loc))); | 7133 loc))); |
6967 fields->push_back(Struct_field(Typed_identifier("val.1", val->type(), loc))); | 7134 fields->push_back(Struct_field(Typed_identifier("val", val->type(), loc))); |
6968 Struct_type* st = Type::make_struct_type(fields, loc); | 7135 Struct_type* st = Type::make_struct_type(fields, loc); |
6969 st->set_is_struct_incomparable(); | 7136 st->set_is_struct_incomparable(); |
6970 | 7137 |
6971 Expression_list* vals = new Expression_list(); | 7138 Expression_list* vals = new Expression_list(); |
6972 vals->push_back(Expression::make_func_code_reference(thunk, loc)); | 7139 vals->push_back(Expression::make_func_code_reference(thunk, loc)); |
6973 vals->push_back(val); | 7140 vals->push_back(val); |
6974 | 7141 |
6975 Expression* ret = Expression::make_struct_composite_literal(st, vals, loc); | 7142 Expression* ret = Expression::make_struct_composite_literal(st, vals, loc); |
6976 | 7143 ret = Expression::make_heap_expression(ret, loc); |
6977 if (!gogo->compiling_runtime() || gogo->package_name() != "runtime") | 7144 |
6978 ret = Expression::make_heap_expression(ret, loc); | 7145 Node* n = Node::make_node(this); |
6979 else | 7146 if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE) |
6980 { | 7147 ret->heap_expression()->set_allocate_on_stack(); |
6981 // When compiling the runtime, method closures do not escape. | 7148 else if (gogo->compiling_runtime() && gogo->package_name() == "runtime") |
6982 // When escape analysis becomes the default, and applies to | 7149 go_error_at(loc, "%s escapes to heap, not allowed in runtime", |
6983 // method closures, this should be changed to make it an error | 7150 n->ast_format(gogo).c_str()); |
6984 // if a method closure escapes. | |
6985 Temporary_statement* ctemp = Statement::make_temporary(st, ret, loc); | |
6986 inserter->insert(ctemp); | |
6987 ret = Expression::make_temporary_reference(ctemp, loc); | |
6988 ret = Expression::make_unary(OPERATOR_AND, ret, loc); | |
6989 ret->unary_expression()->set_does_not_escape(); | |
6990 } | |
6991 | 7151 |
6992 // If necessary, check whether the expression or any embedded | 7152 // If necessary, check whether the expression or any embedded |
6993 // pointers are nil. | 7153 // pointers are nil. |
6994 | 7154 |
6995 Expression* nil_check = NULL; | 7155 Expression* nil_check = NULL; |
7055 return new Bound_method_expression(expr, method, function, location); | 7215 return new Bound_method_expression(expr, method, function, location); |
7056 } | 7216 } |
7057 | 7217 |
7058 // Class Builtin_call_expression. This is used for a call to a | 7218 // Class Builtin_call_expression. This is used for a call to a |
7059 // builtin function. | 7219 // builtin function. |
7060 | |
7061 class Builtin_call_expression : public Call_expression | |
7062 { | |
7063 public: | |
7064 Builtin_call_expression(Gogo* gogo, Expression* fn, Expression_list* args, | |
7065 bool is_varargs, Location location); | |
7066 | |
7067 protected: | |
7068 // This overrides Call_expression::do_lower. | |
7069 Expression* | |
7070 do_lower(Gogo*, Named_object*, Statement_inserter*, int); | |
7071 | |
7072 Expression* | |
7073 do_flatten(Gogo*, Named_object*, Statement_inserter*); | |
7074 | |
7075 bool | |
7076 do_is_constant() const; | |
7077 | |
7078 bool | |
7079 do_numeric_constant_value(Numeric_constant*) const; | |
7080 | |
7081 bool | |
7082 do_discarding_value(); | |
7083 | |
7084 Type* | |
7085 do_type(); | |
7086 | |
7087 void | |
7088 do_determine_type(const Type_context*); | |
7089 | |
7090 void | |
7091 do_check_types(Gogo*); | |
7092 | |
7093 Expression* | |
7094 do_copy(); | |
7095 | |
7096 Bexpression* | |
7097 do_get_backend(Translate_context*); | |
7098 | |
7099 void | |
7100 do_export(Export*) const; | |
7101 | |
7102 virtual bool | |
7103 do_is_recover_call() const; | |
7104 | |
7105 virtual void | |
7106 do_set_recover_arg(Expression*); | |
7107 | |
7108 private: | |
7109 // The builtin functions. | |
7110 enum Builtin_function_code | |
7111 { | |
7112 BUILTIN_INVALID, | |
7113 | |
7114 // Predeclared builtin functions. | |
7115 BUILTIN_APPEND, | |
7116 BUILTIN_CAP, | |
7117 BUILTIN_CLOSE, | |
7118 BUILTIN_COMPLEX, | |
7119 BUILTIN_COPY, | |
7120 BUILTIN_DELETE, | |
7121 BUILTIN_IMAG, | |
7122 BUILTIN_LEN, | |
7123 BUILTIN_MAKE, | |
7124 BUILTIN_NEW, | |
7125 BUILTIN_PANIC, | |
7126 BUILTIN_PRINT, | |
7127 BUILTIN_PRINTLN, | |
7128 BUILTIN_REAL, | |
7129 BUILTIN_RECOVER, | |
7130 | |
7131 // Builtin functions from the unsafe package. | |
7132 BUILTIN_ALIGNOF, | |
7133 BUILTIN_OFFSETOF, | |
7134 BUILTIN_SIZEOF | |
7135 }; | |
7136 | |
7137 Expression* | |
7138 one_arg() const; | |
7139 | |
7140 bool | |
7141 check_one_arg(); | |
7142 | |
7143 static Type* | |
7144 real_imag_type(Type*); | |
7145 | |
7146 static Type* | |
7147 complex_type(Type*); | |
7148 | |
7149 Expression* | |
7150 lower_make(Statement_inserter*); | |
7151 | |
7152 Expression* flatten_append(Gogo*, Named_object*, Statement_inserter*); | |
7153 | |
7154 bool | |
7155 check_int_value(Expression*, bool is_length, bool* small); | |
7156 | |
7157 // A pointer back to the general IR structure. This avoids a global | |
7158 // variable, or passing it around everywhere. | |
7159 Gogo* gogo_; | |
7160 // The builtin function being called. | |
7161 Builtin_function_code code_; | |
7162 // Used to stop endless loops when the length of an array uses len | |
7163 // or cap of the array itself. | |
7164 mutable bool seen_; | |
7165 // Whether the argument is set for calls to BUILTIN_RECOVER. | |
7166 bool recover_arg_is_set_; | |
7167 }; | |
7168 | 7220 |
7169 Builtin_call_expression::Builtin_call_expression(Gogo* gogo, | 7221 Builtin_call_expression::Builtin_call_expression(Gogo* gogo, |
7170 Expression* fn, | 7222 Expression* fn, |
7171 Expression_list* args, | 7223 Expression_list* args, |
7172 bool is_varargs, | 7224 bool is_varargs, |
7370 Expression* e1 = Expression::make_type_descriptor(mt, loc); | 7422 Expression* e1 = Expression::make_type_descriptor(mt, loc); |
7371 Expression* e2 = Expression::make_temporary_reference(map_temp, | 7423 Expression* e2 = Expression::make_temporary_reference(map_temp, |
7372 loc); | 7424 loc); |
7373 Expression* e3 = Expression::make_temporary_reference(key_temp, | 7425 Expression* e3 = Expression::make_temporary_reference(key_temp, |
7374 loc); | 7426 loc); |
7375 e3 = Expression::make_unary(OPERATOR_AND, e3, loc); | 7427 |
7428 // If the call to delete is deferred, and is in a loop, | |
7429 // then the loop will only have a single instance of the | |
7430 // temporary variable. Passing the address of the | |
7431 // temporary variable here means that the deferred call | |
7432 // will see the last value in the loop, not the current | |
7433 // value. So for this unusual case copy the value into | |
7434 // the heap. | |
7435 if (!this->is_deferred()) | |
7436 e3 = Expression::make_unary(OPERATOR_AND, e3, loc); | |
7437 else | |
7438 { | |
7439 Expression* a = Expression::make_allocation(mt->key_type(), | |
7440 loc); | |
7441 Temporary_statement* atemp = | |
7442 Statement::make_temporary(NULL, a, loc); | |
7443 inserter->insert(atemp); | |
7444 | |
7445 a = Expression::make_temporary_reference(atemp, loc); | |
7446 a = Expression::make_dereference(a, NIL_CHECK_NOT_NEEDED, loc); | |
7447 Statement* s = Statement::make_assignment(a, e3, loc); | |
7448 inserter->insert(s); | |
7449 | |
7450 e3 = Expression::make_temporary_reference(atemp, loc); | |
7451 } | |
7452 | |
7376 return Runtime::make_call(Runtime::MAPDELETE, this->location(), | 7453 return Runtime::make_call(Runtime::MAPDELETE, this->location(), |
7377 3, e1, e2, e3); | 7454 3, e1, e2, e3); |
7378 } | 7455 } |
7379 } | 7456 } |
7380 break; | 7457 break; |
7416 { | 7493 { |
7417 default: | 7494 default: |
7418 break; | 7495 break; |
7419 | 7496 |
7420 case BUILTIN_APPEND: | 7497 case BUILTIN_APPEND: |
7421 return this->flatten_append(gogo, function, inserter); | 7498 return this->flatten_append(gogo, function, inserter, NULL, NULL); |
7422 | 7499 |
7423 case BUILTIN_COPY: | 7500 case BUILTIN_COPY: |
7424 { | 7501 { |
7425 Type* at = this->args()->front()->type(); | 7502 Type* at = this->args()->front()->type(); |
7426 for (Expression_list::iterator pa = this->args()->begin(); | 7503 for (Expression_list::iterator pa = this->args()->begin(); |
7534 { | 7611 { |
7535 this->report_error(_("length required when allocating a slice")); | 7612 this->report_error(_("length required when allocating a slice")); |
7536 return Expression::make_error(this->location()); | 7613 return Expression::make_error(this->location()); |
7537 } | 7614 } |
7538 len_arg = Expression::make_integer_ul(0, NULL, loc); | 7615 len_arg = Expression::make_integer_ul(0, NULL, loc); |
7616 len_small = true; | |
7539 } | 7617 } |
7540 else | 7618 else |
7541 { | 7619 { |
7542 len_arg = *parg; | 7620 len_arg = *parg; |
7543 len_arg->determine_type(&int_context); | 7621 len_arg->determine_type(&int_context); |
7622 if (len_arg->type()->integer_type() == NULL) | |
7623 { | |
7624 go_error_at(len_arg->location(), "non-integer len argument in make"); | |
7625 return Expression::make_error(this->location()); | |
7626 } | |
7544 if (!this->check_int_value(len_arg, true, &len_small)) | 7627 if (!this->check_int_value(len_arg, true, &len_small)) |
7545 return Expression::make_error(this->location()); | 7628 return Expression::make_error(this->location()); |
7546 ++parg; | 7629 ++parg; |
7547 } | 7630 } |
7548 | 7631 |
7549 Expression* cap_arg = NULL; | 7632 Expression* cap_arg = NULL; |
7550 bool cap_small = false; | 7633 bool cap_small = false; |
7634 Numeric_constant nclen; | |
7635 Numeric_constant nccap; | |
7636 unsigned long vlen; | |
7637 unsigned long vcap; | |
7551 if (is_slice && parg != args->end()) | 7638 if (is_slice && parg != args->end()) |
7552 { | 7639 { |
7553 cap_arg = *parg; | 7640 cap_arg = *parg; |
7554 cap_arg->determine_type(&int_context); | 7641 cap_arg->determine_type(&int_context); |
7642 if (cap_arg->type()->integer_type() == NULL) | |
7643 { | |
7644 go_error_at(cap_arg->location(), "non-integer cap argument in make"); | |
7645 return Expression::make_error(this->location()); | |
7646 } | |
7555 if (!this->check_int_value(cap_arg, false, &cap_small)) | 7647 if (!this->check_int_value(cap_arg, false, &cap_small)) |
7556 return Expression::make_error(this->location()); | 7648 return Expression::make_error(this->location()); |
7557 | 7649 |
7558 Numeric_constant nclen; | |
7559 Numeric_constant nccap; | |
7560 unsigned long vlen; | |
7561 unsigned long vcap; | |
7562 if (len_arg->numeric_constant_value(&nclen) | 7650 if (len_arg->numeric_constant_value(&nclen) |
7563 && cap_arg->numeric_constant_value(&nccap) | 7651 && cap_arg->numeric_constant_value(&nccap) |
7564 && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID | 7652 && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID |
7565 && nccap.to_unsigned_long(&vcap) == Numeric_constant::NC_UL_VALID | 7653 && nccap.to_unsigned_long(&vcap) == Numeric_constant::NC_UL_VALID |
7566 && vlen > vcap) | 7654 && vlen > vcap) |
7581 Location type_loc = first_arg->location(); | 7669 Location type_loc = first_arg->location(); |
7582 | 7670 |
7583 Expression* call; | 7671 Expression* call; |
7584 if (is_slice) | 7672 if (is_slice) |
7585 { | 7673 { |
7674 if (cap_arg == NULL) | |
7675 { | |
7676 cap_small = len_small; | |
7677 if (len_arg->numeric_constant_value(&nclen) | |
7678 && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID) | |
7679 cap_arg = Expression::make_integer_ul(vlen, len_arg->type(), loc); | |
7680 else | |
7681 { | |
7682 Temporary_statement* temp = Statement::make_temporary(NULL, | |
7683 len_arg, | |
7684 loc); | |
7685 inserter->insert(temp); | |
7686 len_arg = Expression::make_temporary_reference(temp, loc); | |
7687 cap_arg = Expression::make_temporary_reference(temp, loc); | |
7688 } | |
7689 } | |
7690 | |
7586 Type* et = type->array_type()->element_type(); | 7691 Type* et = type->array_type()->element_type(); |
7587 Expression* type_arg = Expression::make_type_descriptor(et, type_loc); | 7692 Expression* type_arg = Expression::make_type_descriptor(et, type_loc); |
7588 if (cap_arg == NULL) | |
7589 { | |
7590 Temporary_statement* temp = Statement::make_temporary(NULL, | |
7591 len_arg, | |
7592 loc); | |
7593 inserter->insert(temp); | |
7594 len_arg = Expression::make_temporary_reference(temp, loc); | |
7595 cap_arg = Expression::make_temporary_reference(temp, loc); | |
7596 cap_small = len_small; | |
7597 } | |
7598 | |
7599 Runtime::Function code = Runtime::MAKESLICE; | 7693 Runtime::Function code = Runtime::MAKESLICE; |
7600 if (!len_small || !cap_small) | 7694 if (!len_small || !cap_small) |
7601 code = Runtime::MAKESLICE64; | 7695 code = Runtime::MAKESLICE64; |
7602 call = Runtime::make_call(code, loc, 3, type_arg, len_arg, cap_arg); | 7696 call = Runtime::make_call(code, loc, 3, type_arg, len_arg, cap_arg); |
7603 } | 7697 } |
7604 else if (is_map) | 7698 else if (is_map) |
7605 { | 7699 { |
7606 Expression* type_arg = Expression::make_type_descriptor(type, type_loc); | 7700 Expression* type_arg = Expression::make_type_descriptor(type, type_loc); |
7607 call = Runtime::make_call(Runtime::MAKEMAP, loc, 4, type_arg, len_arg, | 7701 if (!len_small) |
7608 Expression::make_nil(loc), | 7702 call = Runtime::make_call(Runtime::MAKEMAP64, loc, 3, type_arg, |
7609 Expression::make_nil(loc)); | 7703 len_arg, |
7704 Expression::make_nil(loc)); | |
7705 else | |
7706 { | |
7707 Numeric_constant nclen; | |
7708 unsigned long vlen; | |
7709 if (len_arg->numeric_constant_value(&nclen) | |
7710 && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID | |
7711 && vlen <= Map_type::bucket_size) | |
7712 call = Runtime::make_call(Runtime::MAKEMAP_SMALL, loc, 0); | |
7713 else | |
7714 call = Runtime::make_call(Runtime::MAKEMAP, loc, 3, type_arg, | |
7715 len_arg, | |
7716 Expression::make_nil(loc)); | |
7717 } | |
7610 } | 7718 } |
7611 else if (is_chan) | 7719 else if (is_chan) |
7612 { | 7720 { |
7613 Expression* type_arg = Expression::make_type_descriptor(type, type_loc); | 7721 Expression* type_arg = Expression::make_type_descriptor(type, type_loc); |
7614 call = Runtime::make_call(Runtime::MAKECHAN, loc, 2, type_arg, len_arg); | 7722 Runtime::Function code = Runtime::MAKECHAN; |
7723 if (!len_small) | |
7724 code = Runtime::MAKECHAN64; | |
7725 call = Runtime::make_call(code, loc, 2, type_arg, len_arg); | |
7615 } | 7726 } |
7616 else | 7727 else |
7617 go_unreachable(); | 7728 go_unreachable(); |
7618 | 7729 |
7619 return Expression::make_unsafe_cast(type, call, loc); | 7730 return Expression::make_unsafe_cast(type, call, loc); |
7620 } | 7731 } |
7621 | 7732 |
7622 // Flatten a call to the predeclared append function. We do this in | 7733 // Flatten a call to the predeclared append function. We do this in |
7623 // the flatten phase, not the lowering phase, so that we run after | 7734 // the flatten phase, not the lowering phase, so that we run after |
7624 // type checking and after order_evaluations. | 7735 // type checking and after order_evaluations. If ASSIGN_LHS is not |
7736 // NULL, this append is the right-hand-side of an assignment and | |
7737 // ASSIGN_LHS is the left-hand-side; in that case, set LHS directly | |
7738 // rather than returning a slice. This lets us omit a write barrier | |
7739 // in common cases like a = append(a, ...) when the slice does not | |
7740 // need to grow. ENCLOSING is not NULL iff ASSIGN_LHS is not NULL. | |
7625 | 7741 |
7626 Expression* | 7742 Expression* |
7627 Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function, | 7743 Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function, |
7628 Statement_inserter* inserter) | 7744 Statement_inserter* inserter, |
7745 Expression* assign_lhs, | |
7746 Block* enclosing) | |
7629 { | 7747 { |
7630 if (this->is_error_expression()) | 7748 if (this->is_error_expression()) |
7631 return this; | 7749 return this; |
7632 | 7750 |
7633 Location loc = this->location(); | 7751 Location loc = this->location(); |
7640 Type* element_type = slice_type->array_type()->element_type(); | 7758 Type* element_type = slice_type->array_type()->element_type(); |
7641 | 7759 |
7642 if (args->size() == 1) | 7760 if (args->size() == 1) |
7643 { | 7761 { |
7644 // append(s) evaluates to s. | 7762 // append(s) evaluates to s. |
7763 if (assign_lhs != NULL) | |
7764 return NULL; | |
7645 return args->front(); | 7765 return args->front(); |
7646 } | 7766 } |
7647 | 7767 |
7648 Type* int_type = Type::lookup_integer_type("int"); | 7768 Type* int_type = Type::lookup_integer_type("int"); |
7649 Type* uint_type = Type::lookup_integer_type("uint"); | 7769 Type* uint_type = Type::lookup_integer_type("uint"); |
7756 Expression* zero = Expression::make_integer_ul(0, int_type, loc); | 7876 Expression* zero = Expression::make_integer_ul(0, int_type, loc); |
7757 Expression* ref2 = Expression::make_temporary_reference(ntmp, loc); | 7877 Expression* ref2 = Expression::make_temporary_reference(ntmp, loc); |
7758 // FIXME: Mark this index as not requiring bounds checks. | 7878 // FIXME: Mark this index as not requiring bounds checks. |
7759 ref = Expression::make_index(ref, zero, ref2, NULL, loc); | 7879 ref = Expression::make_index(ref, zero, ref2, NULL, loc); |
7760 | 7880 |
7761 Expression* rhs = Expression::make_conditional(cond, call, ref, loc); | 7881 if (assign_lhs == NULL) |
7762 | 7882 { |
7763 gogo->lower_expression(function, inserter, &rhs); | 7883 Expression* rhs = Expression::make_conditional(cond, call, ref, loc); |
7764 gogo->flatten_expression(function, inserter, &rhs); | 7884 |
7765 | 7885 gogo->lower_expression(function, inserter, &rhs); |
7766 Expression* lhs = Expression::make_temporary_reference(s1tmp, loc); | 7886 gogo->flatten_expression(function, inserter, &rhs); |
7767 Statement* assign = Statement::make_assignment(lhs, rhs, loc); | 7887 |
7768 inserter->insert(assign); | 7888 ref = Expression::make_temporary_reference(s1tmp, loc); |
7889 Statement* assign = Statement::make_assignment(ref, rhs, loc); | |
7890 inserter->insert(assign); | |
7891 } | |
7892 else | |
7893 { | |
7894 gogo->lower_expression(function, inserter, &cond); | |
7895 gogo->flatten_expression(function, inserter, &cond); | |
7896 gogo->lower_expression(function, inserter, &call); | |
7897 gogo->flatten_expression(function, inserter, &call); | |
7898 gogo->lower_expression(function, inserter, &ref); | |
7899 gogo->flatten_expression(function, inserter, &ref); | |
7900 | |
7901 Block* then_block = new Block(enclosing, loc); | |
7902 Assignment_statement* assign = | |
7903 Statement::make_assignment(assign_lhs, call, loc); | |
7904 then_block->add_statement(assign); | |
7905 | |
7906 Block* else_block = new Block(enclosing, loc); | |
7907 assign = Statement::make_assignment(assign_lhs->copy(), ref, loc); | |
7908 // This assignment will not change the pointer value, so it does | |
7909 // not need a write barrier. | |
7910 assign->set_omit_write_barrier(); | |
7911 else_block->add_statement(assign); | |
7912 | |
7913 Statement* s = Statement::make_if_statement(cond, then_block, | |
7914 else_block, loc); | |
7915 inserter->insert(s); | |
7916 | |
7917 ref = Expression::make_temporary_reference(s1tmp, loc); | |
7918 assign = Statement::make_assignment(ref, assign_lhs->copy(), loc); | |
7919 inserter->insert(assign); | |
7920 } | |
7769 | 7921 |
7770 if (this->is_varargs()) | 7922 if (this->is_varargs()) |
7771 { | 7923 { |
7772 // copy(s1tmp[l1tmp:], s2tmp) | 7924 // copy(s1tmp[l1tmp:], s2tmp) |
7773 a1 = Expression::make_temporary_reference(s1tmp, loc); | 7925 a1 = Expression::make_temporary_reference(s1tmp, loc); |
7800 ref = Expression::make_temporary_reference(s1tmp, loc); | 7952 ref = Expression::make_temporary_reference(s1tmp, loc); |
7801 ref2 = Expression::make_temporary_reference(l1tmp, loc); | 7953 ref2 = Expression::make_temporary_reference(l1tmp, loc); |
7802 Expression* off = Expression::make_integer_ul(i, int_type, loc); | 7954 Expression* off = Expression::make_integer_ul(i, int_type, loc); |
7803 ref2 = Expression::make_binary(OPERATOR_PLUS, ref2, off, loc); | 7955 ref2 = Expression::make_binary(OPERATOR_PLUS, ref2, off, loc); |
7804 // FIXME: Mark this index as not requiring bounds checks. | 7956 // FIXME: Mark this index as not requiring bounds checks. |
7805 lhs = Expression::make_index(ref, ref2, NULL, NULL, loc); | 7957 Expression* lhs = Expression::make_index(ref, ref2, NULL, NULL, |
7958 loc); | |
7806 gogo->lower_expression(function, inserter, &lhs); | 7959 gogo->lower_expression(function, inserter, &lhs); |
7807 gogo->flatten_expression(function, inserter, &lhs); | 7960 gogo->flatten_expression(function, inserter, &lhs); |
7808 // The flatten pass runs after the write barrier pass, so we | 7961 // The flatten pass runs after the write barrier pass, so we |
7809 // need to insert a write barrier here if necessary. | 7962 // need to insert a write barrier here if necessary. |
7810 if (!gogo->assign_needs_write_barrier(lhs)) | 7963 // However, if ASSIGN_LHS is not NULL, we have been called |
7964 // directly before the write barrier pass. | |
7965 Statement* assign; | |
7966 if (assign_lhs != NULL | |
7967 || !gogo->assign_needs_write_barrier(lhs)) | |
7811 assign = Statement::make_assignment(lhs, *pa, loc); | 7968 assign = Statement::make_assignment(lhs, *pa, loc); |
7812 else | 7969 else |
7813 { | 7970 { |
7814 Function* f = function == NULL ? NULL : function->func_value(); | 7971 Function* f = function == NULL ? NULL : function->func_value(); |
7815 assign = gogo->assign_with_write_barrier(f, NULL, inserter, | 7972 assign = gogo->assign_with_write_barrier(f, NULL, inserter, |
7816 lhs, *pa, loc); | 7973 lhs, *pa, loc); |
7817 } | 7974 } |
7818 inserter->insert(assign); | 7975 inserter->insert(assign); |
7819 } | 7976 } |
7820 } | 7977 } |
7978 | |
7979 if (assign_lhs != NULL) | |
7980 return NULL; | |
7821 | 7981 |
7822 return Expression::make_temporary_reference(s1tmp, loc); | 7982 return Expression::make_temporary_reference(s1tmp, loc); |
7823 } | 7983 } |
7824 | 7984 |
7825 // Return whether an expression has an integer value. Report an error | 7985 // Return whether an expression has an integer value. Report an error |
7966 }; | 8126 }; |
7967 | 8127 |
7968 int | 8128 int |
7969 Find_call_expression::expression(Expression** pexpr) | 8129 Find_call_expression::expression(Expression** pexpr) |
7970 { | 8130 { |
7971 if ((*pexpr)->call_expression() != NULL | 8131 Expression* expr = *pexpr; |
7972 || (*pexpr)->receive_expression() != NULL) | 8132 if (!expr->is_constant() |
8133 && (expr->call_expression() != NULL | |
8134 || expr->receive_expression() != NULL)) | |
7973 { | 8135 { |
7974 this->found_ = true; | 8136 this->found_ = true; |
7975 return TRAVERSE_EXIT; | 8137 return TRAVERSE_EXIT; |
7976 } | 8138 } |
7977 return TRAVERSE_CONTINUE; | 8139 return TRAVERSE_CONTINUE; |
8140 } | |
8141 | |
8142 // Return whether calling len or cap on EXPR, of array type, is a | |
8143 // constant. The language spec says "the expressions len(s) and | |
8144 // cap(s) are constants if the type of s is an array or pointer to an | |
8145 // array and the expression s does not contain channel receives or | |
8146 // (non-constant) function calls." | |
8147 | |
8148 bool | |
8149 Builtin_call_expression::array_len_is_constant(Expression* expr) | |
8150 { | |
8151 go_assert(expr->type()->deref()->array_type() != NULL | |
8152 && !expr->type()->deref()->is_slice_type()); | |
8153 if (expr->is_constant()) | |
8154 return true; | |
8155 Find_call_expression find_call; | |
8156 Expression::traverse(&expr, &find_call); | |
8157 return !find_call.found(); | |
7978 } | 8158 } |
7979 | 8159 |
7980 // Return whether this is constant: len of a string constant, or len | 8160 // Return whether this is constant: len of a string constant, or len |
7981 // or cap of an array, or unsafe.Sizeof, unsafe.Offsetof, | 8161 // or cap of an array, or unsafe.Sizeof, unsafe.Offsetof, |
7982 // unsafe.Alignof. | 8162 // unsafe.Alignof. |
8002 if (arg_type->points_to() != NULL | 8182 if (arg_type->points_to() != NULL |
8003 && arg_type->points_to()->array_type() != NULL | 8183 && arg_type->points_to()->array_type() != NULL |
8004 && !arg_type->points_to()->is_slice_type()) | 8184 && !arg_type->points_to()->is_slice_type()) |
8005 arg_type = arg_type->points_to(); | 8185 arg_type = arg_type->points_to(); |
8006 | 8186 |
8007 // The len and cap functions are only constant if there are no | |
8008 // function calls or channel operations in the arguments. | |
8009 // Otherwise we have to make the call. | |
8010 if (!arg->is_constant()) | |
8011 { | |
8012 Find_call_expression find_call; | |
8013 Expression::traverse(&arg, &find_call); | |
8014 if (find_call.found()) | |
8015 return false; | |
8016 } | |
8017 | |
8018 if (arg_type->array_type() != NULL | 8187 if (arg_type->array_type() != NULL |
8019 && arg_type->array_type()->length() != NULL) | 8188 && arg_type->array_type()->length() != NULL) |
8020 return true; | 8189 { |
8190 this->seen_ = true; | |
8191 bool ret = Builtin_call_expression::array_len_is_constant(arg); | |
8192 this->seen_ = false; | |
8193 return ret; | |
8194 } | |
8021 | 8195 |
8022 if (this->code_ == BUILTIN_LEN && arg_type->is_string_type()) | 8196 if (this->code_ == BUILTIN_LEN && arg_type->is_string_type()) |
8023 { | 8197 { |
8024 this->seen_ = true; | 8198 this->seen_ = true; |
8025 bool ret = arg->is_constant(); | 8199 bool ret = arg->is_constant(); |
8176 Type* st = struct_expr->type(); | 8350 Type* st = struct_expr->type(); |
8177 if (st->struct_type() == NULL) | 8351 if (st->struct_type() == NULL) |
8178 return false; | 8352 return false; |
8179 if (st->named_type() != NULL) | 8353 if (st->named_type() != NULL) |
8180 st->named_type()->convert(this->gogo_); | 8354 st->named_type()->convert(this->gogo_); |
8355 if (st->is_error_type()) | |
8356 { | |
8357 go_assert(saw_errors()); | |
8358 return false; | |
8359 } | |
8181 int64_t offset; | 8360 int64_t offset; |
8182 this->seen_ = true; | 8361 this->seen_ = true; |
8183 bool ok = st->struct_type()->backend_field_offset(this->gogo_, | 8362 bool ok = st->struct_type()->backend_field_offset(this->gogo_, |
8184 farg->field_index(), | 8363 farg->field_index(), |
8185 &offset); | 8364 &offset); |
8238 | 8417 |
8239 if (rnc.type() != NULL | 8418 if (rnc.type() != NULL |
8240 && !rnc.type()->is_abstract() | 8419 && !rnc.type()->is_abstract() |
8241 && inc.type() != NULL | 8420 && inc.type() != NULL |
8242 && !inc.type()->is_abstract() | 8421 && !inc.type()->is_abstract() |
8243 && !Type::are_identical(rnc.type(), inc.type(), false, NULL)) | 8422 && !Type::are_identical(rnc.type(), inc.type(), |
8423 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, | |
8424 NULL)) | |
8244 return false; | 8425 return false; |
8245 | 8426 |
8246 mpfr_t r; | 8427 mpfr_t r; |
8247 if (!rnc.to_float(&r)) | 8428 if (!rnc.to_float(&r)) |
8248 return false; | 8429 return false; |
8325 case BUILTIN_INVALID: | 8506 case BUILTIN_INVALID: |
8326 default: | 8507 default: |
8327 return Type::make_error_type(); | 8508 return Type::make_error_type(); |
8328 | 8509 |
8329 case BUILTIN_NEW: | 8510 case BUILTIN_NEW: |
8511 { | |
8512 const Expression_list* args = this->args(); | |
8513 if (args == NULL || args->empty()) | |
8514 return Type::make_error_type(); | |
8515 return Type::make_pointer_type(args->front()->type()); | |
8516 } | |
8517 | |
8330 case BUILTIN_MAKE: | 8518 case BUILTIN_MAKE: |
8331 { | 8519 { |
8332 const Expression_list* args = this->args(); | 8520 const Expression_list* args = this->args(); |
8333 if (args == NULL || args->empty()) | 8521 if (args == NULL || args->empty()) |
8334 return Type::make_error_type(); | 8522 return Type::make_error_type(); |
8335 return Type::make_pointer_type(args->front()->type()); | 8523 return args->front()->type(); |
8336 } | 8524 } |
8337 | 8525 |
8338 case BUILTIN_CAP: | 8526 case BUILTIN_CAP: |
8339 case BUILTIN_COPY: | 8527 case BUILTIN_COPY: |
8340 case BUILTIN_LEN: | 8528 case BUILTIN_LEN: |
8712 } | 8900 } |
8713 | 8901 |
8714 if (arg2_type->is_slice_type()) | 8902 if (arg2_type->is_slice_type()) |
8715 { | 8903 { |
8716 Type* e2 = arg2_type->array_type()->element_type(); | 8904 Type* e2 = arg2_type->array_type()->element_type(); |
8717 if (!Type::are_identical(e1, e2, true, NULL)) | 8905 if (!Type::are_identical(e1, e2, Type::COMPARE_TAGS, NULL)) |
8718 this->report_error(_("element types must be the same")); | 8906 this->report_error(_("element types must be the same")); |
8719 } | 8907 } |
8720 else if (arg2_type->is_string_type()) | 8908 else if (arg2_type->is_string_type()) |
8721 { | 8909 { |
8722 if (e1->integer_type() == NULL || !e1->integer_type()->is_byte()) | 8910 if (e1->integer_type() == NULL || !e1->integer_type()->is_byte()) |
8850 || args->front()->type()->is_error() | 9038 || args->front()->type()->is_error() |
8851 || args->back()->is_error_expression() | 9039 || args->back()->is_error_expression() |
8852 || args->back()->type()->is_error()) | 9040 || args->back()->type()->is_error()) |
8853 this->set_is_error(); | 9041 this->set_is_error(); |
8854 else if (!Type::are_identical(args->front()->type(), | 9042 else if (!Type::are_identical(args->front()->type(), |
8855 args->back()->type(), true, NULL)) | 9043 args->back()->type(), |
9044 Type::COMPARE_TAGS, NULL)) | |
8856 this->report_error(_("complex arguments must have identical types")); | 9045 this->report_error(_("complex arguments must have identical types")); |
8857 else if (args->front()->type()->float_type() == NULL) | 9046 else if (args->front()->type()->float_type() == NULL) |
8858 this->report_error(_("complex arguments must have " | 9047 this->report_error(_("complex arguments must have " |
8859 "floating-point type")); | 9048 "floating-point type")); |
8860 } | 9049 } |
8876 this->is_varargs(), | 9065 this->is_varargs(), |
8877 this->location()); | 9066 this->location()); |
8878 | 9067 |
8879 if (this->varargs_are_lowered()) | 9068 if (this->varargs_are_lowered()) |
8880 bce->set_varargs_are_lowered(); | 9069 bce->set_varargs_are_lowered(); |
9070 if (this->is_deferred()) | |
9071 bce->set_is_deferred(); | |
9072 if (this->is_concurrent()) | |
9073 bce->set_is_concurrent(); | |
8881 return bce; | 9074 return bce; |
8882 } | 9075 } |
8883 | 9076 |
8884 // Return the backend representation for a builtin function. | 9077 // Return the backend representation for a builtin function. |
8885 | 9078 |
8920 if (arg_type->points_to() != NULL) | 9113 if (arg_type->points_to() != NULL) |
8921 { | 9114 { |
8922 arg_type = arg_type->points_to(); | 9115 arg_type = arg_type->points_to(); |
8923 go_assert(arg_type->array_type() != NULL | 9116 go_assert(arg_type->array_type() != NULL |
8924 && !arg_type->is_slice_type()); | 9117 && !arg_type->is_slice_type()); |
8925 arg = Expression::make_unary(OPERATOR_MULT, arg, location); | 9118 arg = Expression::make_dereference(arg, NIL_CHECK_DEFAULT, |
9119 location); | |
8926 } | 9120 } |
8927 | 9121 |
8928 Type* int_type = Type::lookup_integer_type("int"); | 9122 Type* int_type = Type::lookup_integer_type("int"); |
8929 Expression* val; | 9123 Expression* val; |
8930 if (this->code_ == BUILTIN_LEN) | 9124 if (this->code_ == BUILTIN_LEN) |
8954 nil = Expression::make_cast(pint_type, nil, location); | 9148 nil = Expression::make_cast(pint_type, nil, location); |
8955 Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, | 9149 Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, |
8956 arg, nil, location); | 9150 arg, nil, location); |
8957 Expression* zero = Expression::make_integer_ul(0, int_type, | 9151 Expression* zero = Expression::make_integer_ul(0, int_type, |
8958 location); | 9152 location); |
8959 Expression* indir = Expression::make_unary(OPERATOR_MULT, | 9153 Expression* indir = |
8960 arg, location); | 9154 Expression::make_dereference(arg, NIL_CHECK_NOT_NEEDED, |
9155 location); | |
8961 val = Expression::make_conditional(cmp, zero, indir, location); | 9156 val = Expression::make_conditional(cmp, zero, indir, location); |
8962 } | 9157 } |
8963 else | 9158 else |
8964 go_unreachable(); | 9159 go_unreachable(); |
8965 } | 9160 } |
8996 nil = Expression::make_cast(pint_type, nil, location); | 9191 nil = Expression::make_cast(pint_type, nil, location); |
8997 Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, | 9192 Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, |
8998 arg, nil, location); | 9193 arg, nil, location); |
8999 Expression* zero = Expression::make_integer_ul(0, int_type, | 9194 Expression* zero = Expression::make_integer_ul(0, int_type, |
9000 location); | 9195 location); |
9001 Expression* indir = Expression::make_unary(OPERATOR_MULT, | 9196 Expression* indir = |
9002 parg, location); | 9197 Expression::make_dereference(parg, NIL_CHECK_NOT_NEEDED, |
9198 location); | |
9003 val = Expression::make_conditional(cmp, zero, indir, location); | 9199 val = Expression::make_conditional(cmp, zero, indir, location); |
9004 } | 9200 } |
9005 else | 9201 else |
9006 go_unreachable(); | 9202 go_unreachable(); |
9007 } | 9203 } |
9455 } | 9651 } |
9456 } | 9652 } |
9457 | 9653 |
9458 // Recognize a call to a builtin function. | 9654 // Recognize a call to a builtin function. |
9459 if (fntype->is_builtin()) | 9655 if (fntype->is_builtin()) |
9460 return new Builtin_call_expression(gogo, this->fn_, this->args_, | 9656 { |
9461 this->is_varargs_, loc); | 9657 Builtin_call_expression* bce = |
9658 new Builtin_call_expression(gogo, this->fn_, this->args_, | |
9659 this->is_varargs_, loc); | |
9660 if (this->is_deferred_) | |
9661 bce->set_is_deferred(); | |
9662 if (this->is_concurrent_) | |
9663 bce->set_is_concurrent(); | |
9664 return bce; | |
9665 } | |
9462 | 9666 |
9463 // If this call returns multiple results, create a temporary | 9667 // If this call returns multiple results, create a temporary |
9464 // variable to hold them. | 9668 // variable to hold them. |
9465 if (this->result_count() > 1 && this->call_temp_ == NULL) | 9669 if (this->result_count() > 1 && this->call_temp_ == NULL) |
9466 { | 9670 { |
9551 // getcallersp returns the frame pointer of the caller. Implement | 9755 // getcallersp returns the frame pointer of the caller. Implement |
9552 // these by turning them into calls to GCC builtin functions. We | 9756 // these by turning them into calls to GCC builtin functions. We |
9553 // could implement them in normal code, but then we would have to | 9757 // could implement them in normal code, but then we would have to |
9554 // explicitly unwind the stack. These functions are intended to be | 9758 // explicitly unwind the stack. These functions are intended to be |
9555 // efficient. Note that this technique obviously only works for | 9759 // efficient. Note that this technique obviously only works for |
9556 // direct calls, but that is the only way they are used. The actual | 9760 // direct calls, but that is the only way they are used. |
9557 // argument to these functions is always the address of a parameter; | 9761 if (gogo->compiling_runtime() && gogo->package_name() == "runtime") |
9558 // we don't need that for the GCC builtin functions, so we just | |
9559 // ignore it. | |
9560 if (gogo->compiling_runtime() | |
9561 && this->args_ != NULL | |
9562 && this->args_->size() == 1 | |
9563 && gogo->package_name() == "runtime") | |
9564 { | 9762 { |
9565 Func_expression* fe = this->fn_->func_expression(); | 9763 Func_expression* fe = this->fn_->func_expression(); |
9566 if (fe != NULL | 9764 if (fe != NULL |
9567 && fe->named_object()->is_function_declaration() | 9765 && fe->named_object()->is_function_declaration() |
9568 && fe->named_object()->package() == NULL) | 9766 && fe->named_object()->package() == NULL) |
9569 { | 9767 { |
9570 std::string n = Gogo::unpack_hidden_name(fe->named_object()->name()); | 9768 std::string n = Gogo::unpack_hidden_name(fe->named_object()->name()); |
9571 if (n == "getcallerpc") | 9769 if ((this->args_ == NULL || this->args_->size() == 0) |
9770 && n == "getcallerpc") | |
9572 { | 9771 { |
9573 static Named_object* builtin_return_address; | 9772 static Named_object* builtin_return_address; |
9574 return this->lower_to_builtin(&builtin_return_address, | 9773 return this->lower_to_builtin(&builtin_return_address, |
9575 "__builtin_return_address", | 9774 "__builtin_return_address", |
9576 0); | 9775 0); |
9577 } | 9776 } |
9578 else if (n == "getcallersp") | 9777 else if ((this->args_ == NULL || this->args_->size() == 0) |
9778 && n == "getcallersp") | |
9579 { | 9779 { |
9580 static Named_object* builtin_frame_address; | 9780 static Named_object* builtin_frame_address; |
9581 return this->lower_to_builtin(&builtin_frame_address, | 9781 return this->lower_to_builtin(&builtin_frame_address, |
9582 "__builtin_frame_address", | 9782 "__builtin_frame_address", |
9583 1); | 9783 1); |
9599 Call_expression::lower_varargs(Gogo* gogo, Named_object* function, | 9799 Call_expression::lower_varargs(Gogo* gogo, Named_object* function, |
9600 Statement_inserter* inserter, | 9800 Statement_inserter* inserter, |
9601 Type* varargs_type, size_t param_count, | 9801 Type* varargs_type, size_t param_count, |
9602 Slice_storage_escape_disp escape_disp) | 9802 Slice_storage_escape_disp escape_disp) |
9603 { | 9803 { |
9604 // When compiling the runtime, varargs slices do not escape. When | |
9605 // escape analysis becomes the default, this should be changed to | |
9606 // make it an error if we have a varargs slice that escapes. | |
9607 if (gogo->compiling_runtime() && gogo->package_name() == "runtime") | |
9608 escape_disp = SLICE_STORAGE_DOES_NOT_ESCAPE; | |
9609 | |
9610 if (this->varargs_are_lowered_) | 9804 if (this->varargs_are_lowered_) |
9611 return; | 9805 return; |
9612 | 9806 |
9613 Location loc = this->location(); | 9807 Location loc = this->location(); |
9614 | 9808 |
9757 ++pa; | 9951 ++pa; |
9758 } | 9952 } |
9759 for (; pa != this->args_->end(); ++pa, ++pp) | 9953 for (; pa != this->args_->end(); ++pa, ++pp) |
9760 { | 9954 { |
9761 go_assert(pp != fntype->parameters()->end()); | 9955 go_assert(pp != fntype->parameters()->end()); |
9762 if (Type::are_identical(pp->type(), (*pa)->type(), true, NULL)) | 9956 if (Type::are_identical(pp->type(), (*pa)->type(), |
9957 Type::COMPARE_TAGS, NULL)) | |
9763 args->push_back(*pa); | 9958 args->push_back(*pa); |
9764 else | 9959 else |
9765 { | 9960 { |
9766 Location loc = (*pa)->location(); | 9961 Location loc = (*pa)->location(); |
9767 Expression* arg = *pa; | 9962 Expression* arg = *pa; |
10075 return; | 10270 return; |
10076 } | 10271 } |
10077 } | 10272 } |
10078 | 10273 |
10079 const Typed_identifier_list* parameters = fntype->parameters(); | 10274 const Typed_identifier_list* parameters = fntype->parameters(); |
10080 if (this->args_ == NULL) | 10275 if (this->args_ == NULL || this->args_->size() == 0) |
10081 { | 10276 { |
10082 if (parameters != NULL && !parameters->empty()) | 10277 if (parameters != NULL && !parameters->empty()) |
10083 this->report_error(_("not enough arguments")); | 10278 this->report_error(_("not enough arguments")); |
10084 } | 10279 } |
10085 else if (parameters == NULL) | 10280 else if (parameters == NULL) |
10134 : this->args_->copy()), | 10329 : this->args_->copy()), |
10135 this->is_varargs_, this->location()); | 10330 this->is_varargs_, this->location()); |
10136 | 10331 |
10137 if (this->varargs_are_lowered_) | 10332 if (this->varargs_are_lowered_) |
10138 call->set_varargs_are_lowered(); | 10333 call->set_varargs_are_lowered(); |
10334 if (this->is_deferred_) | |
10335 call->set_is_deferred(); | |
10336 if (this->is_concurrent_) | |
10337 call->set_is_concurrent(); | |
10139 return call; | 10338 return call; |
10140 } | 10339 } |
10141 | 10340 |
10142 // Return whether we have to use a temporary variable to ensure that | 10341 // Return whether we have to use a temporary variable to ensure that |
10143 // we evaluate this call expression in order. If the call returns no | 10342 // we evaluate this call expression in order. If the call returns no |
10275 // to a struct whose first field is the actual function to call. | 10474 // to a struct whose first field is the actual function to call. |
10276 Type* pfntype = | 10475 Type* pfntype = |
10277 Type::make_pointer_type( | 10476 Type::make_pointer_type( |
10278 Type::make_pointer_type(Type::make_void_type())); | 10477 Type::make_pointer_type(Type::make_void_type())); |
10279 fn = Expression::make_unsafe_cast(pfntype, this->fn_, location); | 10478 fn = Expression::make_unsafe_cast(pfntype, this->fn_, location); |
10280 fn = Expression::make_unary(OPERATOR_MULT, fn, location); | 10479 fn = Expression::make_dereference(fn, NIL_CHECK_NOT_NEEDED, location); |
10281 } | 10480 } |
10282 else | 10481 else |
10283 { | 10482 { |
10284 Expression* first_arg; | 10483 Expression* first_arg; |
10285 fn = this->interface_method_function(interface_method, &first_arg, | 10484 fn = this->interface_method_function(interface_method, &first_arg, |
10533 return Expression::make_array_index(left, start, end, cap, location); | 10732 return Expression::make_array_index(left, start, end, cap, location); |
10534 else if (type->points_to() != NULL | 10733 else if (type->points_to() != NULL |
10535 && type->points_to()->array_type() != NULL | 10734 && type->points_to()->array_type() != NULL |
10536 && !type->points_to()->is_slice_type()) | 10735 && !type->points_to()->is_slice_type()) |
10537 { | 10736 { |
10538 Expression* deref = Expression::make_unary(OPERATOR_MULT, left, | 10737 Expression* deref = |
10539 location); | 10738 Expression::make_dereference(left, NIL_CHECK_DEFAULT, location); |
10540 | 10739 |
10541 // For an ordinary index into the array, the pointer will be | 10740 // For an ordinary index into the array, the pointer will be |
10542 // dereferenced. For a slice it will not--the resulting slice | 10741 // dereferenced. For a slice it will not--the resulting slice |
10543 // will simply reuse the pointer, which is incorrect if that | 10742 // will simply reuse the pointer, which is incorrect if that |
10544 // pointer is nil. | 10743 // pointer is nil. |
10712 } | 10911 } |
10713 | 10912 |
10714 // Check types of an array index. | 10913 // Check types of an array index. |
10715 | 10914 |
10716 void | 10915 void |
10717 Array_index_expression::do_check_types(Gogo* gogo) | 10916 Array_index_expression::do_check_types(Gogo*) |
10718 { | 10917 { |
10719 Numeric_constant nc; | 10918 Numeric_constant nc; |
10720 unsigned long v; | 10919 unsigned long v; |
10721 if (this->start_->type()->integer_type() == NULL | 10920 if (this->start_->type()->integer_type() == NULL |
10722 && !this->start_->type()->is_error() | 10921 && !this->start_->type()->is_error() |
10831 if (this->end_ != NULL && !array_type->is_slice_type()) | 11030 if (this->end_ != NULL && !array_type->is_slice_type()) |
10832 { | 11031 { |
10833 if (!this->array_->is_addressable()) | 11032 if (!this->array_->is_addressable()) |
10834 this->report_error(_("slice of unaddressable value")); | 11033 this->report_error(_("slice of unaddressable value")); |
10835 else | 11034 else |
10836 { | 11035 // Set the array address taken but not escape. The escape |
10837 bool escapes = true; | 11036 // analysis will make it escape to heap when needed. |
10838 | 11037 this->array_->address_taken(false); |
10839 // When compiling the runtime, a slice operation does not | 11038 } |
10840 // cause local variables to escape. When escape analysis | 11039 } |
10841 // becomes the default, this should be changed to make it an | 11040 |
10842 // error if we have a slice operation that escapes. | 11041 // The subexpressions of an array index must be evaluated in order. |
10843 if (gogo->compiling_runtime() && gogo->package_name() == "runtime") | 11042 // If this is indexing into an array, rather than a slice, then only |
10844 escapes = false; | 11043 // the index should be evaluated. Since this is called for values on |
10845 | 11044 // the left hand side of an assigment, evaluating the array, meaning |
10846 this->array_->address_taken(escapes); | 11045 // copying the array, will cause a different array to be modified. |
10847 } | 11046 |
10848 } | 11047 bool |
11048 Array_index_expression::do_must_eval_subexpressions_in_order( | |
11049 int* skip) const | |
11050 { | |
11051 *skip = this->array_->type()->is_slice_type() ? 0 : 1; | |
11052 return true; | |
10849 } | 11053 } |
10850 | 11054 |
10851 // Flatten array indexing by using temporary variables for slices and indexes. | 11055 // Flatten array indexing by using temporary variables for slices and indexes. |
10852 | 11056 |
10853 Expression* | 11057 Expression* |
10917 return true; | 11121 return true; |
10918 | 11122 |
10919 // An index into an array is addressable if the array is | 11123 // An index into an array is addressable if the array is |
10920 // addressable. | 11124 // addressable. |
10921 return this->array_->is_addressable(); | 11125 return this->array_->is_addressable(); |
11126 } | |
11127 | |
11128 void | |
11129 Array_index_expression::do_address_taken(bool escapes) | |
11130 { | |
11131 // In &x[0], if x is a slice, then x's address is not taken. | |
11132 if (!this->array_->type()->is_slice_type()) | |
11133 this->array_->address_taken(escapes); | |
10922 } | 11134 } |
10923 | 11135 |
10924 // Get the backend representation for an array index. | 11136 // Get the backend representation for an array index. |
10925 | 11137 |
10926 Bexpression* | 11138 Bexpression* |
11298 String_index_expression::do_get_backend(Translate_context* context) | 11510 String_index_expression::do_get_backend(Translate_context* context) |
11299 { | 11511 { |
11300 Location loc = this->location(); | 11512 Location loc = this->location(); |
11301 Expression* string_arg = this->string_; | 11513 Expression* string_arg = this->string_; |
11302 if (this->string_->type()->points_to() != NULL) | 11514 if (this->string_->type()->points_to() != NULL) |
11303 string_arg = Expression::make_unary(OPERATOR_MULT, this->string_, loc); | 11515 string_arg = Expression::make_dereference(this->string_, |
11516 NIL_CHECK_NOT_NEEDED, loc); | |
11304 | 11517 |
11305 Expression* bad_index = Expression::check_bounds(this->start_, loc); | 11518 Expression* bad_index = Expression::check_bounds(this->start_, loc); |
11306 | 11519 |
11307 int code = (this->end_ == NULL | 11520 int code = (this->end_ == NULL |
11308 ? RUNTIME_ERROR_STRING_INDEX_OUT_OF_BOUNDS | 11521 ? RUNTIME_ERROR_STRING_INDEX_OUT_OF_BOUNDS |
11434 { | 11647 { |
11435 go_assert(saw_errors()); | 11648 go_assert(saw_errors()); |
11436 return Expression::make_error(loc); | 11649 return Expression::make_error(loc); |
11437 } | 11650 } |
11438 | 11651 |
11439 if (!Type::are_identical(mt->key_type(), this->index_->type(), false, NULL)) | 11652 if (!Type::are_identical(mt->key_type(), this->index_->type(), |
11653 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, | |
11654 NULL)) | |
11440 { | 11655 { |
11441 if (this->index_->type()->interface_type() != NULL | 11656 if (this->index_->type()->interface_type() != NULL |
11442 && !this->index_->is_variable()) | 11657 && !this->index_->is_variable()) |
11443 { | 11658 { |
11444 Temporary_statement* temp = | 11659 Temporary_statement* temp = |
11532 } | 11747 } |
11533 | 11748 |
11534 go_assert(this->value_pointer_ != NULL | 11749 go_assert(this->value_pointer_ != NULL |
11535 && this->value_pointer_->is_variable()); | 11750 && this->value_pointer_->is_variable()); |
11536 | 11751 |
11537 Expression* val = Expression::make_unary(OPERATOR_MULT, this->value_pointer_, | 11752 Expression* val = Expression::make_dereference(this->value_pointer_, |
11538 this->location()); | 11753 NIL_CHECK_NOT_NEEDED, |
11754 this->location()); | |
11539 return val->get_backend(context); | 11755 return val->get_backend(context); |
11540 } | 11756 } |
11541 | 11757 |
11542 // Get an expression for the map index. This returns an expression | 11758 // Get an expression for the map index. This returns an expression |
11543 // that evaluates to a pointer to a value. If the key is not in the | 11759 // that evaluates to a pointer to a value. If the key is not in the |
11643 this->called_fieldtrack_ = true; | 11859 this->called_fieldtrack_ = true; |
11644 | 11860 |
11645 Location loc = this->location(); | 11861 Location loc = this->location(); |
11646 | 11862 |
11647 std::string s = "fieldtrack \""; | 11863 std::string s = "fieldtrack \""; |
11648 Named_type* nt = this->expr_->type()->named_type(); | 11864 Named_type* nt = this->expr_->type()->unalias()->named_type(); |
11649 if (nt == NULL || nt->named_object()->package() == NULL) | 11865 if (nt == NULL || nt->named_object()->package() == NULL) |
11650 s.append(gogo->pkgpath()); | 11866 s.append(gogo->pkgpath()); |
11651 else | 11867 else |
11652 s.append(nt->named_object()->package()->pkgpath()); | 11868 s.append(nt->named_object()->package()->pkgpath()); |
11653 s.push_back('.'); | 11869 s.push_back('.'); |
11769 Interface_field_reference_expression::get_function() | 11985 Interface_field_reference_expression::get_function() |
11770 { | 11986 { |
11771 Expression* ref = this->expr_; | 11987 Expression* ref = this->expr_; |
11772 Location loc = this->location(); | 11988 Location loc = this->location(); |
11773 if (ref->type()->points_to() != NULL) | 11989 if (ref->type()->points_to() != NULL) |
11774 ref = Expression::make_unary(OPERATOR_MULT, ref, loc); | 11990 ref = Expression::make_dereference(ref, NIL_CHECK_DEFAULT, loc); |
11775 | 11991 |
11776 Expression* mtable = | 11992 Expression* mtable = |
11777 Expression::make_interface_info(ref, INTERFACE_INFO_METHODS, loc); | 11993 Expression::make_interface_info(ref, INTERFACE_INFO_METHODS, loc); |
11778 Struct_type* mtable_type = mtable->type()->points_to()->struct_type(); | 11994 Struct_type* mtable_type = mtable->type()->points_to()->struct_type(); |
11779 | 11995 |
11780 std::string name = Gogo::unpack_hidden_name(this->name_); | 11996 std::string name = Gogo::unpack_hidden_name(this->name_); |
11781 unsigned int index; | 11997 unsigned int index; |
11782 const Struct_field* field = mtable_type->find_local_field(name, &index); | 11998 const Struct_field* field = mtable_type->find_local_field(name, &index); |
11783 go_assert(field != NULL); | 11999 go_assert(field != NULL); |
11784 mtable = Expression::make_unary(OPERATOR_MULT, mtable, loc); | 12000 |
12001 mtable = Expression::make_dereference(mtable, NIL_CHECK_NOT_NEEDED, loc); | |
11785 return Expression::make_field_reference(mtable, index, loc); | 12002 return Expression::make_field_reference(mtable, index, loc); |
11786 } | 12003 } |
11787 | 12004 |
11788 // Return an expression for the first argument to pass to the interface | 12005 // Return an expression for the first argument to pass to the interface |
11789 // function. | 12006 // function. |
11791 Expression* | 12008 Expression* |
11792 Interface_field_reference_expression::get_underlying_object() | 12009 Interface_field_reference_expression::get_underlying_object() |
11793 { | 12010 { |
11794 Expression* expr = this->expr_; | 12011 Expression* expr = this->expr_; |
11795 if (expr->type()->points_to() != NULL) | 12012 if (expr->type()->points_to() != NULL) |
11796 expr = Expression::make_unary(OPERATOR_MULT, expr, this->location()); | 12013 expr = Expression::make_dereference(expr, NIL_CHECK_DEFAULT, |
12014 this->location()); | |
11797 return Expression::make_interface_info(expr, INTERFACE_INFO_OBJECT, | 12015 return Expression::make_interface_info(expr, INTERFACE_INFO_OBJECT, |
11798 this->location()); | 12016 this->location()); |
11799 } | 12017 } |
11800 | 12018 |
11801 // Traversal. | 12019 // Traversal. |
11822 } | 12040 } |
11823 | 12041 |
11824 if (!this->expr_->is_variable()) | 12042 if (!this->expr_->is_variable()) |
11825 { | 12043 { |
11826 Temporary_statement* temp = | 12044 Temporary_statement* temp = |
11827 Statement::make_temporary(this->expr_->type(), NULL, this->location()); | 12045 Statement::make_temporary(NULL, this->expr_, this->location()); |
11828 inserter->insert(temp); | 12046 inserter->insert(temp); |
11829 this->expr_ = Expression::make_set_and_use_temporary(temp, this->expr_, | 12047 this->expr_ = Expression::make_temporary_reference(temp, this->location()); |
11830 this->location()); | |
11831 } | 12048 } |
11832 return this; | 12049 return this; |
11833 } | 12050 } |
11834 | 12051 |
11835 // Return the type of an interface field reference. | 12052 // Return the type of an interface field reference. |
11930 | 12147 |
11931 Location loc = type->location(); | 12148 Location loc = type->location(); |
11932 | 12149 |
11933 const Typed_identifier* method_id = type->find_method(name); | 12150 const Typed_identifier* method_id = type->find_method(name); |
11934 if (method_id == NULL) | 12151 if (method_id == NULL) |
11935 return Named_object::make_erroneous_name(Gogo::thunk_name()); | 12152 return Named_object::make_erroneous_name(gogo->thunk_name()); |
11936 | 12153 |
11937 Function_type* orig_fntype = method_id->type()->function_type(); | 12154 Function_type* orig_fntype = method_id->type()->function_type(); |
11938 if (orig_fntype == NULL) | 12155 if (orig_fntype == NULL) |
11939 return Named_object::make_erroneous_name(Gogo::thunk_name()); | 12156 return Named_object::make_erroneous_name(gogo->thunk_name()); |
11940 | 12157 |
11941 Struct_field_list* sfl = new Struct_field_list(); | 12158 Struct_field_list* sfl = new Struct_field_list(); |
11942 // The type here is wrong--it should be the C function type. But it | 12159 // The type here is wrong--it should be the C function type. But it |
11943 // doesn't really matter. | 12160 // doesn't really matter. |
11944 Type* vt = Type::make_pointer_type(Type::make_void_type()); | 12161 Type* vt = Type::make_pointer_type(Type::make_void_type()); |
11945 sfl->push_back(Struct_field(Typed_identifier("fn.0", vt, loc))); | 12162 sfl->push_back(Struct_field(Typed_identifier("fn", vt, loc))); |
11946 sfl->push_back(Struct_field(Typed_identifier("val.1", type, loc))); | 12163 sfl->push_back(Struct_field(Typed_identifier("val", type, loc))); |
11947 Struct_type* st = Type::make_struct_type(sfl, loc); | 12164 Struct_type* st = Type::make_struct_type(sfl, loc); |
11948 st->set_is_struct_incomparable(); | 12165 st->set_is_struct_incomparable(); |
11949 Type* closure_type = Type::make_pointer_type(st); | 12166 Type* closure_type = Type::make_pointer_type(st); |
11950 | 12167 |
11951 Function_type* new_fntype = orig_fntype->copy_with_names(); | 12168 Function_type* new_fntype = orig_fntype->copy_with_names(); |
11952 | 12169 |
11953 std::string thunk_name = Gogo::thunk_name(); | 12170 std::string thunk_name = gogo->thunk_name(); |
11954 Named_object* new_no = gogo->start_function(thunk_name, new_fntype, | 12171 Named_object* new_no = gogo->start_function(thunk_name, new_fntype, |
11955 false, loc); | 12172 false, loc); |
11956 | 12173 |
11957 Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc); | 12174 Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc); |
11958 cvar->set_is_used(); | 12175 cvar->set_is_used(); |
11964 gogo->start_block(loc); | 12181 gogo->start_block(loc); |
11965 | 12182 |
11966 // Field 0 of the closure is the function code pointer, field 1 is | 12183 // Field 0 of the closure is the function code pointer, field 1 is |
11967 // the value on which to invoke the method. | 12184 // the value on which to invoke the method. |
11968 Expression* arg = Expression::make_var_reference(cp, loc); | 12185 Expression* arg = Expression::make_var_reference(cp, loc); |
11969 arg = Expression::make_unary(OPERATOR_MULT, arg, loc); | 12186 arg = Expression::make_dereference(arg, NIL_CHECK_NOT_NEEDED, loc); |
11970 arg = Expression::make_field_reference(arg, 1, loc); | 12187 arg = Expression::make_field_reference(arg, 1, loc); |
11971 | 12188 |
11972 Expression *ifre = Expression::make_interface_field_reference(arg, name, | 12189 Expression *ifre = Expression::make_interface_field_reference(arg, name, |
11973 loc); | 12190 loc); |
11974 | 12191 |
12036 // don't need the thunk. | 12253 // don't need the thunk. |
12037 | 12254 |
12038 Location loc = this->location(); | 12255 Location loc = this->location(); |
12039 | 12256 |
12040 Struct_field_list* fields = new Struct_field_list(); | 12257 Struct_field_list* fields = new Struct_field_list(); |
12041 fields->push_back(Struct_field(Typed_identifier("fn.0", | 12258 fields->push_back(Struct_field(Typed_identifier("fn", |
12042 thunk->func_value()->type(), | 12259 thunk->func_value()->type(), |
12043 loc))); | 12260 loc))); |
12044 fields->push_back(Struct_field(Typed_identifier("val.1", | 12261 fields->push_back(Struct_field(Typed_identifier("val", |
12045 this->expr_->type(), | 12262 this->expr_->type(), |
12046 loc))); | 12263 loc))); |
12047 Struct_type* st = Type::make_struct_type(fields, loc); | 12264 Struct_type* st = Type::make_struct_type(fields, loc); |
12048 st->set_is_struct_incomparable(); | 12265 st->set_is_struct_incomparable(); |
12049 | 12266 |
12288 static_cast<Type_conversion_expression*>(f); | 12505 static_cast<Type_conversion_expression*>(f); |
12289 tce->set_may_convert_function_types(); | 12506 tce->set_may_convert_function_types(); |
12290 return f; | 12507 return f; |
12291 } | 12508 } |
12292 | 12509 |
12293 Named_object* no = gogo->start_function(Gogo::thunk_name(), fntype, false, | 12510 Named_object* no = gogo->start_function(gogo->thunk_name(), fntype, false, |
12294 location); | 12511 location); |
12295 | 12512 |
12296 Named_object* vno = gogo->lookup(receiver_name, NULL); | 12513 Named_object* vno = gogo->lookup(receiver_name, NULL); |
12297 go_assert(vno != NULL); | 12514 go_assert(vno != NULL); |
12298 Expression* ve = Expression::make_var_reference(vno, location); | 12515 Expression* ve = Expression::make_var_reference(vno, location); |
12393 | 12610 |
12394 Expression* | 12611 Expression* |
12395 Allocation_expression::do_copy() | 12612 Allocation_expression::do_copy() |
12396 { | 12613 { |
12397 Allocation_expression* alloc = | 12614 Allocation_expression* alloc = |
12398 new Allocation_expression(this->type_, this->location()); | 12615 new Allocation_expression(this->type_->copy_expressions(), |
12616 this->location()); | |
12399 if (this->allocate_on_stack_) | 12617 if (this->allocate_on_stack_) |
12400 alloc->set_allocate_on_stack(); | 12618 alloc->set_allocate_on_stack(); |
12401 return alloc; | 12619 return alloc; |
12402 } | 12620 } |
12403 | 12621 |
12406 Bexpression* | 12624 Bexpression* |
12407 Allocation_expression::do_get_backend(Translate_context* context) | 12625 Allocation_expression::do_get_backend(Translate_context* context) |
12408 { | 12626 { |
12409 Gogo* gogo = context->gogo(); | 12627 Gogo* gogo = context->gogo(); |
12410 Location loc = this->location(); | 12628 Location loc = this->location(); |
12411 | 12629 Btype* btype = this->type_->get_backend(gogo); |
12412 Node* n = Node::make_node(this); | 12630 |
12413 if (this->allocate_on_stack_ | 12631 if (this->allocate_on_stack_) |
12414 || (n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE)) | |
12415 { | 12632 { |
12416 int64_t size; | 12633 int64_t size; |
12417 bool ok = this->type_->backend_type_size(gogo, &size); | 12634 bool ok = this->type_->backend_type_size(gogo, &size); |
12418 if (!ok) | 12635 if (!ok) |
12419 { | 12636 { |
12420 go_assert(saw_errors()); | 12637 go_assert(saw_errors()); |
12421 return gogo->backend()->error_expression(); | 12638 return gogo->backend()->error_expression(); |
12422 } | 12639 } |
12423 return gogo->backend()->stack_allocation_expression(size, loc); | 12640 Bstatement* decl; |
12424 } | 12641 Named_object* fn = context->function(); |
12425 | 12642 go_assert(fn != NULL); |
12426 Btype* btype = this->type_->get_backend(gogo); | 12643 Bfunction* fndecl = fn->func_value()->get_or_make_decl(gogo, fn); |
12644 Bexpression* zero = gogo->backend()->zero_expression(btype); | |
12645 Bvariable* temp = | |
12646 gogo->backend()->temporary_variable(fndecl, context->bblock(), btype, | |
12647 zero, true, loc, &decl); | |
12648 Bexpression* ret = gogo->backend()->var_expression(temp, loc); | |
12649 ret = gogo->backend()->address_expression(ret, loc); | |
12650 ret = gogo->backend()->compound_expression(decl, ret, loc); | |
12651 return ret; | |
12652 } | |
12653 | |
12427 Bexpression* space = | 12654 Bexpression* space = |
12428 gogo->allocate_memory(this->type_, loc)->get_backend(context); | 12655 gogo->allocate_memory(this->type_, loc)->get_backend(context); |
12429 Btype* pbtype = gogo->backend()->pointer_type(btype); | 12656 Btype* pbtype = gogo->backend()->pointer_type(btype); |
12430 return gogo->backend()->convert_expression(pbtype, space, loc); | 12657 return gogo->backend()->convert_expression(pbtype, space, loc); |
12431 } | 12658 } |
12622 i + 1, reason.c_str()); | 12849 i + 1, reason.c_str()); |
12623 this->set_is_error(); | 12850 this->set_is_error(); |
12624 } | 12851 } |
12625 } | 12852 } |
12626 go_assert(pv == this->vals()->end()); | 12853 go_assert(pv == this->vals()->end()); |
12854 } | |
12855 | |
12856 // Copy. | |
12857 | |
12858 Expression* | |
12859 Struct_construction_expression::do_copy() | |
12860 { | |
12861 Struct_construction_expression* ret = | |
12862 new Struct_construction_expression(this->type_->copy_expressions(), | |
12863 (this->vals() == NULL | |
12864 ? NULL | |
12865 : this->vals()->copy()), | |
12866 this->location()); | |
12867 if (this->traverse_order() != NULL) | |
12868 ret->set_traverse_order(this->traverse_order()); | |
12869 return ret; | |
12627 } | 12870 } |
12628 | 12871 |
12629 // Flatten a struct construction expression. Store the values into | 12872 // Flatten a struct construction expression. Store the values into |
12630 // temporaries in case they need interface conversion. | 12873 // temporaries in case they need interface conversion. |
12631 | 12874 |
13015 Expression_list* vals, Location location) | 13258 Expression_list* vals, Location location) |
13016 : Array_construction_expression(EXPRESSION_FIXED_ARRAY_CONSTRUCTION, | 13259 : Array_construction_expression(EXPRESSION_FIXED_ARRAY_CONSTRUCTION, |
13017 type, indexes, vals, location) | 13260 type, indexes, vals, location) |
13018 { go_assert(type->array_type() != NULL && !type->is_slice_type()); } | 13261 { go_assert(type->array_type() != NULL && !type->is_slice_type()); } |
13019 | 13262 |
13263 | |
13264 // Copy. | |
13265 | |
13266 Expression* | |
13267 Fixed_array_construction_expression::do_copy() | |
13268 { | |
13269 Type* t = this->type()->copy_expressions(); | |
13270 return new Fixed_array_construction_expression(t, this->indexes(), | |
13271 (this->vals() == NULL | |
13272 ? NULL | |
13273 : this->vals()->copy()), | |
13274 this->location()); | |
13275 } | |
13276 | |
13020 // Return the backend representation for constructing a fixed array. | 13277 // Return the backend representation for constructing a fixed array. |
13021 | 13278 |
13022 Bexpression* | 13279 Bexpression* |
13023 Fixed_array_construction_expression::do_get_backend(Translate_context* context) | 13280 Fixed_array_construction_expression::do_get_backend(Translate_context* context) |
13024 { | 13281 { |
13149 return; | 13406 return; |
13150 ast_dump_context->ostream() << "storage=" ; | 13407 ast_dump_context->ostream() << "storage=" ; |
13151 ast_dump_context->dump_expression(this->slice_storage_); | 13408 ast_dump_context->dump_expression(this->slice_storage_); |
13152 } | 13409 } |
13153 | 13410 |
13411 // Copy. | |
13412 | |
13413 Expression* | |
13414 Slice_construction_expression::do_copy() | |
13415 { | |
13416 return new Slice_construction_expression(this->type()->copy_expressions(), | |
13417 this->indexes(), | |
13418 (this->vals() == NULL | |
13419 ? NULL | |
13420 : this->vals()->copy()), | |
13421 this->location()); | |
13422 } | |
13423 | |
13154 // Return the backend representation for constructing a slice. | 13424 // Return the backend representation for constructing a slice. |
13155 | 13425 |
13156 Bexpression* | 13426 Bexpression* |
13157 Slice_construction_expression::do_get_backend(Translate_context* context) | 13427 Slice_construction_expression::do_get_backend(Translate_context* context) |
13158 { | 13428 { |
13185 space = Expression::make_unary(OPERATOR_AND, this->array_val_, loc); | 13455 space = Expression::make_unary(OPERATOR_AND, this->array_val_, loc); |
13186 space->unary_expression()->set_is_slice_init(); | 13456 space->unary_expression()->set_is_slice_init(); |
13187 } | 13457 } |
13188 else | 13458 else |
13189 { | 13459 { |
13460 go_assert(this->storage_escapes_ || this->element_count() == 0); | |
13190 space = Expression::make_heap_expression(this->array_val_, loc); | 13461 space = Expression::make_heap_expression(this->array_val_, loc); |
13191 Node* n = Node::make_node(this); | |
13192 if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE)) | |
13193 { | |
13194 n = Node::make_node(space); | |
13195 n->set_encoding(Node::ESCAPE_NONE); | |
13196 } | |
13197 } | 13462 } |
13198 | 13463 |
13199 // Build a constructor for the slice. | 13464 // Build a constructor for the slice. |
13200 Expression* len = this->valtype_->array_type()->length(); | 13465 Expression* len = this->valtype_->array_type()->length(); |
13201 Expression* slice_val = | 13466 Expression* slice_val = |
13367 this->set_is_error(); | 13632 this->set_is_error(); |
13368 } | 13633 } |
13369 } | 13634 } |
13370 } | 13635 } |
13371 | 13636 |
13637 // Copy. | |
13638 | |
13639 Expression* | |
13640 Map_construction_expression::do_copy() | |
13641 { | |
13642 return new Map_construction_expression(this->type_->copy_expressions(), | |
13643 (this->vals_ == NULL | |
13644 ? NULL | |
13645 : this->vals_->copy()), | |
13646 this->location()); | |
13647 } | |
13648 | |
13372 // Return the backend representation for constructing a map. | 13649 // Return the backend representation for constructing a map. |
13373 | 13650 |
13374 Bexpression* | 13651 Bexpression* |
13375 Map_construction_expression::do_get_backend(Translate_context* context) | 13652 Map_construction_expression::do_get_backend(Translate_context* context) |
13376 { | 13653 { |
13529 { | 13806 { |
13530 Type* type = this->type_; | 13807 Type* type = this->type_; |
13531 | 13808 |
13532 for (int depth = 0; depth < this->depth_; ++depth) | 13809 for (int depth = 0; depth < this->depth_; ++depth) |
13533 { | 13810 { |
13811 type = type->deref(); | |
13534 if (type->array_type() != NULL) | 13812 if (type->array_type() != NULL) |
13535 type = type->array_type()->element_type(); | 13813 type = type->array_type()->element_type(); |
13536 else if (type->map_type() != NULL) | 13814 else if (type->map_type() != NULL) |
13537 { | 13815 { |
13538 if (this->key_path_[depth]) | 13816 if (this->key_path_[depth]) |
14044 } | 14322 } |
14045 } | 14323 } |
14046 } | 14324 } |
14047 | 14325 |
14048 return new Map_construction_expression(type, this->vals_, location); | 14326 return new Map_construction_expression(type, this->vals_, location); |
14327 } | |
14328 | |
14329 // Copy. | |
14330 | |
14331 Expression* | |
14332 Composite_literal_expression::do_copy() | |
14333 { | |
14334 Composite_literal_expression* ret = | |
14335 new Composite_literal_expression(this->type_->copy_expressions(), | |
14336 this->depth_, this->has_keys_, | |
14337 (this->vals_ == NULL | |
14338 ? NULL | |
14339 : this->vals_->copy()), | |
14340 this->all_are_names_, | |
14341 this->location()); | |
14342 ret->key_path_ = this->key_path_; | |
14343 return ret; | |
14049 } | 14344 } |
14050 | 14345 |
14051 // Dump ast representation for a composite literal expression. | 14346 // Dump ast representation for a composite literal expression. |
14052 | 14347 |
14053 void | 14348 void |
14222 this->set_is_error(); | 14517 this->set_is_error(); |
14223 } | 14518 } |
14224 } | 14519 } |
14225 } | 14520 } |
14226 | 14521 |
14522 // Copy. | |
14523 | |
14524 Expression* | |
14525 Type_guard_expression::do_copy() | |
14526 { | |
14527 return new Type_guard_expression(this->expr_->copy(), | |
14528 this->type_->copy_expressions(), | |
14529 this->location()); | |
14530 } | |
14531 | |
14227 // Return the backend representation for a type guard expression. | 14532 // Return the backend representation for a type guard expression. |
14228 | 14533 |
14229 Bexpression* | 14534 Bexpression* |
14230 Type_guard_expression::do_get_backend(Translate_context* context) | 14535 Type_guard_expression::do_get_backend(Translate_context* context) |
14231 { | 14536 { |
14285 Location loc = this->location(); | 14590 Location loc = this->location(); |
14286 Gogo* gogo = context->gogo(); | 14591 Gogo* gogo = context->gogo(); |
14287 Btype* btype = this->type()->get_backend(gogo); | 14592 Btype* btype = this->type()->get_backend(gogo); |
14288 | 14593 |
14289 Expression* alloc = Expression::make_allocation(etype, loc); | 14594 Expression* alloc = Expression::make_allocation(etype, loc); |
14290 Node* n = Node::make_node(this); | 14595 if (this->allocate_on_stack_) |
14291 if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE)) | |
14292 alloc->allocation_expression()->set_allocate_on_stack(); | 14596 alloc->allocation_expression()->set_allocate_on_stack(); |
14293 Bexpression* space = alloc->get_backend(context); | 14597 Bexpression* space = alloc->get_backend(context); |
14294 | 14598 |
14295 Bstatement* decl; | 14599 Bstatement* decl; |
14296 Named_object* fn = context->function(); | 14600 Named_object* fn = context->function(); |
14305 | 14609 |
14306 // If this assignment needs a write barrier, call typedmemmove. We | 14610 // If this assignment needs a write barrier, call typedmemmove. We |
14307 // don't do this in the write barrier pass because in some cases | 14611 // don't do this in the write barrier pass because in some cases |
14308 // backend conversion can introduce new Heap_expression values. | 14612 // backend conversion can introduce new Heap_expression values. |
14309 Bstatement* assn; | 14613 Bstatement* assn; |
14310 if (!etype->has_pointer()) | 14614 if (!etype->has_pointer() || this->allocate_on_stack_) |
14311 { | 14615 { |
14312 space = gogo->backend()->var_expression(space_temp, VE_lvalue, loc); | 14616 space = gogo->backend()->var_expression(space_temp, loc); |
14313 Bexpression* ref = | 14617 Bexpression* ref = |
14314 gogo->backend()->indirect_expression(expr_btype, space, true, loc); | 14618 gogo->backend()->indirect_expression(expr_btype, space, true, loc); |
14315 assn = gogo->backend()->assignment_statement(fndecl, ref, bexpr, loc); | 14619 assn = gogo->backend()->assignment_statement(fndecl, ref, bexpr, loc); |
14316 } | 14620 } |
14317 else | 14621 else |
14320 Bvariable* btemp = | 14624 Bvariable* btemp = |
14321 gogo->backend()->temporary_variable(fndecl, context->bblock(), | 14625 gogo->backend()->temporary_variable(fndecl, context->bblock(), |
14322 expr_btype, bexpr, true, loc, | 14626 expr_btype, bexpr, true, loc, |
14323 &edecl); | 14627 &edecl); |
14324 Bexpression* btempref = gogo->backend()->var_expression(btemp, | 14628 Bexpression* btempref = gogo->backend()->var_expression(btemp, |
14325 VE_lvalue, loc); | 14629 loc); |
14326 Bexpression* addr = gogo->backend()->address_expression(btempref, loc); | 14630 Bexpression* addr = gogo->backend()->address_expression(btempref, loc); |
14327 | 14631 |
14328 Expression* td = Expression::make_type_descriptor(etype, loc); | 14632 Expression* td = Expression::make_type_descriptor(etype, loc); |
14329 Type* etype_ptr = Type::make_pointer_type(etype); | 14633 Type* etype_ptr = Type::make_pointer_type(etype); |
14330 space = gogo->backend()->var_expression(space_temp, VE_rvalue, loc); | 14634 space = gogo->backend()->var_expression(space_temp, loc); |
14331 Expression* elhs = Expression::make_backend(space, etype_ptr, loc); | 14635 Expression* elhs = Expression::make_backend(space, etype_ptr, loc); |
14332 Expression* erhs = Expression::make_backend(addr, etype_ptr, loc); | 14636 Expression* erhs = Expression::make_backend(addr, etype_ptr, loc); |
14333 Expression* call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3, | 14637 Expression* call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3, |
14334 td, elhs, erhs); | 14638 td, elhs, erhs); |
14335 Bexpression* bcall = call->get_backend(context); | 14639 Bexpression* bcall = call->get_backend(context); |
14336 Bstatement* s = gogo->backend()->expression_statement(fndecl, bcall); | 14640 Bstatement* s = gogo->backend()->expression_statement(fndecl, bcall); |
14337 assn = gogo->backend()->compound_statement(edecl, s); | 14641 assn = gogo->backend()->compound_statement(edecl, s); |
14338 } | 14642 } |
14339 decl = gogo->backend()->compound_statement(decl, assn); | 14643 decl = gogo->backend()->compound_statement(decl, assn); |
14340 space = gogo->backend()->var_expression(space_temp, VE_rvalue, loc); | 14644 space = gogo->backend()->var_expression(space_temp, loc); |
14341 return gogo->backend()->compound_expression(decl, space, loc); | 14645 return gogo->backend()->compound_expression(decl, space, loc); |
14342 } | 14646 } |
14343 | 14647 |
14344 // Dump ast representation for a heap expression. | 14648 // Dump ast representation for a heap expression. |
14345 | 14649 |
14659 // Otherwise we have to build a ptrmask variable, and return a | 14963 // Otherwise we have to build a ptrmask variable, and return a |
14660 // pointer to it. | 14964 // pointer to it. |
14661 | 14965 |
14662 Bvariable* bvar = this->type_->gc_ptrmask_var(gogo, ptrsize, ptrdata); | 14966 Bvariable* bvar = this->type_->gc_ptrmask_var(gogo, ptrsize, ptrdata); |
14663 Location bloc = Linemap::predeclared_location(); | 14967 Location bloc = Linemap::predeclared_location(); |
14664 Bexpression* bref = gogo->backend()->var_expression(bvar, VE_rvalue, bloc); | 14968 Bexpression* bref = gogo->backend()->var_expression(bvar, bloc); |
14665 Bexpression* baddr = gogo->backend()->address_expression(bref, bloc); | 14969 Bexpression* baddr = gogo->backend()->address_expression(bref, bloc); |
14666 | 14970 |
14667 Type* uint8_type = Type::lookup_integer_type("uint8"); | 14971 Type* uint8_type = Type::lookup_integer_type("uint8"); |
14668 Type* pointer_uint8_type = Type::make_pointer_type(uint8_type); | 14972 Type* pointer_uint8_type = Type::make_pointer_type(uint8_type); |
14669 Btype* ubtype = pointer_uint8_type->get_backend(gogo); | 14973 Btype* ubtype = pointer_uint8_type->get_backend(gogo); |
14950 { go_unreachable(); } | 15254 { go_unreachable(); } |
14951 | 15255 |
14952 Expression* | 15256 Expression* |
14953 do_copy() | 15257 do_copy() |
14954 { | 15258 { |
14955 return new Slice_value_expression(this->type_, this->valptr_->copy(), | 15259 return new Slice_value_expression(this->type_->copy_expressions(), |
15260 this->valptr_->copy(), | |
14956 this->len_->copy(), this->cap_->copy(), | 15261 this->len_->copy(), this->cap_->copy(), |
14957 this->location()); | 15262 this->location()); |
14958 } | 15263 } |
14959 | 15264 |
14960 Bexpression* | 15265 Bexpression* |
15211 { go_unreachable(); } | 15516 { go_unreachable(); } |
15212 | 15517 |
15213 Expression* | 15518 Expression* |
15214 do_copy() | 15519 do_copy() |
15215 { | 15520 { |
15216 return new Interface_value_expression(this->type_, | 15521 return new Interface_value_expression(this->type_->copy_expressions(), |
15217 this->first_field_->copy(), | 15522 this->first_field_->copy(), |
15218 this->obj_->copy(), this->location()); | 15523 this->obj_->copy(), this->location()); |
15219 } | 15524 } |
15220 | 15525 |
15221 Bexpression* | 15526 Bexpression* |
15306 { go_unreachable(); } | 15611 { go_unreachable(); } |
15307 | 15612 |
15308 Expression* | 15613 Expression* |
15309 do_copy() | 15614 do_copy() |
15310 { | 15615 { |
15311 return new Interface_mtable_expression(this->itype_, this->type_, | 15616 Interface_type* itype = this->itype_->copy_expressions()->interface_type(); |
15617 return new Interface_mtable_expression(itype, | |
15618 this->type_->copy_expressions(), | |
15312 this->is_pointer_, this->location()); | 15619 this->is_pointer_, this->location()); |
15313 } | 15620 } |
15314 | 15621 |
15315 bool | 15622 bool |
15316 do_is_addressable() const | 15623 do_is_addressable() const |
15378 Interface_mtable_expression::do_get_backend(Translate_context* context) | 15685 Interface_mtable_expression::do_get_backend(Translate_context* context) |
15379 { | 15686 { |
15380 Gogo* gogo = context->gogo(); | 15687 Gogo* gogo = context->gogo(); |
15381 Location loc = Linemap::predeclared_location(); | 15688 Location loc = Linemap::predeclared_location(); |
15382 if (this->bvar_ != NULL) | 15689 if (this->bvar_ != NULL) |
15383 return gogo->backend()->var_expression(this->bvar_, VE_rvalue, | 15690 return gogo->backend()->var_expression(this->bvar_, this->location()); |
15384 this->location()); | |
15385 | 15691 |
15386 const Typed_identifier_list* interface_methods = this->itype_->methods(); | 15692 const Typed_identifier_list* interface_methods = this->itype_->methods(); |
15387 go_assert(!interface_methods->empty()); | 15693 go_assert(!interface_methods->empty()); |
15388 | 15694 |
15389 std::string mangled_name = | 15695 std::string mangled_name = |
15419 Btype* btype = this->type()->get_backend(gogo); | 15725 Btype* btype = this->type()->get_backend(gogo); |
15420 std::string asm_name(go_selectively_encode_id(mangled_name)); | 15726 std::string asm_name(go_selectively_encode_id(mangled_name)); |
15421 this->bvar_ = | 15727 this->bvar_ = |
15422 gogo->backend()->immutable_struct_reference(mangled_name, asm_name, | 15728 gogo->backend()->immutable_struct_reference(mangled_name, asm_name, |
15423 btype, loc); | 15729 btype, loc); |
15424 return gogo->backend()->var_expression(this->bvar_, VE_rvalue, | 15730 return gogo->backend()->var_expression(this->bvar_, this->location()); |
15425 this->location()); | |
15426 } | 15731 } |
15427 | 15732 |
15428 // The first element is the type descriptor. | 15733 // The first element is the type descriptor. |
15429 Type* td_type; | 15734 Type* td_type; |
15430 if (!this->is_pointer_) | 15735 if (!this->is_pointer_) |
15485 std::string asm_name(go_selectively_encode_id(mangled_name)); | 15790 std::string asm_name(go_selectively_encode_id(mangled_name)); |
15486 this->bvar_ = gogo->backend()->immutable_struct(mangled_name, asm_name, false, | 15791 this->bvar_ = gogo->backend()->immutable_struct(mangled_name, asm_name, false, |
15487 !is_public, btype, loc); | 15792 !is_public, btype, loc); |
15488 gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, false, | 15793 gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, false, |
15489 !is_public, btype, loc, ctor); | 15794 !is_public, btype, loc, ctor); |
15490 return gogo->backend()->var_expression(this->bvar_, VE_lvalue, loc); | 15795 return gogo->backend()->var_expression(this->bvar_, loc); |
15491 } | 15796 } |
15492 | 15797 |
15493 void | 15798 void |
15494 Interface_mtable_expression::do_dump_expression( | 15799 Interface_mtable_expression::do_dump_expression( |
15495 Ast_dump_context* ast_dump_context) const | 15800 Ast_dump_context* ast_dump_context) const |
15662 | 15967 |
15663 Type* | 15968 Type* |
15664 Conditional_expression::do_type() | 15969 Conditional_expression::do_type() |
15665 { | 15970 { |
15666 Type* result_type = Type::make_void_type(); | 15971 Type* result_type = Type::make_void_type(); |
15667 if (Type::are_identical(this->then_->type(), this->else_->type(), false, | 15972 if (Type::are_identical(this->then_->type(), this->else_->type(), |
15973 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, | |
15668 NULL)) | 15974 NULL)) |
15669 result_type = this->then_->type(); | 15975 result_type = this->then_->type(); |
15670 else if (this->then_->is_nil_expression() | 15976 else if (this->then_->is_nil_expression() |
15671 || this->else_->is_nil_expression()) | 15977 || this->else_->is_nil_expression()) |
15672 result_type = (!this->then_->is_nil_expression() | 15978 result_type = (!this->then_->is_nil_expression() |
15794 | 16100 |
15795 int | 16101 int |
15796 Backend_expression::do_traverse(Traverse*) | 16102 Backend_expression::do_traverse(Traverse*) |
15797 { | 16103 { |
15798 return TRAVERSE_CONTINUE; | 16104 return TRAVERSE_CONTINUE; |
16105 } | |
16106 | |
16107 Expression* | |
16108 Backend_expression::do_copy() | |
16109 { | |
16110 return new Backend_expression(this->bexpr_, this->type_->copy_expressions(), | |
16111 this->location()); | |
15799 } | 16112 } |
15800 | 16113 |
15801 void | 16114 void |
15802 Backend_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const | 16115 Backend_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const |
15803 { | 16116 { |
16024 Numeric_constant::set_float(Type* type, const mpfr_t val) | 16337 Numeric_constant::set_float(Type* type, const mpfr_t val) |
16025 { | 16338 { |
16026 this->clear(); | 16339 this->clear(); |
16027 this->classification_ = NC_FLOAT; | 16340 this->classification_ = NC_FLOAT; |
16028 this->type_ = type; | 16341 this->type_ = type; |
16342 | |
16029 // Numeric constants do not have negative zero values, so remove | 16343 // Numeric constants do not have negative zero values, so remove |
16030 // them here. They also don't have infinity or NaN values, but we | 16344 // them here. They also don't have infinity or NaN values, but we |
16031 // should never see them here. | 16345 // should never see them here. |
16032 if (mpfr_zero_p(val)) | 16346 int bits = 0; |
16347 if (type != NULL | |
16348 && type->float_type() != NULL | |
16349 && !type->float_type()->is_abstract()) | |
16350 bits = type->float_type()->bits(); | |
16351 if (Numeric_constant::is_float_neg_zero(val, bits)) | |
16033 mpfr_init_set_ui(this->u_.float_val, 0, GMP_RNDN); | 16352 mpfr_init_set_ui(this->u_.float_val, 0, GMP_RNDN); |
16034 else | 16353 else |
16035 mpfr_init_set(this->u_.float_val, val, GMP_RNDN); | 16354 mpfr_init_set(this->u_.float_val, val, GMP_RNDN); |
16036 } | 16355 } |
16037 | 16356 |
16041 Numeric_constant::set_complex(Type* type, const mpc_t val) | 16360 Numeric_constant::set_complex(Type* type, const mpc_t val) |
16042 { | 16361 { |
16043 this->clear(); | 16362 this->clear(); |
16044 this->classification_ = NC_COMPLEX; | 16363 this->classification_ = NC_COMPLEX; |
16045 this->type_ = type; | 16364 this->type_ = type; |
16365 | |
16366 // Avoid negative zero as in set_float. | |
16367 int bits = 0; | |
16368 if (type != NULL | |
16369 && type->complex_type() != NULL | |
16370 && !type->complex_type()->is_abstract()) | |
16371 bits = type->complex_type()->bits() / 2; | |
16372 | |
16373 mpfr_t real; | |
16374 mpfr_init_set(real, mpc_realref(val), GMP_RNDN); | |
16375 if (Numeric_constant::is_float_neg_zero(real, bits)) | |
16376 mpfr_set_ui(real, 0, GMP_RNDN); | |
16377 | |
16378 mpfr_t imag; | |
16379 mpfr_init_set(imag, mpc_imagref(val), GMP_RNDN); | |
16380 if (Numeric_constant::is_float_neg_zero(imag, bits)) | |
16381 mpfr_set_ui(imag, 0, GMP_RNDN); | |
16382 | |
16046 mpc_init2(this->u_.complex_val, mpc_precision); | 16383 mpc_init2(this->u_.complex_val, mpc_precision); |
16047 mpc_set(this->u_.complex_val, val, MPC_RNDNN); | 16384 mpc_set_fr_fr(this->u_.complex_val, real, imag, MPC_RNDNN); |
16385 | |
16386 mpfr_clear(real); | |
16387 mpfr_clear(imag); | |
16388 } | |
16389 | |
16390 // Return whether VAL, at a precision of BITS, is a negative zero. | |
16391 // BITS may be zero in which case it is ignored. | |
16392 | |
16393 bool | |
16394 Numeric_constant::is_float_neg_zero(const mpfr_t val, int bits) | |
16395 { | |
16396 if (!mpfr_signbit(val)) | |
16397 return false; | |
16398 if (mpfr_zero_p(val)) | |
16399 return true; | |
16400 mp_exp_t min_exp; | |
16401 switch (bits) | |
16402 { | |
16403 case 0: | |
16404 return false; | |
16405 case 32: | |
16406 // In a denormalized float32 the exponent is -126, and there are | |
16407 // 24 bits of which at least the last must be 1, so the smallest | |
16408 // representable non-zero exponent is -126 - (24 - 1) == -149. | |
16409 min_exp = -149; | |
16410 break; | |
16411 case 64: | |
16412 // Minimum exponent is -1022, there are 53 bits. | |
16413 min_exp = -1074; | |
16414 break; | |
16415 default: | |
16416 go_unreachable(); | |
16417 } | |
16418 return mpfr_get_exp(val) < min_exp; | |
16048 } | 16419 } |
16049 | 16420 |
16050 // Get an int value. | 16421 // Get an int value. |
16051 | 16422 |
16052 void | 16423 void |