1 /* RPC call and callback templates 2 Copyright (C) 2014-2020 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #ifndef CC1_PLUGIN_RPC_HH 21 #define CC1_PLUGIN_RPC_HH 22 23 #include "status.hh" 24 #include "connection.hh" 25 26 namespace cc1_plugin 27 { 28 // The plugin API may contain some "const" method parameters. 29 // However, when unmarshalling we cannot unmarshall into a const 30 // object; and furthermore we want to be able to deallocate pointers 31 // when finished with them. This wrapper class lets us properly 32 // remove the "const" and handle deallocation from pointer types. 33 34 template<typename T> 35 class argument_wrapper 36 { 37 public: 38 argument_wrapper()39 argument_wrapper () { } ~argument_wrapper()40 ~argument_wrapper () { } 41 operator T() const42 operator T () const { return m_object; } 43 unmarshall(connection * conn)44 status unmarshall (connection *conn) 45 { 46 return ::cc1_plugin::unmarshall (conn, &m_object); 47 } 48 49 private: 50 51 T m_object; 52 53 // No copying or assignment allowed. 54 argument_wrapper (const argument_wrapper &); 55 argument_wrapper &operator= (const argument_wrapper &); 56 }; 57 58 // Specialization for any kind of pointer. This is declared but not 59 // defined to avoid bugs if a new pointer type is introduced into 60 // the API. Instead you will just get a compilation error. 61 template<typename T> 62 class argument_wrapper<const T *>; 63 64 // Specialization for string types. 65 template<> 66 class argument_wrapper<const char *> 67 { 68 public: argument_wrapper()69 argument_wrapper () : m_object (NULL) { } ~argument_wrapper()70 ~argument_wrapper () 71 { 72 delete[] m_object; 73 } 74 operator const char*() const75 operator const char * () const 76 { 77 return m_object; 78 } 79 unmarshall(connection * conn)80 status unmarshall (connection *conn) 81 { 82 return ::cc1_plugin::unmarshall (conn, &m_object); 83 } 84 85 private: 86 87 char *m_object; 88 89 // No copying or assignment allowed. 90 argument_wrapper (const argument_wrapper &); 91 argument_wrapper &operator= (const argument_wrapper &); 92 }; 93 94 // Specialization for gcc_type_array. 95 template<> 96 class argument_wrapper<const gcc_type_array *> 97 { 98 public: argument_wrapper()99 argument_wrapper () : m_object (NULL) { } ~argument_wrapper()100 ~argument_wrapper () 101 { 102 // It would be nicer if gcc_type_array could have a destructor. 103 // But, it is in code shared with gdb and cannot. 104 if (m_object != NULL) 105 delete[] m_object->elements; 106 delete m_object; 107 } 108 operator const gcc_type_array*() const109 operator const gcc_type_array * () const 110 { 111 return m_object; 112 } 113 unmarshall(connection * conn)114 status unmarshall (connection *conn) 115 { 116 return ::cc1_plugin::unmarshall (conn, &m_object); 117 } 118 119 private: 120 121 gcc_type_array *m_object; 122 123 // No copying or assignment allowed. 124 argument_wrapper (const argument_wrapper &); 125 argument_wrapper &operator= (const argument_wrapper &); 126 }; 127 128 #ifdef GCC_CP_INTERFACE_H 129 // Specialization for gcc_vbase_array. 130 template<> 131 class argument_wrapper<const gcc_vbase_array *> 132 { 133 public: argument_wrapper()134 argument_wrapper () : m_object (NULL) { } ~argument_wrapper()135 ~argument_wrapper () 136 { 137 // It would be nicer if gcc_type_array could have a destructor. 138 // But, it is in code shared with gdb and cannot. 139 if (m_object != NULL) 140 { 141 delete[] m_object->flags; 142 delete[] m_object->elements; 143 } 144 delete m_object; 145 } 146 operator const gcc_vbase_array*() const147 operator const gcc_vbase_array * () const 148 { 149 return m_object; 150 } 151 unmarshall(connection * conn)152 status unmarshall (connection *conn) 153 { 154 return ::cc1_plugin::unmarshall (conn, &m_object); 155 } 156 157 private: 158 159 gcc_vbase_array *m_object; 160 161 // No copying or assignment allowed. 162 argument_wrapper (const argument_wrapper &); 163 argument_wrapper &operator= (const argument_wrapper &); 164 }; 165 166 // Specialization for gcc_cp_template_args. 167 template<> 168 class argument_wrapper<const gcc_cp_template_args *> 169 { 170 public: argument_wrapper()171 argument_wrapper () : m_object (NULL) { } ~argument_wrapper()172 ~argument_wrapper () 173 { 174 // It would be nicer if gcc_type_array could have a destructor. 175 // But, it is in code shared with gdb and cannot. 176 if (m_object != NULL) 177 { 178 delete[] m_object->elements; 179 delete[] m_object->kinds; 180 } 181 delete m_object; 182 } 183 operator const gcc_cp_template_args*() const184 operator const gcc_cp_template_args * () const 185 { 186 return m_object; 187 } 188 unmarshall(connection * conn)189 status unmarshall (connection *conn) 190 { 191 return ::cc1_plugin::unmarshall (conn, &m_object); 192 } 193 194 private: 195 196 gcc_cp_template_args *m_object; 197 198 // No copying or assignment allowed. 199 argument_wrapper (const argument_wrapper &); 200 argument_wrapper &operator= (const argument_wrapper &); 201 }; 202 203 // Specialization for gcc_cp_function_args. 204 template<> 205 class argument_wrapper<const gcc_cp_function_args *> 206 { 207 public: argument_wrapper()208 argument_wrapper () : m_object (NULL) { } ~argument_wrapper()209 ~argument_wrapper () 210 { 211 // It would be nicer if gcc_type_array could have a destructor. 212 // But, it is in code shared with gdb and cannot. 213 if (m_object != NULL) 214 { 215 delete[] m_object->elements; 216 } 217 delete m_object; 218 } 219 operator const gcc_cp_function_args*() const220 operator const gcc_cp_function_args * () const 221 { 222 return m_object; 223 } 224 unmarshall(connection * conn)225 status unmarshall (connection *conn) 226 { 227 return ::cc1_plugin::unmarshall (conn, &m_object); 228 } 229 230 private: 231 232 gcc_cp_function_args *m_object; 233 234 // No copying or assignment allowed. 235 argument_wrapper (const argument_wrapper &); 236 argument_wrapper &operator= (const argument_wrapper &); 237 }; 238 #endif /* GCC_CP_INTERFACE_H */ 239 240 // There are two kinds of template functions here: "call" and 241 // "callback". They are each repeated multiple times to handle 242 // different numbers of arguments. (This would be improved with 243 // C++11, though applying a call is still tricky until C++14 can be 244 // used.) 245 246 // The "call" template is used for making a remote procedure call. 247 // It starts a query ('Q') packet, marshalls its arguments, waits 248 // for a result, and finally reads and returns the result via an 249 // "out" parameter. 250 251 // The "callback" template is used when receiving a remote procedure 252 // call. This template function is suitable for use with the 253 // "callbacks" and "connection" classes. It decodes incoming 254 // arguments, passes them to the wrapped function, and finally 255 // marshalls a reply packet. 256 257 template<typename R> 258 status call(connection * conn,const char * method,R * result)259 call (connection *conn, const char *method, R *result) 260 { 261 if (!conn->send ('Q')) 262 return FAIL; 263 if (!marshall (conn, method)) 264 return FAIL; 265 if (!marshall (conn, 0)) 266 return FAIL; 267 if (!conn->wait_for_result ()) 268 return FAIL; 269 if (!unmarshall (conn, result)) 270 return FAIL; 271 return OK; 272 } 273 274 template<typename R, R (*func) (connection *)> 275 status callback(connection * conn)276 callback (connection *conn) 277 { 278 R result; 279 280 if (!unmarshall_check (conn, 0)) 281 return FAIL; 282 result = func (conn); 283 if (!conn->send ('R')) 284 return FAIL; 285 return marshall (conn, result); 286 } 287 288 template<typename R, typename A> 289 status call(connection * conn,const char * method,R * result,A arg)290 call (connection *conn, const char *method, R *result, A arg) 291 { 292 if (!conn->send ('Q')) 293 return FAIL; 294 if (!marshall (conn, method)) 295 return FAIL; 296 if (!marshall (conn, 1)) 297 return FAIL; 298 if (!marshall (conn, arg)) 299 return FAIL; 300 if (!conn->wait_for_result ()) 301 return FAIL; 302 if (!unmarshall (conn, result)) 303 return FAIL; 304 return OK; 305 } 306 307 template<typename R, typename A, R (*func) (connection *, A)> 308 status callback(connection * conn)309 callback (connection *conn) 310 { 311 argument_wrapper<A> arg; 312 R result; 313 314 if (!unmarshall_check (conn, 1)) 315 return FAIL; 316 if (!arg.unmarshall (conn)) 317 return FAIL; 318 result = func (conn, arg); 319 if (!conn->send ('R')) 320 return FAIL; 321 return marshall (conn, result); 322 } 323 324 template<typename R, typename A1, typename A2> 325 status call(connection * conn,const char * method,R * result,A1 arg1,A2 arg2)326 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2) 327 { 328 if (!conn->send ('Q')) 329 return FAIL; 330 if (!marshall (conn, method)) 331 return FAIL; 332 if (!marshall (conn, 2)) 333 return FAIL; 334 if (!marshall (conn, arg1)) 335 return FAIL; 336 if (!marshall (conn, arg2)) 337 return FAIL; 338 if (!conn->wait_for_result ()) 339 return FAIL; 340 if (!unmarshall (conn, result)) 341 return FAIL; 342 return OK; 343 } 344 345 template<typename R, typename A1, typename A2, R (*func) (connection *, 346 A1, A2)> 347 status callback(connection * conn)348 callback (connection *conn) 349 { 350 argument_wrapper<A1> arg1; 351 argument_wrapper<A2> arg2; 352 R result; 353 354 if (!unmarshall_check (conn, 2)) 355 return FAIL; 356 if (!arg1.unmarshall (conn)) 357 return FAIL; 358 if (!arg2.unmarshall (conn)) 359 return FAIL; 360 result = func (conn, arg1, arg2); 361 if (!conn->send ('R')) 362 return FAIL; 363 return marshall (conn, result); 364 } 365 366 template<typename R, typename A1, typename A2, typename A3> 367 status call(connection * conn,const char * method,R * result,A1 arg1,A2 arg2,A3 arg3)368 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2, 369 A3 arg3) 370 { 371 if (!conn->send ('Q')) 372 return FAIL; 373 if (!marshall (conn, method)) 374 return FAIL; 375 if (!marshall (conn, 3)) 376 return FAIL; 377 if (!marshall (conn, arg1)) 378 return FAIL; 379 if (!marshall (conn, arg2)) 380 return FAIL; 381 if (!marshall (conn, arg3)) 382 return FAIL; 383 if (!conn->wait_for_result ()) 384 return FAIL; 385 if (!unmarshall (conn, result)) 386 return FAIL; 387 return OK; 388 } 389 390 template<typename R, typename A1, typename A2, typename A3, 391 R (*func) (connection *, A1, A2, A3)> 392 status callback(connection * conn)393 callback (connection *conn) 394 { 395 argument_wrapper<A1> arg1; 396 argument_wrapper<A2> arg2; 397 argument_wrapper<A3> arg3; 398 R result; 399 400 if (!unmarshall_check (conn, 3)) 401 return FAIL; 402 if (!arg1.unmarshall (conn)) 403 return FAIL; 404 if (!arg2.unmarshall (conn)) 405 return FAIL; 406 if (!arg3.unmarshall (conn)) 407 return FAIL; 408 result = func (conn, arg1, arg2, arg3); 409 if (!conn->send ('R')) 410 return FAIL; 411 return marshall (conn, result); 412 } 413 414 template<typename R, typename A1, typename A2, typename A3, typename A4> 415 status call(connection * conn,const char * method,R * result,A1 arg1,A2 arg2,A3 arg3,A4 arg4)416 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2, 417 A3 arg3, A4 arg4) 418 { 419 if (!conn->send ('Q')) 420 return FAIL; 421 if (!marshall (conn, method)) 422 return FAIL; 423 if (!marshall (conn, 4)) 424 return FAIL; 425 if (!marshall (conn, arg1)) 426 return FAIL; 427 if (!marshall (conn, arg2)) 428 return FAIL; 429 if (!marshall (conn, arg3)) 430 return FAIL; 431 if (!marshall (conn, arg4)) 432 return FAIL; 433 if (!conn->wait_for_result ()) 434 return FAIL; 435 if (!unmarshall (conn, result)) 436 return FAIL; 437 return OK; 438 } 439 440 template<typename R, typename A1, typename A2, typename A3, typename A4, 441 R (*func) (connection *, A1, A2, A3, A4)> 442 status callback(connection * conn)443 callback (connection *conn) 444 { 445 argument_wrapper<A1> arg1; 446 argument_wrapper<A2> arg2; 447 argument_wrapper<A3> arg3; 448 argument_wrapper<A4> arg4; 449 R result; 450 451 if (!unmarshall_check (conn, 4)) 452 return FAIL; 453 if (!arg1.unmarshall (conn)) 454 return FAIL; 455 if (!arg2.unmarshall (conn)) 456 return FAIL; 457 if (!arg3.unmarshall (conn)) 458 return FAIL; 459 if (!arg4.unmarshall (conn)) 460 return FAIL; 461 result = func (conn, arg1, arg2, arg3, arg4); 462 if (!conn->send ('R')) 463 return FAIL; 464 return marshall (conn, result); 465 } 466 467 template<typename R, typename A1, typename A2, typename A3, typename A4, 468 typename A5> 469 status call(connection * conn,const char * method,R * result,A1 arg1,A2 arg2,A3 arg3,A4 arg4,A5 arg5)470 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2, 471 A3 arg3, A4 arg4, A5 arg5) 472 { 473 if (!conn->send ('Q')) 474 return FAIL; 475 if (!marshall (conn, method)) 476 return FAIL; 477 if (!marshall (conn, 5)) 478 return FAIL; 479 if (!marshall (conn, arg1)) 480 return FAIL; 481 if (!marshall (conn, arg2)) 482 return FAIL; 483 if (!marshall (conn, arg3)) 484 return FAIL; 485 if (!marshall (conn, arg4)) 486 return FAIL; 487 if (!marshall (conn, arg5)) 488 return FAIL; 489 if (!conn->wait_for_result ()) 490 return FAIL; 491 if (!unmarshall (conn, result)) 492 return FAIL; 493 return OK; 494 } 495 496 template<typename R, typename A1, typename A2, typename A3, typename A4, 497 typename A5, R (*func) (connection *, A1, A2, A3, A4, A5)> 498 status callback(connection * conn)499 callback (connection *conn) 500 { 501 argument_wrapper<A1> arg1; 502 argument_wrapper<A2> arg2; 503 argument_wrapper<A3> arg3; 504 argument_wrapper<A4> arg4; 505 argument_wrapper<A5> arg5; 506 R result; 507 508 if (!unmarshall_check (conn, 5)) 509 return FAIL; 510 if (!arg1.unmarshall (conn)) 511 return FAIL; 512 if (!arg2.unmarshall (conn)) 513 return FAIL; 514 if (!arg3.unmarshall (conn)) 515 return FAIL; 516 if (!arg4.unmarshall (conn)) 517 return FAIL; 518 if (!arg5.unmarshall (conn)) 519 return FAIL; 520 result = func (conn, arg1, arg2, arg3, arg4, arg5); 521 if (!conn->send ('R')) 522 return FAIL; 523 return marshall (conn, result); 524 } 525 526 template<typename R, typename A1, typename A2, typename A3, typename A4, 527 typename A5, typename A6, typename A7> 528 status call(connection * conn,const char * method,R * result,A1 arg1,A2 arg2,A3 arg3,A4 arg4,A5 arg5,A6 arg6,A7 arg7)529 call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2, 530 A3 arg3, A4 arg4, A5 arg5, A6 arg6, A7 arg7) 531 { 532 if (!conn->send ('Q')) 533 return FAIL; 534 if (!marshall (conn, method)) 535 return FAIL; 536 if (!marshall (conn, 7)) 537 return FAIL; 538 if (!marshall (conn, arg1)) 539 return FAIL; 540 if (!marshall (conn, arg2)) 541 return FAIL; 542 if (!marshall (conn, arg3)) 543 return FAIL; 544 if (!marshall (conn, arg4)) 545 return FAIL; 546 if (!marshall (conn, arg5)) 547 return FAIL; 548 if (!marshall (conn, arg6)) 549 return FAIL; 550 if (!marshall (conn, arg7)) 551 return FAIL; 552 if (!conn->wait_for_result ()) 553 return FAIL; 554 if (!unmarshall (conn, result)) 555 return FAIL; 556 return OK; 557 } 558 559 template<typename R, typename A1, typename A2, typename A3, typename A4, 560 typename A5, typename A6, typename A7, 561 R (*func) (connection *, A1, A2, A3, A4, A5, A6, A7)> 562 status callback(connection * conn)563 callback (connection *conn) 564 { 565 argument_wrapper<A1> arg1; 566 argument_wrapper<A2> arg2; 567 argument_wrapper<A3> arg3; 568 argument_wrapper<A4> arg4; 569 argument_wrapper<A5> arg5; 570 argument_wrapper<A6> arg6; 571 argument_wrapper<A7> arg7; 572 R result; 573 574 if (!unmarshall_check (conn, 7)) 575 return FAIL; 576 if (!arg1.unmarshall (conn)) 577 return FAIL; 578 if (!arg2.unmarshall (conn)) 579 return FAIL; 580 if (!arg3.unmarshall (conn)) 581 return FAIL; 582 if (!arg4.unmarshall (conn)) 583 return FAIL; 584 if (!arg5.unmarshall (conn)) 585 return FAIL; 586 if (!arg6.unmarshall (conn)) 587 return FAIL; 588 if (!arg7.unmarshall (conn)) 589 return FAIL; 590 result = func (conn, arg1, arg2, arg3, arg4, arg5, arg6, arg7); 591 if (!conn->send ('R')) 592 return FAIL; 593 return marshall (conn, result); 594 } 595 }; 596 597 #endif // CC1_PLUGIN_RPC_HH 598