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 23enum 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 int32, C type int32_t. 34 RFT_INT32, 35 // Go type int64, C type int64_t. 36 RFT_INT64, 37 // Go type uint64, C type uint64_t. 38 RFT_UINT64, 39 // Go type uintptr, C type uintptr_t. 40 RFT_UINTPTR, 41 // Go type rune, C type int32_t. 42 RFT_RUNE, 43 // Go type float64, C type double. 44 RFT_FLOAT64, 45 // Go type complex64, C type __complex float. 46 RFT_COMPLEX64, 47 // Go type complex128, C type __complex double. 48 RFT_COMPLEX128, 49 // Go type string, C type struct __go_string. 50 RFT_STRING, 51 // Go type unsafe.Pointer, C type "void *". 52 RFT_POINTER, 53 // Go type []any, C type struct __go_open_array. 54 RFT_SLICE, 55 // Go type map[any]any, C type struct __go_map *. 56 RFT_MAP, 57 // Pointer to map iteration type. 58 RFT_MAPITER, 59 // Go type chan any, C type struct __go_channel *. 60 RFT_CHAN, 61 // Go type non-empty interface, C type struct __go_interface. 62 RFT_IFACE, 63 // Go type interface{}, C type struct __go_empty_interface. 64 RFT_EFACE, 65 // Go type func(unsafe.Pointer), C type void (*) (void *). 66 RFT_FUNC_PTR, 67 // Pointer to Go type descriptor. 68 RFT_TYPE, 69 // Pointer to map descriptor. 70 RFT_MAPDESCRIPTOR, 71 72 NUMBER_OF_RUNTIME_FUNCTION_TYPES 73}; 74 75// The Type structures for the runtime function types. 76 77static Type* runtime_function_types[NUMBER_OF_RUNTIME_FUNCTION_TYPES]; 78 79// Get the Type for a Runtime_function_type code. 80 81static Type* 82runtime_function_type(Runtime_function_type bft) 83{ 84 go_assert(bft < NUMBER_OF_RUNTIME_FUNCTION_TYPES); 85 Type* any = Type::make_pointer_type(Type::make_void_type()); 86 if (runtime_function_types[bft] == NULL) 87 { 88 const Location bloc = Linemap::predeclared_location(); 89 Type* t; 90 switch (bft) 91 { 92 default: 93 case RFT_VOID: 94 go_unreachable(); 95 96 case RFT_BOOL: 97 t = Type::make_boolean_type(); 98 break; 99 100 case RFT_BOOLPTR: 101 t = Type::make_pointer_type(Type::lookup_bool_type()); 102 break; 103 104 case RFT_INT: 105 t = Type::lookup_integer_type("int"); 106 break; 107 108 case RFT_INT32: 109 t = Type::lookup_integer_type("int32"); 110 break; 111 112 case RFT_INT64: 113 t = Type::lookup_integer_type("int64"); 114 break; 115 116 case RFT_UINT64: 117 t = Type::lookup_integer_type("uint64"); 118 break; 119 120 case RFT_RUNE: 121 t = Type::lookup_integer_type("int32"); 122 break; 123 124 case RFT_UINTPTR: 125 t = Type::lookup_integer_type("uintptr"); 126 break; 127 128 case RFT_FLOAT64: 129 t = Type::lookup_float_type("float64"); 130 break; 131 132 case RFT_COMPLEX64: 133 t = Type::lookup_complex_type("complex64"); 134 break; 135 136 case RFT_COMPLEX128: 137 t = Type::lookup_complex_type("complex128"); 138 break; 139 140 case RFT_STRING: 141 t = Type::lookup_string_type(); 142 break; 143 144 case RFT_POINTER: 145 t = Type::make_pointer_type(Type::make_void_type()); 146 break; 147 148 case RFT_SLICE: 149 t = Type::make_array_type(any, NULL); 150 break; 151 152 case RFT_MAP: 153 t = Type::make_map_type(any, any, bloc); 154 break; 155 156 case RFT_MAPITER: 157 t = Type::make_pointer_type(Runtime::map_iteration_type()); 158 break; 159 160 case RFT_CHAN: 161 t = Type::make_channel_type(true, true, any); 162 break; 163 164 case RFT_IFACE: 165 { 166 Typed_identifier_list* methods = new Typed_identifier_list(); 167 Type* mtype = Type::make_function_type(NULL, NULL, NULL, bloc); 168 methods->push_back(Typed_identifier("x", mtype, bloc)); 169 Interface_type* it = Type::make_interface_type(methods, bloc); 170 it->finalize_methods(); 171 t = it; 172 } 173 break; 174 175 case RFT_EFACE: 176 t = Type::make_empty_interface_type(bloc); 177 break; 178 179 case RFT_FUNC_PTR: 180 { 181 Typed_identifier_list* param_types = new Typed_identifier_list(); 182 Type* ptrtype = runtime_function_type(RFT_POINTER); 183 param_types->push_back(Typed_identifier("", ptrtype, bloc)); 184 t = Type::make_function_type(NULL, param_types, NULL, bloc); 185 } 186 break; 187 188 case RFT_TYPE: 189 t = Type::make_type_descriptor_ptr_type(); 190 break; 191 192 case RFT_MAPDESCRIPTOR: 193 t = Type::make_pointer_type(Map_type::make_map_descriptor_type()); 194 break; 195 } 196 197 runtime_function_types[bft] = t; 198 } 199 200 return runtime_function_types[bft]; 201} 202 203// Convert an expression to the type to pass to a runtime function. 204 205static Expression* 206convert_to_runtime_function_type(Runtime_function_type bft, Expression* e, 207 Location loc) 208{ 209 switch (bft) 210 { 211 default: 212 case RFT_VOID: 213 go_unreachable(); 214 215 case RFT_BOOL: 216 case RFT_BOOLPTR: 217 case RFT_INT: 218 case RFT_INT32: 219 case RFT_INT64: 220 case RFT_UINT64: 221 case RFT_UINTPTR: 222 case RFT_RUNE: 223 case RFT_FLOAT64: 224 case RFT_COMPLEX64: 225 case RFT_COMPLEX128: 226 case RFT_STRING: 227 case RFT_POINTER: 228 case RFT_MAPITER: 229 case RFT_FUNC_PTR: 230 { 231 Type* t = runtime_function_type(bft); 232 if (!Type::are_identical(t, e->type(), true, NULL)) 233 e = Expression::make_cast(t, e, loc); 234 return e; 235 } 236 237 case RFT_SLICE: 238 case RFT_MAP: 239 case RFT_CHAN: 240 case RFT_IFACE: 241 case RFT_EFACE: 242 return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc); 243 244 case RFT_TYPE: 245 go_assert(e->type() == Type::make_type_descriptor_ptr_type()); 246 return e; 247 248 case RFT_MAPDESCRIPTOR: 249 go_assert(e->type()->points_to() 250 == Map_type::make_map_descriptor_type()); 251 return e; 252 } 253} 254 255// Convert all the types used for runtime functions to the backend 256// representation. 257 258void 259Runtime::convert_types(Gogo* gogo) 260{ 261 for (int i = 0; i < static_cast<int>(NUMBER_OF_RUNTIME_FUNCTION_TYPES); ++i) 262 { 263 Type* t = runtime_function_types[i]; 264 if (t != NULL && t->named_type() != NULL) 265 { 266 bool r = t->verify(); 267 go_assert(r); 268 t->named_type()->convert(gogo); 269 } 270 } 271} 272 273// The type used to define a runtime function. 274 275struct Runtime_function 276{ 277 // Function name. 278 const char* name; 279 // Parameter types. Never more than 6, as it happens. RFT_VOID if 280 // not used. 281 Runtime_function_type parameter_types[6]; 282 // Result types. Never more than 2, as it happens. RFT_VOID if not 283 // used. 284 Runtime_function_type result_types[2]; 285}; 286 287static const Runtime_function runtime_functions[] = 288{ 289 290#define DEF_GO_RUNTIME(CODE, NAME, PARAMS, RESULTS) { NAME, PARAMS, RESULTS } , 291 292#include "runtime.def" 293 294#undef DEF_GO_RUNTIME 295 296}; 297 298static Named_object* 299runtime_function_declarations[Runtime::NUMBER_OF_FUNCTIONS]; 300 301// Get the declaration of a runtime function. 302 303Named_object* 304Runtime::runtime_declaration(Function code) 305{ 306 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS); 307 if (runtime_function_declarations[code] == NULL) 308 { 309 const Runtime_function* pb = &runtime_functions[code]; 310 311 Location bloc = Linemap::predeclared_location(); 312 313 Typed_identifier_list* param_types = NULL; 314 if (pb->parameter_types[0] != RFT_VOID) 315 { 316 param_types = new Typed_identifier_list(); 317 for (unsigned int i = 0; 318 i < (sizeof(pb->parameter_types) 319 / sizeof (pb->parameter_types[0])); 320 i++) 321 { 322 if (pb->parameter_types[i] == RFT_VOID) 323 break; 324 Type* t = runtime_function_type(pb->parameter_types[i]); 325 param_types->push_back(Typed_identifier("", t, bloc)); 326 } 327 } 328 329 Typed_identifier_list* result_types = NULL; 330 if (pb->result_types[0] != RFT_VOID) 331 { 332 result_types = new Typed_identifier_list(); 333 for (unsigned int i = 0; 334 i < sizeof(pb->result_types) / sizeof(pb->result_types[0]); 335 i++) 336 { 337 if (pb->result_types[i] == RFT_VOID) 338 break; 339 Type* t = runtime_function_type(pb->result_types[i]); 340 result_types->push_back(Typed_identifier("", t, bloc)); 341 } 342 } 343 344 Function_type* fntype = Type::make_function_type(NULL, param_types, 345 result_types, bloc); 346 const char* n = pb->name; 347 const char* n1 = strchr(n, '.'); 348 if (n1 != NULL) 349 n = n1 + 1; 350 Named_object* no = Named_object::make_function_declaration(n, NULL, 351 fntype, bloc); 352 no->func_declaration_value()->set_asm_name(pb->name); 353 354 runtime_function_declarations[code] = no; 355 } 356 357 return runtime_function_declarations[code]; 358} 359 360// Make a call to a runtime function. 361 362Call_expression* 363Runtime::make_call(Runtime::Function code, Location loc, 364 int param_count, ...) 365{ 366 go_assert(code < Runtime::NUMBER_OF_FUNCTIONS); 367 368 const Runtime_function* pb = &runtime_functions[code]; 369 370 go_assert(static_cast<size_t>(param_count) 371 <= sizeof(pb->parameter_types) / sizeof(pb->parameter_types[0])); 372 373 Named_object* no = runtime_declaration(code); 374 Expression* func = Expression::make_func_reference(no, NULL, loc); 375 376 Expression_list* args = new Expression_list(); 377 args->reserve(param_count); 378 379 va_list ap; 380 va_start(ap, param_count); 381 for (int i = 0; i < param_count; ++i) 382 { 383 Expression* e = va_arg(ap, Expression*); 384 Runtime_function_type rft = pb->parameter_types[i]; 385 args->push_back(convert_to_runtime_function_type(rft, e, loc)); 386 } 387 va_end(ap); 388 389 return Expression::make_call(func, args, false, loc); 390} 391 392// The type we use for a map iteration. This is really a struct which 393// is four pointers long. This must match the runtime struct 394// __go_hash_iter. 395 396Type* 397Runtime::map_iteration_type() 398{ 399 const unsigned long map_iteration_size = 4; 400 Expression* iexpr = 401 Expression::make_integer_ul(map_iteration_size, NULL, 402 Linemap::predeclared_location()); 403 return Type::make_array_type(runtime_function_type(RFT_POINTER), iexpr); 404} 405