github.com/kidsbmilk/gofronted_all@v0.0.0-20220701224323-6479d5976c5d/go/runtime.cc (about) 1 // runtime.cc -- runtime functions called by generated code 2 3 // Copyright 2011 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 #include "go-system.h" 8 9 #include "gogo.h" 10 #include "types.h" 11 #include "expressions.h" 12 #include "runtime.h" 13 14 // The frontend generates calls to various runtime functions. They 15 // are implemented in libgo/runtime. This is how the runtime 16 // functions are represented in the frontend. Note that there is 17 // currently nothing which ensures that the compiler's understanding 18 // of the runtime function matches the actual implementation in 19 // libgo/runtime. 20 21 // Parameter and result types used by runtime functions. 22 23 enum Runtime_function_type 24 { 25 // General indicator that value is not used. 26 RFT_VOID, 27 // Go untyped bool, C type _Bool. 28 RFT_BOOL, 29 // Go type *bool, C type _Bool*. 30 RFT_BOOLPTR, 31 // Go type int, C type intgo. 32 RFT_INT, 33 // Go type uint, C type uintgo. 34 RFT_UINT, 35 // Go type uint8, C type uint8_t. 36 RFT_UINT8, 37 // Go type uint16, C type uint16_t. 38 RFT_UINT16, 39 // Go type int32, C type int32_t. 40 RFT_INT32, 41 // Go type uint32, C type uint32_t. 42 RFT_UINT32, 43 // Go type int64, C type int64_t. 44 RFT_INT64, 45 // Go type uint64, C type uint64_t. 46 RFT_UINT64, 47 // Go type uintptr, C type uintptr_t. 48 RFT_UINTPTR, 49 // Go type rune, C type int32_t. 50 RFT_RUNE, 51 // Go type float64, C type double. 52 RFT_FLOAT64, 53 // Go type complex64, C type __complex float. 54 RFT_COMPLEX64, 55 // Go type complex128, C type __complex double. 56 RFT_COMPLEX128, 57 // Go type string, C type struct __go_string. 58 RFT_STRING, 59 // Go type unsafe.Pointer, C type "void *". 60 RFT_POINTER, 61 // Go type []any, C type struct __go_open_array. 62 RFT_SLICE, 63 // Go type map[any]any, C type struct __go_map *. 64 RFT_MAP, 65 // Go type chan any, C type struct __go_channel *. 66 RFT_CHAN, 67 // Go type non-empty interface, C type struct __go_interface. 68 RFT_IFACE, 69 // Go type interface{}, C type struct __go_empty_interface. 70 RFT_EFACE, 71 // Pointer to Go type descriptor. 72 RFT_TYPE, 73 // [2]string. 74 RFT_ARRAY2STRING, 75 // [3]string. 76 RFT_ARRAY3STRING, 77 // [4]string. 78 RFT_ARRAY4STRING, 79 // [5]string. 80 RFT_ARRAY5STRING, 81 82 NUMBER_OF_RUNTIME_FUNCTION_TYPES 83 }; 84 85 // The Type structures for the runtime function types. 86 87 static Type* runtime_function_types[NUMBER_OF_RUNTIME_FUNCTION_TYPES]; 88 89 // Get the Type for a Runtime_function_type code. 90 91 static Type* 92 runtime_function_type(Runtime_function_type bft) 93 { 94 go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES); 95 Type* any = Type::make_pointer_type(Type::make_void_type()); 96 if (runtime_function_types[bft] == NULL) 97 { 98 const Location bloc = Linemap::predeclared_location(); 99 Type* t; 100 switch (bft) 101 { 102 default: 103 case RFT_VOID: 104 go_unreachable(); 105 106 case RFT_BOOL: 107 t = Type::make_boolean_type(); 108 break; 109 110 case RFT_BOOLPTR: 111 t = Type::make_pointer_type(Type::lookup_bool_type()); 112 break; 113 114 case RFT_INT: 115 t = Type::lookup_integer_type("int"); 116 break; 117 118 case RFT_UINT: 119 t = Type::lookup_integer_type("uint"); 120 break; 121 122 case RFT_UINT8: 123 t = Type::lookup_integer_type("uint8"); 124 break; 125 126 case RFT_UINT16: 127 t = Type::lookup_integer_type("uint16"); 128 break; 129 130 case RFT_INT32: 131 t = Type::lookup_integer_type("int32"); 132 break; 133 134 case RFT_UINT32: 135 t = Type::lookup_integer_type("uint32"); 136 break; 137 138 case RFT_INT64: 139 t = Type::lookup_integer_type("int64"); 140 break; 141 142 case RFT_UINT64: 143 t = Type::lookup_integer_type("uint64"); 144 break; 145 146 case RFT_RUNE: 147 t = Type::lookup_integer_type("int32"); 148 break; 149 150 case RFT_UINTPTR: 151 t = Type::lookup_integer_type("uintptr"); 152 break; 153 154 case RFT_FLOAT64: 155 t = Type::lookup_float_type("float64"); 156 break; 157 158 case RFT_COMPLEX64: 159 t = Type::lookup_complex_type("complex64"); 160 break; 161 162 case RFT_COMPLEX128: 163 t = Type::lookup_complex_type("complex128"); 164 break; 165 166 case RFT_STRING: 167 t = Type::lookup_string_type(); 168 break; 169 170 case RFT_POINTER: 171 t = Type::make_pointer_type(Type::make_void_type()); 172 break; 173 174 case RFT_SLICE: 175 t = Type::make_array_type(any, NULL); 176 break; 177 178 case RFT_MAP: 179 t = Type::make_map_type(any, any, bloc); 180 break; 181 182 case RFT_CHAN: 183 t = Type::make_channel_type(true, true, any); 184 break; 185 186 case RFT_IFACE: 187 { 188 Typed_identifier_list* methods = new Typed_identifier_list(); 189 Type* mtype = Type::make_function_type(NULL, NULL, NULL, bloc); 190 methods->push_back(Typed_identifier("x", mtype, bloc)); 191 Interface_type* it = Type::make_interface_type(methods, bloc); 192 it->finalize_methods(); 193 t = it; 194 } 195 break; 196 197 case RFT_EFACE: 198 t = Type::make_empty_interface_type(bloc); 199 break; 200 201 case RFT_TYPE: 202 t = Type::make_type_descriptor_ptr_type(); 203 break; 204 205 case RFT_ARRAY2STRING: 206 { 207 Array_type* at = 208 Type::make_array_type(Type::make_string_type(), 209 Expression::make_integer_ul(2, NULL, 210 bloc)); 211 at->set_is_array_incomparable(); 212 t = at; 213 } 214 break; 215 216 case RFT_ARRAY3STRING: 217 { 218 Array_type* at = 219 Type::make_array_type(Type::make_string_type(), 220 Expression::make_integer_ul(3, NULL, 221 bloc)); 222 at->set_is_array_incomparable(); 223 t = at; 224 } 225 break; 226 227 case RFT_ARRAY4STRING: 228 { 229 Array_type* at = 230 Type::make_array_type(Type::make_string_type(), 231 Expression::make_integer_ul(4, NULL, 232 bloc)); 233 at->set_is_array_incomparable(); 234 t = at; 235 } 236 break; 237 238 case RFT_ARRAY5STRING: 239 { 240 Array_type* at = 241 Type::make_array_type(Type::make_string_type(), 242 Expression::make_integer_ul(5, NULL, 243 bloc)); 244 at->set_is_array_incomparable(); 245 t = at; 246 } 247 break; 248 } 249 250 runtime_function_types[bft] = t; 251 } 252 253 return runtime_function_types[bft]; 254 } 255 256 // Convert an expression to the type to pass to a runtime function. 257 258 static Expression* 259 convert_to_runtime_function_type(Runtime_function_type bft, Expression* e, 260 Location loc) 261 { 262 switch (bft) 263 { 264 default: 265 case RFT_VOID: 266 go_unreachable(); 267 268 case RFT_BOOL: 269 case RFT_BOOLPTR: 270 case RFT_INT: 271 case RFT_UINT: 272 case RFT_UINT8: 273 case RFT_UINT16: 274 case RFT_INT32: 275 case RFT_UINT32: 276 case RFT_INT64: 277 case RFT_UINT64: 278 case RFT_UINTPTR: 279 case RFT_RUNE: 280 case RFT_FLOAT64: 281 case RFT_COMPLEX64: 282 case RFT_COMPLEX128: 283 case RFT_STRING: 284 case RFT_POINTER: 285 { 286 Type* t = runtime_function_type(bft); 287 if (!Type::are_identical(t, e->type(), true, NULL)) 288 e = Expression::make_cast(t, e, loc); 289 return e; 290 } 291 292 case RFT_SLICE: 293 case RFT_MAP: 294 case RFT_CHAN: 295 case RFT_IFACE: 296 case RFT_EFACE: 297 case RFT_ARRAY2STRING: 298 case RFT_ARRAY3STRING: 299 case RFT_ARRAY4STRING: 300 case RFT_ARRAY5STRING: 301 return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc); 302 303 case RFT_TYPE: 304 go_assert(e->type() == Type::make_type_descriptor_ptr_type()); 305 return e; 306 } 307 } 308 309 // Convert all the types used for runtime functions to the backend 310 // representation. 311 312 void 313 Runtime::convert_types(Gogo* gogo) 314 { 315 for (int i = 0; i < static_cast<int>(NUMBER_OF_RUNTIME_FUNCTION_TYPES); ++i) 316 { 317 Type* t = runtime_function_types[i]; 318 if (t != NULL && t->named_type() != NULL) 319 { 320 bool r = t->verify(); 321 go_assert(r); 322 t->named_type()->convert(gogo); 323 } 324 } 325 } 326 327 // The type used to define a runtime function. 328 329 struct Runtime_function 330 { 331 // Function name. 332 const char* name; 333 // Parameter types. Never more than 6, as it happens. RFT_VOID if 334 // not used. 335 Runtime_function_type parameter_types[6]; 336 // Result types. Never more than 2, as it happens. RFT_VOID if not 337 // used. 338 Runtime_function_type result_types[2]; 339 }; 340 341 static const Runtime_function runtime_functions[] = 342 { 343 344 #define DEF_GO_RUNTIME(CODE, NAME, PARAMS, RESULTS) { NAME, PARAMS, RESULTS } , 345 346 #include "runtime.def" 347 348 #undef DEF_GO_RUNTIME 349 350 }; 351 352 static Named_object* 353 runtime_function_declarations[Runtime::NUMBER_OF_FUNCTIONS]; 354 355 // Get the declaration of a runtime function. 356 357 Named_object* 358 Runtime::runtime_declaration(Function code) 359 { 360 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS); 361 if (runtime_function_declarations[code] == NULL) 362 { 363 const Runtime_function* pb = &runtime_functions[code]; 364 365 Location bloc = Linemap::predeclared_location(); 366 367 Typed_identifier_list* param_types = NULL; 368 if (pb->parameter_types[0] != RFT_VOID) 369 { 370 param_types = new Typed_identifier_list(); 371 for (unsigned int i = 0; 372 i < (sizeof(pb->parameter_types) 373 / sizeof (pb->parameter_types[0])); 374 i++) 375 { 376 if (pb->parameter_types[i] == RFT_VOID) 377 break; 378 Type* t = runtime_function_type(pb->parameter_types[i]); 379 param_types->push_back(Typed_identifier("", t, bloc)); 380 } 381 } 382 383 Typed_identifier_list* result_types = NULL; 384 if (pb->result_types[0] != RFT_VOID) 385 { 386 result_types = new Typed_identifier_list(); 387 for (unsigned int i = 0; 388 i < sizeof(pb->result_types) / sizeof(pb->result_types[0]); 389 i++) 390 { 391 if (pb->result_types[i] == RFT_VOID) 392 break; 393 Type* t = runtime_function_type(pb->result_types[i]); 394 result_types->push_back(Typed_identifier("", t, bloc)); 395 } 396 } 397 398 Function_type* fntype = Type::make_function_type(NULL, param_types, 399 result_types, bloc); 400 const char* n = pb->name; 401 const char* n1 = strchr(n, '.'); 402 if (n1 != NULL) 403 n = n1 + 1; 404 Named_object* no = Named_object::make_function_declaration(n, NULL, 405 fntype, bloc); 406 no->func_declaration_value()->set_asm_name(pb->name); 407 408 runtime_function_declarations[code] = no; 409 } 410 411 return runtime_function_declarations[code]; 412 } 413 414 // Make a call to a runtime function. 415 416 Call_expression* 417 Runtime::make_call(Runtime::Function code, Location loc, 418 int param_count, ...) 419 { 420 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS); 421 422 const Runtime_function* pb = &runtime_functions[code]; 423 424 go_assert(static_cast<size_t>(param_count) 425 <= sizeof(pb->parameter_types) / sizeof(pb->parameter_types[0])); 426 427 Named_object* no = runtime_declaration(code); 428 Expression* func = Expression::make_func_reference(no, NULL, loc); 429 430 Expression_list* args = new Expression_list(); 431 args->reserve(param_count); 432 433 va_list ap; 434 va_start(ap, param_count); 435 for (int i = 0; i < param_count; ++i) 436 { 437 Expression* e = va_arg(ap, Expression*); 438 Runtime_function_type rft = pb->parameter_types[i]; 439 args->push_back(convert_to_runtime_function_type(rft, e, loc)); 440 } 441 va_end(ap); 442 443 return Expression::make_call(func, args, false, loc); 444 } 445 446 // Get the runtime code for a named builtin function. This is used as a helper 447 // when creating function references for call expressions. Every reference to 448 // a builtin runtime function should have the associated runtime code. If the 449 // name is ambiguous and can refer to many runtime codes, return 450 // NUMBER_OF_FUNCTIONS. 451 452 Runtime::Function 453 Runtime::name_to_code(const std::string& name) 454 { 455 Function code = Runtime::NUMBER_OF_FUNCTIONS; 456 457 // Look through the known names for a match. 458 for (size_t i = 0; i < Runtime::NUMBER_OF_FUNCTIONS; i++) 459 { 460 const char* runtime_function_name = runtime_functions[i].name; 461 if (strcmp(runtime_function_name, name.c_str()) == 0) 462 code = static_cast<Runtime::Function>(i); 463 // The names in the table have "runtime." prefix. We may be 464 // called with a name without the prefix. Try matching 465 // without the prefix as well. 466 if (strncmp(runtime_function_name, "runtime.", 8) == 0 467 && strcmp(runtime_function_name + 8, name.c_str()) == 0) 468 code = static_cast<Runtime::Function>(i); 469 } 470 return code; 471 }